You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Tobias Bading <tb...@web.de> on 2013/06/25 16:24:36 UTC

1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Dear Devs,

GNU Emacs 24.3 was behaving a little odd today while trying to display a 
svn diff from Annotate mode. It simply barked "svn: Unable to find 
repository location for '...' in revision ..." at me :-(. Since this 
wasn't the first time Emacs left me in the rain like this, I thought it 
was time to take a closer look.

This much I was able to figure out:

If you copy a file from revision N-1, modify the copy and then commit it 
as revision N, 'svn diff -cN FILE' works as expected afterwards. It 
works no matter whether you use Subversion 1.6 or 1.8, no matter whether 
you specify FILE as a working copy path or a repository URL. "Works as 
expected" meaning that it shows the modifications you made, not the 
entire file as an add.

However, if you copy a file from a revision M that is smaller than N-1, 
modify the copy and then commit it as revision N, 'svn diff -cN FILE' 
won't play along. Subversion 1.6 simply barks "svn: Unable to find 
repository location for 'FILE' in revision N-1", whereas Subversion 1.8 
shows the whole file as an add, i.e. does a diff -r0:N :-(. An 'svn diff 
-rM:N FILE' on the other hand works fine.

Emacs executes 'svn --non-interactive diff -r N-1:N FILE' for revision N 
at the current line when you press d in Annotate mode, which of course 
barfs just as much as 'diff -cN' does in the described case with M < N-1.

Would it be possible to spice up the semantics of -cN a bit?
I don't know enough about the innards of Subversion to understand why 
-rM:N works but -rN-1:N doesn't, but I think trying to figure out the 
correct value of M for the current line in Emacs' Annotate mode might 
get painfull.

I've appended a little script to this mail that reproduces the problem.

Kind Regards,
Tobias


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jun 25, 2013 at 9:47 PM, Johan Corveleyn <jc...@gmail.com> wrote:
> On Tue, Jun 25, 2013 at 4:24 PM, Tobias Bading <tb...@web.de> wrote:
>> Dear Devs,
>>
>> GNU Emacs 24.3 was behaving a little odd today while trying to display a svn
>> diff from Annotate mode. It simply barked "svn: Unable to find repository
>> location for '...' in revision ..." at me :-(. Since this wasn't the first
>> time Emacs left me in the rain like this, I thought it was time to take a
>> closer look.
>>
>> This much I was able to figure out:
>>
>> If you copy a file from revision N-1, modify the copy and then commit it as
>> revision N, 'svn diff -cN FILE' works as expected afterwards. It works no
>> matter whether you use Subversion 1.6 or 1.8, no matter whether you specify
>> FILE as a working copy path or a repository URL. "Works as expected" meaning
>> that it shows the modifications you made, not the entire file as an add.
>>
>> However, if you copy a file from a revision M that is smaller than N-1,
>> modify the copy and then commit it as revision N, 'svn diff -cN FILE' won't
>> play along. Subversion 1.6 simply barks "svn: Unable to find repository
>> location for 'FILE' in revision N-1", whereas Subversion 1.8 shows the whole
>> file as an add, i.e. does a diff -r0:N :-(.
>
> No, it doesn't:
>
> [[[
> C:\Temp\svntest>svn --version -q
> 1.8.0
>
> C:\Temp\svntest>svnadmin create repos
>
> C:\Temp\svntest>svn co file:///c:/temp/svntest/repos wc
> Checked out revision 0.
>
> C:\Temp\svntest>cd wc
>
> C:\Temp\svntest\wc>echo "line 1" > file.txt
>
> C:\Temp\svntest\wc>svn add file.txt
> A         file.txt
>
> C:\Temp\svntest\wc>svn ci -mm
> Adding         file.txt
> Transmitting file data .
> Committed revision 1.
>
> C:\Temp\svntest\wc>svn mkdir -mm file:///c:/temp/svntest/repos/dir
>
> Committed revision 2.
>
> C:\Temp\svntest\wc>svn up
> Updating '.':
> A    dir
> Updated to revision 2.
>
> C:\Temp\svntest\wc>svn mv file.txt moved.txt
> A         moved.txt
> D         file.txt
>
> C:\Temp\svntest\wc>echo "line 2" >> moved.txt
>
> C:\Temp\svntest\wc>svn st
> D       file.txt
>         > moved to moved.txt
> A  +    moved.txt
>         > moved from file.txt
>
> C:\Temp\svntest\wc>svn ci -mm
> Deleting       file.txt
> Adding         moved.txt
> Transmitting file data .
> Committed revision 3.
>
> C:\Temp\svntest\wc>svn up
> Updating '.':
> At revision 3.
>
> C:\Temp\svntest\wc>svn diff -c3
> Index: file.txt
> ===================================================================
> --- file.txt    (revision 2)
> +++ file.txt    (revision 3)
> @@ -1 +0,0 @@
> -"line 1"
> Index: moved.txt
> ===================================================================
> --- moved.txt   (revision 0)
> +++ moved.txt   (revision 3)
> @@ -0,0 +1,2 @@
> +"line 1"
> +"line 2"
>
> C:\Temp\svntest\wc>svn diff -c3 moved.txt
> Index: file.txt
> ===================================================================
> --- file.txt    (.../file.txt)  (revision 2)
> +++ file.txt    (.../moved.txt) (revision 3)
> @@ -1 +1,2 @@
>  "line 1"
> +"line 2"
> ]]]
>
> That last diff seems to be the one you want, right?
>
> Or could this be a mixed revision thingy? In your script there was no
> 'svn update' after committing revision 2, so the copy was made from f1
> with working revision 1. In my example it's copied from working
> revision 2 (even though it was last changed in r1).
>

Okay, gotcha:

[[[
C:\Temp\svntest>svnadmin create repos

C:\Temp\svntest>svn co file:///c:/temp/svntest/repos wc
Checked out revision 0.

C:\Temp\svntest>cd wc

C:\Temp\svntest\wc>echo "line 1" > file.txt

C:\Temp\svntest\wc>svn add file.txt
A         file.txt

C:\Temp\svntest\wc>svn ci -mm
Adding         file.txt
Transmitting file data .
Committed revision 1.

C:\Temp\svntest\wc>svn mkdir -mm file:///c:/temp/svntest/repos/dir

Committed revision 2.

C:\Temp\svntest\wc>svn mv file.txt moved.txt
A         moved.txt
D         file.txt

C:\Temp\svntest\wc>echo "line 2" >> moved.txt

C:\Temp\svntest\wc>svn st
D       file.txt
        > moved to moved.txt
A  +    moved.txt
        > moved from file.txt

C:\Temp\svntest\wc>svn ci -mm
Deleting       file.txt
Adding         moved.txt
Transmitting file data .
Committed revision 3.

C:\Temp\svntest\wc>svn diff -c3
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +0,0 @@
-"line 1"
Index: moved.txt
===================================================================
--- moved.txt   (revision 0)
+++ moved.txt   (revision 3)
@@ -0,0 +1,2 @@
+"line 1"
+"line 2"

C:\Temp\svntest\wc>svn diff -c3 moved.txt
Index: moved.txt
===================================================================
--- moved.txt   (revision 0)
+++ moved.txt   (revision 3)
@@ -0,0 +1,2 @@
+"line 1"
+"line 2"

C:\Temp\svntest\wc>svn up
Updating '.':
A    dir
Updated to revision 3.

C:\Temp\svntest\wc>svn diff -c3 moved.txt
Index: moved.txt
===================================================================
--- moved.txt   (revision 0)
+++ moved.txt   (revision 3)
@@ -0,0 +1,2 @@
+"line 1"
+"line 2"

C:\Temp\svntest\wc>svn diff -c3
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +0,0 @@
-"line 1"
Index: moved.txt
===================================================================
--- moved.txt   (revision 0)
+++ moved.txt   (revision 3)
@@ -0,0 +1,2 @@
+"line 1"
+"line 2"
]]]

That's indeed ... strange, to say the least. Why should it matter, in
this case, what working revision the copy was made from? I'd say this
is a bug.


Interestingly, 'svnlook diff --diff-copy-from' shows the correct thing
in both cases:
[[[
C:\Temp\svntest\repos>svnlook diff --diff-copy-from -r3 .
Deleted: file.txt
===================================================================
--- file.txt    2013-06-25 19:48:59 UTC (rev 2)
+++ file.txt    2013-06-25 19:49:07 UTC (rev 3)
@@ -1 +0,0 @@
-"line 1"

Copied: moved.txt (from rev 1, file.txt)
===================================================================
--- file.txt    2013-06-25 19:48:55 UTC (rev 1)
+++ moved.txt   2013-06-25 19:49:07 UTC (rev 3)
@@ -1 +1,2 @@
 "line 1"
+"line 2"


C:\Temp\svntest\repos>svnlook diff --diff-copy-from --no-diff-deleted -r3 .
Copied: moved.txt (from rev 1, file.txt)
===================================================================
--- file.txt    2013-06-25 19:48:55 UTC (rev 1)
+++ moved.txt   2013-06-25 19:49:07 UTC (rev 3)
@@ -1 +1,2 @@
 "line 1"
+"line 2"
]]]

So it seems 'svnlook diff' has the better logic here (or at least a
good option).

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jun 25, 2013 at 4:24 PM, Tobias Bading <tb...@web.de> wrote:
> Dear Devs,
>
> GNU Emacs 24.3 was behaving a little odd today while trying to display a svn
> diff from Annotate mode. It simply barked "svn: Unable to find repository
> location for '...' in revision ..." at me :-(. Since this wasn't the first
> time Emacs left me in the rain like this, I thought it was time to take a
> closer look.
>
> This much I was able to figure out:
>
> If you copy a file from revision N-1, modify the copy and then commit it as
> revision N, 'svn diff -cN FILE' works as expected afterwards. It works no
> matter whether you use Subversion 1.6 or 1.8, no matter whether you specify
> FILE as a working copy path or a repository URL. "Works as expected" meaning
> that it shows the modifications you made, not the entire file as an add.
>
> However, if you copy a file from a revision M that is smaller than N-1,
> modify the copy and then commit it as revision N, 'svn diff -cN FILE' won't
> play along. Subversion 1.6 simply barks "svn: Unable to find repository
> location for 'FILE' in revision N-1", whereas Subversion 1.8 shows the whole
> file as an add, i.e. does a diff -r0:N :-(.

No, it doesn't:

[[[
C:\Temp\svntest>svn --version -q
1.8.0

C:\Temp\svntest>svnadmin create repos

C:\Temp\svntest>svn co file:///c:/temp/svntest/repos wc
Checked out revision 0.

C:\Temp\svntest>cd wc

C:\Temp\svntest\wc>echo "line 1" > file.txt

C:\Temp\svntest\wc>svn add file.txt
A         file.txt

C:\Temp\svntest\wc>svn ci -mm
Adding         file.txt
Transmitting file data .
Committed revision 1.

C:\Temp\svntest\wc>svn mkdir -mm file:///c:/temp/svntest/repos/dir

Committed revision 2.

C:\Temp\svntest\wc>svn up
Updating '.':
A    dir
Updated to revision 2.

C:\Temp\svntest\wc>svn mv file.txt moved.txt
A         moved.txt
D         file.txt

C:\Temp\svntest\wc>echo "line 2" >> moved.txt

C:\Temp\svntest\wc>svn st
D       file.txt
        > moved to moved.txt
A  +    moved.txt
        > moved from file.txt

C:\Temp\svntest\wc>svn ci -mm
Deleting       file.txt
Adding         moved.txt
Transmitting file data .
Committed revision 3.

C:\Temp\svntest\wc>svn up
Updating '.':
At revision 3.

C:\Temp\svntest\wc>svn diff -c3
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +0,0 @@
-"line 1"
Index: moved.txt
===================================================================
--- moved.txt   (revision 0)
+++ moved.txt   (revision 3)
@@ -0,0 +1,2 @@
+"line 1"
+"line 2"

C:\Temp\svntest\wc>svn diff -c3 moved.txt
Index: file.txt
===================================================================
--- file.txt    (.../file.txt)  (revision 2)
+++ file.txt    (.../moved.txt) (revision 3)
@@ -1 +1,2 @@
 "line 1"
+"line 2"
]]]

That last diff seems to be the one you want, right?

Or could this be a mixed revision thingy? In your script there was no
'svn update' after committing revision 2, so the copy was made from f1
with working revision 1. In my example it's copied from working
revision 2 (even though it was last changed in r1).

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Wed, Jun 26, 2013 at 12:15:22AM +0200, Branko Čibej wrote:
> The point where this breaks is when you want to create a diff that can
> be applied by plain-vanilla patch and will remove one file and add
> another one. That case requires different output, and maybe
> --show-copies-as-adds is the right option to use in that case (but I'd
> prefer to call it "--patch" or something more semantically close to the
> intended result).

You're probably looking for the --patch-compatible option which is
new in 1.8. 'svn diff' has too many options, doesn't it :)

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Branko Čibej <br...@wandisco.com>.
On 26.06.2013 00:07, Ben Reser wrote:
> On Tue, Jun 25, 2013 at 11:54 PM, Johan Corveleyn <jc...@gmail.com> wrote:
>> In that post I thought that --show-copies-as-adds (svn) was the
>> reverse from --diff-copy-from (svnlook), but I observed that it didn't
>> really work:
>>
>> "However, I just
>> quickly tested an 'svn diff -c XXX' of some revision which has a move,
>> and it always shows the moved file in full as a delete and an add, no
>> matter if I use --show-copies-as-adds or not. So it seems that
>> detecting copies with their sources is broken in 'svn diff'. "
>>
>> Funny to read that back now :-).
> I even vaguely remember that thread.  It is indeed funny how things
> come back around.

I would not be averse to seeing diff show actual differences between
current and last-changed revision in the -cN or -rN-1:N case, with or
without --git. Both parameters mean, "what changed in revision N".

The point where this breaks is when you want to create a diff that can
be applied by plain-vanilla patch and will remove one file and add
another one. That case requires different output, and maybe
--show-copies-as-adds is the right option to use in that case (but I'd
prefer to call it "--patch" or something more semantically close to the
intended result).

Note that IIRC patch will parse the index header, so that you can have:

Index b
=================
a (then)
b (now)

and show just the differences between the old and new locations of the
renamed file, and afterwards issue a "delete" diff for 'a'; but that's
just an optimization (and not all versions of patch may actually get
that right).

-- Brane

-- 
Branko Čibej | Director of Subversion
WANdisco // Non-Stop Data
e. brane@wandisco.com

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Ben Reser <be...@reser.org>.
On Tue, Jun 25, 2013 at 11:54 PM, Johan Corveleyn <jc...@gmail.com> wrote:
> In that post I thought that --show-copies-as-adds (svn) was the
> reverse from --diff-copy-from (svnlook), but I observed that it didn't
> really work:
>
> "However, I just
> quickly tested an 'svn diff -c XXX' of some revision which has a move,
> and it always shows the moved file in full as a delete and an add, no
> matter if I use --show-copies-as-adds or not. So it seems that
> detecting copies with their sources is broken in 'svn diff'. "
>
> Funny to read that back now :-).

I even vaguely remember that thread.  It is indeed funny how things
come back around.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jun 25, 2013 at 11:35 PM, Ben Reser <be...@reser.org> wrote:
> On Tue, Jun 25, 2013 at 11:29 PM, Johan Corveleyn <jc...@gmail.com> wrote:
>> Wow, wait a minute. Are you suggesting removing the (existing)
>> diff-copy-from option from 'svnlook diff'? Why? What's wrong with it?
>> It provides very useful functionality. I definitely use it for
>> post-commit mails, because it makes them much more focused on the
>> interesting diff portion. It's very clear in what it does, and it does
>> it well :-).
>
> No, I didn't realize that it already existed, thought you were
> proposing to add it.
>
>> I see no inconsistency here. 'svnlook diff' simply has an option (a
>> very good one IMHO) that 'svn diff' doesn't have. And that option
>> happens to solve the issue at hand (albeit only for svnlook right now,
>> not for svn).
>
> Yeah, in that case we ought to just add the option --diff-copy-from to
> svn.  --git should imply the --diff-copy-from option, since we should
> represent the copies as extended headers.

While we're on the subject, I'd like to point to a post from half a
year ago, where I listed some of the inconsistencies between 'svnlook
diff' and 'svn diff':

http://svn.haxx.se/dev/archive-2012-11/0480.shtml

(part of a thread started as "Re: multiple targets for 'svnlook
propget'", but Julian then re-subjected to "'svn diff' vs 'svnlook
diff'" when he replied)

In that post I thought that --show-copies-as-adds (svn) was the
reverse from --diff-copy-from (svnlook), but I observed that it didn't
really work:

"However, I just
quickly tested an 'svn diff -c XXX' of some revision which has a move,
and it always shows the moved file in full as a delete and an add, no
matter if I use --show-copies-as-adds or not. So it seems that
detecting copies with their sources is broken in 'svn diff'. "

Funny to read that back now :-).

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Ben Reser <be...@reser.org>.
On Tue, Jun 25, 2013 at 11:29 PM, Johan Corveleyn <jc...@gmail.com> wrote:
> Wow, wait a minute. Are you suggesting removing the (existing)
> diff-copy-from option from 'svnlook diff'? Why? What's wrong with it?
> It provides very useful functionality. I definitely use it for
> post-commit mails, because it makes them much more focused on the
> interesting diff portion. It's very clear in what it does, and it does
> it well :-).

No, I didn't realize that it already existed, thought you were
proposing to add it.

> I see no inconsistency here. 'svnlook diff' simply has an option (a
> very good one IMHO) that 'svn diff' doesn't have. And that option
> happens to solve the issue at hand (albeit only for svnlook right now,
> not for svn).

Yeah, in that case we ought to just add the option --diff-copy-from to
svn.  --git should imply the --diff-copy-from option, since we should
represent the copies as extended headers.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jun 25, 2013 at 11:23 PM, Ben Reser <be...@reser.org> wrote:
> On Tue, Jun 25, 2013 at 11:17 PM, Johan Corveleyn <jc...@gmail.com> wrote:
>> Not by default perhaps, but we could do it by adding the same option
>> to 'svn diff' that you need for 'svnlook diff' for this to work:
>>
>> C:\>svnlook help diff
>> ...
>>   --diff-copy-from         : print differences against the copy source
>
> Why the heck not, if our commands aren't even consistent between
> svnlook and svn then we have a bug somewhere.  We should fix the bug
> not add another option to change the behavior.
>
> Sure it might cause problems for some people, so we probably shouldn't
> change the behavior till 1.9, when we can point it out to people in
> release notes and it's part of their major upgrade.

Wow, wait a minute. Are you suggesting removing the (existing)
diff-copy-from option from 'svnlook diff'? Why? What's wrong with it?
It provides very useful functionality. I definitely use it for
post-commit mails, because it makes them much more focused on the
interesting diff portion. It's very clear in what it does, and it does
it well :-).

I see no inconsistency here. 'svnlook diff' simply has an option (a
very good one IMHO) that 'svn diff' doesn't have. And that option
happens to solve the issue at hand (albeit only for svnlook right now,
not for svn).

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 23:23, Ben Reser wrote:
> On Tue, Jun 25, 2013 at 11:17 PM, Johan Corveleyn <jc...@gmail.com> wrote:
>> Not by default perhaps, but we could do it by adding the same option
>> to 'svn diff' that you need for 'svnlook diff' for this to work:
>> 
>> C:\>svnlook help diff
>> ...
>>  --diff-copy-from         : print differences against the copy source
> 
> Why the heck not, if our commands aren't even consistent between
> svnlook and svn then we have a bug somewhere.  We should fix the bug
> not add another option to change the behavior.
> 
> Sure it might cause problems for some people, so we probably shouldn't
> change the behavior till 1.9, when we can point it out to people in
> release notes and it's part of their major upgrade.

+0.01 for the "We should fix the bug not add another option to change the behavior."

After all I've learned so far, my summary is this:
The output of 'svn diff -cN FILE' is unpredictable, if you know that FILE was the target of a copy or move operation in revision N, but know nothing about the source of that copy or move.

Use case example:
1. 'svn cp http://.../FILE .', where the URL refers to a file in a repository and the current working directory is a working copy of that repository.
2. Modify FILE.
3. Go to lunch.
4. Commit FILE, thus creating revision N.
5. 'svn diff -cN FILE'

Result:
The output of step 5 depends on the eating habits of your co-workers.

There are at least three possible outcomes of step 5:
a) If all your co-workers went to lunch as well, i.e. nobody committed anything to the repository between steps 1 and 4, step 5 will show what you did in step 2. This works fine with Subversion 1.6.23 and 1.8.0, and it's the behavior I'd say is what most users would expect. Well, at least I do :-).
b) If at least one of your co-workers doesn't like the cantina, i.e. comits at least one revision to the repository between steps 1 and 4, the result of step 5 depends on your Subversion version. Subversion 1.6.23 barks "svn: Unable to find repository location for 'FILE' in revision N-1". Subversion 1.8.0 prints the entire contents of FILE.

I'd say 'svn diff -cN FILE' is useless in this (maybe edge) case. Even if you're using 1.8.0 and prefer to see the whole file printed, you can't count on this to work, because the output depends on whether the source of the copy or move was some file from revision N-1 or from a revision older than N-1.

So, what would happen if you'd change the output of 'svn diff -cN FILE' in this case, so that it always shows the delta to the copy/move source? Would that really break anything? If --show-copies-as-adds and --patch-compatible work as advertised, thus presenting proper options for people who want/need to see copies as new files, maybe this change wouldn't hurt anyone?

Tobias


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Ben Reser <be...@reser.org>.
On Tue, Jun 25, 2013 at 11:17 PM, Johan Corveleyn <jc...@gmail.com> wrote:
> Not by default perhaps, but we could do it by adding the same option
> to 'svn diff' that you need for 'svnlook diff' for this to work:
>
> C:\>svnlook help diff
> ...
>   --diff-copy-from         : print differences against the copy source

Why the heck not, if our commands aren't even consistent between
svnlook and svn then we have a bug somewhere.  We should fix the bug
not add another option to change the behavior.

Sure it might cause problems for some people, so we probably shouldn't
change the behavior till 1.9, when we can point it out to people in
release notes and it's part of their major upgrade.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Tue, Jun 25, 2013 at 10:56 PM, Stefan Sperling <st...@elego.de> wrote:
> On Tue, Jun 25, 2013 at 10:26:08PM +0200, Ben Reser wrote:
>> Back to your issue.  Since Subversion can't represent the copy as part
>> of the diff it tries to do the interoperable thing which is to
>> represent the addition of a new file (from a copy) as an addition.
>
> That's not quite true in general. It's more like:
>
> 1) If the copyfrom source is part of the operative revision range of
>    the diff command, show a modification against the copyfrom source.
>    Unless --show-copies-as-adds was passed, because then we always
>    show copied files as an addition.
>
> 2) If the copyfrom source is not part of the operative revision range,
>    history of the file isn't traced back to that revision, so it appears
>    as an addition.
>
> It could be argued that 2) is weird special case, and that it should
> behave like 1) (i.e. trace back to the copyfrom source anyway) and
> only show an addition with --show-copies-as-adds.
>
> Johan pointed out that svnlook diff seems to traverse to the copyfrom
> source even in case 2). If this is indeed the case, these commands are
> now behaving in contradictory ways :( However, I think it's too late
> to change either command now.

Not by default perhaps, but we could do it by adding the same option
to 'svn diff' that you need for 'svnlook diff' for this to work:

C:\>svnlook help diff
...
  --diff-copy-from         : print differences against the copy source

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Thu, Jun 27, 2013 at 9:38 AM, Bert Huijben <be...@qqmail.nl> wrote:
>
>
>> -----Original Message-----
>> From: Johan Corveleyn [mailto:jcorvel@gmail.com]
>> Sent: woensdag 26 juni 2013 23:53
>> To: Johan Corveleyn; Ben Reser; Tobias Bading; Peter Samuelson; Subversion
>> Development
>> Subject: Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if
> the file
>> was created in rev N by copying
>>
>> On Wed, Jun 26, 2013 at 3:01 PM, Stefan Sperling <st...@elego.de> wrote:
>> > On Wed, Jun 26, 2013 at 01:39:59PM +0200, Johan Corveleyn wrote:
>> >> As Tobias pointed out, 'svn diff' does indeed do the diff against the
>> >> copy source, but *only if you're lucky*. I would consider this erratic
>> >> behavior definitely a bug, because it makes the output unpredictable,
>> >> and thus unusable in general.
>> >
>> > OK, you've both convinced me now. I agree that diff -c could trace
>> > copyfrom even if the copfrom rev is outside the operative revision
>> > range, and display an 'added' file only with --show-copies-as-adds.
>> >
>> > Now, the problem is that the repos->repos diff case doesn't support
>> > --show-copies-as-adds yet (see do_diff() in libsvn_client/diff.c).
>> > So it's not a trivial fix and might require some work to get done.
>>
>> Perhaps we should regard that as a separate problem. Isn't the fact
>> that --show-copies-as-adds doesn't work for repos->repos diff,
>> orthogonal to fixing the default behavior (non-show-copies-as-adds)
>> regarding moved files?
>>
>> Or do you feel that the change in behavior ("fix") of diff -c is
>> dependent on a good working --show-copies-as-adds?
>
> We can't just redefine the behavior of '-c'
> The 'svn' commandline client explicitly implements '-c' as '-r N-1:N' (or -r
> N:N-1 when passing -c -N)

Maybe I gave the wrong impression, but I'm not trying to completely
redefine the behavior of 'diff -c'. However the current behavior, when
looking at a moved file, is unpredictable: it depends on whether or
not the move source's revision was exactly 1 revision before the
move-commit. That unpredictability is not good.

Either we always show the diff relative to it's copy source, or we
always show it as a complete add. Not sometimes this and sometimes
that.

If we resolve this inconsistency by always diffing against the copy
source, this happens to solve the problem of the OP. If we resolve it
the other way, that's fine too, and then I'll suggest adding an option
--diff-copy-from (cf. 'svnlook diff') to get the other behavior (and
solve the problem of the OP).

> This behavior is tied to more commands than diff and the internal APIs just
> see the revision numbers.
>
> Besides
> $ svn diff -c 12 FILE
> has many use cases
>
> what would you expect after:
> $ svn rm FILE
> $ svn cp OTHER-FILE@6 FILE
> $ svn ci -m "r12"
> (copy file with some history)

Interestingly, this has the same problem. If you do the copy from
OTHER-FILE@11 the result is currently different from if you do the
copy from OTHER-FILE@6.

Two minimal recipes to demonstrate (find the difference):

1) Copy from N-1

    svnadmin create repos
    svn co file:///c:/temp/svntest5/repos wc
    cd wc
    echo other line 1 > other.txt
    svn add other.txt
    svn ci -m "r1"
    echo line 1 > file.txt
    svn add file.txt
    svn ci -m "r2"
    svn up
    svn rm file.txt
    svn cp other.txt file.txt
    echo other line 2 >> file.txt
    svn ci -m "r3"

2) Copy from N-2

    svnadmin create repos
    svn co file:///c:/temp/svntest6/repos wc
    cd wc
    echo other line 1 > other.txt
    svn add other.txt
    svn ci -m "r1"
    echo line 1 > file.txt
    svn add file.txt
    svn ci -m "r2"
    svn rm file.txt
    svn cp other.txt file.txt
    echo other line 2 >> file.txt
    svn ci -m "r3"


In scenario 1 (copy from N-1) you'll get the diff against the copy
source with 'svn diff -c3 file.txt' (but only if you give 'file.txt'
as explicit target --- if you give no explicit target, the copyfrom
isn't taken into account ... even more confusing :-)  --- perhaps this
difference is intentional ... I don't know).

[[[
C:\Temp\svntest5\wc>svn diff -c3 file.txt
Index: other.txt
===================================================================
--- other.txt   (.../other.txt) (revision 2)
+++ other.txt   (.../file.txt)  (revision 3)
@@ -1 +1,2 @@
 other line 1
+other line 2

C:\Temp\svntest5\wc>svn diff -c3
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +1,2 @@
-line 1
+other line 1
+other line 2

C:\Temp\svntest5\wc>svn diff -c3 --notice-ancestry
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +0,0 @@
-line 1
Index: file.txt
===================================================================
--- file.txt    (revision 0)
+++ file.txt    (revision 3)
@@ -0,0 +1,2 @@
+other line 1
+other line 2
]]]


In scenario 2 (copy from N-2) the output of 'svn diff -c 3 file.txt'
is different (the other outputs remain the same):

[[[
C:\Temp\svntest6\wc>svn diff -c 3 file.txt
Index: file.txt
===================================================================
--- file.txt    (revision 2)
+++ file.txt    (revision 3)
@@ -1 +1,2 @@
-line 1
+other line 1
+other line 2
]]]

> or after:
> $ svn rm FILE
> echo "QQQ" > FILE
> $ svn add FILE
> $ svn ci -m "r12"
> (add new file)
>
> $ echo new line >> FILE
> $ svn ci -m "r12"
> (text change)
>
> [There are even more variants possible if you replace an ancestor instead of
> just the node itself]
>
> We can't handle all these use cases with a simple -r N-1:N. We really need
> more flags to capture all these cases.
>
> 'svn diff' is already implemented as layer over layer over layer of use
> cases.
>
> E.g. by default diff doesn't describe the ancestry of nodes: A file replaced
> by a file or a directory by a directory is described as a simple content
> change unless you pass --notice-ancestry (or --git). Which is nice if you
> want to use 'svn diff' as input for GNU patch, but not if you want it to
> describe the local changes.
>
>
>
> Another interesting case is that our merge is also build on top of diff, so
> users would expect that
> svn diff ^/trunk -c 1234
>
> Would be the same as what you merge with
> svn merge ^/trunk -c 1234

Okay, now I wonder how merge will handle the unpredictable output as
shown above. I hope the result will be the same in both scenarios
(possibly the built-in conflict resolution of merge will absorb the
difference). No time to dig into that right now though.

> (And then of course there is that problem of backwards compatibility)

Okay, but that only goes so far when we're walking the thin line
between feature and bug.

> If you really want to make your head explode ...

Not right now, thanks :-).

> Redefining any of this requires taking into account all these other ugly
> corner cases... and our backwards compatibility guarantees...
>
>
> (Small steps forward...)

Okay, gotcha. It may be (vastly) more difficult than I thought to
change any of this. But I'd like to at least find consensus that the
existing (erratic) behavior can / should be improved, regardless of
how hard/risky it would be to change it. If we keep the scope of the
problem we're trying to solve very limited, I think it should be
doable without breaking things.

(note: this is not a personal itch of mine, I have no direct impact of
this issue ... I'm just trying to mediate in this discussion (and I
got involved because I noted the different behavior of 'svnlook diff'
and its --diff-copy-from option))

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 27.06.2013 09:38, Bert Huijben wrote:
> We can't just redefine the behavior of '-c'
> The 'svn' commandline client explicitly implements '-c' as '-r N-1:N' (or -r
> N:N-1 when passing -c -N)
>
> This behavior is tied to more commands than diff and the internal APIs just
> see the revision numbers.
>
> Besides
> $ svn diff -c 12 FILE
> has many use cases
>
> what would you expect after:
> $ svn rm FILE
> $ svn cp OTHER-FILE@6 FILE
> $ svn ci -m "r12"
> (copy file with some history)

Granted, this is a toughy.
My 0.02 cents (after a first glance, I hereby reserve the right to 
totally reverse my opinion later on in this thread ;-):
I'd expect 'diff -r11:12 (aka -c12) FILE' to show... umm... err... 
Mom!!!! I don't want to play with Bert anymore, he's a party pooper! ;-)
Seriously, 'diff -c12 FILE' (without --notice-ancestry) should probably 
ignore the fact that an other FILE@11 existed and show the differences 
between OTHER-FILE@6 and FILE@12, that is work just like 'diff -r6:12 
FILE' in this case.
'diff --notice-ancestry -c12 FILE' or 'diff -c12 DIR' (with DIR being 
the directory containing FILE) should show the replacement, that is 
FILE@12 as a new file.

Merge should probably work the other way around as usual, i.e. 'merge 
-c12 FILE-IN-REPO' should replace an existing FILE and 'merge 
--ignore-ancestry -c12 FILE-IN-REPO' should merge the changes between 
OTHER-FILE@6 and FILE@12 into the local FILE.

> or after:
> $ svn rm FILE
> $ echo "QQQ">  FILE
> $ svn add FILE
> $ svn ci -m "r12"
> (add new file)

See above I'd say. Just a bit simpler here, because of the missing hole 
in the time-space continuum created by copying OTHER-FILE@6 to FILE@12.

> $ echo new line>>  FILE
> $ svn ci -m "r12"
> (text change)

I don't get this one. Just a simple line added in r12?

> [There are even more variants possible if you replace an ancestor instead of
> just the node itself]
>
> We can't handle all these use cases with a simple -r N-1:N. We really need
> more flags to capture all these cases.
>
> 'svn diff' is already implemented as layer over layer over layer of use
> cases.
>
> E.g. by default diff doesn't describe the ancestry of nodes: A file replaced
> by a file or a directory by a directory is described as a simple content
> change unless you pass --notice-ancestry (or --git). Which is nice if you
> want to use 'svn diff' as input for GNU patch, but not if you want it to
> describe the local changes.
>
>
>
> Another interesting case is that our merge is also build on top of diff, so
> users would expect that
> svn diff ^/trunk -c 1234
>
> Would be the same as what you merge with
> svn merge ^/trunk -c 1234

I agree, you should be able to foresee the result of a merge after 
taking a look at the diff. Proper use of --ignore-ancestry or 
--notice-ancestry provided of course.

> (And then of course there is that problem of backwards compatibility)

The reason for me to start this thread was the very specific problem of 
the 'hole in the time-space continuum' that every copy of from-file@M to 
to-file@N with M < N-1 creates. If you're looking at an annotated 
version of to-file and found an interesting line, whose revision number 
is -- ta-da! -- N, 'svn diff -rN-1:N to-file' fails in Subversion 1.6.23 
and simply prints to-file@N as a new file in Subversion 1.8.0. This is a 
very specific case, but a common use case IMHO.

I don't know if the changed behavior in this case in 1.8.0 was on 
purpose, or if it's just an unintended side effect of some code change. 
At the moment, neither Subversion 1.6.23 nor 1.8.0 are able to deal with 
this case properly, so you shouldn't break anything if it was possible 
to change the behavior for just this specific case, right?

> If you really want to make your head explode we can also bring in the
> problems around the definition or -r BASE in the context of diff or other
> commands.
> -r BASE is mostly used to describe the PRISTINE version of a node, but in
> some cases also as the clean checked out version... Which can be different
> in the case of a direct and/or ancestor replacement.

*BOOM!*

> Redefining any of this requires taking into account all these other ugly
> corner cases... and our backwards compatibility guarantees...
>
>
> (Small steps forward...)

Precision surgery, if possible? ;-)

Tobias


RE: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Bert Huijben <be...@qqmail.nl>.

> -----Original Message-----
> From: Johan Corveleyn [mailto:jcorvel@gmail.com]
> Sent: woensdag 26 juni 2013 23:53
> To: Johan Corveleyn; Ben Reser; Tobias Bading; Peter Samuelson; Subversion
> Development
> Subject: Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if
the file
> was created in rev N by copying
> 
> On Wed, Jun 26, 2013 at 3:01 PM, Stefan Sperling <st...@elego.de> wrote:
> > On Wed, Jun 26, 2013 at 01:39:59PM +0200, Johan Corveleyn wrote:
> >> As Tobias pointed out, 'svn diff' does indeed do the diff against the
> >> copy source, but *only if you're lucky*. I would consider this erratic
> >> behavior definitely a bug, because it makes the output unpredictable,
> >> and thus unusable in general.
> >
> > OK, you've both convinced me now. I agree that diff -c could trace
> > copyfrom even if the copfrom rev is outside the operative revision
> > range, and display an 'added' file only with --show-copies-as-adds.
> >
> > Now, the problem is that the repos->repos diff case doesn't support
> > --show-copies-as-adds yet (see do_diff() in libsvn_client/diff.c).
> > So it's not a trivial fix and might require some work to get done.
> 
> Perhaps we should regard that as a separate problem. Isn't the fact
> that --show-copies-as-adds doesn't work for repos->repos diff,
> orthogonal to fixing the default behavior (non-show-copies-as-adds)
> regarding moved files?
> 
> Or do you feel that the change in behavior ("fix") of diff -c is
> dependent on a good working --show-copies-as-adds?

We can't just redefine the behavior of '-c'
The 'svn' commandline client explicitly implements '-c' as '-r N-1:N' (or -r
N:N-1 when passing -c -N)

This behavior is tied to more commands than diff and the internal APIs just
see the revision numbers.

Besides
$ svn diff -c 12 FILE
has many use cases

what would you expect after:
$ svn rm FILE
$ svn cp OTHER-FILE@6 FILE
$ svn ci -m "r12"
(copy file with some history)

or after:
$ svn rm FILE
echo "QQQ" > FILE
$ svn add FILE
$ svn ci -m "r12"
(add new file)

$ echo new line >> FILE
$ svn ci -m "r12"
(text change)

[There are even more variants possible if you replace an ancestor instead of
just the node itself]

We can't handle all these use cases with a simple -r N-1:N. We really need
more flags to capture all these cases.

'svn diff' is already implemented as layer over layer over layer of use
cases.

E.g. by default diff doesn't describe the ancestry of nodes: A file replaced
by a file or a directory by a directory is described as a simple content
change unless you pass --notice-ancestry (or --git). Which is nice if you
want to use 'svn diff' as input for GNU patch, but not if you want it to
describe the local changes.



Another interesting case is that our merge is also build on top of diff, so
users would expect that
svn diff ^/trunk -c 1234

Would be the same as what you merge with
svn merge ^/trunk -c 1234

(And then of course there is that problem of backwards compatibility)


If you really want to make your head explode we can also bring in the
problems around the definition or -r BASE in the context of diff or other
commands.
-r BASE is mostly used to describe the PRISTINE version of a node, but in
some cases also as the clean checked out version... Which can be different
in the case of a direct and/or ancestor replacement.




Redefining any of this requires taking into account all these other ugly
corner cases... and our backwards compatibility guarantees...


(Small steps forward...)

	Bert




Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Wed, Jun 26, 2013 at 3:01 PM, Stefan Sperling <st...@elego.de> wrote:
> On Wed, Jun 26, 2013 at 01:39:59PM +0200, Johan Corveleyn wrote:
>> As Tobias pointed out, 'svn diff' does indeed do the diff against the
>> copy source, but *only if you're lucky*. I would consider this erratic
>> behavior definitely a bug, because it makes the output unpredictable,
>> and thus unusable in general.
>
> OK, you've both convinced me now. I agree that diff -c could trace
> copyfrom even if the copfrom rev is outside the operative revision
> range, and display an 'added' file only with --show-copies-as-adds.
>
> Now, the problem is that the repos->repos diff case doesn't support
> --show-copies-as-adds yet (see do_diff() in libsvn_client/diff.c).
> So it's not a trivial fix and might require some work to get done.

Perhaps we should regard that as a separate problem. Isn't the fact
that --show-copies-as-adds doesn't work for repos->repos diff,
orthogonal to fixing the default behavior (non-show-copies-as-adds)
regarding moved files?

Or do you feel that the change in behavior ("fix") of diff -c is
dependent on a good working --show-copies-as-adds?

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Wed, Jun 26, 2013 at 01:39:59PM +0200, Johan Corveleyn wrote:
> As Tobias pointed out, 'svn diff' does indeed do the diff against the
> copy source, but *only if you're lucky*. I would consider this erratic
> behavior definitely a bug, because it makes the output unpredictable,
> and thus unusable in general.

OK, you've both convinced me now. I agree that diff -c could trace
copyfrom even if the copfrom rev is outside the operative revision
range, and display an 'added' file only with --show-copies-as-adds.

Now, the problem is that the repos->repos diff case doesn't support
--show-copies-as-adds yet (see do_diff() in libsvn_client/diff.c).
So it's not a trivial fix and might require some work to get done.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Johan Corveleyn <jc...@gmail.com>.
On Wed, Jun 26, 2013 at 11:51 AM, Stefan Sperling <st...@elego.de> wrote:
> On Tue, Jun 25, 2013 at 11:20:02PM +0200, Ben Reser wrote:
...
>> > Johan pointed out that svnlook diff seems to traverse to the copyfrom
>> > source even in case 2). If this is indeed the case, these commands are
>> > now behaving in contradictory ways :( However, I think it's too late
>> > to change either command now.
>>
>> I'd call that a bug and fix it.  In this case I'd probably make
>> svnlook match svn and fix svn diff --git to provide the behavior
>> because of what I mentioned before.  svnlook should probably also grow
>> --git and some of the other diff options.
>
> Consistency is good. Generally, I won't object to such changes being made.
> But I'd be careful about changing this output in a patch release.
> We can change it in 1.9, of course, and document the change
>
> I would prefer adding a --diff-copy-from option for 'svn diff',
> to make it match the current 'svnlook diff' behaviour:

As said in my previous post in this thread (and in the old thread it
refers), I thought once that --show-copies-as-adds (option of 'svn
diff') had actually the inverse meaning of --diff-copy-from (option of
'svnlook diff'). Is that or is that not the case?

I.e., given those existing options, I would have thought that 'svn
diff', without any options, always does the diff against the copy
source (the --diff-copy-from behavior), and that you had to explicitly
tell it to show the copies as adds with the --show-copies-as-adds
option. And 'svnlook diff' always shows the full add, unless you pass
it the option --diff-copy-from.

As Tobias pointed out, 'svn diff' does indeed do the diff against the
copy source, but *only if you're lucky*. I would consider this erratic
behavior definitely a bug, because it makes the output unpredictable,
and thus unusable in general.

So, if my above understanding is correct, there is no need for any
more options. We "just" need to correct the default behavior of 'svn
diff' regarding copy source, to make it work like 'svnlook diff
--diff-copy-from' and like 'svn diff --feeling-lucky'. The 'show the
entire copied file as an add' behavior is still available with the
--show-copies-as-adds option (implicit in the --patch-compatible
option), which seems to be the way it's designed. Right?

(I have no objection on trying to achieve consistency between 'svn
diff' and 'svnlook diff', but it seems superfluous to add an option
--diff-copy-from, when you already have an option
--show-copies-as-adds which seems to mean the exact opposite ---
what's the behavior then if you add neither option? Or both?)

--
Johan

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Tue, Jun 25, 2013 at 11:20:02PM +0200, Ben Reser wrote:
> E.G. here's the behavior based on the example environment produced by
> the script in the original post:
> [[[
>  svn diff -r1:3 --show-copies-as-adds wc/f2
> Index: wc/f1
> ===================================================================
> --- wc/f1 (.../f1) (revision 1)
> +++ wc/f1 (.../f2) (revision 3)
> @@ -1 +1,2 @@
>  file 1
> +added line
> ]]]
> 
> In fact I'm not even sure what the point of --show-copies-as-adds is
> based on the behavior we have.  I'm sure it was added for some reason
> but the behavior of diff here seems utterly not what a user would
> expect give the descriptions of the commands.

The problem you're seeing here is that --show-copies-as-adds doesn't
work for repos-repos diffs yet:
http://subversion.tigris.org/issues/show_bug.cgi?id=2543#desc13
The test mentioned in that link still has these comments:

  # Repos->repos diff after the rename
  ### --show-copies-as-adds has no effect
  exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff',
                                                            '-r', '2:3',
                                                            pi2_path)
So that's a known bug.
 
> > Johan pointed out that svnlook diff seems to traverse to the copyfrom
> > source even in case 2). If this is indeed the case, these commands are
> > now behaving in contradictory ways :( However, I think it's too late
> > to change either command now.
> 
> I'd call that a bug and fix it.  In this case I'd probably make
> svnlook match svn and fix svn diff --git to provide the behavior
> because of what I mentioned before.  svnlook should probably also grow
> --git and some of the other diff options.

Consistency is good. Generally, I won't object to such changes being made.
But I'd be careful about changing this output in a patch release.
We can change it in 1.9, of course, and document the change.

I would prefer adding a --diff-copy-from option for 'svn diff',
to make it match the current 'svnlook diff' behaviour:

$ svnlook diff -r4 repos                 
Copied: trunk/alpha2 (from rev 2, trunk/alpha)
===================================================================
--- trunk/alpha2                                (rev 0)
+++ trunk/alpha2        2013-06-26 09:44:59 UTC (rev 4)
@@ -0,0 +1,2 @@
+alpha
+mmm

$ svnlook diff -r4 repos --diff-copy-from
Copied: trunk/alpha2 (from rev 2, trunk/alpha)
===================================================================
--- trunk/alpha 2013-06-26 09:44:37 UTC (rev 2)
+++ trunk/alpha2        2013-06-26 09:44:59 UTC (rev 4)
@@ -1 +1,2 @@
 alpha
+mmm

> > I'm not quite sure if we can already recommend the --git diff option
> > for widespread use.
> 
> Then we shouldn't have released with it enabled.  Releasing a command
> with an option and then saying we don't recommend people to use it is
> like throwing a live hand grenade in the room of friends and saying
> that you don't recommend that your friends occupy the room.

The --git option is supported in the sense that the current functionality
provided is implemented correctly. However, the functionality isn't very
useful because it is incomplete, at least in terms of the lofty goals we
were aiming for. That's because at the time the option was added we didn't
have a good way of extending it further. We lacked proper copyfrom reporting
for diffs (probably fixed by Bert in 1.8) and also lacked rename tracking
(fixed for working copies in 1.8, but not for diffs involving the server).
These problems prevented us from making diff --git show copies and moves
properly, especially for repos-repos diffs.

> > I intend to get back to it once we can produce proper information for renames.
> 
> But it doesn't even properly handle the cases we can handle or at
> least should be able to handle now.

Which cases do you mean exactly?

>  Renames has nothing to do with
> the current issue, I don't see a reason to wait for that to fix this.

I did in fact intend to add 'rename' headers to diff --git diffs in 1.8,
but I forgot about doing it. Sorry. It would only have worked for WC-WC
diffs anyway, though.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 23:20, Ben Reser wrote:
> On Tue, Jun 25, 2013 at 10:56 PM, Stefan Sperling <st...@elego.de> wrote:
>> I'm not quite sure if we can already recommend the --git diff option
>> for widespread use.
> 
> Then we shouldn't have released with it enabled.  Releasing a command
> with an option and then saying we don't recommend people to use it is
> like throwing a live hand grenade in the room of friends and saying
> that you don't recommend that your friends occupy the room.

LOL. I like your sense of humor, Ben.


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 23:20, Ben Reser wrote:
> On Tue, Jun 25, 2013 at 10:56 PM, Stefan Sperling <st...@elego.de> wrote:
>> I'm not quite sure if we can already recommend the --git diff option
>> for widespread use.
> 
> Then we shouldn't have released with it enabled.  Releasing a command
> with an option and then saying we don't recommend people to use it is
> like throwing a live hand grenade in the room of friends and saying
> that you don't recommend that your friends occupy the room.

This is the Tempora-Prism surveillance bot.
Your score in category 'subversion probability' just went up by 0.1.
Your total score is now 0.4. Please refrain from any actions that could increase it further.
If your score reaches 0.9, please expect to be contacted by our friendly personal assistants.

We will continue to monitor this line for your security.
Thank you for your cooperation.



(Sorry, couldn't resist, because I just saw this: http://www.tagesspiegel.de/images/karikatur_big_brother_ts/8396586/2-formatOriginal.jpg)


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Ben Reser <be...@reser.org>.
On Tue, Jun 25, 2013 at 10:56 PM, Stefan Sperling <st...@elego.de> wrote:
> That's not quite true in general. It's more like:
>
> 1) If the copyfrom source is part of the operative revision range of
>    the diff command, show a modification against the copyfrom source.
>    Unless --show-copies-as-adds was passed, because then we always
>    show copied files as an addition.
>
> 2) If the copyfrom source is not part of the operative revision range,
>    history of the file isn't traced back to that revision, so it appears
>    as an addition.

Well if our intention wasn't to provide interoperability here then I
have no idea why we made this choice because frankly I think it's poor
behavior.

> It could be argued that 2) is weird special case, and that it should
> behave like 1) (i.e. trace back to the copyfrom source anyway) and
> only show an addition with --show-copies-as-adds.

Yes, I'd agree with that.

However, I'll point out that --show-copies-as-adds doesn't, in my
opinion, behave properly when the copyfrom source is part of the
operative revision range.  I'd argue in that case it should
effectively also behave as --stop-on-copy (which diff doesn't have)
since the delta of the file over that range should just be the
addition of the file since you told it to show copies as adds.

E.G. here's the behavior based on the example environment produced by
the script in the original post:
[[[
 svn diff -r1:3 --show-copies-as-adds wc/f2
Index: wc/f1
===================================================================
--- wc/f1 (.../f1) (revision 1)
+++ wc/f1 (.../f2) (revision 3)
@@ -1 +1,2 @@
 file 1
+added line
]]]

In fact I'm not even sure what the point of --show-copies-as-adds is
based on the behavior we have.  I'm sure it was added for some reason
but the behavior of diff here seems utterly not what a user would
expect give the descriptions of the commands.

> Johan pointed out that svnlook diff seems to traverse to the copyfrom
> source even in case 2). If this is indeed the case, these commands are
> now behaving in contradictory ways :( However, I think it's too late
> to change either command now.

I'd call that a bug and fix it.  In this case I'd probably make
svnlook match svn and fix svn diff --git to provide the behavior
because of what I mentioned before.  svnlook should probably also grow
--git and some of the other diff options.

> I'm not quite sure if we can already recommend the --git diff option
> for widespread use.

Then we shouldn't have released with it enabled.  Releasing a command
with an option and then saying we don't recommend people to use it is
like throwing a live hand grenade in the room of friends and saying
that you don't recommend that your friends occupy the room.

> I intend to get back to it once we can produce proper information for renames.

But it doesn't even properly handle the cases we can handle or at
least should be able to handle now.  Renames has nothing to do with
the current issue, I don't see a reason to wait for that to fix this.

> It's never going to be fully interoperable
> with other VCSs in any case because Subversion needs to show all paths
> in --git diff headers relative to the repository root to avoid ambiguity
> in copyfrom paths. So instead of a/foo/bar.txt like git would show for
> any branch, for instance, we get paths like a/trunk/foo/bar.txt or
> a/branches/mybranch/foo/bar.txt with svn diff --git, depending on the
> branch the diff is made on.

Right, we really can't interoperate fully here, which is part of the
reason we never could agree on a format because once you get into
describing tree changes things diverge in ways that make it hard to
agree.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Tue, Jun 25, 2013 at 10:26:08PM +0200, Ben Reser wrote:
> Back to your issue.  Since Subversion can't represent the copy as part
> of the diff it tries to do the interoperable thing which is to
> represent the addition of a new file (from a copy) as an addition.

That's not quite true in general. It's more like:

1) If the copyfrom source is part of the operative revision range of
   the diff command, show a modification against the copyfrom source.
   Unless --show-copies-as-adds was passed, because then we always
   show copied files as an addition.

2) If the copyfrom source is not part of the operative revision range,
   history of the file isn't traced back to that revision, so it appears
   as an addition.

It could be argued that 2) is weird special case, and that it should
behave like 1) (i.e. trace back to the copyfrom source anyway) and
only show an addition with --show-copies-as-adds.

Johan pointed out that svnlook diff seems to traverse to the copyfrom
source even in case 2). If this is indeed the case, these commands are
now behaving in contradictory ways :( However, I think it's too late
to change either command now.

> While I understand your interpretation I don't think we are likely to
> change the default output of diff to behave this way.  I can see an
> argument for an option to diff to tell it to use the base of copies as
> where they were copied from, but I'm not sure if that's really useful
> when you'd end up not seeing where it was copied from in the diff.  So
> IMHO the correct solution to this is to fix the --git option and
> change your vc-svn.el module to pass that flag.

I'm not quite sure if we can already recommend the --git diff option
for widespread use. I intend to get back to it once we can produce
proper information for renames. It's never going to be fully interoperable
with other VCSs in any case because Subversion needs to show all paths
in --git diff headers relative to the repository root to avoid ambiguity
in copyfrom paths. So instead of a/foo/bar.txt like git would show for
any branch, for instance, we get paths like a/trunk/foo/bar.txt or
a/branches/mybranch/foo/bar.txt with svn diff --git, depending on the
branch the diff is made on.

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Ben Reser <be...@reser.org>.
On Tue, Jun 25, 2013 at 8:33 PM, Tobias Bading <tb...@web.de> wrote:
> I think I can already hear Emacs developers of both VC camps, the Bazaar'ians and the Git'ians, laughing together in harmony in the distance... ;-)
> No disrespect & thank you for the hint, but shouldn't a version control system be able to answer the question "what's changed?" without making you jump through hoops?

Yes Git has better behavior here (not sure about Bazaar).  Git also
has a way to represent tree modifications in their diff format.  The
problem here is that Subversion's diff isn't really tree versioning
aware.  This goes back to the fact that when Subversion was written
there wasn't a format for representing tree deltas.  Git's format has
become somewhat of a standard (though even it isn't really sufficient
for us).  We still don't have a good format for this that's cross VC
and the Subversion project never felt like it wanted to take it upon
itself to just ship something that couldn't interoperate with others.
There were efforts to agree on a format across VC systems, but it was
not possible to agree.  We probably should have in retrospect just
developed a format.  Git however, had no choice because their
fundamental purpose was to manage passing patches around.  Unified
diff couldn't solve this problem so they solved it on their own.
Subversion being based on a centralized repository didn't have the
same requirements of being able to represent every change with diff,
so our output favors interoperability with the patch command.

Back to your issue.  Since Subversion can't represent the copy as part
of the diff it tries to do the interoperable thing which is to
represent the addition of a new file (from a copy) as an addition.
Simply using a revision range isn't exactly what is changing the
output you're getting.  You can't just use -rM:N where M < N-1, M
*MUST* be the revision you copied from.  When you specify this then
the base of the diff ends up being the file you copied from since
Subversion follows the copy and you get the result you want.  A great
way to see this is to simply add another unrelated file in r1 in your
example script and change your diffs to use -c4 and -r1:4.  Your copy
now comes from r2 and you'll see the same output for both -c4 and
-r1:4, where as -r2:4 provides the output you want.

>From the perspective of someone who is wanting to see the change done
in the repository with diff then I can see your point.  From the point
of view of someone that wants to send the diff to someone to apply
with the patch command that isn't necessarily using Subversion or even
the same repository, the way things work now properly are better.

Fortunately, the problem I mention above where sending tree changes
with the delta should be solved with the --git option to diff (the git
people can laugh some more that the solution to your problem should be
to pass that option).  However, if you use it you'll have the same
issues that you have already.  Simply because the --git option hasn't
really been fully finished being implemented.  Subversion doesn't have
proper move tracking or even really move heuristics yet, so it can't
represent moves.  However, it does have fully knowledge of the copy
and in this case I would consider it a bug that the --git option does
not return the the git extended header as "copy from ..." instead of
"new file" as it does now and then provide a diff off the copy.

While I understand your interpretation I don't think we are likely to
change the default output of diff to behave this way.  I can see an
argument for an option to diff to tell it to use the base of copies as
where they were copied from, but I'm not sure if that's really useful
when you'd end up not seeing where it was copied from in the diff.  So
IMHO the correct solution to this is to fix the --git option and
change your vc-svn.el module to pass that flag.

That doesn't help you much right now, but I think that's the right
solution.  The other solutions people have suggested, using log to
find the copy from and then setting the range right won't help you
with vc-svn.el because if there are multiple files copied from
different revs, it will be impossible to get the base correct on all
of them.

Side note for anyone wondering: Git doesn't track copies, however,
when the copy is in the same change then it will always find it.  So
even without the humorously named --find-copies-harder the equivalent
case in Git will always behave as Tobias expects.  However, you can
end up with similar issues with git when the copy isn't so easy to
find (and then you have to start using -C or --find-copies-harder to
get the output you expect).

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Julian Foad <ju...@btopenworld.com>.
Peter Samuelson wrote:

> [Tobias Bading]
>>  No disrespect & thank you for the hint, but shouldn't a version
>>  control system be able to answer the question "what's changed?"
>>  without making you jump through hoops?
> 
> Well, I forgot about "svn log --diff -l1 new_foo".

Please tell us what you forgot about it or what is interesting about it.

(If that command shows the diff against the file's copy-from source, whereas an "svn diff -cX new_foo" doesn't, then that would be an interesting observation because I would expect "svn log --diff" to show "the change that happened in a revision X" and I would expect that to be the same as "svn diff -cX".)

- Julian

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Peter Samuelson <pe...@p12n.org>.
> > Well, I forgot about "svn log --diff -l1 new_foo".

[Tobias Bading]
> Good idea, but unfortunately no cigar.

You're right.  I tested that command but somehow glazed over the fact
that it did not do what I said it did.  Sorry.  Anyway, parsing the
'svn log -v -l1 {filename}' output, then running 'svn diff -rM:N', is
still correct.

How do git et al. deal with the ambiguity you are presenting, anyway?
I mean, you have this file, it is present in this revision, it came
from _somewhere_ but not from the parent revision.  How do you tell it
that you don't want the usual thing, a diff against the parent revision
('git show'), but instead, a diff against wherever the file came from?

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 20:42, Peter Samuelson wrote:
> [Tobias Bading]
>> No disrespect & thank you for the hint, but shouldn't a version
>> control system be able to answer the question "what's changed?"
>> without making you jump through hoops?
> 
> Well, I forgot about "svn log --diff -l1 new_foo".

Good idea, but unfortunately no cigar. Same problems as diff -cN. Only works if the file was copied from rN-1 to rN. If a file was copied from rM to rN with M < N-1, 'svn log --diff -l1 FILE' performs a diff between r0 and rN just like 'svn diff -cN FILE'.


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Peter Samuelson <pe...@p12n.org>.
[Tobias Bading]
> No disrespect & thank you for the hint, but shouldn't a version
> control system be able to answer the question "what's changed?"
> without making you jump through hoops?

Well, I forgot about "svn log --diff -l1 new_foo".

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 20:08, Peter Samuelson wrote:
> [Tobias Bading]
>> Seriously though, what would you have to do if you have the path of a
>> FILE in the working copy and a revision number N and you would like
>> to know what was changed in that file in that revision?
> 
> Something like this:
> 
> $ LC_ALL=C svn log -v -l1 new_foo
> ------------------------------------------------------------------------
> r6 | peters | 2013-06-25 13:05:16 -0500 (Tue, 25 Jun 2013) | 1 line
> Changed paths:
>   A /new_foo (from /foo:1)
> 
> Copied and modified foo@1 to new_foo.
> ------------------------------------------------------------------------
> 
> Parse the "A" line, then use that information to construct a diff
> command line.  Either of the following will work:
> 
>    svn diff -r1:6 new_foo
>    svn diff ^/foo@1 ^/new_foo@6
> 
> Peter

I think I can already hear Emacs developers of both VC camps, the Bazaar'ians and the Git'ians, laughing together in harmony in the distance... ;-)
No disrespect & thank you for the hint, but shouldn't a version control system be able to answer the question "what's changed?" without making you jump through hoops?

Tobias


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Peter Samuelson <pe...@p12n.org>.
[Tobias Bading]
> Seriously though, what would you have to do if you have the path of a
> FILE in the working copy and a revision number N and you would like
> to know what was changed in that file in that revision?

Something like this:

$ LC_ALL=C svn log -v -l1 new_foo
------------------------------------------------------------------------
r6 | peters | 2013-06-25 13:05:16 -0500 (Tue, 25 Jun 2013) | 1 line
Changed paths:
   A /new_foo (from /foo:1)

Copied and modified foo@1 to new_foo.
------------------------------------------------------------------------


Parse the "A" line, then use that information to construct a diff
command line.  Either of the following will work:

    svn diff -r1:6 new_foo
    svn diff ^/foo@1 ^/new_foo@6

Peter

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 18:45, Stefan Sperling wrote:
> On Tue, Jun 25, 2013 at 05:59:27PM +0200, Tobias Bading wrote:
>> Hmm, but why is diff -cM:N working if the file was copied from
>> revision M? Sure, the target of the copy operation did not exist in
>> revision N-1 if M < N-1, but it didn't exist in revision M either.
> 
> The file did exist at the copyfrom location in revision M, correct?
> In which case Subversion can detect that the files at their respective
> paths in revision M and N are related, so it displays a diff between
> them. The revision N-1 doesn't matter in this case. It is not "operative"
> on the file, and is ignored.
> 
> But if you restrict the operative revision range of your diff such that
> the copy source is not within that range, why would you expect Subversion to
> still look for changes in that revision, and show a diff against the copy
> source? I believe that 'svn diff' is giving you the right answer based on
> parameters you've given it to work with.
> 
> I realise that I'm not helping you much. I'm just explaining the
> current intended behaviour. I don't think you've found a bug.

I wouldn't call it a bug either, but even less a feature ;-). I'm simply expecting -cN to mean "the changes made in revision N", not the changes between revisions N-1 and N. In most cases there's no difference in both interpretations, but with copies that warp time (so to speak) by copying from source@M to target@N with M < N-1, 'diff -cN target' is as useful as 'cat </dev/null' :-(.

> The emacs vc-svn.el (sorry I didn't know that "plugin" is not the proper
> term to use here) would indeed need to pass something more clever than
> a hardcoded -rN-1:N to yield a useful result in your use case.

*slowly waves his hand in front of Stefan*
"This is not the editor you're looking for... move along." :-D

Seriously though, what would you have to do if you have the path of a FILE in the working copy and a revision number N and you would like to know what was changed in that file in that revision?
Something like 'svn log --limit 2 -rN:0 FILE' and if that returns two revision, take the second one (let's call it M) and do a 'svn diff -rM:N FILE'?
Where's my Beißholz when I need it?!? :-D

> The location of a file across revision history is not a very simple issue
> in Subversion, and can sometimes be counterintuitive. If you haven't
> done so I recommend reading this page for more information about how
> Subversion resolves paths in history:
> http://svnbook.red-bean.com/en/1.7/svn.advanced.pegrevs.html

Thanks for the tip. I read it a few years ago, maybe I should read it again :-).

Tobias


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Tue, Jun 25, 2013 at 05:59:27PM +0200, Tobias Bading wrote:
> Hmm, but why is diff -cM:N working if the file was copied from
> revision M? Sure, the target of the copy operation did not exist in
> revision N-1 if M < N-1, but it didn't exist in revision M either.

The file did exist at the copyfrom location in revision M, correct?
In which case Subversion can detect that the files at their respective
paths in revision M and N are related, so it displays a diff between
them. The revision N-1 doesn't matter in this case. It is not "operative"
on the file, and is ignored.

But if you restrict the operative revision range of your diff such that
the copy source is not within that range, why would you expect Subversion to
still look for changes in that revision, and show a diff against the copy
source? I believe that 'svn diff' is giving you the right answer based on
parameters you've given it to work with.

I realise that I'm not helping you much. I'm just explaining the
current intended behaviour. I don't think you've found a bug.

The emacs vc-svn.el (sorry I didn't know that "plugin" is not the proper
term to use here) would indeed need to pass something more clever than
a hardcoded -rN-1:N to yield a useful result in your use case.

The location of a file across revision history is not a very simple issue
in Subversion, and can sometimes be counterintuitive. If you haven't
done so I recommend reading this page for more information about how
Subversion resolves paths in history:
http://svnbook.red-bean.com/en/1.7/svn.advanced.pegrevs.html

Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Tobias Bading <tb...@web.de>.
On 25.06.2013, at 16:45, Stefan Sperling wrote:
> On Tue, Jun 25, 2013 at 04:24:36PM +0200, Tobias Bading wrote:
>> Dear Devs,
>> 
>> GNU Emacs 24.3 was behaving a little odd today while trying to
>> display a svn diff from Annotate mode. It simply barked "svn: Unable
>> to find repository location for '...' in revision ..." at me :-(.
>> Since this wasn't the first time Emacs left me in the rain like
>> this, I thought it was time to take a closer look.
>> 
>> This much I was able to figure out:
>> 
>> If you copy a file from revision N-1, modify the copy and then
>> commit it as revision N, 'svn diff -cN FILE' works as expected
>> afterwards. It works no matter whether you use Subversion 1.6 or
>> 1.8, no matter whether you specify FILE as a working copy path or a
>> repository URL. "Works as expected" meaning that it shows the
>> modifications you made, not the entire file as an add.
>> 
>> However, if you copy a file from a revision M that is smaller than
>> N-1, modify the copy and then commit it as revision N, 'svn diff -cN
>> FILE' won't play along. Subversion 1.6 simply barks "svn: Unable to
>> find repository location for 'FILE' in revision N-1", whereas
>> Subversion 1.8 shows the whole file as an add, i.e. does a diff
>> -r0:N :-(. An 'svn diff -rM:N FILE' on the other hand works fine.
> 
> There is a related issue that was fixed in 1.7.2:
> http://subversion.tigris.org/issues/show_bug.cgi?id=2873
> 
>> Emacs executes 'svn --non-interactive diff -r N-1:N FILE' for
>> revision N at the current line when you press d in Annotate mode,
>> which of course barfs just as much as 'diff -cN' does in the
>> described case with M < N-1.
>> 
>> Would it be possible to spice up the semantics of -cN a bit?
> 
> The meaning of -c is and always has been '-r N-1:N'.
> I don't think we'd want to change this, even if only for compatibility
> purposes.
> 
>> I don't know enough about the innards of Subversion to understand
>> why -rM:N works but -rN-1:N doesn't, but I think trying to figure
>> out the correct value of M for the current line in Emacs' Annotate
>> mode might get painfull.
> 
> I cannot comment on the emacs plugin you're using.

There's no plugin involved, simply GNU Emacs' vc-svn.el, i.e. the implementation of Emacs version control features for Subversion. There are other implementations for git/bazaar/..., all using the same menus, keyboard shortcuts etc. Annotate mode is simply the output of 'svn blame' (or similar for other VC systems) with rainbow coloring on top, that is coloring from red for new lines to blue for old ones.

> Note that however if the file does not exist at revision N-1 and does exist at rN, and you're asking 'svn diff' to show how this file differs between revision N-1 and N, you'll always see a full copy of the file. I don't see anything wrong with that.

Hmm, but why is diff -cM:N working if the file was copied from revision M? Sure, the target of the copy operation did not exist in revision N-1 if M < N-1, but it didn't exist in revision M either.

> I would say the emacs plugin needs to be made smarter about the
> revision ranges it is diffing when showing changes. Perhaps try
> to contact the plugin's maintainer for help.

IMHO this has nothing to do with Emacs, at least not from my point of view. But maybe I'm just expecting too much of 'diff -cN'.

This is how I personally use 'svn diff -cN XYZ' and what I expect to see when using it:
If XYZ is a directory in a working copy or a directory in a repository, show me what was changed in revision N below that directory (including property changes of the directory itself).
If XYZ is a file in a working copy or a file in a repository, show me what was changed in revision N in that file (including property changes).

My expectations and reality usually match nicely (in this case). But there's always someone who doesn't want to play along ;-).

So the question is this:
If I'd like to see (or merge) the changes made in a revision N to a file that was created by copying and then modifying in that very revision, what would be the proper command to run?

Let's say the log of a revision 42 says:
   A /D2/f (from /D1/f:7)
This log line alone does not tell me whether f was simply copied, or copied and then modified. Do I really have to do a 'svn diff -r7:42 D2/f' (or even worse 'svn diff D1/f@7 D2/f@42') to figure out whether the copy was modified? How is a tool supposed to come up with the 7, if the user would simply like to know "What was changed in revision 42 in D2/f?" The tool would have to look at the log of D2/f to check for the revision prior to 42 and then do the 'diff -r7:42'. A working 'diff -c42' would be that much nicer...

Tobias


Re: 1.6 vs. 1.8: strange behavior of 'svn diff -cN WC-FILE' if the file was created in rev N by copying

Posted by Stefan Sperling <st...@elego.de>.
On Tue, Jun 25, 2013 at 04:24:36PM +0200, Tobias Bading wrote:
> Dear Devs,
> 
> GNU Emacs 24.3 was behaving a little odd today while trying to
> display a svn diff from Annotate mode. It simply barked "svn: Unable
> to find repository location for '...' in revision ..." at me :-(.
> Since this wasn't the first time Emacs left me in the rain like
> this, I thought it was time to take a closer look.
> 
> This much I was able to figure out:
> 
> If you copy a file from revision N-1, modify the copy and then
> commit it as revision N, 'svn diff -cN FILE' works as expected
> afterwards. It works no matter whether you use Subversion 1.6 or
> 1.8, no matter whether you specify FILE as a working copy path or a
> repository URL. "Works as expected" meaning that it shows the
> modifications you made, not the entire file as an add.
>
> However, if you copy a file from a revision M that is smaller than
> N-1, modify the copy and then commit it as revision N, 'svn diff -cN
> FILE' won't play along. Subversion 1.6 simply barks "svn: Unable to
> find repository location for 'FILE' in revision N-1", whereas
> Subversion 1.8 shows the whole file as an add, i.e. does a diff
> -r0:N :-(. An 'svn diff -rM:N FILE' on the other hand works fine.

There is a related issue that was fixed in 1.7.2:
http://subversion.tigris.org/issues/show_bug.cgi?id=2873

> Emacs executes 'svn --non-interactive diff -r N-1:N FILE' for
> revision N at the current line when you press d in Annotate mode,
> which of course barfs just as much as 'diff -cN' does in the
> described case with M < N-1.
> 
> Would it be possible to spice up the semantics of -cN a bit?

The meaning of -c is and always has been '-r N-1:N'.
I don't think we'd want to change this, even if only for compatibility
purposes.

> I don't know enough about the innards of Subversion to understand
> why -rM:N works but -rN-1:N doesn't, but I think trying to figure
> out the correct value of M for the current line in Emacs' Annotate
> mode might get painfull.

I cannot comment on the emacs plugin you're using. Note that however
if the file does not exist at revision N-1 and does exist at rN, and
you're asking 'svn diff' to show how this file differs between
revision N-1 and N, you'll always see a full copy of the file.
I don't see anything wrong with that.

I would say the emacs plugin needs to be made smarter about the
revision ranges it is diffing when showing changes. Perhaps try
to contact the plugin's maintainer for help.