| WC to WC Copy |
| ============= |
| |
| In 1.6 a wc-to-wc copy of a directory first does a plain copy, |
| including the admin directory, and then adjust the metadata to make it |
| a copy. With a centralised db the metadata has to be copied |
| separately and explicitly. |
| |
| When copying a mixed revision working copy the source may have nodes |
| that are in states such as absent, excluded, not-present or |
| incomplete, as well as nodes at different revisions and nodes with |
| local modifications. |
| |
| Consider copying and committing |
| |
| $ svn cp wc/S wc/X |
| $ svn ci wc/X |
| |
| where S contains a child T. When the copy is committed certain |
| changes have to be made in the repository. Some examples: |
| |
| Source Commit after copy |
| Parent Child Parent Child |
| |
| /S@N /S/T@N A /X (from /S@N) |
| or |
| A /X (from /S@N) M /X/T |
| (with local mods) |
| |
| /S@N /S/T@M A /X (from /S@N) |
| (if server finds T@M is same thing as T@N) |
| or |
| A /X (from /S@N) A /X/T (from /S/A@M) |
| or |
| A /X (from /S@N) R /X/T (from /S/A@M) |
| (the FS layer converts |
| A to R if required) |
| |
| /S@N added A /X (from S@N) A /X/T |
| or |
| A /X (from S@N) R /X/T |
| |
| /S@N copied A /X (from S@N) A /X/T (from G@M) |
| or |
| A /X (from S@N) R /X/T (from G@M) |
| |
| /S@N not-present A /X (from /S@N) D /X/T |
| |
| /S@N excluded A /X (from S@N) |
| |
| /S@N base-deleted A /X (from S@N) D /X/T |
| |
| A single revision source produces a copy that is a gets committed as a |
| single copy. Local modifications, before or after the copy, get |
| committed as modifications to the copied nodes. |
| |
| A mixed revision copy is represented as multiple copies when |
| committed. We could represent this with a single copy operation root |
| in the working tree by using the copyfrom_revision field in the |
| working node. |
| |
| Child nodes added, copied or replaced in the source can remain added, |
| copied or replaced in the copy. Since these adds, copies and replaces |
| are root operations in the source they will be root operations in the |
| copy. This means that a single copy operation will produce a working |
| tree that contains several operation roots. We could allow these |
| child operation roots to be individually reverted in the copy. |
| |
| There is a subtle difference between committing a copy from a mixed |
| revision source and from a source with a locally added or replaced |
| child. In both cases the commit must either add or replace the child |
| and if the copy is from a source that is locally added or replaced the |
| client can make the distinction and send a delete before adding the |
| replacement. For a mixed revision, as the client doesn't know whether |
| the child existed in its parent's revision and so can't distinguish |
| between add and replace, it always sends an add and the FS layer |
| converts to a replace as required (for details see 2010-04-19 comments |
| in issue 3314). We will probably have to continue rely on this in |
| WC-NG as there is not enough information in the source to determine |
| whether or not the child also exists in the parent's revision. |
| |
| If the mixed-rev source has a "not-present" child (effectively the |
| same as "updated to r0"), then the copy schedules this as "delete". |
| The client doesn't know whether the child existed in its parent's |
| revision, so it can't distinguish between delete and no-op, so it |
| always sends a delete. |
| |
| ### This current fails, in both 1.6 and trunk. |
| |
| ### TODO: The server needs to silently elide a delete, or the client |
| needs to detect the error and recover from it and continue if that |
| is possible. |
| |
| Child nodes not-present in the source become not-present working nodes |
| in the copy, this ensures that they get deleted by the commit. We |
| might want to use a new not-copied state instead, since these deletes |
| cannot be reverted. |
| |
| Child nodes that are excluded in the source can remain excluded in the |
| copy. |
| |
| Child nodes that are base-deleted in the source become not-present in |
| the copy. These deletes can be individually reverted. |
| |
| Child nodes that are incomplete in the source become incomplete in the |
| copy. Some operations, like delete, could be possible on the |
| incomplete node. Could "svn up" retrieve the missing information and |
| make them complete? The commit processing would probably choose not |
| to allow incomplete directories. |
| |
| Child nodes that are absent in the source cannot be copied and |
| committed. During the commit the copy of the parent will fail with an |
| authz error since Subversion requires read access to the whole tree |
| being copied. |
| |
| -- |
| |
| URL-to-wc copy is equivalent to a single revision wc-to-wc copy. |
| |
| -- |
| |
| The child /S/T may also be switched wrt the parent /S. At present |
| this is handled badly by 1.6. |
| |
| $ svn sw ^/G wc/S/T |
| $ svn cp wc/S wc/X |
| |
| the working copy X/T will look like /G but the switch status is lost. |
| If X/T is unmodified then the commit will add /X (from /S@N) and do |
| nothing for /X/T so /X/T in the repository looks like /S/T. (This is |
| rather like committing a non-copied switch and so is not necessarily a |
| bug, although whether users would expect it I don't know--I had to |
| experiment to verify the behaviour.) |
| |
| If X/T is a modifed file the commit fails with a checksum error, the |
| wrong text-base is used. If X/T is a directory that is modified or |
| contains modified children the commit is unreliable as again changes |
| are made against the wrong base. |
| |
| How should a copied, switched node be handled? The switch could be |
| preserved so that the copied node points to the same node as switched |
| source node. This would almost certainly require extending the client |
| commit code to handle this. It's not currently possible to switch an |
| added node so is it sensible for copy to do it? |
| |
| An alternative would be to convert the switch into a replace. |
| Relatively easy to do but it would mean that node is no longer really |
| switched. |
| |
| -- |