You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by cm...@collab.net on 2001/11/15 19:26:27 UTC

copy-planz.txt

Ben and I are pretty much fielding the bulk of the `svn cp' and `svn
mv' commands.  He's done a huge chunk already, working out many of the
nuances of what it means to do a copy on the working copy side of
things.  I've excitedly claimed the task of handling all the
copy-related stuff that happens outside the working copy.  My
thoughts/plans are below.

There are all kinds of little nuances involved in this stuff, and all
kinds of considerations I'm making regarding how to factorize code so
that it's maintainable and yet usable.  This will probably result in
the 27th rewrite of the commit crawler, but we'll see.

Anyway, these are my plans thus far.  Feedback *about the planz* (If
you have complaints or suggestions about the API, start a different
thread, please) is welcome (and expected, darnit!).

----

Here's the generic routine for accomplishing a copy/move given two
paths.  It was comforting to find, after I had worked out this
algorithm, that Ben had done pretty much exactly this already in
svn_client_copy().

   if (not exist src_path)
     return ERR_BAD_SRC error
   if (exist dst_path)
     {
       if (dst_path is directory)
         copy src_path into dst_path as basename (src_path)
       else
         return ERR_OBSTRUCTION error
     }
   else
     {
       if (not exist parent_of_dst_path)
         return ERR_BAD_DST error
       else
         copy src_path into parent_of_dst_path as basename (dst_path)
     }
   if (this is a move)
     delete src_path
   
----

Here is how I plan to handle the four basic cases for `svn copy/move',
as determined by the type of paths supplied as the SRC and DST
arguments to the copy command.

* Case I - SRC is working copy path, DST is working copy path:

   I don't care about it.  Ben Collins-Sussman is handling that. :-)

* Case II - SRC is working copy path, DST is repository URL:

   To accomplish this operation, we drive the commit crawler/editor in
   pretty much the same way we would if performing an import, except
   we are using an existing working copy to determine the items being
   imported instead of disk dirents.  All items in SRC tree are added,
   either implicitly (as a side effect of their parents having been
   added) or explicitly (at the top of the SRC tree, or because they
   have a different revision from that of their parent).  Also, local
   modifications to items in SRC are transmitted as part of the commit
   as well.

   If this a `move' operation, SRC (or, the URL associate with SRC in
   the repository) will be deleted as part of the commit process.

   The working copy is never modified during this process is this is a
   `copy'.  For `move's, we *could* go ahead and remove SRC in the
   working copy, but I'm planning to just take the easy route for now
   and require the user to update.  I'd like to keep this a WC-free
   operation.

* Case III - SRC is repository URL, DST is working copy path:

   There are two routes to take with this:

   - Treat this as a Case IV (using DST's constructed repository URL)
     plug a checkout of DST, or

   - Treat this is a special checkout of SRC (at the optionally supplied
     revision, even), except that once the checkout is complete, you
     have DST scheduled for commit as a copy.

   I personally like the former, seems cleaner to me, and it allows
   `move's to happen atomically.

* Case IV - SRC is repository URL, DST is repository URL:

   This is a freaky special commit drive, where we operate purely on
   our ability to split paths up into components, and then "crawl"
   those trees based purely on the layout of those path components.
   Actually, for copies this is pretty much a four-line commit:

      e->replace_root (dst)
      e->add_(file/dir) (dst_basename, copyfrom=src)
      e->close_dir
      e->close_edit

   The part that requires all the path component attention is if this
   is a move, because we have make sure to anchor the edit at the
   longest common ancestor of SRC and DST so we can delete SRC as part
   of the same transaction as our addition of DST.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by cm...@collab.net.
Greg Stein <gs...@lyra.org> writes:

> I think a move to a URL should be illegal.

Fine.

> A copy from a URL to a working copy seems okay (but only under the semantics
> of the next option). But a move doesn't.

Fine.  This and the above case both seemed like twisted operations
nobody would seriously want to perform anyway.

> > * Case IV - SRC is repository URL, DST is repository URL:
> > 
> >    This is a freaky special commit drive, where we operate purely on
> >    our ability to split paths up into components, and then "crawl"
> >    those trees based purely on the layout of those path components.
> >    Actually, for copies this is pretty much a four-line commit:
> > 
> >       e->replace_root (dst)
> >       e->add_(file/dir) (dst_basename, copyfrom=src)
> >       e->close_dir
> >       e->close_edit
> > 
> >    The part that requires all the path component attention is if this
> >    is a move, because we have make sure to anchor the edit at the
> >    longest common ancestor of SRC and DST so we can delete SRC as part
> >    of the same transaction as our addition of DST.
> 
> As mentioned in the other note, I don't think you even do a "crawl" or
> "drive" for this, but you simply call those editor functions manually on the
> editors. Very straight-forward.

For a copy, yes, it is just this simple.  For a move, this is not the
case.  As an example:  

   `svn move http://server/repo/experimental/my_work http://server/repo/trunk`

We'll assume that trunk exists, so we are creating a new directory in
trunk called my_work.

The proper editor commands for this operation are:

   e->replace_root (http://server/repo)
     e->replace_dir (trunk)
       e->add_dir (my_work, copyfrom=http://server/repo/experimental/my_work)
       e->close_dir ()
     e->close_dir ()
     e->replace_dir (experimental)
       e->delete_entry (my_work)
     e->close_dir ()
   e->close_dir ()
   e->close_edit ()

Were this just a copy, we would have only done:

   e->replace_root (http://server/repo/trunk)
     e->add_dir (my_work, copyfrom=http://server/repo/experimental/my_work)
     e->close_dir ()
   e->close_dir ()
   e->close_edit ()

Note the different anchor points, different drive depths, etc.  Sure,
I don't have to "crawl" in the sense that I'm digging around through
dirents and such, but editor semantics need to be obeyed regardless,
and that will require a programmatic approach to move operations in
the repository.  Not that the above is difficult to figure out at all,
just extra code.  If we disallow moves in cases II and III, then we've
knocked out all the areas of concern that I had for this work in
progress.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by Greg Stein <gs...@lyra.org>.
On Thu, Nov 15, 2001 at 01:26:27PM -0600, cmpilato@collab.net wrote:
>...
> * Case II - SRC is working copy path, DST is repository URL:
>...
>    If this a `move' operation, SRC (or, the URL associate with SRC in
>    the repository) will be deleted as part of the commit process.
> 
>    The working copy is never modified during this process is this is a
>    `copy'.  For `move's, we *could* go ahead and remove SRC in the
>    working copy, but I'm planning to just take the easy route for now
>    and require the user to update.  I'd like to keep this a WC-free
>    operation.

I think a move to a URL should be illegal. It is hard to really define what
the logic "should" be. With a copy, it seems pretty obvious that your WC
won't be affected (you're just copying it). But a move is different. But
with a move, you've got trouble.

a) You modify the WC. This is different than the copy case. I'd also be wary
   of accidentally deleting unversioned files in the WC. Seems dangerous.

b) You don't modify the WC. That leaves a bunch of stuff in the WC that
   "shouldn't be there." Fine, it will get fixed on the next update. But
   wait: if you have local mods, then you're going to get conflicts all over
   the place on an update. Copies don't have that problem.

Moving to a URL doesn't really make good sense under either option.

> * Case III - SRC is repository URL, DST is working copy path:
> 
>    There are two routes to take with this:
> 
>    - Treat this as a Case IV (using DST's constructed repository URL)
>      plug a checkout of DST, or

A copy from a URL to a working copy seems okay (but only under the semantics
of the next option). But a move doesn't. Again, it is that edge case that
you're doing two things: a commit in the repository *and* a checkout to the
WC. Eek.

>    - Treat this is a special checkout of SRC (at the optionally supplied
>      revision, even), except that once the checkout is complete, you
>      have DST scheduled for commit as a copy.

These semantics make sense for copying from a URL to the working copy.

>    I personally like the former, seems cleaner to me, and it allows
>    `move's to happen atomically.

I don't think a move should happen. The behavior isn't intuitive.

> * Case IV - SRC is repository URL, DST is repository URL:
> 
>    This is a freaky special commit drive, where we operate purely on
>    our ability to split paths up into components, and then "crawl"
>    those trees based purely on the layout of those path components.
>    Actually, for copies this is pretty much a four-line commit:
> 
>       e->replace_root (dst)
>       e->add_(file/dir) (dst_basename, copyfrom=src)
>       e->close_dir
>       e->close_edit
> 
>    The part that requires all the path component attention is if this
>    is a move, because we have make sure to anchor the edit at the
>    longest common ancestor of SRC and DST so we can delete SRC as part
>    of the same transaction as our addition of DST.

As mentioned in the other note, I don't think you even do a "crawl" or
"drive" for this, but you simply call those editor functions manually on the
editors. Very straight-forward.

This one *does* make sense for both moves and copies. I could easily see it
done for moving stuff around in a repository, and for tagging stuff.

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by Greg Hudson <gh...@mit.edu>.
On 16 Nov 2001 cmpilato@collab.net wrote:
> - copying a dir where a dir exists
>
>   (a merge of sorts happens, the result being a directory that has all
>   the non-conflicting contents of both the original SRC and DST dirs.
>   conflicting contents are handled by the individual rules that applies)

This sounds like fine behavior to me, although it's a lot more difficult
than the other alternatives under consideration.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by cm...@collab.net.
Greg Hudson <gh...@mit.edu> writes:

> With files, we replace.  Consistency seems like a win.  Automatically
> replacing a directory sounds dangerous, but, well, we are a version
> control system; it's not like we  ever lose data.  (Although data in a
> working copy could be lost, I suppose.)

My linux box's copy command does this:

- copying a file where a file exists
 
  (replace file)

- copying a dir where a dir exists

  (a merge of sorts happens, the result being a directory that has all
  the non-conflicting contents of both the original SRC and DST dirs.
  conflicting contents are handled by the individual rules that applies)

- copy a file where a dir exists

  ("cannot overwrite directory with non-directory" error)

- copy a dir where a file exists

  ("cannot create directory `1/boo': File exists" error)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by Greg Hudson <gh...@mit.edu>.
On 16 Nov 2001 cmpilato@collab.net wrote:
> > What if dst_path/{basename src_path} already exists?
>
> Replace or bomb out.  We don't have an easy way to query "Are you
> sure?", so maybe bombing out would be best.

With files, we replace.  Consistency seems like a win.  Automatically
replacing a directory sounds dangerous, but, well, we are a version
control system; it's not like we  ever lose data.  (Although data in a
working copy could be lost, I suppose.)


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by cm...@collab.net.
Greg Hudson <gh...@mit.edu> writes:

> On 15 Nov 2001 cmpilato@collab.net wrote:
> >    if (exist dst_path)
> >      {
> >        if (dst_path is directory)
> >          copy src_path into dst_path as basename (src_path)
> 
> What if dst_path/{basename src_path} already exists?

Hmm, yes.

Replace or bomb out.  We don't have an easy way to query "Are you
sure?", so maybe bombing out would be best.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by Greg Hudson <gh...@mit.edu>.
On 15 Nov 2001 cmpilato@collab.net wrote:
>    if (exist dst_path)
>      {
>        if (dst_path is directory)
>          copy src_path into dst_path as basename (src_path)

What if dst_path/{basename src_path} already exists?


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: copy-planz.txt

Posted by Bruce Atherton <br...@callenish.com>.
At 01:26 PM 11/15/2001 -0600, cmpilato@collab.net wrote:
>* Case II - SRC is working copy path, DST is repository URL:
>
>    The working copy is never modified during this process is this is a
>    `copy'.  For `move's, we *could* go ahead and remove SRC in the
>    working copy, but I'm planning to just take the easy route for now
>    and require the user to update.  I'd like to keep this a WC-free
>    operation.

If you were going to involve the wc, wouldn't it make more sense to 
"switch" it so that it pointed to the DST in the repository? Not important 
now, but something to keep in mind.



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org