Ev1.5 Representation of Moves

Summary

The original “svn_delta_editor_t” is colloquially known as “Ev1” now that a proposed new “svn_editor_t” known as “Editor version 2” (Ev2) has been around for some time.

This document sets out a proposal for revising Ev1 to support move tracking – specifically, to enable move semantics to be transmitted over the editor interface.

Since the name “Ev2” is already taken, let's call the result “Ev1.5”.

Specification

Changes to svn_delta_editor_t to support moves:

Examples

Here are some examples of move scenarios that can be difficult, and their solutions.

Example 1: Insert a directory level

|                     |
+--A  mv--\     (add) +--A
           \             |
            \-->         +--B

The add cannot happen before the move-away, but must happen before the move-here.

  1. move-away(A, id=1)
  2. add-directory(A, copy-from=null)
  3. move-here(A/B, id=1)
  4. close-directory(A/B)
  5. close-directory(A)

Example 1b: Remove a directory level (by deletion)

|                     |
+--A (del)     /-->   +--A
   |          /
   +--B  mv--/

The move-away must happen before the delete, while the move-here cannot happen before the delete.

  1. open-directory(A)
  2. move-away(A/B, id=1)
  3. close-directory(A)
  4. delete(A)
  5. move-here(A, id=1)
  6. close-directory(A)

Example 1c: Remove a directory level (by move-away)

|                       |
|              /-->     +--X
|             /         |
+--A   mv----/   /-->   +--A
   |            /
   +--B  mv----/

Move-away B, then move-away A, then move-here original B at new path A:

  1. open-directory(A)
  2. move-away(A/B, id=1)
  3. close-directory(A)
  4. move-away(A, id=2)
  5. move-here(A, id=1)
  6. close-directory(A)
  7. move-here(X, id=2)
  8. close-directory(X)

(A possible alternative, starting with move-away A, then move-away B from inside the moved A, is only possible if we've been able to complete that move by this time. It also violates the rule that the edit driver should not move a previously moved node.)

Example 2: Swap two siblings

|                     |
+--A     mv--\ /-->   +--A
|             X       |
+--B     mv--/ \-->   +--B

Neither of the moves can be completed before doing the move-away part of the other one.

  1. move-away(A, id=1)
  2. rename(B, A)
  3. close-directory(A)
  4. move-here(B, id=1)
  5. close-directory(B)

Example 3: Swap two directory levels

|                     |
+--A     mv--\ /-->   +--A
   |          X          |
   +--B  mv--/ \-->      +--B

Neither of the moves can be completed before doing the move-away part of the other one.

  1. open-directory(A)
  2. move-away(A/B, id=1)
  3. close-directory(A)
  4. move-away(A, id=2)
  5. move-here(A, id=1)
  6. move-here(A/B, id=2)
  7. close-directory(A/B)
  8. close-directory(A)

Example 4: Swap A with A/B/C

|                            |
+-- A          mv--\   /-->  +-- A
    |               \ /          |
    +-- B      mv--- X --->      +-- B
        |           / \              |
        +-- C  mv--/   \-->          +-- C
  1. open-directory(A)
  2. open-directory(A/B)
  3. move-away(A/B/C, id=1)
  4. close-directory(A/B)
  5. move-away(A/B, id=2)
  6. close-directory(A)
  7. move-away(A, id=3)
  8. move-here(A, id=1)
  9. move-here(A/B, id=2)
  10. move-here(A/B/C, id=3)
  11. close-directory(A/B/C)
  12. close-directory(A/B)
  13. close-directory(A)

(Other similar examples are possible. Instead of B being moved (as shown), it could be deleted from the old A and re-created in the new A, or the original B could move away and the new B could move into place, each by naturally following along with the move of its own parent directory.)

Concerns and Enhancements

Half-Moves at the Edge of the Subtree

An edit is scoped to a pathwise subtree of the repository (for a commit) or of the WC (for an update). It is possible for the edit to involve a node that, if seen in a wider scope, would move into or out of this subtree. With this specification the edit driver has to describe such a move as an add or delete.

There are potential advantages to describing it as a move (or rather as half of a move). This would give the consumer the ability to inform or warn the user, raise a tree conflict, or even perhaps commit or update an additional subtree in order to avoid breaking the move.

The consumer can convert a move-out to a delete trivially. The consumer can convert a move-in to an add (of sorts) by requesting the node's content from the server, which is trivial during a commit (when the consumer is the server), but hard during an update (when the consumer is the client).

References

MoveDev/MovesOverDeltaEditor – a proposal for a way to transparently encode move semantics into an old Ev1 editor drive and decode it on the receiving end – in other words, a way to tunnel move semantics through an old Ev1 connection.

MoveDev/Ev2MovesDesign – a proposal for defining moves in Ev2.

MoveDev/Ev15MovesDesign (last edited 2013-09-05 10:17:20 by JulianFoad)