# HG changeset patch # User Patrick Mezard # Date 1241404964 18000 # Node ID 963d27a0b1c29a65f5bea08751f33af84b0d1ae9 # Parent 2257bfc017494d09f97e95e76f0819f3f8d07722 svnexternals: do not use peg revisions as --rev replacements Peg revisions are now parsed separately. If a revision is supplied but not a peg revision, we used the former as peg revision, as subversion seems to do. diff --git a/svnexternals.py b/svnexternals.py --- a/svnexternals.py +++ b/svnexternals.py @@ -78,7 +78,6 @@ class BadDefinition(Exception): re_defold = re.compile(r'^(.*?)\s+(?:-r\s*(\d+)\s+)?([a-zA-Z]+://.*)$') re_defnew = re.compile(r'^(?:-r\s*(\d+)\s+)?((?:[a-zA-Z]+://|\^/).*)\s+(.*)$') -re_pegrev = re.compile(r'^(.*)@(\d+)$') re_scheme = re.compile(r'^[a-zA-Z]+://') def parsedefinition(line): @@ -89,19 +88,18 @@ def parsedefinition(line): # potential quotes. svn documentation is not really talkative about # these either. line = line.strip() + pegrev = None m = re_defnew.search(line) if m: rev, source, path = m.group(1, 2, 3) + if '@' in source: + source, pegrev = source.rsplit('@', 1) else: m = re_defold.search(line) if not m: raise BadDefinition() path, rev, source = m.group(1, 2, 3) - # Look for peg revisions - m = re_pegrev.search(source) - if m: - source, rev = m.group(1, 2) - return (path, rev, source) + return (path, rev, source, pegrev) def parsedefinitions(ui, repo, svnroot, exts): """Return (targetdir, revision, source) tuples. Fail if nested @@ -111,7 +109,7 @@ def parsedefinitions(ui, repo, svnroot, for base in sorted(exts): for line in exts[base]: try: - path, rev, source = parsedefinition(line) + path, rev, source, pegrev = parsedefinition(line) except BadDefinition: ui.warn(_('ignoring invalid external definition: %r' % line)) continue @@ -124,7 +122,7 @@ def parsedefinitions(ui, repo, svnroot, continue wpath = hgutil.pconvert(os.path.join(base, path)) wpath = hgutil.canonpath(repo.root, '', wpath) - defs.append((wpath, rev, source)) + defs.append((wpath, rev, source, pegrev)) # Check target dirs are not nested defs.sort() for i, d in enumerate(defs): @@ -189,13 +187,18 @@ class externalsupdater: self.repo = repo self.ui = ui - def update(self, wpath, rev, source): + def update(self, wpath, rev, source, pegrev): path = self.repo.wjoin(wpath) revspec = [] if rev: revspec = ['-r', rev] if os.path.isdir(path): exturl, extroot, extrev = getsvninfo(path) + # Comparing the source paths is not enough, but I don't + # know how to compare path+pegrev. The following update + # might fail if the path was replaced by another unrelated + # one. It can be fixed manually by deleting the externals + # and updating again. if source == exturl: if extrev != rev: self.ui.status(_('updating external on %s@%s\n') % @@ -208,6 +211,10 @@ class externalsupdater: cwd = os.path.join(self.repo.root, cwd) if not os.path.isdir(cwd): os.makedirs(cwd) + if not pegrev and rev: + pegrev = rev + if pegrev: + source = '%s@%s' % (source, pegrev) self.ui.status(_('fetching external %s@%s\n') % (wpath, rev or 'HEAD')) self.svn(['co'] + revspec + [source, dest], cwd) @@ -264,7 +271,7 @@ def updateexternals(ui, args, repo, **op actions = computeactions(ui, repo, svnroot, oldext, newext) for action, ext in actions: if action == 'u': - updater.update(ext[0], ext[1], ext[2]) + updater.update(ext[0], ext[1], ext[2], ext[3]) elif action == 'd': updater.delete(ext[0]) else: diff --git a/tests/fixtures/externals.sh b/tests/fixtures/externals.sh --- a/tests/fixtures/externals.sh +++ b/tests/fixtures/externals.sh @@ -38,13 +38,13 @@ svn ci -m "set externals on ." # Add another one cat > externals < externals <> a +svn ci -m 'change a' cd ../.. svnadmin dump testrepo > ../externals.svndump diff --git a/tests/fixtures/externals.svndump b/tests/fixtures/externals.svndump --- a/tests/fixtures/externals.svndump +++ b/tests/fixtures/externals.svndump @@ -1,6 +1,6 @@ SVN-fs-dump-format-version: 2 -UUID: ab7049d2-24fc-4035-b126-5f7012d66a0d +UUID: ac40e40a-7fbf-47e1-90a7-c1de12a5b013 Revision-number: 0 Prop-content-length: 56 @@ -9,7 +9,7 @@ Content-length: 56 K 8 svn:date V 27 -2009-01-12T23:19:30.150669Z +2009-05-03T14:07:14.149596Z PROPS-END Revision-number: 1 @@ -27,7 +27,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:30.267365Z +2009-05-03T14:07:14.234026Z PROPS-END Node-path: branches @@ -72,7 +72,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:31.232927Z +2009-05-03T14:07:15.135488Z PROPS-END Node-path: externals/project1 @@ -90,6 +90,7 @@ Node-action: add Prop-content-length: 10 Text-content-length: 2 Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3 +Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b Content-length: 12 PROPS-END @@ -111,6 +112,7 @@ Node-action: add Prop-content-length: 10 Text-content-length: 2 Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3 +Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b Content-length: 12 PROPS-END @@ -132,7 +134,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:32.212750Z +2009-05-03T14:07:16.180110Z PROPS-END Node-path: trunk @@ -155,6 +157,7 @@ Node-action: add Prop-content-length: 10 Text-content-length: 2 Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3 +Text-content-sha1: 3f786850e387550fdab836ed7e6dc881de23001b Content-length: 12 PROPS-END @@ -176,20 +179,20 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:33.180250Z +2009-05-03T14:07:17.092210Z PROPS-END Node-path: trunk Node-kind: dir Node-action: change -Prop-content-length: 105 -Content-length: 105 +Prop-content-length: 111 +Content-length: 111 K 13 svn:externals -V 70 +V 76 ^/externals/project1 deps/project1 -^/externals/project2 deps/project2 +-r2 ^/externals/project2@2 deps/project2 PROPS-END @@ -209,19 +212,19 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:34.270854Z +2009-05-03T14:07:18.165337Z PROPS-END Node-path: trunk Node-kind: dir Node-action: change -Prop-content-length: 70 -Content-length: 70 +Prop-content-length: 76 +Content-length: 76 K 13 svn:externals -V 35 -^/externals/project2 deps/project2 +V 41 +-r2 ^/externals/project2@2 deps/project2 PROPS-END @@ -269,7 +272,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:37.185743Z +2009-05-03T14:07:21.092911Z PROPS-END Node-path: branches/branch1 @@ -277,19 +280,6 @@ Node-kind: dir Node-action: add Node-copyfrom-rev: 5 Node-copyfrom-path: trunk -Prop-content-length: 94 -Content-length: 94 - -K 13 -svn:externals -V 35 -^/externals/project2 deps/project2 - -K 13 -svn:mergeinfo -V 0 - -PROPS-END Node-path: branches/branch1/subdir2 @@ -316,7 +306,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:39.198328Z +2009-05-03T14:07:23.097507Z PROPS-END Node-path: branches/branch2 @@ -324,12 +314,8 @@ Node-kind: dir Node-action: add Node-copyfrom-rev: 5 Node-copyfrom-path: trunk -Prop-content-length: 34 -Content-length: 34 - -K 13 -svn:mergeinfo -V 0 +Prop-content-length: 10 +Content-length: 10 PROPS-END @@ -358,7 +344,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:40.183807Z +2009-05-03T14:07:24.086967Z PROPS-END Node-path: trunk/subdir @@ -380,7 +366,7 @@ pmezard K 8 svn:date V 27 -2009-01-12T23:19:41.180477Z +2009-05-03T14:07:25.093557Z PROPS-END Node-path: trunk/subdir2 @@ -392,3 +378,55 @@ Content-length: 10 PROPS-END +Revision-number: 10 +Prop-content-length: 127 +Content-length: 127 + +K 7 +svn:log +V 25 +remove externals project2 +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2009-05-03T14:07:27.088306Z +PROPS-END + +Node-path: externals/project2 +Node-action: delete + + +Revision-number: 11 +Prop-content-length: 109 +Content-length: 109 + +K 7 +svn:log +V 8 +change a +K 10 +svn:author +V 7 +pmezard +K 8 +svn:date +V 27 +2009-05-03T14:07:28.065953Z +PROPS-END + +Node-path: trunk/a +Node-kind: file +Node-action: change +Text-content-length: 4 +Text-content-md5: 0d227f1abf8c2932d342e9b99cc957eb +Text-content-sha1: d7c8127a20a396cff08af086a1c695b0636f0c29 +Content-length: 4 + +a +a + + diff --git a/tests/test_externals.py b/tests/test_externals.py --- a/tests/test_externals.py +++ b/tests/test_externals.py @@ -33,19 +33,19 @@ class TestFetchExternals(test_util.TestB # Taken from svn book samples = [ ('third-party/sounds http://svn.example.com/repos/sounds', - ('third-party/sounds', None, 'http://svn.example.com/repos/sounds')), + ('third-party/sounds', None, 'http://svn.example.com/repos/sounds', None)), ('third-party/skins -r148 http://svn.example.com/skinproj', - ('third-party/skins', '148', 'http://svn.example.com/skinproj')), + ('third-party/skins', '148', 'http://svn.example.com/skinproj', None)), ('third-party/skins -r 148 http://svn.example.com/skinproj', - ('third-party/skins', '148', 'http://svn.example.com/skinproj')), + ('third-party/skins', '148', 'http://svn.example.com/skinproj', None)), ('http://svn.example.com/repos/sounds third-party/sounds', - ('third-party/sounds', None, 'http://svn.example.com/repos/sounds')), + ('third-party/sounds', None, 'http://svn.example.com/repos/sounds', None)), ('-r148 http://svn.example.com/skinproj third-party/skins', - ('third-party/skins', '148', 'http://svn.example.com/skinproj')), + ('third-party/skins', '148', 'http://svn.example.com/skinproj', None)), ('-r 148 http://svn.example.com/skinproj third-party/skins', - ('third-party/skins', '148', 'http://svn.example.com/skinproj')), + ('third-party/skins', '148', 'http://svn.example.com/skinproj', None)), ('http://svn.example.com/skin-maker@21 third-party/skins/toolkit', - ('third-party/skins/toolkit', '21', 'http://svn.example.com/skin-maker')), + ('third-party/skins/toolkit', None, 'http://svn.example.com/skin-maker', '21')), ] for line, expected in samples: @@ -60,12 +60,12 @@ class TestFetchExternals(test_util.TestB self.assertEqual(ref0, repo[0]['.hgsvnexternals'].data()) ref1 = """[.] ^/externals/project1 deps/project1 - ^/externals/project2 deps/project2 + -r2 ^/externals/project2@2 deps/project2 """ self.assertEqual(ref1, repo[1]['.hgsvnexternals'].data()) ref2 = """[.] - ^/externals/project2 deps/project2 + -r2 ^/externals/project2@2 deps/project2 [subdir] ^/externals/project1 deps/project1 [subdir2] @@ -75,7 +75,7 @@ class TestFetchExternals(test_util.TestB self.assertEqual(ref2, actual) ref3 = """[.] - ^/externals/project2 deps/project2 + -r2 ^/externals/project2@2 deps/project2 [subdir] ^/externals/project1 deps/project1 """ @@ -87,14 +87,14 @@ class TestFetchExternals(test_util.TestB self.assertEqual(ref4, repo[4]['.hgsvnexternals'].data()) ref5 = """[.] - ^/externals/project2 deps/project2 + -r2 ^/externals/project2@2 deps/project2 [subdir2] ^/externals/project1 deps/project1 """ self.assertEqual(ref5, repo[5]['.hgsvnexternals'].data()) ref6 = """[.] - ^/externals/project2 deps/project2 + -r2 ^/externals/project2@2 deps/project2 """ self.assertEqual(ref6, repo[6]['.hgsvnexternals'].data())