You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by Apache subversion Wiki <co...@subversion.apache.org> on 2012/03/06 12:28:58 UTC

[Subversion Wiki] Update of "MultiLayerMoves" by PhilipMartin

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Subversion Wiki" for change notification.

The "MultiLayerMoves" page has been changed by PhilipMartin:
http://wiki.apache.org/subversion/MultiLayerMoves?action=diff&rev1=15&rev2=16

  
  Now scan_deletion(A/B/C/D) needs to tell us moved_to is Q at op-depth=4, Z/D at op-depth=3, X at op-depth=2. Quite how it does this is an open question. Does the caller pass the op-depth? Where would the caller get it?  Does the function return some sort of array of (op-depth, moved-to) pairs?
  
- = Copy/Move Differences =
+ = Nested Moves =
  
  || op-depth || local-relpath || presence || moved-to ||
  ||    0     ||    A          || normal   ||          ||
  ||    0     ||    A/F        || normal   ||          ||
  
+ Move A to B and then B/F to B/G
- Move A to B and B/F to B/G (or A/F to A/G and A to B):
- 
- '''gstein''': does the B/F to B/G have an op-depth of 2? That would change the table below. The current depiction seems very difficult to construct a commit process: if you move A to B, then how do you move A/F (no longer existing) to B/G?? And you can't do the A/F to B/G first since B does not exist. I think this seeming difficulty is based on the wrong op-depth for the B/F to B/G move.
- 
- '''philip''': that's essentially the inconsistency mentioned below: it's not clear what the op-depth should be for nested moves. The node starts at A/F and ends at B/G. The current non-multi-layer move stuff records that move in base.  Perhaps multi-layer move doesn't record that move at all, but records the A->B and B/F->B/G. In the short term move information is not used to contruct a commit, the commit still consists of copies and deletes.
  
  || op-depth || local-relpath || presence     || moved-to ||
  ||    0     ||    A          || normal       ||          ||
  ||    0     ||    A/F        || normal       ||          ||
- ||    1     ||    A          || base-deleted ||  B       ||
+ ||    1     ||    A          || base-deleted ||    B     ||
- ||    1     ||    A/F        || base-deleted ||  B/G     ||
+ ||    1     ||    A/F        || base-deleted ||          ||
  ||    1     ||    B          || normal       ||          ||
  ||    1     ||    B/F        || normal       ||          ||
+ 
+ || op-depth || local-relpath || presence     || moved-to ||
+ ||    0     ||    A          || normal       ||          ||
+ ||    0     ||    A/F        || normal       ||          ||
+ ||    1     ||    A          || base-deleted ||    B     ||
- ||    2     ||    B/F        || base-deleted ||          ||
+ ||    1     ||    A/F        || base-deleted ||          ||
+ ||    1     ||    B          || normal       ||          ||
+ ||    1     ||    B/F        || normal       ||          ||
+ ||    2     ||    B/F        || base-deleted ||    B/G   ||
  ||    2     ||    B/G        || normal       ||          ||
  
- We end up with two moves recorded A->B and A/F->B/G.  We don't record B/F->B/G.
+ Alternatively, move A/F to A/G and then A to B
+ 
+ || op-depth || local-relpath || presence     || moved-to ||
+ ||    0     ||    A          || normal       ||          ||
+ ||    0     ||    A/F        || normal       ||          ||
+ ||    2     ||    A/F        || base-deleted ||   A/G    ||
+ ||    2     ||    A/G        || normal       ||          ||
+ 
+ || op-depth || local-relpath || presence     || moved-to ||
+ ||    0     ||    A          || normal       ||          ||
+ ||    0     ||    A/F        || normal       ||          ||
+ ||    1     ||    A          || base-deleted ||    B     ||
+ ||    1     ||    A/F        || base-deleted ||          ||
+ ||    1     ||    B          || normal       ||          ||
+ ||    1     ||    B/F        || normal       ||          ||
+ ||    2     ||    B/F        || base-deleted ||    B/G   ||
+ ||    2     ||    B/G        || normal       ||          ||
+ 
+ The final database state is the same independent of the order of the moves.  The second move in the second case causes the explicit moved-to associated with A/F to be removed.
+ 
+ = Copy compared to Move =
  
  Now consider copying A instead of moving it, so copy A to C then move C/F to C/G.
  
@@ -120, +144 @@

  ||    2     ||    C/F        || base-deleted ||   C/G    ||
  ||    2     ||    C/G        || normal       ||          ||
  
- There is only one move recorded C/F->C/G.
+ There is only one move recorded C/F->C/G.  The move inside the copy is recorded in a similar way to the move inside a move.
  
- It would be possible to both of these in the same working copy, either A to C then A to B, or A to B then B to C and we end up with three moves recorded A->B, A/F->B/G and C/F->C/G. There is an inconsistency, we record C/F to C/G but not B/F to B/G. Does this matter? Perhaps it is wrong to record A/F->B/G, perhaps we should be recording B/F->B/G instead?
- 
- If we recorded moves-in-moves within the move, the above move A to B and B/F to B/G would look as follows:
- 
- || op-depth || local-relpath || presence     || moved-to ||
- ||    0     ||    A          || normal       ||          ||
- ||    0     ||    A/F        || normal       ||          ||
- ||    1     ||    A          || base-deleted ||  B       ||
- ||    1     ||    A/F        || base-deleted ||          ||
- ||    1     ||    B          || normal       ||          ||
- ||    1     ||    B/F        || normal       ||          ||
- ||    2     ||    B/F        || base-deleted ||  B/G     ||
- ||    2     ||    B/G        || normal       ||          ||
- 
- 
- This would involve rewriting the moves inside A when A is moved to B.
- 
- The DB state should be independent of the order of moves. We not care about the order in which moves were performed, only about the resulting state. So the end result should be the same for both "A -> B; B/F -> B/G;" and "A/F -> A/G; A -> B";
- 
- The first case, A -> B; B/F -> B/G, is shown above.
- 
- For the second sequence we would need transitions between the following states:
- 
- || op-depth || local-relpath || presence || moved-to ||
- ||    0     ||    A          || normal   ||          ||
- ||    0     ||    A/F        || normal   ||          ||
- 
- Move A/F -> A/G
- 
- || op-depth || local-relpath || presence     || moved-to ||
- ||    0     ||    A          || normal       ||          ||
- ||    2     ||    A/F        || base-deleted ||   A/G    ||
- ||    2     ||    A/G        || normal       ||          ||
- 
- Move A -> B
- 
- || op-depth || local-relpath || presence     || moved-to ||
- ||    0     ||    A          || normal       ||          ||
- ||    0     ||    A/F        || normal       ||          ||
- ||    1     ||    A          || base-deleted ||  B       ||
- ||    1     ||    A/F        || base-deleted ||          ||
- ||    1     ||    B          || normal       ||          ||
- ||    1     ||    B/F        || normal       ||          ||
- ||    2     ||    B/F        || base-deleted ||  B/G     ||
- ||    2     ||    B/G        || normal       ||          ||
- 
- So when moving a tree which contains moves, we must clear moved-to information for moved nodes within the delete-half of the move,
- and add the corresponding path-adjusted moved-to information within the add-half of the move. The nested moves also become their own op-roots within the copied-half.
-