One of the limitations I am hitting on shelving is inconsistent API for sending
modifications from and to a WC.
The APIs need to support complete WC changes including multi-layered copy
operations.
For getting changes out of the WC, what better API than the one we use to
commit? That necessarily supports all committable changes, and it includes the
copy-from info relating to multi-layered copies.
We could direct this 'commit' output to places other than the repository:
* 'commit' to a shelf -- even perhaps implemented as a small real FSFS inside
the WC metadata area, initialized to match the base state of the WC; or
* 'commit' to another WC, duplicating the state of one WC into another WC:
- first set up WC2 with the same WC base state:
"svn viewspec export WC1 | svn viewspec import WC2"
- then duplicate the changes from WC1 into WC2
drive the 'commit' API from WC1 connected to a 'receiver' API of WC2
What is the 'commit receiver' WC API? It doesn't exist yet. It would be another
delta-editor API, and it needs to make changes to the WC working state rather
like 'merge' does, except merge does not try to recreate the source branch's
copies in the target WC.
Merge uses the svn_ra_do_diff3() as a diff source, and this sends no copyfrom
info. Merge converts each incoming add to be recorded in the WC as a copy from
the merge source, but that is only a single flat subtree for each incoming
added subtree. By contrast, what we need is when an incoming copied subtree 'A'
(copy-from pathA@rA) contains another copied sub-subtree 'A/B' (from pathB@rB),
we need to layer both copies in the WC. Not terribly hard: just the same as if
we manually ran "svn cp URL_A@rA A; svn cp URL_B@B A/B".
The benefit of designing this second thing -- this featurette to duplicate
changes from WC1 to WC2 -- is not that it has any current practical use, but
that it would testably prove the two-way API, without needing to build any
shelf storage infrastructure behind it. Once that is stable, we could use these
APIs to build better shelving.
On the 'changes in to WC' side, I might start by:
- extracting the diff-and-apply functionality from the 'merge' code;
- asking it to call svn_ra_do_switch() instead of _diff() in order to get
copyrom info sent;
- making the delta-editor-to-diff-processor conversion pass copyfrom info
along, in libsvn_client/repos_diff.c;
- making merge_dir_added() and merge_file_added() perform a repo-to-WC copy
when copyfrom is present.
On the 'changes out from WC' side, I might start by:
- extracting the basic 'drive a commit' functionality from the 'commit' code;
- that's it.
--
- Julian