You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Blair Zajac <bl...@orcaware.com> on 2002/06/19 21:08:07 UTC

Failed commit after renames

<aside>
Why is it that every time I add more functionality to svn_load_dir.pl
it finds svn bugs :)  This is the third or fourth bug it's identified.
Maybe it should be added to the test suite.
</aside>

The following little recipe derived from svn_load_dir.pl commands fails.
This happens over ra_dav and ra_local.

  svnadmin create repos
  svn co file:///`pwd`/repos -d r
  cd r
  mkdir 1
  touch 1/1
  svn add 1 1/1
  svn ci -F /dev/null
  svn mv 1 2
  svn mv 2/1 2/2
  svn ci -F /dev/null

The last command gives this message

Deleting       1
Adding         2
Deleting       2/1
Adding         2/2

svn_error: #21066 : <Filesystem has no item>
  Commit failed (details follow):

svn_error: #21066 : <Filesystem has no item>
  file not found: revision `1', path `/2/1'

Best,
Blair

-- 
Blair Zajac <bl...@orcaware.com>
Web and OS performance plots - http://www.orcaware.com/orca/

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

Re: Failed commit after renames

Posted by Blair Zajac <bl...@orcaware.com>.
Ben Collins-Sussman wrote:
> 
> >   svnadmin create repos
> >   svn co file:///`pwd`/repos -d r
> >   cd r
> >   mkdir 1
> >   touch 1/1
> >   svn add 1 1/1
> >   svn ci -F /dev/null
> >   svn mv 1 2
> >   svn mv 2/1 2/2
> >   svn ci -F /dev/null
> 
> I see the bug, and I know what's wrong.

Thanks, I opened issue 756 to mark this bug.  I've added some additional
comments on this thread there.

Blair

-- 
Blair Zajac <bl...@orcaware.com>
Web and OS performance plots - http://www.orcaware.com/orca/

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

Re: Failed commit after renames

Posted by Ben Collins-Sussman <su...@collab.net>.
Ben Collins-Sussman <su...@collab.net> writes:

>    svn cp A B
>    svn cp B C
> 
> is illegal, and needs to be prevented by libsvn_wc...

Clarification -- this is only illegal in terms of scheduling
operations in the working copy.  These two local mods can't be in the
same changeset.  Things work fine if you commit between the two
commands.

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

Re: Failed commit after renames

Posted by William Uther <wi...@cs.cmu.edu>.
On 19/6/02 5:24 PM, "Ben Collins-Sussman" <su...@collab.net> wrote:

> And we *don't*
> allow something to be copied twice.  In other words:
> 
>  svn cp A B
>  svn cp B C
> 
> is illegal, and needs to be prevented by libsvn_wc...

I'm not sure I agree with this as a long term design decision.  As a short
term "we're not supporting this for 1.0" maybe, but not long term.

> Here's a comment from our code, at the bottom of libsvn_wc/copy.c:
> 
> /*
> Rabbinic Commentary
> 
> 
> Q:  Why can't we 'svn cp' something that we just copied?
>     i.e.  'svn cp foo foo2;  svn cp foo2 foo3"
> 
> A:  It leads to inconsistencies.
> 
>     In the example above, foo2 has no associated repository URL,
>     because it hasn't been committed yet.  But suppose foo3 simply
>     inherited foo's URL (i.e. foo3 'pointed' to foo as a copy
>     ancestor by virtue of transitivity.)

This sounds fine to me.

>     For one, this is not what the user would expect.  That's
>     certainly not what the user typed!

How is it not what the user would expect?  You have a current working
copy... You make some changes... Each time you commit you get to add log
information.  At the time you do the second 'cp', foo2 has the same log
information as 'foo'.  This seems entirely consistent to me.  It works
because of transitivity as the comment said.

>     Second, suppose that the
>     user did a commit between the two 'svn cp' commands.  Now foo3
>     really *would* point to foo2, but without that commit, it
>     pointed to foo.  Ugly inconsistency, and the user has no idea
>     that foo3's ancestor would be different in each case.

I can see two possible semantics for this solution:

Case 1)  (when something is copied it gets its history from the last thing
in the repository with history - transitivity happens at copy time)

(file Foo exists and has history)

svn cp Foo Foo2  (file Foo2 gets its history from Foo)

svn cp Foo2 Foo3 (file Foo3 gets its history from Foo as Foo2 hasn't been
committed - As far as the entries file is concerned, foo3 might as well have
been copied from foo.)

svn commit Foo2  (foo2 is committed with reference to foo's history.  Foo3
still references the history of foo)

svn commit Foo3  (foo3 is committed with reference to foo's history - this
is the history that foo2 had when foo3 is copied.

Note that it doesn't matter which order things are committed - both foo2 and
foo3 reference the history of foo, the only history that existed when they
were created.

Case 2)  (when something is copied the working copy stores a ref to the
thing it was copied from, that ref is resolved at commit time - transitivity
happens at commit time)

Example I)

(file Foo exists and has history)

svn cp Foo Foo2  (file Foo2 gets its history from Foo)

svn cp Foo2 Foo3 (file Foo3 gets its history from Foo2, even though foo2
only exists in the working copy)

svn commit Foo2 (file Foo2 gets committed with a reference to the history in
Foo.  Nothing changes WRT Foo3.)

svn commit Foo3 (file Foo3 gets committed.  As it is being committed, the
client notices that Foo2 has been committed and so takes its history from
foo2.)

Example II)

(file Foo exists and has history)

svn cp Foo Foo2  (file Foo2 gets its history from Foo)

svn cp Foo2 Foo3 (file Foo3 gets its history from Foo2, even though foo2
only exists in the working copy)

svn commit Foo3 (file Foo3 gets committed.  As it is being committed, the
client notices that it was copied from Foo2, which is an uncommitted copy of
Foo.  The client does the transitivity and commits with a reference to the
history in Foo.)

svn commit Foo2 (file Foo2 gets committed with a reference to the history in
Foo.  Nothing changes WRT Foo3.)


>     And even if somehow we *could* make foo3 point to foo2 before
>     foo2 existed in the repository... what's to prevent a user from
>     committing foo3 first?  That would break.

All your objections refer to case 2).  While I think it could be made to
work, I agree with you that it is ugly.  I think that case 1) is viable.  If
you say that 'svn cp' copies the last committed history at copy time, then
everything is consistent.

And I certainly prefer to this to "you can't copy things more than once".

The failure of "svn mv a b; svn mv b c" is annoying - I've already hit this.
More annoying is that I know that I could replace the pair with a single
"svn mv a c" if I could just remember how to revert the first mv that you've
already done... But reverting mv's is not trivial.  You have to revert both
source and target of the move.  And you have to delete the copy (see the
example below).  I think adding the ability to move twice is very useful in
this situation and I think the problems you're pointing out only exist with
one of the possible sets of semantics.

Later,

\x/ill          :-}


E.g (trying to revert a mv):

% mkdir svntest
[will@BATFISH:~:Thu 20, 9:20PM]
% cd svntest
[will@BATFISH:~/svntest:Thu 20, 9:20PM]
% svnadmin create repos
[will@BATFISH:~/svntest:Thu 20, 9:21PM]
% svn co file://`pwd`/repos -d root
Checked out revision 0.
[will@BATFISH:~/svntest:Thu 20, 9:21PM]
% cd root
[will@BATFISH:~/svntest/root:Thu 20, 9:21PM]
% ls
[will@BATFISH:~/svntest/root:Thu 20, 9:21PM]
% touch a
% svn add a
A         a
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% svn commit a -m ""
Adding         a
Transmitting file data .
Committed revision 1.
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% svn mv a b
A         b
D  a
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% ls -l
total 0
-rw-r--r--  1 will  staff  0 Jun 20 21:22 b
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% svn revert b
Reverted b
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% ls -la
total 0
drwxr-xr-x   5 will  staff  126 Jun 20 21:22 .
drwxr-xr-x   4 will  staff   92 Jun 20 21:21 ..
drwxr-xr-x  12 will  staff  364 Jun 20 21:22 .svn
-rw-r--r--   1 will  staff    0 Jun 20 21:22 b
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% svn revert a
Reverted a
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% ls -la
total 0
drwxr-xr-x   5 will  staff  126 Jun 20 21:22 .
drwxr-xr-x   4 will  staff   92 Jun 20 21:21 ..
drwxr-xr-x  12 will  staff  364 Jun 20 21:22 .svn
-rw-r--r--   1 will  staff    0 Jun 20 21:22 a
-rw-r--r--   1 will  staff    0 Jun 20 21:22 b
[will@BATFISH:~/svntest/root:Thu 20, 9:22PM]
% svn st
?      ./b


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

Re: Failed commit after renames

Posted by Ben Collins-Sussman <su...@collab.net>.
>   svnadmin create repos
>   svn co file:///`pwd`/repos -d r
>   cd r
>   mkdir 1
>   touch 1/1
>   svn add 1 1/1
>   svn ci -F /dev/null
>   svn mv 1 2
>   svn mv 2/1 2/2
>   svn ci -F /dev/null

I see the bug, and I know what's wrong.

The bug is that the second 'mv' command didn't just error out right
there on the spot, as it should have.  

Remember that a scheduled 'mv' is just a scheduled 'cp'
(add-with-history) followed by a scheduled 'rm'.  And we *don't*
allow something to be copied twice.  In other words:

   svn cp A B
   svn cp B C

is illegal, and needs to be prevented by libsvn_wc... which it's
apparently not doing anymore.  The second 'cp' is clobbering the
entry's copyfrom-url field (which already existed from the first
copy.)

Here's a comment from our code, at the bottom of libsvn_wc/copy.c:

/*
  Rabbinic Commentary


  Q:  Why can't we 'svn cp' something that we just copied?
      i.e.  'svn cp foo foo2;  svn cp foo2 foo3"

  A:  It leads to inconsistencies.

      In the example above, foo2 has no associated repository URL,
      because it hasn't been committed yet.  But suppose foo3 simply
      inherited foo's URL (i.e. foo3 'pointed' to foo as a copy
      ancestor by virtue of transitivity.)
 
      For one, this is not what the user would expect.  That's
      certainly not what the user typed!  Second, suppose that the
      user did a commit between the two 'svn cp' commands.  Now foo3
      really *would* point to foo2, but without that commit, it
      pointed to foo.  Ugly inconsistency, and the user has no idea
      that foo3's ancestor would be different in each case.

      And even if somehow we *could* make foo3 point to foo2 before
      foo2 existed in the repository... what's to prevent a user from
      committing foo3 first?  That would break.

*/

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