--- a/hgext/convert/subversion.py Sun May 09 19:11:02 2010 +0200
+++ b/hgext/convert/subversion.py Sun May 09 19:11:02 2010 +0200
@@ -645,14 +645,7 @@
self.ui.debug("gone from %s\n" % ent.copyfrom_rev)
pmodule, prevnum = self.revsplit(parents[0])[1:]
parentpath = pmodule + "/" + entrypath
- self.ui.debug("entry %s\n" % parentpath)
-
- # We can avoid the reparent calls if the module has
- # not changed but it probably does not worth the pain.
- prevmodule = self.reparent('')
- fromkind = svn.ra.check_path(self.ra, parentpath.strip('/'),
- prevnum)
- self.reparent(prevmodule)
+ fromkind = self._checkpath(entrypath, prevnum, pmodule)
if fromkind == svn.core.svn_node_file:
removed.add(self.recode(entrypath))
@@ -668,11 +661,18 @@
else:
self.ui.debug('unknown path in revision %d: %s\n' % \
(revnum, path))
- elif kind == svn.core.svn_node_dir:
- # If the directory just had a prop change,
- # then we shouldn't need to look for its children.
+ elif kind == svn.core.svn_node_dir:
if ent.action == 'M':
+ # If the directory just had a prop change,
+ # then we shouldn't need to look for its children.
continue
+ elif ent.action == 'R' and parents:
+ # If a directory is replacing a file, mark the previous
+ # file as deleted
+ pmodule, prevnum = self.revsplit(parents[0])[1:]
+ pkind = self._checkpath(entrypath, prevnum, pmodule)
+ if pkind == svn.core.svn_node_file:
+ removed.add(self.recode(entrypath))
children = sorted(self._find_children(path, revnum))
for child in children:
@@ -898,11 +898,18 @@
self.ui.debug('%r is not under %r, ignoring\n' % (path, module))
return None
- def _checkpath(self, path, revnum):
- # ra.check_path does not like leading slashes very much, it leads
- # to PROPFIND subversion errors
- return svn.ra.check_path(self.ra, path.strip('/'), revnum)
-
+ def _checkpath(self, path, revnum, module=None):
+ if module is not None:
+ prevmodule = self.reparent('')
+ path = module + '/' + path
+ try:
+ # ra.check_path does not like leading slashes very much, it leads
+ # to PROPFIND subversion errors
+ return svn.ra.check_path(self.ra, path.strip('/'), revnum)
+ finally:
+ if module is not None:
+ self.reparent(prevmodule)
+
def _getlog(self, paths, start, end, limit=0, discover_changed_paths=True,
strict_node_history=False):
# Normalize path names, svn >= 1.5 only wants paths relative to
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/replace.svndump Sun May 09 19:11:02 2010 +0200
@@ -0,0 +1,241 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 4a895937-439c-4e56-b7b0-fa1c8acc0c20
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2010-05-09T14:57:31.007802Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+initial
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-05-09T14:57:32.094732Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b
+Content-length: 12
+
+PROPS-END
+a
+
+
+Node-path: trunk/d
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/d/b
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 3b5d5c3712955042212316173ccf37be
+Text-content-sha1: 89e6c98d92887913cadf06b2adb97f26cde4849b
+Content-length: 12
+
+PROPS-END
+b
+
+
+Node-path: trunk/dlink
+Node-kind: file
+Node-action: add
+Prop-content-length: 33
+Text-content-length: 6
+Text-content-md5: cca56829f18345718a4980bb02b6d8c3
+Text-content-sha1: 7c54cc5d472b78c94a04382df34b0f4f0f4f2d49
+Content-length: 39
+
+K 11
+svn:special
+V 1
+*
+PROPS-END
+link d
+
+Node-path: trunk/dlink2
+Node-kind: file
+Node-action: add
+Prop-content-length: 33
+Text-content-length: 6
+Text-content-md5: cca56829f18345718a4980bb02b6d8c3
+Text-content-sha1: 7c54cc5d472b78c94a04382df34b0f4f0f4f2d49
+Content-length: 39
+
+K 11
+svn:special
+V 1
+*
+PROPS-END
+link d
+
+Node-path: trunk/dlink3
+Node-kind: file
+Node-action: add
+Prop-content-length: 33
+Text-content-length: 6
+Text-content-md5: cca56829f18345718a4980bb02b6d8c3
+Text-content-sha1: 7c54cc5d472b78c94a04382df34b0f4f0f4f2d49
+Content-length: 39
+
+K 11
+svn:special
+V 1
+*
+PROPS-END
+link d
+
+Revision-number: 2
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 15
+clobber symlink
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2010-05-09T14:57:33.071117Z
+PROPS-END
+
+Node-path: trunk/dlink3
+Node-kind: file
+Node-action: change
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: e29311f6f1bf1af907f9ef9f44b8328b
+Text-content-sha1: e983f374794de9c64e3d1c1de1d490c0756eeeff
+Content-length: 12
+
+PROPS-END
+d
+
+
+Revision-number: 3
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 8
+clobber1
+K 10
+svn:author
+V 4
+evil
+K 8
+svn:date
+V 27
+2010-05-09T14:57:35.268057Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: dir
+Node-action: delete
+
+Node-path: trunk/a
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/d
+
+
+
+
+Node-path: trunk/dlink
+Node-kind: dir
+Node-action: delete
+
+Node-path: trunk/dlink
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/d
+
+
+
+
+Revision-number: 4
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 8
+clobber2
+K 10
+svn:author
+V 4
+evil
+K 8
+svn:date
+V 27
+2010-05-09T14:57:35.521816Z
+PROPS-END
+
+Node-path: trunk/dlink3
+Node-kind: file
+Node-action: delete
+
+Node-path: trunk/dlink3
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: trunk/dlink2
+Text-copy-source-md5: cca56829f18345718a4980bb02b6d8c3
+Text-copy-source-sha1: 7c54cc5d472b78c94a04382df34b0f4f0f4f2d49
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/svndump-replace.sh Sun May 09 19:11:02 2010 +0200
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+RSVN="`pwd`/rsvn.py"
+export PATH=/bin:/usr/bin
+mkdir temp
+cd temp
+
+svnadmin create repo
+svn co file://`pwd`/repo wc
+
+cd wc
+mkdir trunk branches
+cd trunk
+echo a > a
+mkdir d
+echo b > d/b
+ln -s d dlink
+ln -s d dlink2
+ln -s d dlink3
+cd ..
+svn add *
+svn ci -m 'initial'
+# Clobber symlink with file with similar content
+cd trunk
+ls -Alh
+readlink dlink3 > dlink3tmp
+rm dlink3
+mv dlink3tmp dlink3
+svn propdel svn:special dlink3
+svn ci -m 'clobber symlink'
+cd ..
+svn up
+
+# Clobber files and symlink with directories
+cd ..
+cat > clobber.rsvn <<EOF
+rdelete trunk/a
+rdelete trunk/dlink
+rcopy trunk/d trunk/a
+rcopy trunk/d trunk/dlink
+EOF
+
+python $RSVN --message=clobber1 --username=evil `pwd`/repo < clobber.rsvn
+
+# Clobber non-symlink with symlink with same content (kudos openwrt)
+cat > clobber.rsvn <<EOF
+rdelete trunk/dlink3
+rcopy trunk/dlink2 trunk/dlink3
+EOF
+
+python $RSVN --message=clobber2 --username=evil `pwd`/repo < clobber.rsvn
+
+svn log -v file://`pwd`/repo
+
+svnadmin dump repo > ../replace.svndump
--- a/tests/test-convert-svn-move Sun May 09 19:11:02 2010 +0200
+++ b/tests/test-convert-svn-move Sun May 09 19:11:02 2010 +0200
@@ -33,3 +33,21 @@
echo '% check branches'
hg branches | sed 's/:.*/:/'
cd ..
+
+mkdir test-replace
+cd test-replace
+svnadmin create svn-repo
+cat "$TESTDIR/svn/replace.svndump" | svnadmin load svn-repo > /dev/null
+
+echo '% convert files being replaced by directories'
+hg convert svn-repo hg-repo
+cd hg-repo
+echo '% manifest before'
+hg -v manifest -r 1
+echo '% manifest after clobber1'
+hg -v manifest -r 2
+echo '% manifest after clobber2'
+hg -v manifest -r 3
+echo '% try updating'
+hg up -qC default
+cd ..
--- a/tests/test-convert-svn-move.out Sun May 09 19:11:02 2010 +0200
+++ b/tests/test-convert-svn-move.out Sun May 09 19:11:02 2010 +0200
@@ -52,3 +52,31 @@
% check branches
default 13:
d1 6:
+% convert files being replaced by directories
+initializing destination hg-repo repository
+scanning source...
+sorting...
+converting...
+3 initial
+2 clobber symlink
+1 clobber1
+0 clobber2
+% manifest before
+644 a
+644 d/b
+644 @ dlink
+644 @ dlink2
+644 dlink3
+% manifest after clobber1
+644 a/b
+644 d/b
+644 dlink/b
+644 @ dlink2
+644 dlink3
+% manifest after clobber2
+644 a/b
+644 d/b
+644 dlink/b
+644 @ dlink2
+644 @ dlink3
+% try updating