[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Move Tracking in the Update Editor

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: Thu, 5 Sep 2013 13:58:03 +0100 (BST)

Philip Martin wrote:

> Julian Foad <julianfoad_at_btopenworld.com> writes:
>> Philip Martin wrote:
>>> There is a related issue with mixed-revision working copies.  Suppose A
>>> gets moved to B in some commit.  A mixed-revision working copy could
>>> contain both A and B so what does the update that includes that commit
>>> do?  I suppose the server still sends some sort of "move A B" operation
>>
>> Yes.  That's this scenario:
>>
>> <https://wiki.apache.org/subversion/MoveDev/MoveTrackingUpdateEditor#One_Move.2C_One_Non-Move>.
>>
>>   WC: (A_at_10, B_at_20); repo: (r10: mkdir A; r20: mv A B)
>>   Update to r20; A moves to B, and also the existing B is updated.

Oops, that should be update to r30, and assume that there are changes in each commit as well as the move, because I want to demonstrate that there are two different sets of incoming changes when we update.

>> and the steps would be:
>>
>>   move away A; move to B (original A)
>>   delete B  # move-away
>>   add B (copy-from ... A)  # move-here: it conflicts
>
> Not sure I follow that, we don't want to delete B as it may have local
> mods and the final B is the same node so those mods should be preserved.

Notation.  I was using the notation of sending the move info in a separate prefix and then using the existing "delete" and "add-with-copy" instructions to actually execute the "move-away" and "move-here" operations respectively.

Nevertheless, you bring up a good problem.  I agree "we" (the client) quite likely do not want to delete B in such a case; the most likely conflict resolution we'd choose would be to merge the local mods from A into those in B.  But I was trying to envision an edit driver in the server that does not make that decision but rather sends commands for each of the two original paths separately and lets the receiver (client) decide how to handle the conflict.

However, I see the problem with that.  There is no sane way for the driver to describe both the move from A to B and the update to the original B in the same edit drive.

Switching to Ev1.5 notation with "move-away" and "move-here" as first class operations, as described in <http://wiki.apache.org/subversion/MoveDev/Ev15MovesDesign#Specification>, the move from A to B would be:

  rename(A,B)
  [edits in B, relative to original *A*]
  close-directory(B)

and the update to the original B would be:

  open-directory(B)
  [edits in B, relative to original *B*]
  close-directory(B)

I suppose the edit driver *could* just send both sets of instructions, one after the other, but that's pretty severely overloading the editor definition.  It likely would not play nicely with lazy/late closing of the directories, which I think we do these days.

The alternative is for the merging (and conflict resolution?) to happen earlier.  Is that feasible?  In the server where it receives a report of the WC base state and drives the editor, perhaps?

> A current Ev1 drive would be:
>
>     delete A
>     open B
>     change_prop B
>     close B

Right.  Note that here the changes in B are expressed relative to the pre-existing 'B' base state.

> For the Ev1+ drive we add move and drop the "delete A" and "open
> B":
>
>     move away A id=1
>     move here id=1 B
>     change prop B
>     close B

Well, now, are you thinking that the "move here" operation just conveys a semantic intent but does not actually do anything to B, and then editor expresses the necessary changes in B relative to the existing base state at path B (^/B_at_20); or that the "move here" executes a move (or copy) of the base state in the WC and expresses the changes relative to that state (^/A_at_10)?  It matters -- they're different sets of changes.

> However if B did not exist in the initial working copy the Ev1 drive
> would be different:
>
>     delete A
>     add B
>     change_prop B
>     close B

Agreed.

> but with Ev1+ we would get the same sequence.  So it appears that "move
> here" is somehow replacing both open and add.  The driver can
> distinguish these cases and I think it should be telling the receiver.

My definition in the Wiki has "move-here" meaning to actually move the referenced base state to the target path, and any following edits will be based on that new state.

(I can't usefully respond to the remainder below until we get more precise in our notation.)

- Julian

>>> but we may want the server to tell the client that B is not being
>>> replaced.
>>
>> That happens naturally.  If B is being replaced by the moved A:
>>
>>   WC: (A_at_10, B_at_10); repo: (r10: mkdir A B; r20: delete B; mv A B)
>>   Update to r20; A moves to B, replacing the previous B.
>>
>> then the server would include an additional "delete A" step:
>>
>>   move away A; move to B (original A)
>>   delete B  # move-away
>>   delete A
>>   add B (copy-from ... A)  # move-here: it conflicts
>
> There are 3 cases:
>
>     1)  A moved to B where B does not exist
>     2)  A moved to B where B exists and is the same node
>     3)  A moved to B where B exists but is a different node
>
> 1 and 2 are the cases above.  For 3 the current Ev1 drive would be:
>
>     delete A
>     delete B
>     add B
>     change prop B
>     close B
>
> I suppose the Ev1+ drive might be something like:
>
>     move away A id=1
>     delete B
>     move here id=1 B
>     change prop B
>     close B
>
> In this case local mods to B would cause a tree-conflict due to the
> delete/replace.
>
> It might be interesting to see how Ev2 would handle these 3 cases.
>
>     1)  A moved to B where B does not exist
>
>     alter dir ., children=A,B
>     move A B, replaces_rev=-1
>     alter B
>
>     2)  A moved to B where B exists and is the same node
>
>     alter dir ., children=A,B
>     move A B, replaces_rev=-1
>     alter B
>
>     3)  A moved to B where B exists and is a different node
>
>     alter dir ., children=A,B
>     move A B, replaces_rev=N
>     alter B
>
> Ev2 distinguishes between add and replace via the replaces_rev flag but
> as with Ev1+ the driver knows about the difference between 1 and 2 but
> doesn't communicate it to the receiver.
Received on 2013-09-05 14:59:05 CEST

This is an archived mail posted to the Subversion Dev mailing list.