| 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 response 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. |
| |
| |