# HG changeset patch # User Patrick Mezard # Date 1226701104 21600 # Node ID 3b60f223893af24997440ca6e8140def265bfb7f # Parent b033d74be76b51720b73989152c485e0c85e9df2 fetch_command: handle nullid parent in stupid non-diffy mode diff --git a/fetch_command.py b/fetch_command.py --- a/fetch_command.py +++ b/fetch_command.py @@ -306,30 +306,36 @@ def stupid_fetch_branchrev(svn, hg_edito return files, filectxfn files = [] - branchprefix = branchpath + '/' - for path, e in r.paths.iteritems(): - if not path.startswith(branchprefix): - continue - kind = svn.checkpath(path, r.revnum) - path = path[len(branchprefix):] - if kind == 'f': - files.append(path) - elif kind == 'd': - if e.action == 'M': - # Ignore property changes for now - continue - dirpath = branchprefix + path - for child, k in svn.list_files(dirpath, r.revnum): - if k == 'f': - files.append(path + '/' + child) - else: - if path in parentctx: + if parentid == revlog.nullid: + # Initial revision, fetch all files + for path, kind in svn.list_files(branchpath, r.revnum): + if kind == 'f': files.append(path) + else: + branchprefix = branchpath + '/' + for path, e in r.paths.iteritems(): + if not path.startswith(branchprefix): continue - # Assume it's a deleted directory - path = path + '/' - deleted = [f for f in parentctx if f.startswith(path)] - files += deleted + kind = svn.checkpath(path, r.revnum) + path = path[len(branchprefix):] + if kind == 'f': + files.append(path) + elif kind == 'd': + if e.action == 'M': + # Ignore property changes for now + continue + dirpath = branchprefix + path + for child, k in svn.list_files(dirpath, r.revnum): + if k == 'f': + files.append(path + '/' + child) + else: + if path in parentctx: + files.append(path) + continue + # Assume it's a deleted directory + path = path + '/' + deleted = [f for f in parentctx if f.startswith(path)] + files += deleted copies = getcopies(svn, hg_editor, branch, branchpath, r, files, parentid) diff --git a/tests/fixtures/truncatedhistory.sh b/tests/fixtures/truncatedhistory.sh new file mode 100755 --- /dev/null +++ b/tests/fixtures/truncatedhistory.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Generate truncatedhistory.svndump +# + +mkdir temp +cd temp + +mkdir project-orig +cd project-orig +mkdir project1 +mkdir project2 +cd .. + +svnadmin create testrepo +svnurl=file://`pwd`/testrepo +svn import project-orig $svnurl -m "init project" + +svn co $svnurl project +# Make a single revision in trunk +cd project/project1 +echo a > a +svn add a +svn ci -m "add a" +cd .. +svn up +# Rename the project +svn mv project1 project2/trunk +svn ci -m "rename project1" +cd project2/trunk +echo b > b +svn add b +svn ci -m "add b" +cd ../../.. + +svnadmin dump testrepo > ../truncatedhistory.svndump diff --git a/tests/fixtures/truncatedhistory.svndump b/tests/fixtures/truncatedhistory.svndump new file mode 100644 --- /dev/null +++ b/tests/fixtures/truncatedhistory.svndump @@ -0,0 +1,147 @@ +SVN-fs-dump-format-version: 2 + +UUID: a632509c-657a-43d2-ae0b-85387476b20e + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2008-11-11T19:00:25.260082Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 114 +Content-length: 114 + +K 7 +svn:log +V 12 +init project +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2008-11-11T19:00:25.322759Z +PROPS-END + +Node-path: project1 +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: project2 +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Revision-number: 2 +Prop-content-length: 106 +Content-length: 106 + +K 7 +svn:log +V 5 +add a +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2008-11-11T19:00:26.173269Z +PROPS-END + +Node-path: project1/a +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2 +Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3 +Content-length: 12 + +PROPS-END +a + + +Revision-number: 3 +Prop-content-length: 117 +Content-length: 117 + +K 7 +svn:log +V 15 +rename project1 +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2008-11-11T19:00:29.152593Z +PROPS-END + +Node-path: project2/trunk +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: project1 +Prop-content-length: 34 +Content-length: 34 + +K 13 +svn:mergeinfo +V 0 + +PROPS-END + + +Node-path: project1 +Node-action: delete + + +Revision-number: 4 +Prop-content-length: 106 +Content-length: 106 + +K 7 +svn:log +V 5 +add b +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2008-11-11T19:00:30.178261Z +PROPS-END + +Node-path: project2/trunk/b +Node-kind: file +Node-action: add +Prop-content-length: 10 +Text-content-length: 2 +Text-content-md5: 3b5d5c3712955042212316173ccf37be +Content-length: 12 + +PROPS-END +b + + diff --git a/tests/run.py b/tests/run.py --- a/tests/run.py +++ b/tests/run.py @@ -7,6 +7,7 @@ sys.path.append(os.path.dirname(os.path. import test_fetch_command import test_fetch_command_regexes import test_fetch_renames +import test_fetch_truncated import test_push_command import test_push_renames import test_push_dirs @@ -16,6 +17,7 @@ def suite(): return unittest.TestSuite([test_fetch_command.suite(), test_fetch_command_regexes.suite(), test_fetch_renames.suite(), + test_fetch_truncated.suite(), test_push_command.suite(), test_push_renames.suite(), test_push_dirs.suite(), diff --git a/tests/test_fetch_truncated.py b/tests/test_fetch_truncated.py new file mode 100644 --- /dev/null +++ b/tests/test_fetch_truncated.py @@ -0,0 +1,40 @@ +import unittest + +from mercurial import hg +from mercurial import ui + +import fetch_command +import test_util + +class TestFetchTruncatedHistory(test_util.TestBase): + def test_truncated_history(self, stupid=False): + # Test repository does not follow the usual layout + test_util.load_svndump_fixture(self.repo_path, 'truncatedhistory.svndump') + svn_url = test_util.fileurl(self.repo_path + '/project2') + fetch_command.fetch_revisions(ui.ui(), + svn_url=svn_url, + hg_repo_path=self.wc_path, + stupid=stupid) + repo = hg.repository(ui.ui(), self.wc_path) + + # We are converting /project2/trunk coming from: + # + # Changed paths: + # D /project1 + # A /project2/trunk (from /project1:2) + # + # Here a full fetch should be performed since we are starting + # the conversion on an already filled branch. + tip = repo['tip'] + files = tip.manifest().keys() + files.sort() + self.assertEqual(files, ['a', 'b']) + self.assertEqual(repo['tip']['a'].data(), 'a\n') + + def test_truncated_history_stupid(self): + self.test_truncated_history(True) + +def suite(): + all = [unittest.TestLoader().loadTestsFromTestCase(TestFetchTruncatedHistory), + ] + return unittest.TestSuite(all)