[patch 07/11] Implement fast-forward when only tree (but not commits) match
From: Paolo 'Blaisorblade' Giarrusso <hidden>
Date: 2016-06-15 22:42:06
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Paolo 'Blaisorblade' Giarrusso <redacted> 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 <redacted> --- stgit/git.py | 30 ++++++++++++++++-------------- stgit/stack.py | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py@@ -119,8 +119,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)
@@ -286,7 +290,7 @@ def update_cache(files = [], force = Fal 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
@@ -298,15 +302,15 @@ def commit(message, files = [], parents 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 = ''
@@ -326,11 +330,9 @@ def commit(message, files = [], parents 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
diff --git a/stgit/stack.py b/stgit/stack.py
--- a/stgit/stack.py
+++ b/stgit/stack.py@@ -495,13 +495,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)