# HG changeset patch # User Patrick Mezard # Date 1273425935 -7200 # Node ID ee8ea6356733fddf4c70dc4edd90fcf3f11562dd # Parent 0bedcbcb3ae2caca7f8894c6b53c901475aad6a1# Parent a9b427b5821e7006c7033ddc4075455c572d6d3a Merge with crew-stable diff -r 0bedcbcb3ae2 -r ee8ea6356733 hgext/convert/subversion.py --- a/hgext/convert/subversion.py Fri May 07 23:31:49 2010 +0200 +++ b/hgext/convert/subversion.py Sun May 09 19:25:35 2010 +0200 @@ -386,7 +386,7 @@ self.modecache = {} (paths, parents) = self.paths[rev] if parents: - files, copies = self.expandpaths(rev, paths, parents) + files, self.removed, copies = self.expandpaths(rev, paths, parents) else: # Perform a full checkout on roots uuid, module, revnum = self.revsplit(rev) @@ -395,6 +395,7 @@ files = [n for n, e in entries.iteritems() if e.kind == svn.core.svn_node_file] copies = {} + self.removed = set() files.sort() files = zip(files, [rev] * len(files)) @@ -610,7 +611,7 @@ return prevmodule def expandpaths(self, rev, paths, parents): - entries = [] + changed, removed = set(), set() # Map of entrypath, revision for finding source of deleted # revisions. copyfrom = {} @@ -626,7 +627,7 @@ kind = self._checkpath(entrypath, revnum) if kind == svn.core.svn_node_file: - entries.append(self.recode(entrypath)) + changed.add(self.recode(entrypath)) if not ent.copyfrom_path or not parents: continue # Copy sources not in parent revisions cannot be @@ -644,41 +645,34 @@ 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: - entries.append(self.recode(entrypath)) + removed.add(self.recode(entrypath)) elif fromkind == svn.core.svn_node_dir: - if ent.action == 'C': - children = self._find_children(path, prevnum) - else: - oroot = parentpath.strip('/') - nroot = path.strip('/') - children = self._find_children(oroot, prevnum) - children = [s.replace(oroot, nroot) for s in children] - + oroot = parentpath.strip('/') + nroot = path.strip('/') + children = self._find_children(oroot, prevnum) + children = [s.replace(oroot, nroot) for s in children] for child in children: childpath = self.getrelpath("/" + child, pmodule) - if not childpath: - continue - if childpath in copies: - del copies[childpath] - entries.append(childpath) + if childpath: + removed.add(self.recode(childpath)) 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: @@ -691,7 +685,7 @@ # Need to filter out directories here... kind = self._checkpath(entrypath, revnum) if kind != svn.core.svn_node_dir: - entries.append(self.recode(entrypath)) + changed.add(self.recode(entrypath)) # Handle directory copies if not ent.copyfrom_path or not parents: @@ -717,7 +711,8 @@ copytopath = self.getrelpath(copytopath) copies[self.recode(copytopath)] = self.recode(entrypath) - return (list(set(entries)), copies) + changed.update(removed) + return (list(changed), removed, copies) def _fetch_revisions(self, from_revnum, to_revnum): if from_revnum < to_revnum: @@ -846,6 +841,8 @@ def _getfile(self, file, rev): # TODO: ra.get_file transmits the whole file instead of diffs. + if file in self.removed: + raise IOError() mode = '' try: new_module, revnum = self.revsplit(rev)[1:] @@ -901,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 0bedcbcb3ae2 -r ee8ea6356733 tests/svn/move.svndump --- a/tests/svn/move.svndump Fri May 07 23:31:49 2010 +0200 +++ b/tests/svn/move.svndump Sun May 09 19:25:35 2010 +0200 @@ -1,6 +1,6 @@ SVN-fs-dump-format-version: 2 -UUID: 9de99ecc-876b-46e5-bc59-bff9b2b58b1e +UUID: 7d15f7c2-5863-4c16-aa2a-3418b1721d3a Revision-number: 0 Prop-content-length: 56 @@ -9,7 +9,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:26.678698Z +2010-05-09T13:02:37.336239Z PROPS-END Revision-number: 1 @@ -27,7 +27,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:27.278689Z +2010-05-09T13:02:37.372834Z PROPS-END Node-path: trunk @@ -124,7 +124,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:28.312955Z +2010-05-09T13:02:38.049068Z PROPS-END Node-path: trunk/a @@ -166,7 +166,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:29.183467Z +2010-05-09T13:02:39.044479Z PROPS-END Node-path: subproject @@ -195,7 +195,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:30.300975Z +2010-05-09T13:02:40.057804Z PROPS-END Node-path: subproject/trunk @@ -222,7 +222,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:31.354398Z +2010-05-09T13:02:41.058871Z PROPS-END Node-path: subproject/branches @@ -249,7 +249,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:32.121901Z +2010-05-09T13:02:42.046689Z PROPS-END Node-path: subproject/trunk/d1 @@ -278,7 +278,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:32.317815Z +2010-05-09T13:02:42.071413Z PROPS-END Node-path: subproject/trunk/d2 @@ -307,7 +307,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:33.418320Z +2010-05-09T13:02:43.062018Z PROPS-END Node-path: subproject/trunk/d1/b @@ -341,7 +341,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:34.126542Z +2010-05-09T13:02:44.047997Z PROPS-END Node-path: subproject/branches/d1 @@ -370,7 +370,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:34.436015Z +2010-05-09T13:02:44.086619Z PROPS-END Node-path: subproject/trunk/d @@ -397,7 +397,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:34.803189Z +2010-05-09T13:02:44.111550Z PROPS-END Node-path: subproject/trunk/d2 @@ -422,7 +422,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:36.531735Z +2010-05-09T13:02:45.067982Z PROPS-END Node-path: subproject/trunk/d3 @@ -484,7 +484,7 @@ K 8 svn:date V 27 -2009-06-21T14:32:38.281829Z +2010-05-09T13:02:47.061259Z PROPS-END Node-path: subproject/trunk/d3/d31 @@ -498,3 +498,72 @@ Node-copyfrom-path: subproject/trunk/d3 +Revision-number: 14 +Prop-content-length: 110 +Content-length: 110 + +K 7 +svn:log +V 9 +add d4old +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2010-05-09T13:02:49.063363Z +PROPS-END + +Node-path: subproject/trunk/d4old +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: subproject/trunk/d4old/g +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2 +Text-content-md5: f5302386464f953ed581edac03556e55 +Text-content-sha1: a5938ace3f424be1a26904781cdb06d55b614e6b +Content-length: 12 + +PROPS-END +g + + +Revision-number: 15 +Prop-content-length: 125 +Content-length: 125 + +K 7 +svn:log +V 23 +rename d4old into d4new +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2010-05-09T13:02:51.047304Z +PROPS-END + +Node-path: subproject/trunk/d4new +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 14 +Node-copyfrom-path: subproject/trunk/d4old + + +Node-path: subproject/trunk/d4old +Node-action: delete + + diff -r 0bedcbcb3ae2 -r ee8ea6356733 tests/svn/replace.svndump --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svn/replace.svndump Sun May 09 19:25:35 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 0bedcbcb3ae2 -r ee8ea6356733 tests/svn/svndump-move.sh --- a/tests/svn/svndump-move.sh Fri May 07 23:31:49 2010 +0200 +++ b/tests/svn/svndump-move.sh Sun May 09 19:25:35 2010 +0200 @@ -68,6 +68,16 @@ svn copy subproject/trunk/d3 subproject/trunk/d4 svn rm subproject/trunk/d3/d31 svn ci -m "copy dir and remove subdir" + +# Test directory moves +svn up +mkdir -p subproject/trunk/d4old +echo g > subproject/trunk/d4old/g +svn add subproject/trunk/d4old +svn ci -m "add d4old" +svn mv subproject/trunk/d4old subproject/trunk/d4new +svn ci -m "rename d4old into d4new" + cd .. svnadmin dump svn-repo > ../move.svndump \ No newline at end of file diff -r 0bedcbcb3ae2 -r ee8ea6356733 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:25:35 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 0bedcbcb3ae2 -r ee8ea6356733 tests/test-convert-svn-move --- a/tests/test-convert-svn-move Fri May 07 23:31:49 2010 +0200 +++ b/tests/test-convert-svn-move Sun May 09 19:25:35 2010 +0200 @@ -28,5 +28,26 @@ cd A-hg hg glog --template '{rev} {desc|firstline} files: {files}\n' +echo '% check move copy records' +hg st --rev 12:13 --copies +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 0bedcbcb3ae2 -r ee8ea6356733 tests/test-convert-svn-move.out --- a/tests/test-convert-svn-move.out Fri May 07 23:31:49 2010 +0200 +++ b/tests/test-convert-svn-move.out Sun May 09 19:25:35 2010 +0200 @@ -3,18 +3,24 @@ scanning source... sorting... converting... -11 createtrunk -10 moved1 -9 moved1 -8 moved2 -7 changeb and rm d2 -6 changeb and rm d2 -5 moved1again -4 moved1again -3 copyfilefrompast -2 copydirfrompast -1 add d3 -0 copy dir and remove subdir +13 createtrunk +12 moved1 +11 moved1 +10 moved2 +9 changeb and rm d2 +8 changeb and rm d2 +7 moved1again +6 moved1again +5 copyfilefrompast +4 copydirfrompast +3 add d3 +2 copy dir and remove subdir +1 add d4old +0 rename d4old into d4new +o 13 rename d4old into d4new files: d4new/g d4old/g +| +o 12 add d4old files: d4old/g +| o 11 copy dir and remove subdir files: d3/d31/e d4/d31/e d4/f | o 10 add d3 files: d3/d31/e d3/f @@ -39,5 +45,38 @@ | o 0 createtrunk files: -default 11: +% check move copy records +A d4new/g + d4old/g +R d4old/g +% 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