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

Re: svn commit: r1431114 - /subversion/trunk/subversion/svn/merge-cmd.c

From: Paul Burba <ptburba_at_gmail.com>
Date: Thu, 10 Jan 2013 13:58:40 -0500

On Thu, Jan 10, 2013 at 12:38 PM, Bert Huijben <bert_at_qqmail.nl> wrote:
>
>
>> -----Original Message-----
>> From: pburba_at_apache.org [mailto:pburba_at_apache.org]
>> Sent: woensdag 9 januari 2013 23:04
>> To: commits_at_subversion.apache.org
>> Subject: svn commit: r1431114 - /subversion/trunk/subversion/svn/merge-
>> cmd.c
>>
>> Author: pburba
>> Date: Wed Jan 9 22:04:24 2013
>> New Revision: 1431114
>>
>> URL: http://svn.apache.org/viewvc?rev=1431114&view=rev
>> Log:
>> Fix issue #4139 'Subversion cannot perform merge if there's a file with
>> the same name as directory'.
>>
>> * subversion/svn/merge-cmd.c
>> (svn_cl__merge): If the basename of the source is the same as the
>> basename of the current working directory, then assume the cwd is the
>> target.
>
> I never heard of and/or noticed this behavior

Hi Bert,

Which behavior are you referring to: The old behavior, the bug with
the old behavior, or the new behavior?

The old behavior was this:

'svn merge ^/src/base-name .' and 'svn merge ^src/base-name' both used
the cwd at the merge target *unless* there is a file in the cwd with
the same name as the source basename. In that case the file was the
merge target.

The problem in issue #4139 centered on the case where the base name of
the source, the base name of the cwd's repos path, and a file in the
cwd all share the same value:

1.7.x>svn ls -R ^^/
branches/
branches/1.0/
branches/1.0/foo/
branches/1.0/foo/foo
         ^^^
         file 'foo' in dir 'foo'
trunk/
trunk/foo/
trunk/foo/foo
         ^^^
         file 'foo' in dir 'foo'

1.7.x>svn info
Path: .
Working Copy Root Path:
C:\SVN\src-trunk-2\Debug\subversion\tests\cmdline\svn-test-work\working_copies\4139-1.7-WC
URL: http://localhost/svn-test-work/repositories/4139-REPOS/branches/1.0/foo
Repository Root: http://localhost/svn-test-work/repositories/4139-REPOS
Repository UUID: 3c30021b-156f-8648-ba21-a13a0af7285d
Revision: 4
Node Kind: directory
Schedule: normal
Last Changed Author: jrandom
Last Changed Rev: 2
Last Changed Date: 2013-01-10 13:34:55 -0500 (Thu, 10 Jan 2013)

What happened was that the aforementioned behavior would select the
*file* child as the merge target, resulting in this error:

1.7.x>svn merge -c4 ^^/trunk/foo
..\..\..\subversion\svn\util.c:913: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10955: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10909: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10909: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10879: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:8857: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:6775: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:5191: (apr_err=160017)
..\..\..\subversion\libsvn_ra_neon\fetch.c:711: (apr_err=160017)
svn: E160017: Can't get text contents of a directory

1.7.x>svn merge -c4 ^^/trunk/foo .
..\..\..\subversion\svn\util.c:913: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10955: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10909: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10909: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:10879: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:8857: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:6775: (apr_err=160017)
..\..\..\subversion\libsvn_client\merge.c:5191: (apr_err=160017)
..\..\..\subversion\libsvn_ra_neon\fetch.c:711: (apr_err=160017)
svn: E160017: Can't get text contents of a directory

The workaround is pretty simple, set the cwd to the parent of the
earlier target:

1.7.x>cd ..

1.7.x>svn merge -c4 ^^/trunk/foo 4139-1.7-WC
--- Merging r4 into '4139-1.7-WC':
U 4139-1.7-WC\foo
--- Recording mergeinfo for merge of r4 into '4139-1.7-WC':
 U 4139-1.7-WC

However that obviously doesn't work if the cwd is the drive root. In
that case you'd have to switch the WC to the repos parent of
^^/branches/1.0/foo. But even that leaves the situation (albeit
pretty unlikely) that the WC root is the drive root *and* represents
the repos root. In that case you had no choice but to checkout (or
simply move) the WC to a non-drive root.

My change in r1431114 kept the earlier behavior of targeting a file in
the implied WC target if it had the same name as the basename in the
merge source, but before it got to that point it checks if the repos
path basename of the implied WC target is the same as the basename of
the merge source. In that case it selected the implied WC target
(i.e. the cwd) as the merge target:

1.8-dev>svn info
Path: .
Working Copy Root Path:
C:\SVN\src-trunk-2\Debug\subversion\tests\cmdline\svn-test-work\working_copies\4139-WC
URL: http://localhost/svn-test-work/repositories/4139-REPOS/branches/1.0/foo
Relative URL: ^/branches/1.0/foo
Repository Root: http://localhost/svn-test-work/repositories/4139-REPOS
Repository UUID: 3c30021b-156f-8648-ba21-a13a0af7285d
Revision: 4
Node Kind: directory
Schedule: normal
Last Changed Author: jrandom
Last Changed Rev: 2
Last Changed Date: 2013-01-10 13:34:55 -0500 (Thu, 10 Jan 2013)

1.8-dev>svn merge -c4 ^^/trunk/foo
--- Merging r4 into '.':
U foo
--- Recording mergeinfo for merge of r4 into '.':
 U .

This change does add a wrinkle if the merge source is a file with the
same basename as the repos path of the cwd:

1.8-dev>svn revert -Rq .

1.8-dev>svn merge -c4 ^^/trunk/foo/foo
..\..\..\subversion\svn\util.c:553: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:11234: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:11200: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:9383: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:9088: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:8950: (apr_err=160005)
..\..\..\subversion\libsvn_client\merge.c:5366: (apr_err=160005)
..\..\..\subversion\libsvn_ra_serf\update.c:2870: (apr_err=160005)
..\..\..\subversion\libsvn_ra_serf\util.c:949: (apr_err=160005)
svn: E160005: Cannot replace a directory from within

But at least the workaround there is simple, we just need to
explicitly state the file target:

1.8-dev>svn merge -c4 ^^/trunk/foo/foo foo
--- Merging r4 into 'foo':
U foo
--- Recording mergeinfo for merge of r4 into 'foo':
 U foo

> Should we also apply something like this patch to make sure that this 'guessing' is disabled if the user adds an explicit "." as last argument?

Possibly. I was trying to preserve as much of the old behavior as
possible, but maybe it makes sense to treat "." and "" slightly
differently, at least as far as the targeting heuristics go.

> The argument normalization functions would normalize the dot to "", which triggers this guessing behavior of where to apply, while I would say the user clearly provided the current directory as target.

Are you suggesting that:

Merge target: "." --> No guessing, the target is *always* the cwd.

Merge target: "" --> Target guessing heuristics apply.

?

-- 
Paul T. Burba
CollabNet, Inc. -- www.collab.net -- Enterprise Cloud Development
Skype: ptburba
> [[
> * subversion/svn/merge.c
>   (svn_cl__merge): Only guess the intended target if the user didn't provide a target, instead of also when the target is . or the empty string.
> ]]
>
>         Bert
Received on 2013-01-10 19:59:15 CET

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.