diff wrappers.py @ 331:75f082b5897e

Switch to using url scheme wrappers instead of duplicating each command we wrap. The 'hg svn url' command has been killed; the replacement is '.hg/hgrc'. More stuff related to its disappearance has been stripped, including two tests. HgChangeReceiver now takes a UUID argument, which it uses to ensure that remote repositories remain unchanged. This is a temporary solution, and I'm not entirely satisfied with how it's done either. Access to the UUID file has been isolated in a HgChangeReceiver property. Some more tests have been updated to use ui.pushbuffer()/popbuffer(), and to pass through the Mercurial API. Moved the arguments to wrappers.pull() to the UI configuration. Also, remove HgChangeReceiver.opts in favour of a 'usebranchnames' instance & configuration variable. The name is taken from the ConvertExtension.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Fri, 15 May 2009 19:18:43 +0200
parents 235022089da6
children
line wrap: on
line diff
--- a/wrappers.py
+++ b/wrappers.py
@@ -87,24 +87,36 @@ def diff(orig, ui, repo, *args, **opts):
                                                   }))
     ui.write(cmdutil.filterdiff(''.join(it), baserev, newrev))
 
-
-def push(orig, ui, repo, dest=None, *args, **opts):
+def push(repo, dest="default", force=False, revs=None):
     """push revisions starting at a specified head back to Subversion.
     """
-    opts.pop('svn', None) # unused in this case
-    svnurl = repo.ui.expandpath(dest or 'default-push', dest or 'default')
-    if not cmdutil.issvnurl(svnurl):
-        return orig(ui, repo, dest=dest, *args, **opts)
+    assert not revs, 'designated revisions for push remains unimplemented.'
+    print dest
+    ui = repo.ui
+    svnurl = util.normalize_url(repo.ui.expandpath(dest))
     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(),
-                                 hge.revmap.iterkeys()))
-    user, passwd = util.getuserpass(opts)
+    svnurl, revs, checkout = hg.parseurl(svnurl, revs)
+    # TODO: do credentials specified in the URL still work?
+    user = repo.ui.config('hgsubversion', 'username')
+    passwd = repo.ui.config('hgsubversion', 'password')
+    svn = svnwrap.SubversionRepo(svnurl, user, passwd)
+    hge = hg_delta_editor.HgChangeReceiver(repo=repo, uuid=svn.uuid)
+
+    # Check if we are up-to-date with the Subversion repository.
+    if hge.last_known_revision() != svn.last_changed_rev:
+        # Based on localrepository.push() in localrepo.py:1559. 
+        # TODO: Ideally, we would behave exactly like other repositories:
+        #  - push everything by default
+        #  - handle additional heads in the same way
+        #  - allow pushing single revisions, branches, tags or heads using
+        #    the -r/--rev flag.
+        if force:
+            ui.warn("note: unsynced remote changes!\n")
+        else:
+            ui.warn("abort: unsynced remote changes!\n")
+            return None, 0
+
     # Strategy:
     # 1. Find all outgoing commits from this head
     if len(repo.parents()) != 1:
@@ -112,6 +124,8 @@ def push(orig, ui, repo, dest=None, *arg
         return 1
     workingrev = repo.parents()[0]
     ui.status('searching for changes\n')
+    svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
+                                 hge.revmap.iterkeys()))
     outgoing = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, workingrev.node())
     if not (outgoing and len(outgoing)):
         ui.status('no changes found\n')
@@ -143,12 +157,10 @@ def push(orig, ui, repo, dest=None, *arg
                      old_ctx)
             return 1
         # 3. Fetch revisions from svn
-        # TODO this probably should pass in the source explicitly
-        r = pull(None, ui, repo, svn=True, stupid=opts.get('svn_stupid', False),
-                 username=user, password=passwd)
+        # TODO: this probably should pass in the source explicitly - rev too?
+        r = pull(repo, source=dest, force=force)
         assert not r or r == 0
         # 4. Find the new head of the target branch
-        repo = hg.repository(ui, hge.path)
         oldtipctx = repo[oldtip]
         replacement = [c for c in oldtipctx.children() if c not in old_children
                        and c.branch() == oldtipctx.branch()]
@@ -161,8 +173,9 @@ def push(orig, ui, repo, dest=None, *arg
                 if ctx.node() == oldest:
                     return
                 extra['branch'] = ctx.branch()
+            # TODO: can we avoid calling our own rebase wrapper here?
             rebase(hgrebase.rebase, ui, repo, svn=True, svnextrafn=extrafn,
-                   svnsourcerev=needs_transplant, **opts)
+                   svnsourcerev=needs_transplant)
             repo = hg.repository(ui, hge.path)
             for child in repo[replacement.node()].children():
                 rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid)))
@@ -175,7 +188,8 @@ def push(orig, ui, repo, dest=None, *arg
                         if children:
                             child = children[0]
                         rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid)))
-        hge = hg_delta_editor.HgChangeReceiver(hge.path, ui_=ui)
+        # TODO: stop constantly creating the HgChangeReceiver instances.
+        hge = hg_delta_editor.HgChangeReceiver(hge.repo, ui_=ui, uuid=svn.uuid)
         svn_commit_hashes = dict(zip(hge.revmap.itervalues(), hge.revmap.iterkeys()))
     util.swap_out_encoding(old_encoding)
     return 0
@@ -234,25 +248,20 @@ def clone(orig, ui, source, dest=None, *
     return res
 
 
-def pull(orig, ui, repo, source="default", *args, **opts):
+def pull(repo, source="default", rev=None, force=False):
     """pull new revisions from Subversion
 
     Also takes svn, svn_stupid, and create_new_dest kwargs.
     """
-    svn = opts.pop('svn', None)
-    svn_stupid = opts.pop('svn_stupid', False)
-    create_new_dest = opts.pop('create_new_dest', False)
-    url = ((repo and repo.ui) or ui).expandpath(source)
-    if orig and not (cmdutil.issvnurl(url) or svn or create_new_dest):
-        return orig(ui, repo, source=source, *args, **opts)
-    svn_url = url
-    svn_url = util.normalize_url(svn_url)
+    url = repo.ui.expandpath(source)
+    svn_url = util.normalize_url(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'))
+    svn_url, revs, checkout = hg.parseurl(svn_url, rev)
     old_encoding = util.swap_out_encoding()
     # TODO implement skipto support
     skipto_rev = 0
-    have_replay = not svn_stupid
+    have_replay = not repo.ui.configbool('hgsubversion', 'stupid')
     if have_replay and not callable(
         delta.svn_txdelta_apply(None, None, None)[0]): #pragma: no cover
         ui.status('You are using old Subversion SWIG bindings. Replay will not'
@@ -261,46 +270,23 @@ def pull(orig, ui, repo, source="default
                   ' contribute a patch to use the ctypes bindings instead'
                   ' of SWIG.\n')
         have_replay = False
-    initializing_repo = False
-    user, passwd = util.getuserpass(opts)
+
+    # FIXME: enable this
+    user = repo.ui.config('hgsubversion', 'username')
+    passwd = repo.ui.config('hgsubversion', 'password')
     svn = svnwrap.SubversionRepo(svn_url, user, passwd)
-    author_host = ui.config('hgsubversion', 'defaulthost', svn.uuid)
-    tag_locations = ['tags', ]
-    authors = opts.pop('svn_authors', None)
-    filemap = opts.pop('svn_filemap', None)
-    if repo:
-        hg_editor = hg_delta_editor.HgChangeReceiver(repo=repo,
-                                                     subdir=svn.subdir,
-                                                     author_host=author_host,
-                                                     tag_locations=tag_locations,
-                                                     authors=authors,
-                                                     filemap=filemap)
-    else:
-        hg_editor = hg_delta_editor.HgChangeReceiver(ui_=ui,
-                                                     path=create_new_dest,
-                                                     subdir=svn.subdir,
-                                                     author_host=author_host,
-                                                     tag_locations=tag_locations,
-                                                     authors=authors,
-                                                     filemap=filemap)
-    hg_editor.opts = opts
-    if os.path.exists(hg_editor.uuid_file):
-        uuid = open(hg_editor.uuid_file).read()
-        assert uuid == svn.uuid
-        start = hg_editor.last_known_revision()
-    else:
-        open(hg_editor.uuid_file, 'w').write(svn.uuid)
-        open(hg_editor.svn_url_file, 'w').write(svn_url)
-        initializing_repo = True
-        start = skipto_rev
+    hg_editor = hg_delta_editor.HgChangeReceiver(repo=repo, subdir=svn.subdir,
+                                                 uuid=svn.uuid)
+
+    start = max(hg_editor.last_known_revision(), skipto_rev)
+    initializing_repo = (hg_editor.last_known_revision() <= 0)
+    ui = repo.ui
 
     if initializing_repo and start > 0:
         raise hgutil.Abort('Revision skipping at repository initialization '
                            'remains unimplemented.')
 
     revisions = 0
-    if not initializing_repo:
-        oldheads = len(repo.changelog.heads())
 
     # start converting revisions
     for r in svn.revisions(start=start):
@@ -344,14 +330,6 @@ def pull(orig, ui, repo, source="default
         return
     else:
         ui.status("added %d svn revisions\n" % revisions)
-    if not initializing_repo:
-        newheads = len(repo.changelog.heads())
-        # postincoming needs to know if heads were added or removed
-        # 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'), checkout)
-
 
 def rebase(orig, ui, repo, **opts):
     """rebase current unpushed revisions onto the Subversion head