[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: API proposal - issue 2188 - svn_client_copy/move

From: Julian Foad <julianfoad_at_btopenworld.com>
Date: 2005-11-10 04:38:39 CET

Madan U Sreenivasan wrote:
> The pain area as of now is
> - The inability to return error when the destination folder already
> exists

Well, that's one aspect of it. The inability to be sure exactly where the item
will end up is another big problem.

Here I present my analysis of the requirements, with some details undecided.


We are talking about interfaces for moving/copying a single item. Perhaps we
should consider interfaces for moving multiple items too, especially as Hyrum
Wright is currently working on it
<http://svn.haxx.se/dev/archive-2005-11/0393.shtml>, but we need not consider
that right here and now.

For a move, both the source and the destination have to be writable, and they
both have to be updated at the same time. That makes most sense when operating
either within a repository or within a WC. We could in the future extend the
support to moves from WC to repos and repos to WC, but we need not consider
that extension now.

The following three forms are therefore required, in which "path" means a full
specification for the new item, including its (possibly new) name.

* Move:
     Source: item in repository (head)
     Destination: path in repository (head)

* Move:
     Source: versioned item in WC
     Destination: path in WC

* Copy:
     Source: item in repository (at a given revision) or versioned item in WC
     Destination: path in repository (head) or in WC


I mention here each of the potential variations I can think of, and decide
whether the behaviour should be fixed or optional in each respect.

* Move/copy what: file/dir/special/any item?
   -> Any item.
   (As existing API.)

* Change the item's name/location/both?
   -> Both. (That seems reasonable when moving/copying a single item.)
   (As existing API.)

* If dest is already a dir, move src into it?
   -> No. (It is unreasonable for a caller not to know where it wants the
destination to go. The only reason such an ambiguous command is usable at the
command line is because users have out-of-band knowledge of whether the
destination directory already exists.)
   (Differs from existing API.)

* Create parent directories if needed: yes/error?
   -> Yes? Optional? (Any obstruction to creating them will result in failure:
an "overwrite destination" flag will not apply to an obstruction here.)
   ### Please discuss.
   (Existing API: ?)

* Remove parent directories emptied by moving away the source item?
   -> No. (That doesn't seem like part of this function's job.)
   (As existing API.)

* If destination exists: overwrite/error?
   -> Optional. We may also want this to differ depending on the types of the
existing and new items.
   ### Please discuss.
   (This option applies only to the destination itself, not to the creation of
any parent directories in which to put it.)
   (Differs from existing API.)

* With history: yes/no?
   -> Yes. (I don't think we should support without-history semantics in this
API; it's complex enough already and that doesn't feel like the fundamental
meaning of "move" or "copy". An "add" interface should be used to make a new
item without history, even if the source happens to be an existing versioned
item, and even when doing so directly in the repository. This decision implies
that the source must be a versioned item. Note that this is an API spec; it
doesn't prevent a client from providing copy-without-history behaviour.)
   (As existing API.)

Up to this point, I had not looked at the existing API, but now I have, and it
raises some more issues.

* Local changes in WC source: keep/discard/error?
   -> Keep. (That is, move or copy them. The whole point of a working copy is
to hold one's local changes. I am amazed that the current svn_client_move3()
discards local changes if forced (is that true?), otherwise errors out. If one
wants the base version, one should specify the base version or revert the changes.)
   (Differs from existing API.)

* Unversioned items in WC source (if source is a dir): keep/discard/error?
   -> Move to WC: keep? Copy to repos: discard. Copy to WC: keep?
   (A WC-to-repos copy (and move, if it were allowed) must inherently discard
unversioned items. Within a WC, a move should keep them because that is the
intuitive behaviour for moving a directory; the alternative name "rename" also
implies that. For a copy within a WC, I have no opinion except that
consistency with "move" would be good.)
   ### Please discuss.
   (Differs from existing API.)


First I will note that the lower-level APIs such as svn_wc_copy2() may need to
be augmented to support this.

# Move a versioned item. Semantics as discussed above.
# Error if source and dest are not both in WC or both in repos.
      overwrite-dest?[, create-parents?])
   -> error

# Copy a versioned item. Semantics as discussed above.
copy(source-rev, source-path-or-url,
      overwrite-dest?[, create-parents?])
   -> error

There is only one successful outcome with each of these (unlike the old API).

The options are still under discussion.

Other features of the existing API such as provisions for reporting,
authentication, log message, etc., should be retained in this new API.

With the options undecided, this looks very much like the existing API, but I
believe it was helpful to go through the design to confirm the basic form and
change some of the semantics to be more useful.


How can the existing svn_client_copy2() be implemented in terms of this new
API? I assert that we must provide an API with which that can be done. On the
other hand, I don't believe the new API needs to be such that a client can
trivially convert to using it and still get the old behaviour.

Answer: it can't be implemented atomically. It can be implemented as:

   Try copy/move src-path to dest-path.
   If that fails,
     Try copy/move src-path to dest-path + "/" + src-name.

That can fail if an item is simultaneously being deleted at dest-path, whereas
the original would always succeed (assuming it was implemented atomically - I
haven't checked).

I believe that this is good enough. There are plenty of other scenarios in
which it would fail anyway; this just adds another with small probability.


The interface I propose here is syntactically similar to the existing one, but
has some significant semantic differences that make it more intuitive,
deterministic and useful. The implementation will require deeper changes than
had probably been anticipated.


- Julian

To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Nov 10 04:39:29 2005

This is an archived mail posted to the Subversion Dev mailing list.