# HG changeset patch # User Patrick Mezard # Date 1273425062 -7200 # Node ID a9b427b5821e7006c7033ddc4075455c572d6d3a # Parent ab575114ddd8519a5b03fcb72c234168b7b155a2 convert/svn: handle files/links replaced by dirs (issue2166) diff -r ab575114ddd8 -r a9b427b5821e hgext/convert/subversion.py --- 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 diff -r ab575114ddd8 -r a9b427b5821e tests/svn/replace.svndump --- /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 + + + + diff -r ab575114ddd8 -r a9b427b5821e tests/svn/svndump-replace.sh --- /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 < clobber.rsvn < ../replace.svndump diff -r ab575114ddd8 -r a9b427b5821e tests/test-convert-svn-move --- 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 .. diff -r ab575114ddd8 -r a9b427b5821e tests/test-convert-svn-move.out --- 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