blob: d5f5774296b01e24f6b058aa9a63aee8e8ff9f61 [file] [log] [blame]
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
directory.
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
follows:
* 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
unacceptable.
* 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.