vsds: version control data structures (and algorithms)
Types: Diff Keep Change DiffsExtender Picks Patch
Functions
- fn normalize(s) -> ds.squash(ds.trimEnd(s))
normalize a line for comparing (anchoring).
This just squashes and trims the end.
- fn apply(base, changes, out--[[{}]]) -> out
Apply changes to base (TableLines), push to out
- fn toChanges(diffs, full)
- fn toDiffs(base, changes) -> diffs
Convert Changes to Diffs with full context
- fn createAnchorTop(base, l, aLen)
- fn createAnchorBot(base, l, aLen)
- fn findAnchor(base, baseMap, anchors, above--[[false]]) -> (l, c)
Find the actual anchor by searching for uniqueness in the anchors
- above=true: find above (search up)
- above=false: find below (search down)
- fn pickAnchorsTop(pick) -> isStartOfFile, anchors
- fn pickAnchorsBot(base, pick) -> isEndOfFile, anchors
- fn createPatch(base, baseMap, pick)
Create a patch item from a pick
At it's most basic it would just be:
- find line position via top and/or bottom anchor. We want at least 2 lines
- convert pick to change. Walk the text applying the change.
There are some strategies to fix common anchor misses:
- If an anchor is missing, the nearby change can be used instead. Use either
the removed or added lines. For instance, if we are supposed to remove lines
then try and find them. Conversely if the patch was already applied then the
supposed-to-be added lines will already be there!
- When adding, existing identical text is okay.
- When removing, missing text is okay as long as it's followed by an anchor of
some kind
- Keep lines act as an anchor (for above) but are otherwise not required - they
are "free" to change or be removed. If they are missing then the algorithm will
try to continue the change with or without them (dynamic programming)
- empty lines are entirely ignored and are not considered an anchor
Single Line Diff
This type is good for displaying differences to a user.
Fields:
- .b(base) orig file. '+'=added
- .c(change) new file. '-'=removed
- .text
Methods
Fields:
Methods
- fn len(k) -> k.num and k.num or #k
Fields:
Methods
Fields:
Create picks (aka cherry picks) iterator from changes.
These can then be applied to a new base using vcds.patch(base, picks)
Each "pick" is a list of Diffs which are anchored by the lines
above and below (unless they are start/end of file).
Fields:
Methods
- fn groupChanges(p, ci)
Get which changes to include in a patch group.
A group is a series of patches with Keep:len() < anchorLen (default=3)
between them.
Fields: