[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
                               or,
              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.