== Towards using a Delta Editor to get changes into and out of WC == I wanted to find out about the options for using a standard interface to transfer local modifications from the WC to a shelf and from a shelf to the WC. Therefore I studied the svn_delta_editor_t, as this is known to be functionally complete. (Earlier I looked at the svn_diff_tree_processor_t, and this seems not to be ready for such a task.)
svn_delta_editor_t is used widely throughout Subversion but not consistently. In particular, handling of copy source ('copyfrom') is inconsistent. === Copy-from in a commit === A WC working state is a place for preparing a commit -- a single new revision. The new revision will be built from the changes specified by the WC, through a delta editor. One of the possible changes is 'add with history', with copyfrom revision and path parameters to specify the backward-pointing line of history for that node. When the commit is finalized, it will be based on a repository revision that is newer than (or equal to) the copy source revision of any added-with-history subtree. It is the repository's job (I assume) to enforce a valid copy source, where a node of the right kind already existed. The WC commit editor driver therefore sends copyfrom info, and the repository commit editor receives copyfrom info, in order for the repository to link a copied node to its line of history. === Copy-from sent to the client === In the other direction, we have several editor implementations for sending changes from repository to client: * do_diff / diff editor * do_status / status editor - using 'reporter'; no copyfrom info * do_update / update editor * do_switch / switch editor - using 'reporter'; optional weak copyfrom info (see below) * replay (one revision at a time) - sends full copyfrom info (see below) The 'do_diff' functionality can be used to diff any pair of locations in the repository. (Actually, using the reporter to describe the left-hand side, it can compare any mixed tree on the left-hand side with any single tree on the right-hand side.) The change that it describes does not necessarily represent the construction of one revision from the previous revision. Information about the line of history of each node in the right-hand-side tree is rather incidental. For example, it is not fundamentally more interesting than the history of the left-hand-side tree, and knowing the backward history connections is not fundamentally more interesting than knowing the forward connections. In contrast, 'commit' fundamentally can only create backward connections from the new nodes. 'do_status' is meant to provide a cheap preview of 'do_update' and/or 'do_switch', AFAIK; I am not considering it further here. 'do_update' and 'do_switch' are not concerned with history connections. They only need to provide a new base layer for the WC, containing a snapshot of content but not history connections. Bear in mind that update and switch can go backward in time as well as forward. === Why do update and switch have optional weak copyfrom? === Was this added in an attempt to transmit 'move' information to the update editor? There is a big difference between a (backward pointing) history connection in the repository and a "move" modification. A "move" modification has to be understood in the context of the modification being studied -- the left and right sides of a diff. === Other editors that send/receive copyfrom === 'copy' command svnmucc svnrdump load svnsync - these send copyfrom (as a full URL) to commit editor ra_serf/update.c - uses copyfrom to select a base file version for delta - passes any copyfrom through to the update editor - the update editor asserts that no copyfrom shall ever arrive (svn_wc__get_update_editor/svn_wc__get_switch_editor) svnrdump dump - calls svn_ra_do_update3(send_copy_from_args=False) for the initial full revision (if not 'incremental') - then expects to receive copyfrom info (files and dirs) so it can write out a complete dump record - ### it won't receive any copyfrom so will write a broken initial full revision record :-( === Sending 'copyfrom' to svn_delta_editor_t === I found the following sending of 'copyfrom' arguments: Client commit editor (do_item_commit()): - sends copyfrom for both dirs and files, - fully with nesting (as is required for a commit). svn_repos_begin_report3(send_copy_from_args=True): - sends copyfrom to editor->add_file(), - for files only (in "add_file_smartly()"), - only when the file itself was the copy root. RA-local/serf/svn driving svn_repos_begin_report3(): - do_diff, do_status: send_copy_from_args=False; - do_update, do_switch: send_copy_from_args is optional. Callers of svn_ra_do_update|switch(): - none request send_copyfrom_args. svn_repos_replay2(): - sends copyfrom for both dirs and files, - fully with nesting (as is required for 'svnsync') svn_repos_dir_delta2(): - doesn't send any copyfrom; - this function is almost obsolete anyway. == Conclusions and Actions == To get a copyfrom-delta out of WC, use the "commit" code: -> decouple the delta-sending part from the repository-aware part of client "commit" -> write features that perform a "commit" from WC to other existing delta editors (useful for testing, at least; maybe for users too): - "commit to dumpfile" To get a copyfrom-delta into a WC as working modifications: -> write a WC modifications editor (receiver) -> write features that push modifications into a WC: - copy the mods from one WC into another - pull a single rev from a repo into the WC -> write round-trip testing using these facilities No current caller of svn_ra_do_update|switch requests sending copyfrom. If any third-party code does, it only gets copyfrom in very limited cases. So, -> can the 'send_copy_from_args' option be deprecated, server-side? -> this API option should be deprecated, client-side; -> the ra_serf update code using copyfrom should be removed (following r998193 which removed its last use) Test and fix svnrdump dump (initial full revision): -> test whether it works -- presumably not -> write more thorough tests, e.g. run it alongside 'svnadmin dump' 'everywhere' and compare their outputs -> fix it -- - Julian