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

the GHP

From: Ben Collins-Sussman <sussman_at_collab.net>
Date: 2001-07-11 21:34:28 CEST

                    The "Greg Hudson" Problems
              Why versioning directories is Really Hard

(Greg, please pardon the name. You were the first to point out these
philosophical problems, so we've started using your name to refer to
them. :-) )

PROBLEM 1 : the lagging parent directory

Assume my working copy has two directories both at revision 3:

       A/D : 3
       A/D/H : 3

Now I `svn rm A/D/H` and commit, which produces revision 6 in the
repository. My working copy now looks like:

       A/D : 3

A/D/H is gone, because the RA layer told us it was a target that was
successfully committed. The client routine log_do_committed() got
this message, saw that the A/D/H entry was originally scheduled to be
deleted, and so it took the liberty of actually removing it during
commit cleanup.

Now, when I `svn up` to revision 6, the client sends an incomplete
report to the server on the working copy state:

       A/D : 3

It's incomplete, because there's no mention of A/D/H anywhere. As a
result, the repository *assumes* that the client still has A/D/H:3,
and thus tells the client to remove A/D/H. This is an error -- A/D/H
is already gone.

(Incidentally, this bug would still be the same if H were a file,
instead of a dir.)

PROBLEM 2 : the incomplete directory

Assume my working copy has a directory, everything at revision 3:

       A/D : 3
       A/D/H : 3
       A/D/foo.c : 3

Now, unbeknownst to me, somebody else adds a new file `bar.c' to this
directory, creating revision 4.

Then I add a property to A/D and commit. The RA layer replies that
A/D was successfully committed, creating revision 5, so
log_do_committed() bumps A/D's revision to 5 in my working copy.

Of course, this is completely bogus. My working copy does *not* have
revision 5 of A/D -- it has no idea that `bar.c' exists.

SOLUTION to Problem 1 (in progress)

A subversion entry has more than just a "schedule" flag. It now has
an "existence" flag, used specifically to describe an entry that is
out-of-sync with its parent's revision.

>> Adding a "deleted" flag

Thus, when log_do_committed() is told that A/D/H was committed, and
sees A/D/H was slated for deletion, it examines revision numbers. If
the committed target's revision (6) is newer than the parent's
revision (3), it marks the entry with "existence = deleted." (If the
two revision numbers are the same, then the entry is removed instead.)

>> Make state-reports smarter

svn_wc_crawl_revisions now notices the "deleted" flag and gives an
accurate working-copy report to the repository:

      A/D : 3
      A/D/H : missing

And now the repository will *not* tell the client to remove A/D/H.

>> Removing the "deleted" flag

There are three scenarios whereby the "deleted" flag goes away:

  * updating parent to a revision where the entry exists

     Assume that A/D/H is re-added in revision 10, and we're updating
     to this revision. Or assume we're updating to revision 4, where
     the removal hasn't happened yet.

     The repository will tell the update-editor to re-add H. The
     update-editor notices that H already exists -- but instead of
     producing an "obstructed update" error, it sees the "deleted"
     flag and instead removes and re-writes the whole entry.

  * updating parent to a revision where the entry has been deleted

     After an update finishes, ensure_uniform_revision() sets all
     working-copy revisions to the same value. It notices a "deleted"
     entry, and if it's own revision is less than or equal to the new
     uniform revision, it can safely remove the entry. The parent has
     "caught up" with the child.

  * committing parent

     If the parent is committed, log_do_committed() will be informed
     that it was successfully committed to a new revision number.
     (This new revision number *must* be higher than 6, the
     deleted-child's revision!)

     So log_do_committed() will notice the parent's "deleted" child at
     revision 6, which is younger, and remove the entry altogether.

SOLUTION to Problem 2

Still thinking on this one. Yikes.

To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:36:33 2006

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