Branching Trees under VaMP



September 5th, 2021 by Diana Coman

Since there's nothing better than heavy, real-life use to test any new tool, my 2 weeks old VaMP got to handle already all the various small and large, light and heavy, straightforward and even utterly gnarly codebases that I care about currently. While there was no trouble whatsoever from VaMP itself, the exercise did point out and basically enforced at times some further cleaning and better structuring of the code being thus inspected - and I count this as an added benefit of finally having a proper versioning tool!

The resulting trees are also so much clearer and easier to follow (for NOT having 1001 spurious "dependencies" in them, mostly) that exploratory branches or connected projects or even regrinds1 of some set of patches simply find their natural and even *helpful* place in the complete tree, alongside everything else. If anything, it's actually the visualization that lags now behind and is increasingly in the way, to the point that I suspect I'll have to do something about it sooner rather than later, since it's a rather ridiculous situation to have the supposedly-clearer picture end up unable to fully show what the underlying tool is capable of. Still, I might take my time on this, since after all my time really is my own and there's no lack of interesting things competing for it.

Keeping for now the legacy visualisation and as an example, here's the VaMP tree that branches off to obtain the latest base layer, VaMP or Eulora client. Note that with VaMP, even such a closely related set of branches that obviously share a significant number of files are nevertheless clearly and unambiguously separated (and no, not relying for this on the manifest file, either):

vamp_trees_1_640.jpg

For an even more obvious illustration of how much clearer VaMP trees can be, I intended first to look at the regrind of ye olde EuCrypt, since such a regrind allows at least a direct comparison of resulting trees, too, why not. This ran however quickly into another one of the old V's issues, namely unintended branching forced on by the tool, like this: while the mpi component is added in the 2nd patch, it literally ... vanishes from the "pressing" of any subsequent patches between 8th and 14th simply because these patches only add new files rather than changing existing ones. And since at that time there wasn't any manifest file as a sort of workaround for this and I refused to just change some files specifically to compensate for V's own problems, the effect is that for anything between the 8th and the 11th patches, inclusive, the user is forced to either make do with only a partial snapshot of the codebase or otherwise manually put it together out of 2 or 3 "presses" - just the sort of self-inflicted trouble that V provides. The V-tree of EuCrypt makes both the unintended branches and the forceful reunion of them all via the chapter 12 patch quite clear, too:

vamp_trees_2_640.jpg

Given the above, this regrind of EuCrypt takes therefore the shortest path: the first 7 patches match directly the old first 7 patches, but then there is simply one single patch to bring the code to what was the last published version of EuCrypt. Since the detailed regrind is anyway needed more for historical reasons than for any current practical use, I am really not inclined at all to sink more time into it merely for the sake of fully recovering each and every patch as it should have been in the first place. The good news with VaMP is that even if I decide to do a fully detailed, history-preserving regrind at a later time, there will be no problem whatsoever, as it will simply appear in the VaMP tree alongside this quick regrind, effectively as a more detailed, finer-grained alternative and quite obvious as such simply from the graph visualisation directly. For now though, the VaMP tree of EuCrypt has only 8 patches in total and is just a very straight line. Even so, there is perhaps enough contrast if you compare the first 7 patches with the original ones: in the VaMP tree, even these 7 patches very clearly and unambiguously follow one another in direct sequence, without any "alternative" paths between them, spuriously created by the tool rather than intended by the user:

vamp_trees_3_640.jpg

For a concrete example of VaMP in action, here's how I made the first new patch of EuCrypt, as a regrind of the old eucrypt_genesis.vpatch (the listing includes the "pressing" with v.sh of eucrypt_genesis as well as the first cleanup required: all those initial README files were identical and therefore VaMP listed them all as duplicates; once this issue was sorted so that there were no more duplicates, the patch was swiftly created and duly signed, too, since something unsigned is not even a patch at all, by definition):

$v.sh press p1 patches/eucrypt_genesis.vpatch
creating eucrypt/README
creating eucrypt/mpi/README
creating eucrypt/smg_comm/README
creating eucrypt/smg_keccak/README
creating eucrypt/smg_rsa/README
creating eucrypt/smg_serpent/README
$mkdir eucrypt/v1
$nano eucrypt/v1/manifest.vamp
$vamp add
ERROR: Main_V: Usage: vamp add dirnew patchfilename keyfile dirold
$vamp add eucrypt/p1/ data/patches/eucrypt_init.patch data/keys/***.priv eucrypt/v1/
Enter a password for key in data/keys/***.priv:
STATUS: Diff-ing directories eucrypt/v1/ and eucrypt/p1/ to patch data/patches/eucrypt_init.patch with hash length -1
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
ERROR: duplicates in eucrypt/p1/ files/dirs are not acceptable under V, sorry. Found to be duplicates in eucrypt/p1/:
 eucrypt/smg_comm/README
 eucrypt/mpi/README
 eucrypt/smg_rsa/README
 eucrypt/smg_keccak/README
 eucrypt/smg_serpent/README
ERROR: Main_V: Directory eucrypt/p1/ contains duplicates and/or empty directories and/or special files that are not acceptable under V, sorry.
See the list(s) provided. Kindly clean these up and run V again.
$cd eucrypt/p1/eucrypt/
$nano -wF mpi/README smg_rsa/README smg_keccak/README smg_serpent/README
$cd ../../../
$ vamp add eucrypt/p1/ data/patches/eucrypt_init.patch data/keys/***.priv eucrypt/v1/
Enter a password for key in data/keys/***.priv:
STATUS: Diff-ing directories eucrypt/v1/ and eucrypt/p1/ to patch data/patches/eucrypt_init.patch with hash length -1
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Signing patch and writing to sig file data/sigs/eucrypt_init.patch.sig
STATUS: Patch written to data/patches/eucrypt_init.patch and signature written to data/sigs/eucrypt_init.patch.sig

The resulting eucrypt_init.patch is 57 lines long so not a heavy read by any measure. Moving on, the rest of the patches are created similarly, with the only annoyance being ofc that the duplicates issue has to be fixed for each of the old patches' output since the old v is unhelpful as always. And for a check, one can simply "go"2 to the output of this patch and then diff the directories:

$ vamp go eucrypt/v2/ data/patches/eucrypt_init.patch
using keys from data/keys signatures from data/sigs patches from data/patches, aiming to go from eucrypt/v2/ to data/patches/eucrypt_init.patch.
There are  1 trusted keys found in data/keys.
There are  11 patches included.
Creating the graph of all patches...
Reading/calculating indices for all patches...
Calculating all links between patches...
Allocating numerical ids...
Finding the shortest path from eucrypt/v2/ to output of patch data/patches/eucrypt_init.patch
data/patches/eucrypt_init.patch
The above set of patches will update eucrypt/v2/ to the output of patch data/patches/eucrypt_init.patch. Proceed (y/n)?
y
STATUS: Attempting to apply patch data/patches/eucrypt_init.patch on dir eucrypt/v2/
STATUS: CREATING dir eucrypt/v2/eucrypt
STATUS: CREATING dir eucrypt/v2/eucrypt/mpi
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_comm
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_keccak
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_rsa
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_serpent
STATUS: PATCHING file eucrypt/v2/manifest.vamp
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_keccak/README
STATUS: CREATING new file eucrypt/v2/eucrypt/mpi/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_rsa/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_serpent/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_comm/README
STATUS: CREATING new file eucrypt/v2/eucrypt/README
STATUS: Checking for validity the resulting dir eucrypt/v2/
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Patch successfully applied.

As for the manual check of the two directories, first at the hands of the old vdiff for the sake of using it one last time and then, rather more specific, via VaMP itself:

$vdiff eucrypt/p1 eucrypt/v2
$vamp diff eucrypt/p1 eucrypt/v2
STATUS: Diff-ing directories eucrypt/p1 and eucrypt/v2 to file listing_p1_v2.diff with hash length -1
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Differences written to listing_p1_v2.diff

$more listing_p1_v2.diff 

UNCHANGED file eucrypt/README f95012efab511d8bcb069ce2676f236fda68421d6fc55a6e0e8682f4f16f
731b3dff9a1900012f92011d253c2749bd264ed493e33de8575c5b8a205ddea313108b93865717256127047fdc
23bd10f57fc577472965a7e893a031a5b1325077f619d2604b7fc83158ad9b06f3b3b069462bea26d7a8f78168
f2ae551198d156b6927d339a7f4ef20731892e8bfe6f370e2fd0d9621c4418b3ad67c9a0723b56be45f2a34285
9baa1539ac145eeddf327fa9e420aa4436bdeb4406a3cb7bb124a4bc9dfdcce17ca71b634550db8bc542013523
15af23e9eb9e7ff5565bb0c1182940202f271f6255cef0cb2aa63a008157de3763
UNCHANGED file eucrypt/mpi/README 581dbae69cf2aa6b42997b5e3fb9f551884f4b33a22280f8f3857a2f
10061a68b553b236355e63858975cad7c4ffb665f117c83d836b06a70c1d6523fd199ba2c1143a60196115e23a
050b705cd769ade2e629b01cbd65538b178654db8fb52506148d0008d57bd746516a39cd505e9d246e026d49d1
6ab166afdd68d29cc84c336e00286b6f2826d22c28632cec25efb3cd7532ae74f24fe5a4661f637c31fd843da9
f816dc820cc2d97237c25aec0a337d08e8c316f057e92345ef48d88c2ca21085230e0f30425f5ceef3f394901a
6db8ff2863ee3d2e2d09fdcac886d5f83d08117d59f4a77576e7ffaefaf327d1efb76d
UNCHANGED file eucrypt/smg_comm/README f7f739e8292418e621d2db623a7c7e5f1180a60145a89a72969
de8856eba2896faeed587a8c241d476a218b6dda753ed72693da5493fef065b49085e01dca130955f7fcb2aa79
a0c8d6e4436a188916f51504169a27eb021550dfc211a00dcecb28d24c9273526867533ee4490bb8115b298441
846cca7987d4b1395af49c3d1183fb090b5ee971194aa46a2de1f6656ee9b225fb6b58fad64ce8a9fa331688b2
021b36553f774047d1257a3d8905351f6bf57a87be4d4a6c42ff141a66f911c64ec8ef1eea18433e42856b4762
d7810db3010bd13799f426c591472abbf0693197501722114151eaafdc3efc36b1933cefb50
UNCHANGED file eucrypt/smg_keccak/README 4a76c7a5aba2a4c181e6608764ac292a57e965c14ae41d7cf
57fd8ceaa09eeaf4d4cd8a14f3f8746a2f9f3f2130aab3becdfb37f8b3f8e2dbec59238aa58659325c9a676230
a7382168d1d252045e8b658945e854898c9f7fb413da95e0a7406b142518d3fa28992a595f71fe75f05575f288
e102fbe93af8f641cc5c1d57e081052585ed94957db79e607fe90cabdaada8ebd20eade5cee0eba43f8659e655
51f3c235f3cb899b7eeac503999594a64138cb781569274ec81813553ca5a2a18789fe2b5483aa7daeaeb7d360
29a250170d9379c0f3c4cb958164ad658df1feeddc963d854bbf552c91f901331520269edb388
UNCHANGED file eucrypt/smg_rsa/README 8175ba70c4849627a412f9ebbef48f0bbc246d4c41533917d75a
03c081e516865d9670f6338259931908ba8a6c76f3684b21023d3affda0447b1877d871356b21fa065a26cab86
ed406be901e3b350c4495b5fb038198a19ffb9e63ed4eab99ab0edc802ae21fb3683862d2ac4cfb77765ed749d
4d52429597dc74a6908f19a357b660b8f6c245cdf8d705bf0980730fa1fb2837d93bcba88b04964e72d6904bea
0b956a91a9e65d41ab835903c19bb093ac7419b28b041ce42feba7a94cce169b4cb4319b430614826e68074aeb
5790c9a6a18a3ede90f1c6e0a327c1a647f237d3759849782d9ad812bb87d7cff22f447bbe
UNCHANGED file eucrypt/smg_serpent/README ba52bbe68a8d74e40f07218d3e8db179ff5567a6051491d5
e00c4e4e8d96f7b80ff64638df8b01bb0eb3413cb14edaa3c1e631ff8af280d5581e6ef5119fdb6ef073368b90
4027ed71973ed1516f32ab4136e3538a13d6df158c02f32403babd2504ad9929a60f3e2bcc4356128612d64b78
71ee89e1c6d397873833bb6ee68a824a0cadc5bb3aed8d37d2e116c790dc043f99fb3c47fd3be9175c81af6eeb
075a64b960057b4ad9cc42e56742ec978acb475aca5ba5fa5d67246883519b9b3d5732e04e633f71530e7ad5d8
436ef899c329e881f115e2e8ca52b69110e03658584e6574581f5485baac1b40c1ad91ad882e39
UNCHANGED file manifest.vamp 5cf22534fa176541099d83b47f34940b0ca9499d97777dc7dc9f789c8b56b
41c5d14f2b34c47371d62c0360ad0c35972db8e08a51ec445d0402c40f9e58aaa035331acab6621977ca34a6f7
32e2c2d764b59e1df94d73cdfc0c46f7fb7e1c382081e917d33773471303fd1cad7bfa17e792cc0ea99f92d37a
3f88414f4641bb3594571a512884aa3eb973b3b0f3f24436caa5f77237cb59e75a4df419960a64ba43716ea6c0
dd8cfd45378779e1b70f7929a43d850ded315cb778070cd92b58452de61ff639634d47af7546f8304f460164b6
7d4abe6549a226111ef7ba56611fc03664cbe439d81e92b66b78998cc64dca095

From the above output, you might be tempted to say that VaMP is more verbose than vdiff, perhaps. I think that the more accurate description though would be that VaMP is more explicit than vdiff and I'll add to this that VaMP is indeed by design explicit rather than implicit, whenever possible. So yes, VaMP's own "diff" command always provides a full comparison of the two inputs, listing not only what is different but also what is identical. And now that I finally have this explicit and very helpful tool, I don't want to go back to the "implicit" way for anything in the world, either.


  1. Moreover, regrinding itself is not at all the huge pain that it used to be. And in losing the pain factor, it further gained in usefulness as it literally allows and supports for instance the gradual "digestion" of a huge initial codebase that may be perhaps imported first as a giant patch that gets nevertheless broken down into more manageable pieces as comprehension advances. In other words, VaMP can help indeed with code study and comprehension, too. 

  2. While this name might still change, it's both short and fitting enough for my current needs, since what one wants is to get to the *exact and guaranteed* result of the specified patch, as simple as that. So VaMP will simply go from where the code you give as input happens to be to where the patch takes it - provided that there is a fully valid path (possibly involving multiple patches) that verifiably gets you there, of course. 

Comments feed: RSS 2.0

Leave a Reply