Catalin Marinas [off-list ref] wrote:
After some tests, it looks like 'git-diff-tree -p ... | git-apply
--index' is about 3 times faster than 'git-read-tree -m' (in the best
case for git-read-tree with minor modifications of the base). It now
takes ~0.5s to push a single patch (compared to ~1.5s).
And that's the patch for whoever wants to try. I will also add it to
the repository tonight:
Optimise 'push' to use git-apply instead of git-read-tree
With this patch, 'push' will use 'git-diff-tree | git-apply' first. If this
operation fails, it will fall back to the three-way merge with
git-read-tree.
Signed-off-by: Catalin Marinas <redacted>
---
stgit/git.py | 9 +++++++++
stgit/stack.py | 19 +++++++++++--------
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -355,6 +355,15 @@ def commit(message, files = [], parents
return commit_id
+def apply_diff(rev1, rev2):
+ """Apply the diff between rev1 and rev2 onto the current
+ index. This function doesn't need to raise an exception since it
+ is only used for fast-pushing a patch. If this operation fails,
+ the pushing would fall back to the three-way merge.
+ """
+ return os.system('git-diff-tree -p %s %s | git-apply --index 2> /dev/null'
+ % (rev1, rev2)) == 0
+
def merge(base, head1, head2):
"""Perform a 3-way merge between base, head1 and head2 into the
local treediff --git a/stgit/stack.py b/stgit/stack.py
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -598,14 +598,17 @@ class Series:
# The current patch is empty after merge.
patch.set_bottom(head, backup = True)
patch.set_top(head, backup = True)
- # merge/refresh can fail but the patch needs to be pushed
- try:
- git.merge(bottom, head, top)
- except git.GitException, ex:
- print >> sys.stderr, \
- 'The merge failed during "push". ' \
- 'Use "refresh" after fixing the conflicts'
- pass
+
+ # Try the fast applying first. If this fails, fall back to the
+ # three-way merge
+ if not git.apply_diff(bottom, top):
+ # merge can fail but the patch needs to be pushed
+ try:
+ git.merge(bottom, head, top)
+ except git.GitException, ex:
+ print >> sys.stderr, \
+ 'The merge failed during "push". ' \
+ 'Use "refresh" after fixing the conflicts'
append_string(self.__applied_file, name)
--
Catalin