Philip Martin <philip.mar...@wandisco.com> writes:

> What about alter_dir?  I think the rule is that alter_dir on a directory
> should occur before add or delete affects the children of the directory.
> There is also a rule:
>
>  * - The ancestor of an added, copied-here, moved-here, or
>  *   modified node may not be deleted. The ancestor may not be moved
>  *   (instead: perform the move, *then* the edits).

I've been thinking about alter_dir and I see no reason, in the update
editor at least, for a rule that requires alter_dir before adding or
removing children.  The Ev2 "once" rule is designed to ensure that Ev2
actions can be applied to the nodes in the working copy as the actions
are received and that the working copy nodes will always reflect
repository nodes.  This doesn't require alter_dir on the parent before
add/delete of children.

Consider a working copy with three nodes:

   A@6
   A/B@6
   A/C@6

that gets updated to

   A@8
   A/D@8
   A/E@8

That's two adds, two deletes and an alter and the update editor can
handle them in any order, even this order:

   add_dir A/D
   delete A/B
   alter_dir A, children=D,E
   add_dir A/E
   delete A/C

Lets see how NODES would work:

     relpath  rev  status
     A         6   normal
     A/B       6   normal
     A/C       6   normal

   add_dir A/D

     relpath  rev  status
     A         6   normal
     A/B       6   normal
     A/C       6   normal
     A/D       8   normal

   delete A/B

     relpath  rev  status
     A         6   normal
     A/B       6   not-present
     A/C       6   normal
     A/D       8   normal

   alter_dir A

     relpath  rev  status
     A         8   normal
     A/C       6   normal
     A/D       8   normal
     A/E       8   incomplete

   add_dir A/E

     relpath  rev  status
     A         8   normal
     A/C       6   normal
     A/D       8   normal
     A/E       8   normal

   delete A/C

     relpath  rev  status
     A         8   normal
     A/D       8   normal
     A/E       8   normal

Every intermediate state has NODES rows that reflect repository nodes.
If interrupted every intermediate state can be correctly updated to
either r6, r8 or any other revision.

The delete introduces a not-present node if the parent revision is
different from the target revision, otherwise it simply removes the
node.

The alter removes any not-present children and introduces incomplete for
any missing children.

Any children that are replaced, i.e. add with replaces-rev set, do not
require alter_dir on the parent at all, although some other change to
the parent may require it.

> It's not clear where alter_dir should occur w.r.t the moves in my
> example.  Does alter_dir count as an edit that should occur after move?
> Do we pass initial state paths:
>
>    alter_dir .,     children='A'
>    alter_dir A,     children=''
>    alter_dir A/B,   children='C'
>    alter_dir A/B/C, children='B'
>
> or final_state paths:
>
>    alter_dir .,     children='A'
>    alter_dir A,     children='B'
>    alter_dir A/B,   children='C'
>    alter_dir A/B/C, children=''

So we don't necessarily have to do alter_dir on the parent before moving
children.  What about alter on the moved node itself?  Perhaps we do
that between move_away and move_here.

     relpath    rev  status       repo
     A           6   normal       A
     A/B         6   normal       A/B
     A/B/C       6   normal       A/B/C

   move_away A/B/C, id=1

     relpath    rev  status       repo
     A           6   normal       A
     A/B         6   normal       A/B
     A/B/C       6   not-present  A/B/C

   move_away A/B, id=2

     relpath    rev  status       repo
     A           6   normal       A
     A/B         6   not-present  A/B

   move_away A, id=3

     relpath    rev  status       repo
     A           6   not-present  A

   alter_dir id=1, children=B
   move_here id=1, A

     relpath    rev  status      repo
     A           8   normal      A
     A/B         8   incomplete  A

   alter_dir id=2, children=C
   move_here id=2, A/B

     relpath    rev  status      repo
     A           8   normal      A
     A/B         8   normal      A/B
     A/B/C       8   incomplete  A/B/C

   alter_dir id=3, children=
   move_here id=3, A/B/C

     relpath    rev  status      repo
     A           8   normal      A
     A/B         8   normal      A/B
     A/B/C       8   normal      A/B/C

That looks like the set of NODES tables that we want. At each stage the
NODES rows reflect nodes in the repository and if interrupted an update
to any revision is possible.

This also means that NODES.repos_path and NODE.revision in the NODES
table always reflect nodes in the repository.  If we try to do alter
before or after move we end up with things that look switched or nodes
that are not valid.  Consider an update that moves A/B to A/C:

     relpath    rev  status       repo
     A           6   normal       A
     A/B         6   normal       A/B

If we move before alter we either get

   move A/B A/C

     relpath    rev  status       repo
     A           6   normal       A
     A/C         6   normal       A/C

or

     relpath    rev  status       repo
     A           6   normal       A
     A/C         6   normal       A/B

The first has an invalid row A/C@6 the second has A/C switched.  If we
alter before move we either get

   alter_dir C, children=

     relpath    rev  status       repo
     A           6   normal       A
     A/B         8   normal       A/B

or

     relpath    rev  status       repo
     A           6   normal       A
     A/B         8   normal       A/C

again either invalid or switched. This implies that if we want to
combine

     move_away A, id=1
     move_here id=1, B

into a single

     move A, B

then move and alter need to be combined:

     move_dir  A, B, children=, props=
     move_file A, B, checksum=, props=

-- 
Philip Martin | Subversion Committer
WANdisco // *Non-Stop Data*

Reply via email to