anchors_and_targets.txt   [plain text]

Of Anchors and Targets

Definitions (contextually bound, of course):

   anchor - The name given to the directory at which an editor is
            rooted.  That is to say, the directory baton returned by
            editor->replace_root() is meant to describe the anchor

   editor - A function vtable containing methods used to describe
            changes to a directory tree.  [see include/svn_delta.h]

   target - The file(s) or directory(s), relative to the anchor,
            designated as the actual intended subject of a given
            operation (update, commit, etc.).  This, in practice, can
            be NULL if the anchor itself is the intended subject.

A Little Background

   The concept of anchors and targets trickled out of the brains of
   C. Michael Pilato and Ben Collins-Sussman during the course of
   debugging the `svn up' command.  Updates are not atomic, so each
   item-to-be-updated ("update target") passed to this command gets
   its own update procedure.  The update procedure involves describing
   the update target in the working copy to the repository using a
   "reporter".  The repository then, using an editor, modifies the
   update target in the working copy to look exactly as it does in
   the repository (usually in the youngest revision, but optionally,
   at any revision snapshot of the tree).

   At that time, if the update target was a directory, the editor
   handed to the repository was rooted at that directory.  If the
   update target was a file, the editor was rooted at the parent
   directory containing that file.

   It became apparent rather quickly that the orderly design of the
   editor apparatus required more precise usage in order to get the
   desired results.  Some of the problems in the original usage are as

     * For directory updates, it was impossible for the driver of the
       editor to request that the update target be deleted.  The
       editor's delete_entry() receives as parameters a directory
       baton, and the name of an entry in that directory to be
       deleted.  If an editor is rooted at the update target, it is
       impossible for there to exist a directory baton describing its
       parent, and therefore no way to delete it as a named entry in
       its parent.  Clearly, this limitation to the update command was

    * For file updates, having an editor rooted at the parent
      directory without supplying addition information to the editor's
      driver meant that if siblings of the update target were also
      "out of date" with respect to the update request, they too would
      be affected by the editor drive.  Clearly it was unacceptable to
      have items in the working copy modified that should have been
      considered outside the scope of the requested update operation.
   And so the notion of anchors and targets was born. 

The Implementation

   Anchors had been present all along as the root of the editor drive,
   but were not going to be chosen in a way that expanded the scope of
   the knowledge that the editor has about the tree.  Targets became
   the "additional information" passed to the editor driver to
   restrict the scope of the editor's legitimate activity to only the
   file or directory intended as the focus of the update.

   A new function, svn_wc_get_actual_target() was created and given
   the responsibility of deciding, given an update target path (and
   access to the working copy administrative directory), what the
   actual anchor and target of the editor drive would be.  The rules
   are fairly straightforward:

     * For directory updates, if the parent directory of the update
       target is a valid place to root an editor, that parent
       directory becomes the anchor, and the update target itself
       becomes the target.  If the parent directory is not a valid
       place to root an editor, the update target becomes both the
       anchor and the target (the target is passed as NULL).  Validity
       of the parent directory in the working copy is determined by
       whether or not it is also the update target's parent directory
       in the repository.
     * For file updates, the update target file's parent directory is
       the anchor, and the file itself is the target.

   Shortly after this was implemented for updates, it became apparent
   that commits needed the same sort of ideology in place.  That was
   implented as well.

The Status Quo

   There currently exist a few kinks in the system, not (in my
   opinion) in the theoretical design of the anchor/target scheme, but
   in their handling as those items get passed around through the
   working copy, RA layer, and filesystem modules.  Some complaints
   have been raised about the theoretical design of the anchor/target
   scheme, however, such as the need to examine the a directory
   target's parent, and perhaps a handful of unspecified
   "spidey-sense" warnings.  PLEASE, if you have valid technical
   complaints, (re-)voice them in reponse to this mail so they can be
   evaluated more closely, offering better solutions if you can.

   For example, the editor could be changed so that some flavor of
   delete_entry() could delete the item represented by the baton given
   it (perhaps, delete_this()).  I believe this to be inelegant.

     * The only way to get that baton would be to add or replace the
       file or directory, operations which are obviously tied to
       entirely different notions.  

     * The only *required* place for this would be in attempting to
       delete a directory whose parent in the working copy was not
       also its parent in the repository, which would (in either the
       update or the commit case), result in the completely destroyed
       working copy.  In the commit case, I suppose this is alright,
       but it would certainly be strange for a user who had checked
       out a repository subdirectory which has recently been deleted
       to run `svn up' and find their working copy missing.

     * It requires special handling for the directory that maps
       to the root of the repository, which simply cannot be deleted
       (theoretical wrongness all over the place).  Currently, the
       solution has no "special cases".

In Conclusion

   There are likely better ideas out there that never crossed my mind.
   Please submit them for review and discussion!  Currently, I suspect
   that the most of the bugs in the present system exist because the
   distinction of the anchor and target notions is lost when at some
   point in the code path they are concatenated back together on the
   "server" side (or, some place that doesn't have access to the
   working copy module, since I think there are issues in both ra_dav
   and ra_local) into a single path.