changeset 159:85eae64ca9e2

applied octopatch from dimichxp
author Scott Chacon <schacon@gmail.com>
date Wed, 27 May 2009 17:14:41 -0700
parents 2fa3ac775983
children 3dc1ba5fec31
files git_handler.py
diffstat 1 files changed, 69 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/git_handler.py	Tue May 19 10:00:56 2009 -0700
+++ b/git_handler.py	Wed May 27 17:14:41 2009 -0700
@@ -201,6 +201,12 @@
         for i, rev in enumerate(self.repo.changelog):
             if i%100 == 0:
                 self.ui.status(_("at: %*d/%d\n") % (magnitude, i, total))
+            
+            ctx = self.repo.changectx(rev)
+            state = ctx.extra().get('hg-git', None)
+            if state == 'octopus':
+                self.ui.debug("revision %d is a part of octopus explosion\n" % rev)
+                continue
             pgit_sha, already_written = self.export_hg_commit(rev)
             if not already_written:
                 self.save_map()
@@ -209,6 +215,9 @@
     # go through the manifest, convert all blobs/trees we don't have
     # write the commit object (with metadata info)
     def export_hg_commit(self, rev):
+        def is_octopus_part(ctx):
+            return ctx.extra().get('hg-git', None) in set(['octopus', 'octopus-done'])
+
         # return if we've already processed this
         node = self.repo.changelog.lookup(rev)
         phgsha = hex(node)
@@ -219,7 +228,22 @@
         self.ui.status(_("converting revision %s\n") % str(rev))
 
         # make sure parents are converted first
-        parents = self.repo.parents(rev)
+        ctx = self.repo.changectx(rev)
+        extra = ctx.extra()
+
+        parents = []
+        if extra.get('hg-git', None) == 'octopus-done':
+            # implode octopus parents
+            part = ctx
+            while is_octopus_part(part):
+                (p1, p2) = part.parents()
+                assert not is_octopus_part(p1)
+                parents.append(p1)
+                part = p2
+            parents.append(p2)
+        else:
+            parents = ctx.parents()
+
         for parent in parents:
             p_rev = parent.rev()
             hgsha = hex(parent.node())
@@ -228,7 +252,6 @@
                 if not git_sha:
                     self.export_hg_commit(p_rev)
 
-        ctx = self.repo.changectx(rev)
         tree_sha, renames = self.write_git_tree(ctx)
         
         commit = {}
@@ -243,7 +266,6 @@
         message = ctx.description()
         commit['message'] = ctx.description() + "\n"
 
-        extra = ctx.extra()
         if 'committer' in extra:
             # fixup timezone
             (name_timestamp, timezone) = extra['committer'].rsplit(' ', 1)
@@ -528,10 +550,16 @@
     def update_hg_bookmarks(self, remote_name):
         try:
             bms = bookmarks.parse(self.repo)
-            for head, sha in self.git.remote_refs(remote_name).iteritems():
+            if remote_name:
+                template = remote_name+'/%s'
+                refs = self.git.remote_refs(remote_name)
+            else:
+                template = '%s'
+                refs = self.git.heads()
+            for head, sha in refs.iteritems():
                 hgsha = hex_to_sha(self.map_hg_get(sha))
                 if not head == 'HEAD':
-                    bms[remote_name + '/' + head] = hgsha
+                    bms[template % head] = hgsha
             bookmarks.write(self.repo, bms)
         except AttributeError:
             self.ui.warn(_('creating bookmarks failed, do you have'
@@ -599,6 +627,12 @@
         
         (strip_message, hg_renames, hg_branch) = self.extract_hg_metadata(commit.message)
         
+        # get a list of the changed, added, removed files
+        files = self.git.get_files_changed(commit)
+
+        date = (commit.author_time, -commit.author_timezone)
+        text = strip_message
+
         def getfilectx(repo, memctx, f):
             try:
                 (mode, sha, data) = self.git.get_file(commit, f)
@@ -611,27 +645,32 @@
                 copied_path = None
             return context.memfilectx(f, data, 'l' in e, 'x' in e, copied_path)
 
-        p1 = nullid
-        p2 = nullid
-        if len(commit.parents) > 0:
-            sha = commit.parents[0]
-            p1 = self.map_hg_get(sha)
-        if len(commit.parents) > 1:
-            sha = commit.parents[1]
-            p2 = self.map_hg_get(sha)
-        if len(commit.parents) > 2:
-            # TODO : map extra parents to the extras file
-            pass
+        gparents = map(self.map_hg_get, commit.parents)
+        p1, p2 = (nullid, nullid)
+        octopus = False
+
+        if len(gparents) > 1:
+            # merge, possibly octopus
+            def commit_octopus(p1, p2):
+                ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx,
+                                     commit.author, date, {'hg-git': 'octopus'})
+                return hex(self.repo.commitctx(ctx))
 
-        # get a list of the changed, added, removed files
-        files = self.git.get_files_changed(commit)
+            octopus = len(gparents) > 2
+            p2 = gparents.pop()
+            p1 = gparents.pop()
+            while len(gparents) > 0:
+                p2 = commit_octopus(p1, p2)
+                p1 = gparents.pop()
+        else:
+            if gparents:
+                p1 = gparents.pop()
 
-        # wierd hack for explicit file renames in first but not second branch
-        if not (p2 == nullid):
-            vals = [item for item in self.renames[p1].values() if not item in self.renames[p2].values()]
-            for removefile in vals:
-                files.remove(removefile)
-            
+            # wierd hack for explicit file renames in first but not second branch
+            if not (p2 == nullid):
+                vals = [item for item in self.renames[p1].values() if not item in self.renames[p2].values()]
+                for removefile in vals:
+                    files.remove(removefile)
         extra = {}
 
         # if named branch, add to extra
@@ -648,16 +687,16 @@
         if hg_branch:
             extra['branch'] = hg_branch
 
-        text = strip_message
-        date = (commit.author_time, -commit.author_timezone)
+        if octopus:
+            extra['hg-git'] ='octopus-done'
+
         ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx,
                              commit.author, date, extra)
-        a = self.repo.commitctx(ctx)
+        node = self.repo.commitctx(ctx)
 
-        # get changeset id
-        cs = hex(self.repo.changelog.tip())
         # save changeset to mapping file
-        gitsha = commit.id
+        cs = hex(node)
+        self.map_set(commit.id, cs)
         
         # saving rename info
         if (not (p2 == nullid) or (p1 == nullid)):
@@ -667,7 +706,6 @@
             
         self.renames[cs].update(hg_renames)
         
-        self.map_set(gitsha, cs)
 
     def check_bookmarks(self):
         if self.ui.config('extensions', 'hgext.bookmarks') is not None: