changeset 152:1fde85a10f9e

push: Fix the bad implementation that required modifying the dirstate to push.
author Augie Fackler <durin42@gmail.com>
date Mon, 22 Dec 2008 21:22:11 -0600
parents 2decec74ad0c
children 46f6b872c988
files diff_cmd.py push_cmd.py util.py utility_commands.py
diffstat 4 files changed, 42 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/diff_cmd.py
+++ b/diff_cmd.py
@@ -32,8 +32,8 @@ def diff_command(ui, repo, hg_repo_path,
                                            ui_=ui)
     svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
                                  hge.revmap.iterkeys()))
-    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
     parent = repo.parents()[0]
+    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, parent.node())
     if o_r:
         parent = repo[o_r[-1]].parents()[0]
     base_rev, _junk = svn_commit_hashes[parent.node()]
--- a/push_cmd.py
+++ b/push_cmd.py
@@ -24,13 +24,14 @@ def push_revisions_to_subversion(ui, rep
                                  hge.revmap.iterkeys()))
     # Strategy:
     # 1. Find all outgoing commits from this head
-    outgoing = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
-    if not (outgoing and len(outgoing)):
-        ui.status('No revisions to push.')
-        return 0
     if len(repo.parents()) != 1:
         ui.status('Cowardly refusing to push branch merge')
         return 1
+    workingrev = repo.parents()[0]
+    outgoing = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, workingrev.node())
+    if not (outgoing and len(outgoing)):
+        ui.status('No revisions to push.')
+        return 0
     while outgoing:
         oldest = outgoing.pop(-1)
         old_ctx = repo[oldest]
@@ -69,14 +70,22 @@ def push_revisions_to_subversion(ui, rep
                 if ctx.node() == oldest:
                     return
                 extra['branch'] = ctx.branch()
-            hg.clean(repo, needs_transplant)
-            utility_commands.rebase_commits(ui, repo, hg_repo_path, extrafn=extrafn, **opts)
+            utility_commands.rebase_commits(ui, repo, hg_repo_path,
+                                            extrafn=extrafn,
+                                            sourcerev=needs_transplant,
+                                            **opts)
             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)))
                 if rebasesrc in outgoing:
-                    rebsrcindex = outgoing.index(rebasesrc)
-                    outgoing = outgoing[0:rebsrcindex] + [child.node(), ] + outgoing[rebsrcindex+1:]
+                    while rebasesrc in outgoing:
+                        rebsrcindex = outgoing.index(rebasesrc)
+                        outgoing = (outgoing[0:rebsrcindex] +
+                                    [child.node(), ] + outgoing[rebsrcindex+1:])
+                        children = [c for c in child.children() if c.branch() == child.branch()]
+                        if children:
+                            child = children[0]
+                        rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid)))
         hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, ui_=ui)
         svn_commit_hashes = dict(zip(hge.revmap.itervalues(), hge.revmap.iterkeys()))
     merc_util._encoding = oldencoding
--- a/util.py
+++ b/util.py
@@ -82,23 +82,21 @@ class PrefixMatch(object):
     def __call__(self, fn):
         return fn.startswith(self.p)
 
-def outgoing_revisions(ui, repo, hg_editor, reverse_map):
+def outgoing_revisions(ui, repo, hg_editor, reverse_map, sourcerev):
     """Given a repo and an hg_editor, determines outgoing revisions for the
     current working copy state.
     """
     outgoing_rev_hashes = []
-    working_rev = repo.parents()
-    assert len(working_rev) == 1
-    working_rev = working_rev[0]
-    if working_rev.node() in reverse_map:
+    if sourcerev in reverse_map:
         return
-    while (not working_rev.node() in reverse_map
-           and working_rev.node() != node.nullid):
-        outgoing_rev_hashes.append(working_rev.node())
-        working_rev = working_rev.parents()
-        assert len(working_rev) == 1
-        working_rev = working_rev[0]
-    if working_rev.node() != node.nullid:
+    sourcerev = repo[sourcerev]
+    while (not sourcerev.node() in reverse_map
+           and sourcerev.node() != node.nullid):
+        outgoing_rev_hashes.append(sourcerev.node())
+        sourcerev = sourcerev.parents()
+        assert len(sourcerev) == 1
+        sourcerev = sourcerev[0]
+    if sourcerev.node() != node.nullid:
         return outgoing_rev_hashes
 
 
--- a/utility_commands.py
+++ b/utility_commands.py
@@ -23,11 +23,11 @@ def run_svn_info(ui, repo, hg_repo_path,
                                            ui_=ui)
     svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
                                  hge.revmap.iterkeys()))
-    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
-    ha = repo.parents()[0]
+    workingctx = repo.parents()[0]
+    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, workingctx.node())
     if o_r:
-        ha = repo[o_r[-1]].parents()[0]
-    r, br = svn_commit_hashes[ha.node()]
+        workingctx = repo[o_r[-1]].parents()[0]
+    r, br = svn_commit_hashes[workingctx.node()]
     if br == None:
         branchpath = '/trunk'
     else:
@@ -36,7 +36,7 @@ def run_svn_info(ui, repo, hg_repo_path,
     if url[-1] == '/':
         url = url[:-1]
     url = '%s%s' % (url, branchpath)
-    author = '@'.join(ha.user().split('@')[:-1])
+    author = '@'.join(workingctx.user().split('@')[:-1])
     ui.status('''URL: %(url)s
 Repository Root: %(reporoot)s
 Repository UUID: %(uuid)s
@@ -51,7 +51,7 @@ Last Changed Date: %(date)s\n''' %
                'author': author,
                'revision': r,
                # TODO I'd like to format this to the user's local TZ if possible
-               'date': mutil.datestr(ha.date(),
+               'date': mutil.datestr(workingctx.date(),
                                      '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
               })
 
@@ -65,7 +65,7 @@ def print_parent_revision(ui, repo, hg_r
     svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
                                  hge.revmap.iterkeys()))
     ha = repo.parents()[0]
-    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
+    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, ha.node())
     if o_r:
         ha = repo[o_r[-1]].parents()[0]
     if ha.node() != node.nullid:
@@ -78,7 +78,7 @@ def print_parent_revision(ui, repo, hg_r
 
 
 @util.register_subcommand('rebase')
-def rebase_commits(ui, repo, hg_repo_path, extrafn=None, **opts):
+def rebase_commits(ui, repo, hg_repo_path, extrafn=None, sourcerev=None, **opts):
     """Rebases current unpushed revisions onto Subversion head
 
     This moves a line of development from making its own head to the top of
@@ -92,15 +92,17 @@ def rebase_commits(ui, repo, hg_repo_pat
             """
             extra['branch'] = ctx.branch()
         extrafn = extrafn2
+    if sourcerev is None:
+        sourcerev = repo.parents()[0].node()
     hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
                                            ui_=ui)
     svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
                                  hge.revmap.iterkeys()))
-    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
+    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, sourcerev=sourcerev)
     if not o_r:
         ui.status('Nothing to rebase!\n')
         return 0
-    if len(repo.parents()[0].children()):
+    if len(repo[sourcerev].children()):
         ui.status('Refusing to rebase non-head commit like a coward\n')
         return 0
     parent_rev = repo[o_r[-1]].parents()[0]
@@ -121,7 +123,7 @@ def rebase_commits(ui, repo, hg_repo_pat
         return 0
     # TODO this is really hacky, there must be a more direct way
     return rebase.rebase(ui, repo, dest=node.hex(target_rev.node()),
-                         base=node.hex(repo.parents()[0].node()),
+                         base=node.hex(sourcerev),
                          extrafn=extrafn)
 
 
@@ -133,7 +135,7 @@ def show_outgoing_to_svn(ui, repo, hg_re
                                            ui_=ui)
     svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
                                  hge.revmap.iterkeys()))
-    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes)
+    o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, repo.parents()[0])
     if not (o_r and len(o_r)):
         ui.status('No outgoing changes found.\n')
         return 0