changeset 713:69c0e7c4faf9

clone: call the wrapped function (fixes #181) This is a regression that was brought to my attention in #mercurial: hgsubversion breaks the --update flag. The cause is that we call hg.clone() directly rather than the original wrapped function. A comment in 'wrapper.py' noted that the call to hg.clone() should be kept in sync with 'mercurial/commands.py'. That didn't happen. The original reason for calling hg.clone() directly was that we needed its return values. Another wrapper is added (and cleared) within clone() to get them anyway.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Wed, 29 Sep 2010 18:04:26 +0200
parents 1041fb1bec8c
children 7e55483a56ca
files hgsubversion/wrappers.py tests/run.py tests/test_unaffected_core.py
diffstat 3 files changed, 115 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/wrappers.py
+++ b/hgsubversion/wrappers.py
@@ -6,6 +6,7 @@ from mercurial import hg
 from mercurial import util as hgutil
 from mercurial import node
 from mercurial import i18n
+from mercurial import extensions
 
 import replay
 import pushmod
@@ -417,20 +418,39 @@ def clone(orig, ui, source, dest=None, *
     them as well as other ways of customising the conversion process.
     """
 
-    branch = opts.get('branch', None)
-    if branch:
-        ui.setconfig('hgsubversion', 'branch', branch[-1])
+    data = {}
+    def hgclonewrapper(orig, ui, origsource, dest, **opts):
+        if isinstance(origsource, str):
+            source, branch, checkout = util.parseurl(ui.expandpath(origsource),
+                                         opts.get('branch'))
+            srcrepo = hg.repository(ui, source)
+        else:
+            srcrepo = origsource
+
+        if srcrepo.capable('subversion'):
+            branches = opts.pop('branch', None)
+            if branches:
+                data['branches'] = branches
+                ui.setconfig('hgsubversion', 'branch', branches[-1])
+
+        data['srcrepo'], data['dstrepo'] = orig(ui, origsource, dest, **opts)
 
     for opt, (section, name) in optionmap.iteritems():
         if opt in opts and opts[opt]:
             ui.setconfig(section, name, str(opts.pop(opt)))
 
-    # this must be kept in sync with mercurial/commands.py
-    srcrepo, dstrepo = hg.clone(util.remoteui(ui, opts), source, dest,
-                                pull=opts.get('pull'),
-                                stream=opts.get('uncompressed'),
-                                rev=opts.get('rev'),
-                                update=not opts.get('noupdate'))
+    # calling hg.clone directoly to get the repository instances it returns,
+    # breaks in subtle ways, so we double-wrap
+    orighgclone = extensions.wrapfunction(hg, 'clone', hgclonewrapper)
+    orig(ui, source, dest, **opts)
+    hg.clone = orighgclone
+
+    # do this again; the ui instance isn't shared between the wrappers
+    if data.get('branches'):
+        ui.setconfig('hgsubversion', 'branch', data['branches'][-1])
+
+    dstrepo = data.get('dstrepo')
+    srcrepo = data.get('srcrepo')
 
     if dstrepo.local() and srcrepo.capable('subversion'):
         fd = dstrepo.opener("hgrc", "a", text=True)
--- a/tests/run.py
+++ b/tests/run.py
@@ -27,6 +27,7 @@ def tests():
     import test_tags
     import test_template_keywords
     import test_utility_commands
+    import test_unaffected_core
     import test_urls
 
     sys.path.append(os.path.dirname(__file__))
new file mode 100644
--- /dev/null
+++ b/tests/test_unaffected_core.py
@@ -0,0 +1,85 @@
+import test_util
+
+import os
+import unittest
+
+from mercurial import commands
+from mercurial import dispatch
+from mercurial import error
+from mercurial import hg
+from mercurial import node
+from mercurial import ui
+
+class TestMercurialCore(test_util.TestBase):
+    '''
+    Test that the core Mercurial operations aren't broken by hgsubversion.
+    '''
+
+    @test_util.requiresoption('updaterev')
+    def test_update(self):
+        ''' Test 'clone --updaterev' '''
+        ui = self.ui()
+        dispatch._dispatch(ui, ['init', self.wc_path])
+        repo = self.repo
+        repo.ui.setconfig('ui', 'username', 'anonymous')
+
+        fpath = os.path.join(self.wc_path, 'it')
+        f = file(fpath, 'w')
+        f.write('C1')
+        f.flush()
+        commands.add(ui, repo)
+        commands.commit(ui, repo, message="C1")
+        f.write('C2')
+        f.flush()
+        commands.commit(ui, repo, message="C2")
+        f.write('C3')
+        f.flush()
+        commands.commit(ui, repo, message="C3")
+
+        self.assertEqual(len(repo), 3)
+
+        updaterev = 1
+        dispatch._dispatch(ui, ['clone', self.wc_path, self.wc_path + '2',
+                                '--updaterev=%s' % updaterev])
+
+        repo2 = hg.repository(ui, self.wc_path + '2')
+
+        self.assertEqual(str(repo[updaterev]), str(repo2['.']))
+
+    @test_util.requiresoption('branch')
+    def test_branch(self):
+        ''' Test 'clone --branch' '''
+        ui = self.ui()
+        dispatch._dispatch(ui, ['init', self.wc_path])
+        repo = self.repo
+        repo.ui.setconfig('ui', 'username', 'anonymous')
+
+        fpath = os.path.join(self.wc_path, 'it')
+        f = file(fpath, 'w')
+        f.write('C1')
+        f.flush()
+        commands.add(ui, repo)
+        commands.branch(ui, repo, label="B1")
+        commands.commit(ui, repo, message="C1")
+        f.write('C2')
+        f.flush()
+        commands.branch(ui, repo, label="default")
+        commands.commit(ui, repo, message="C2")
+        f.write('C3')
+        f.flush()
+        commands.branch(ui, repo, label="B2")
+        commands.commit(ui, repo, message="C3")
+
+        self.assertEqual(len(repo), 3)
+
+        branch = 'B1'
+        dispatch._dispatch(ui, ['clone', self.wc_path, self.wc_path + '2',
+                                '--branch', branch])
+
+        repo2 = hg.repository(ui, self.wc_path + '2')
+
+        self.assertEqual(repo[branch].hex(), repo2['.'].hex())
+
+def suite():
+    all = [unittest.TestLoader().loadTestsFromTestCase(TestMercurialCore)]
+    return unittest.TestSuite(all)