chiark / gitweb /
Implement fast-forward when only tree (but not
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Fri, 16 Sep 2005 19:35:20 +0000 (21:35 +0200)
committerCatalin Marinas <catalin.marinas@gmail.com>
Sat, 17 Sep 2005 07:56:05 +0000 (08:56 +0100)
From: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>

When the "bottom" commit and the HEAD don't match, but they refer to the
same tree (for instance after a refresh where only the description
changed), we can still fast-forward, by keeping the same top tree and
calling git-commit-tree (which only requires the tree object) with the new
parent. I've altered git.commit to allow this.

Btw, I've also avoided the use of .commitmsg and switched to piping the
description.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
stgit/git.py
stgit/stack.py

index 26616229f13aac98deb71347b8c2bd6341a1e7e3..9ad6f0d18241893750954bb1f7f440880d09406f 100644 (file)
@@ -126,8 +126,12 @@ def _output(cmd):
         raise GitException, '%s failed' % str(cmd)
     return string
 
-def _output_one_line(cmd):
+def _output_one_line(cmd, file_desc = None):
     p=popen2.Popen3(cmd)
+    if file_desc != None:
+        for line in file_desc:
+            p.tochild.write(line)
+        p.tochild.close()
     string = p.fromchild.readline().strip()
     if p.wait():
         raise GitException, '%s failed' % str(cmd)
@@ -297,7 +301,7 @@ def update_cache(files = [], force = False):
     return True
 
 def commit(message, files = [], parents = [], allowempty = False,
-           cache_update = True,
+           cache_update = True, tree_id = None,
            author_name = None, author_email = None, author_date = None,
            committer_name = None, committer_email = None):
     """Commit the current tree to repository
@@ -309,15 +313,15 @@ def commit(message, files = [], parents = [], allowempty = False,
             raise GitException, 'No changes to commit'
 
     # get the commit message
-    f = file('.commitmsg', 'w+')
-    if message[-1:] == '\n':
-        f.write(message)
-    else:
-        print >> f, message
-    f.close()
+    if message[-1:] != '\n':
+        message += '\n'
 
+    must_switch = True
     # write the index to repository
-    tree_id = _output_one_line('git-write-tree')
+    if tree_id == None:
+        tree_id = _output_one_line('git-write-tree')
+    else:
+        must_switch = False
 
     # the commit
     cmd = ''
@@ -337,11 +341,9 @@ def commit(message, files = [], parents = [], allowempty = False,
     for p in parents:
         cmd += ' -p %s' % p
 
-    cmd += ' < .commitmsg'
-
-    commit_id = _output_one_line(cmd)
-    __set_head(commit_id)
-    os.remove('.commitmsg')
+    commit_id = _output_one_line(cmd, message)
+    if must_switch:
+        __set_head(commit_id)
 
     return commit_id
 
index 55c49a85c3312ab842faf89de4531735ba22740f..71091860a9bb0dc6514250ac2d8fa84880a62227 100644 (file)
@@ -517,13 +517,40 @@ class Series:
             # top != bottom always since we have a commit for each patch
             if head == bottom:
                 # reset the backup information
-                patch.set_bottom(bottom, backup = True)
+                patch.set_bottom(head, backup = True)
                 patch.set_top(top, backup = True)
 
             else:
-                top = head
-                # stop the fast-forwarding, must do a real merge
-                break
+                head_tree = git.get_commit(head).get_tree()
+                bottom_tree = git.get_commit(bottom).get_tree()
+                if head_tree == bottom_tree:
+                    # We must just reparent this patch and create a new commit
+                    # for it
+                    descr = patch.get_description()
+                    author_name = patch.get_authname()
+                    author_email = patch.get_authemail()
+                    author_date = patch.get_authdate()
+                    committer_name = patch.get_commname()
+                    committer_email = patch.get_commemail()
+
+                    top_tree = git.get_commit(top).get_tree()
+
+                    top = git.commit(message = descr, parents = [head],
+                                     cache_update = False,
+                                     tree_id = top_tree,
+                                     allowempty = True,
+                                     author_name = author_name,
+                                     author_email = author_email,
+                                     author_date = author_date,
+                                     committer_name = committer_name,
+                                     committer_email = committer_email)
+
+                    patch.set_bottom(head, backup = True)
+                    patch.set_top(top, backup = True)
+                else:
+                    top = head
+                    # stop the fast-forwarding, must do a real merge
+                    break
 
             forwarded+=1
             unapplied.remove(name)