git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[StGit PATCH 6/6] Handle failed pushes differently depending on cause

From
Karl Hasselström <kha@treskal.com>
Date
Mar 20, 2008, 00:32 UTC
Message-ID
<20080320003202.13102.54792.stgit@yoghurt>
In-Reply-To
<20080320002604.13102.53757.stgit@yoghurt>

Specifically, if the push failed because of a merge conflict, the patch should be applied but empty; and if it fails for any other reason (such as a too-dirty worktree), the patch should not be applied.

This fixes the data loss bug tested for by t3000.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
 stgit/lib/git.py         |   21 ++++++++++++++-------
 stgit/lib/transaction.py |    4 +++-
 t/t3000-dirty-merge.sh   |    2 +-
 3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index cdfe885..35b9bbf 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -433,6 +433,9 @@ class Repository(RunWithEnv):
 class MergeException(exception.StgException):
     pass
 
+class MergeConflictException(MergeException):
+    pass
+
 class Index(RunWithEnv):
     def __init__(self, repository, filename):
         self.__repository = repository
@@ -517,14 +520,18 @@ class IndexAndWorktree(RunWithEnv):
         assert isinstance(ours, Tree)
         assert isinstance(theirs, Tree)
         try:
-            self.run(['git', 'merge-recursive', base.sha1, '--', ours.sha1,
-                      theirs.sha1],
-                     env = { 'GITHEAD_%s' % base.sha1: 'ancestor',
-                             'GITHEAD_%s' % ours.sha1: 'current',
-                             'GITHEAD_%s' % theirs.sha1: 'patched'}
-                     ).cwd(self.__worktree.directory).discard_output()
+            r = self.run(['git', 'merge-recursive', base.sha1, '--', ours.sha1,
+                          theirs.sha1],
+                         env = { 'GITHEAD_%s' % base.sha1: 'ancestor',
+                                 'GITHEAD_%s' % ours.sha1: 'current',
+                                 'GITHEAD_%s' % theirs.sha1: 'patched'}
+                         ).cwd(self.__worktree.directory)
+            r.discard_output()
         except run.RunException, e:
-            raise MergeException('Index/worktree dirty')
+            if r.exitcode == 1:
+                raise MergeConflictException()
+            else:
+                raise MergeException('Index/worktree dirty')
     def changed_files(self):
         return self.run(['git', 'diff-files', '--name-only']).output_lines()
     def update_index(self, files):
diff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py
index 3613b15..2946a67 100644
--- a/stgit/lib/transaction.py
+++ b/stgit/lib/transaction.py
@@ -197,10 +197,12 @@ class StackTransaction(object):
                 tree = iw.index.write_tree()
                 self.__current_tree = tree
                 s = ' (modified)'
-            except git.MergeException:
+            except git.MergeConflictException:
                 tree = ours
                 merge_conflict = True
                 s = ' (conflict)'
+            except git.MergeException, e:
+                self.__halt(str(e))
         cd = cd.set_tree(tree)
         self.patches[pn] = self.__stack.repository.commit(cd)
         del self.unapplied[self.unapplied.index(pn)]
diff --git a/t/t3000-dirty-merge.sh b/t/t3000-dirty-merge.sh
index dd81c9e..d87bba1 100755
--- a/t/t3000-dirty-merge.sh
+++ b/t/t3000-dirty-merge.sh
@@ -22,7 +22,7 @@ test_expect_success 'Pop one patch and update the other' '
     stg refresh
 '
 
-test_expect_failure 'Push with dirty worktree' '
+test_expect_success 'Push with dirty worktree' '
     echo 4 > a &&
     [ "$(echo $(stg applied))" = "p1" ] &&
     [ "$(echo $(stg unapplied))" = "p2" ] &&
Previous: Karl HasselströmNext: Catalin Marinas
Message 7 of 14 in “Two bugfixes”
  1. 0/6 Two bugfixesKarl Hasselström, Mar 20, 2008
  2. 1/6 Use a special exit code for bugsKarl Hasselström, Mar 20, 2008
  3. 2/6 Make sure patches with no parents have an empty list of parentsKarl Hasselström, Mar 20, 2008
  4. 3/6 Try uncommitting a commit with not exactly one parentKarl Hasselström, Mar 20, 2008
  5. 4/6 Make sure that we only uncommit commits with exactly one parentKarl Hasselström, Mar 20, 2008
  6. 5/6 New test: conflicting push in dirty worktreeKarl Hasselström, Mar 20, 2008
  7. 6/6 Handle failed pushes differently depending on causeKarl Hasselström, Mar 20, 2008
  8. Catalin MarinasMar 20, 2008
  9. Karl HasselströmMar 24, 2008
  10. Catalin MarinasMar 24, 2008
  11. Karl HasselströmMar 24, 2008
  12. Catalin MarinasMar 25, 2008
  13. Karl HasselströmMar 25, 2008
  14. Catalin MarinasMar 25, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.