Update with text modification
Editor v1
Updating using the current v1 editor changes the base node tree in several steps converting to and from mixed-revisions. Starting with a simple singe-revision tree:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A1 |
|
|
the v1 editor starts the update with open root:
op-depth |
local-relpath |
presence |
revision |
0 |
|
incomplete |
4 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A2 |
|
|
then open directory A:
op-depth |
local-relpath |
presence |
revision |
0 |
|
incomplete |
4 |
0 |
A |
incomplete |
4 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A3 |
|
|
then open file A/f which doesn't modify NODES. The change to A/f only exists as in-memory structures in the editor. Then apply textdelta followed by close file A/f. It's the close file that modifes NODES:
op-depth |
local-relpath |
presence |
revision |
0 |
|
incomplete |
4 |
0 |
A |
incomplete |
4 |
0 |
A/f |
normal |
4 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A4 |
|
|
then close directory A:
op-depth |
local-relpath |
presence |
revision |
0 |
|
incomplete |
4 |
0 |
A |
normal |
4 |
0 |
A/f |
normal |
4 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A5 |
|
|
then close directory for the root:
op-depth |
local-relpath |
presen |
revision |
0 |
|
normal |
4 |
0 |
A |
normal |
4 |
0 |
A/f |
normal |
4 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A6 |
|
|
then close edit for the root:
op-depth |
local-relpath |
presen |
revision |
0 |
|
normal |
4 |
0 |
A |
normal |
4 |
0 |
A/f |
normal |
4 |
0 |
A/B |
normal |
4 |
0 |
B |
normal |
4 |
|
table A7 |
|
|
In the v1 editor directories move from state normal at the old revision to incomplete at the new revision, then all the children get updated to state normal at the new revision and finally the directory gets updated to state normal at the new revision. Files don't get marked incomplete, the changes made by the sequence of operations: open file, change file prop, apply textdelta and close file accumulate inside the editor and the NODES row is updated state normal at the old revision to state normal at the new revision.
Editor v2
With editor v2, the update process will construct an editor that will perform its editing operations and apply a specific revision to each node touched. After all operations are done, the callback for svn_editor_complete() will mark all nodes with that target revision.
For the example above, svn_editor_alter_file("A/f") will update a single row:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
4 |
0 |
A/B |
normal |
3 |
0 |
B |
normal |
3 |
|
table A8 |
|
|
and then the complete call will update the rest of the tree to revision 4 giving table A7.
Update with additions
Editor v1
Start with a single-revision tree:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
|
table B1 |
|
|
Update A, open root marks A incomplete at 6:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
incomplete |
6 |
0 |
A/f |
normal |
3 |
|
table B2 |
|
|
then add directory A/B adds A/B as incomplete at 6:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
incomplete |
6 |
0 |
A/B |
incomplete |
6 |
0 |
A/f |
normal |
3 |
|
table B3 |
|
|
then add file A/B/f doesn't modify NODES, at this stage the new file only exists as in-memory structures in the editor. Add file is followed by apply textdelta and then close file A/B/f. It is close file that modifies NODES:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
incomplete |
6 |
0 |
A/B |
incomplete |
6 |
0 |
A/B/f |
normal |
6 |
0 |
A/f |
normal |
3 |
|
table B4 |
|
|
close dir on A/B:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
incomplete |
6 |
0 |
A/B |
normal |
6 |
0 |
A/B/f |
normal |
6 |
0 |
A/f |
normal |
3 |
|
table B5 |
|
|
close dir on A:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
6 |
0 |
A/B |
normal |
6 |
0 |
A/B/f |
normal |
6 |
0 |
A/f |
normal |
3 |
|
table B6 |
|
|
close edit on A bumps the revision of all other nodes under A, in this case A/f:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
6 |
0 |
A/B |
normal |
6 |
0 |
A/B/f |
normal |
6 |
0 |
A/f |
normal |
6 |
|
table B7 |
|
|
Delete, Commit and Update
Start with a single-revision tree:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
|
table C1 |
|
|
Delete A/f, the revision of the base-deleted node has no meaning:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
2 |
A/f |
base-deleted |
|
|
table C2 |
|
|
Delete A, subsuming A/f:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
3 |
0 |
A/B |
normal |
3 |
1 |
A |
base-deleted |
|
1 |
A/f |
base-deleted |
|
1 |
A/B |
base-deleted |
|
|
table C3 |
|
|
Commit, once again the revision of the not-present node has no meaning:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
not-present |
|
|
table C4 |
|
|
After the commit the parent of the deleted node is still at the old revision because the commit did not modify that directory. A subsequent update to some revision other than r3 will remove the not-present node. An update to r3 will cause the not-present node, and its children, to be reinstated.
WC-WC Copy
Start with a mixed-revision BASE node tree, with an added directory X:
op-depth |
local-relpath |
presence |
revision |
0 |
|
normal |
3 |
0 |
A |
normal |
3 |
0 |
A/f |
normal |
4 |
0 |
A/B |
not-present |
|
1 |
X |
normal |
|
|
table D1 |
|
|
The not-present A/B would usually the result of a commit/delete.
Copy A to X/Y:
op-depth |
local-relpath |
presence |
repos-path |
revision |
0 |
|
normal |
/ |
3 |
0 |
A |
normal |
/A |
3 |
0 |
A/f |
normal |
/A/f |
4 |
0 |
A/B |
not-present |
/A/B |
|
1 |
X |
normal |
|
|
2 |
X/Y |
normal |
/A |
3 |
2 |
X/Y/f |
not-present |
/A/f |
|
3 |
X/Y/f |
normal |
/A/f |
4 |
2 |
X/Y/B |
not-present |
/A/B |
|
|
|
table D2 |
|
|
The not-present A/B becomes not-present X/Y/B. This shows up as status 'D' and will generate a delete on commit if necessary (by contacting the repository to determine if X/Y/B exists after the copy). The mixed-rev A/f becomes the not-present X/Y/f at op-depth=2 and the normal X/Y/f at op-depth=3. On commit this causes an add or repace of X/Y/f.