# HG changeset patch # User Martijn Pieters # Date 1240843179 18000 # Node ID f8f9a29937057b78847d32570a0954993a7af715 # Parent 521d9c1bb11d459eecebb102050ed3c5c2fc6186 Implement parseurl support (#revision in repository urls) Note: Normally when using parseurl, hg clone will treat the revision after # as if it was passed in as --rev, treats that rev as a head and won't clone beyond that. This wasn't implemented here, hence all the TODO's in the comments. All we do is use the checkout parameter where appropriate to update the wc to the selected revision. diff --git a/cmdutil.py b/cmdutil.py --- a/cmdutil.py +++ b/cmdutil.py @@ -284,6 +284,8 @@ def commit_from_rev(ui, repo, rev_ctx, h def islocalrepo(url): if not url.startswith('file:///'): return False + if '#' in url.split('/')[-1]: # strip off #anchor + url = url[:url.rfind('#')] path = urllib.unquote(url[len('file://'):]) while '/' in path: if reduce(lambda x,y: x and y, diff --git a/tests/test_fetch_branches.py b/tests/test_fetch_branches.py --- a/tests/test_fetch_branches.py +++ b/tests/test_fetch_branches.py @@ -1,8 +1,11 @@ import unittest +from mercurial import hg from mercurial import node +from mercurial import ui import test_util +import wrappers class TestFetchBranches(test_util.TestBase): @@ -11,6 +14,12 @@ class TestFetchBranches(test_util.TestBa self.wc_path, stupid=stupid, noupdate=noupdate) + def _load_fixture_and_fetch_with_anchor(self, fixture_name, anchor): + test_util.load_svndump_fixture(self.repo_path, fixture_name) + source = '%s#%s' % (test_util.fileurl(self.repo_path), anchor) + wrappers.clone(None, ui.ui(), source=source, dest=self.wc_path) + return hg.repository(ui.ui(), self.wc_path) + def test_unrelatedbranch(self, stupid=False): repo = self._load_fixture_and_fetch('unrelatedbranch.svndump', stupid) heads = [repo[n] for n in repo.heads()] @@ -68,6 +77,12 @@ class TestFetchBranches(test_util.TestBa def test_branch_tip_update_to_default_stupid(self): self.test_branch_tip_update_to_default(True) + + def test_branch_tip_update_to_branch_anchor(self): + repo = self._load_fixture_and_fetch_with_anchor( + 'unorderedbranch.svndump', 'branch') + self.assertEqual(repo[None].branch(), 'branch') + self.assertEqual(repo[None].parents()[0], repo[repo.branchheads()[0]]) def suite(): all = [unittest.TestLoader().loadTestsFromTestCase(TestFetchBranches), diff --git a/util.py b/util.py --- a/util.py +++ b/util.py @@ -26,7 +26,11 @@ def version(ui): def normalize_url(svnurl): if svnurl.startswith('svn+http'): svnurl = svnurl[4:] - return svnurl.rstrip('/') + url, revs, checkout = hg.parseurl(svnurl) + url = url.rstrip('/') + if checkout: + url = '%s#%s' % (url, checkout) + return url REVMAP_FILE_VERSION = 1 diff --git a/wrappers.py b/wrappers.py --- a/wrappers.py +++ b/wrappers.py @@ -42,6 +42,8 @@ def outgoing(orig, ui, repo, dest=None, if not (cmdutil.issvnurl(svnurl) or opts.get('svn', False)): return orig(ui, repo, dest, *args, **opts) + # split off #rev; TODO implement --revision/#rev support + svnurl, revs, checkout = hg.parseurl(svnurl, opts.get('rev')) hge = hg_delta_editor.HgChangeReceiver(repo=repo) svn_commit_hashes = dict(zip(hge.revmap.itervalues(), hge.revmap.iterkeys())) @@ -96,6 +98,8 @@ def push(orig, ui, repo, dest=None, *arg old_encoding = util.swap_out_encoding() hge = hg_delta_editor.HgChangeReceiver(repo=repo) svnurl = util.normalize_url(svnurl) + # split of #rev; TODO: implement --rev/#rev support + svnurl, revs, checkout = hg.parseurl(svnurl, opts.get('rev')) if svnurl != hge.url: raise hgutil.Abort('wrong subversion url!') svn_commit_hashes = dict(zip(hge.revmap.itervalues(), @@ -191,7 +195,7 @@ def clone(orig, ui, source, dest=None, * return orig(ui, source=source, dest=dest, *args, **opts) if not dest: - dest = hg.defaultdest(source) + '-hg' + dest = hg.defaultdest(hg.parseurl(source)[0]) + '-hg' ui.status("Assuming destination %s\n" % dest) if os.path.exists(dest): @@ -217,7 +221,9 @@ def clone(orig, ui, source, dest=None, * fp.write("default = %(url)s\nsvn = %(url)s\n" % {'url': svnurl}) fp.close() if (res is None or res == 0) and not opts.get('noupdate', False): - for test in ('default', 'tip'): + # Split off #rev + url, revs, checkout = hg.parseurl(svnurl) + for test in (checkout, 'default', 'tip'): try: uprev = repo.lookup(test) break @@ -241,6 +247,8 @@ def pull(orig, ui, repo, source="default return orig(ui, repo, source=source, *args, **opts) svn_url = url svn_url = util.normalize_url(svn_url) + # Split off #rev; TODO: implement --rev/#rev support limiting the pulled/cloned revisions + svn_url, revs, checkout = hg.parseurl(svn_url, opts.get('rev')) old_encoding = util.swap_out_encoding() # TODO implement skipto support skipto_rev = 0 @@ -341,7 +349,7 @@ def pull(orig, ui, repo, source="default # calculation based on mercurial.localrepo.addchangegroup # 0 means no changes, 1 no new heads, > 1 new heads, < 0 heads removed modheads = newheads - oldheads + (newheads < oldheads and -1 or 1) - commands.postincoming(ui, repo, modheads, opts.get('update'), None) + commands.postincoming(ui, repo, modheads, opts.get('update'), checkout) def rebase(orig, ui, repo, **opts):