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

[StGit PATCH 1/5] Check for local changes with "goto"

From
CMCatalin Marinas <catalin.marinas@arm.com>
Date
Mar 12, 2009, 12:08 UTC
Message-ID
<20090312120856.2992.48548.stgit@pc1117.cambridge.arm.com>
In-Reply-To
<20090312120426.2992.35213.stgit@pc1117.cambridge.arm.com>

This is done by default, unless the --keep option is passed, for consistency with the "pop" command. The index is checked in the Transaction.run() function so that other commands could benefit from this feature (off by default).

This behaviour can be overridden by setting the stgit.autokeep option.
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
 examples/gitconfig        |    3 +++
 stgit/argparse.py         |    5 +++++
 stgit/commands/goto.py    |    7 +++++--
 stgit/lib/git.py          |   14 ++++++++++++--
 stgit/lib/transaction.py  |   10 +++++++++-
 t/t2300-refresh-subdir.sh |    2 +-
 t/t2800-goto-subdir.sh    |    4 ++--
 t/t3000-dirty-merge.sh    |    2 +-
 8 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/examples/gitconfig b/examples/gitconfig
index 9efc089..2fc5f52 100644
--- a/examples/gitconfig
+++ b/examples/gitconfig
@@ -103,6 +103,9 @@
 	# -O/--diff-opts). For example, -M turns on rename detection.
 	#diff-opts = -M
 
+	# Behave as if the --keep option is always passed
+	#autokeep = no
+
 [mail "alias"]
 	# E-mail aliases used with the 'mail' command
 	git = git@vger.kernel.org
diff --git a/stgit/argparse.py b/stgit/argparse.py
index 418a506..85ee6e3 100644
--- a/stgit/argparse.py
+++ b/stgit/argparse.py
@@ -220,6 +220,11 @@ def _person_opts(person, short):
 def author_options():
     return _person_opts('author', 'auth')
 
+def keep_option():
+    return [opt('-k', '--keep', action = 'store_true',
+                short = 'Keep the local changes',
+                default = config.get('stgit.autokeep') == 'yes')]
+
 class CompgenBase(object):
     def actions(self, var): return set()
     def words(self, var): return set()
diff --git a/stgit/commands/goto.py b/stgit/commands/goto.py
index 60a917e..0f67314 100644
--- a/stgit/commands/goto.py
+++ b/stgit/commands/goto.py
@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 from stgit.commands import common
 from stgit.lib import transaction
 from stgit import argparse
+from stgit.argparse import opt
 
 help = 'Push or pop patches to the given one'
 kind = 'stack'
@@ -27,7 +28,7 @@ Push/pop patches to/from the stack until the one given on the command
 line becomes current."""
 
 args = [argparse.other_applied_patches, argparse.unapplied_patches]
-options = []
+options = argparse.keep_option()
 
 directory = common.DirectoryHasRepositoryLib()
 
@@ -38,7 +39,9 @@ def func(parser, options, args):
 
     stack = directory.repository.current_stack
     iw = stack.repository.default_iw
-    trans = transaction.StackTransaction(stack, 'goto')
+    clean_iw = not options.keep and iw or None
+    trans = transaction.StackTransaction(stack, 'goto',
+                                         check_clean_iw = clean_iw)
     if patch in trans.applied:
         to_pop = set(trans.applied[trans.applied.index(patch)+1:])
         assert not trans.pop_patches(lambda pn: pn in to_pop)
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index e2b4266..07079b8 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -706,9 +706,11 @@ class Index(RunWithEnv):
                     ).output_one_line())
         except run.RunException:
             raise MergeException('Conflicting merge')
-    def is_clean(self):
+    def is_clean(self, tree):
+        """Check whether the index is clean relative to the given treeish."""
         try:
-            self.run(['git', 'update-index', '--refresh']).discard_output()
+            self.run(['git', 'diff-index', '--quiet', '--cached', tree.sha1]
+                    ).discard_output()
         except run.RunException:
             return False
         else:
@@ -858,6 +860,14 @@ class IndexAndWorktree(RunWithEnvCwd):
         cmd = ['git', 'update-index', '--remove']
         self.run(cmd + ['-z', '--stdin']
                  ).input_nulterm(paths).discard_output()
+    def worktree_clean(self):
+        """Check whether the worktree is clean relative to index."""
+        try:
+            self.run(['git', 'update-index', '--refresh']).discard_output()
+        except run.RunException:
+            return False
+        else:
+            return True
 
 class Branch(object):
     """Represents a Git branch."""
diff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py
index 54de127..5a81f9d 100644
--- a/stgit/lib/transaction.py
+++ b/stgit/lib/transaction.py
@@ -75,7 +75,8 @@ class StackTransaction(object):
       your refs and index+worktree, or fail without having done
       anything."""
     def __init__(self, stack, msg, discard_changes = False,
-                 allow_conflicts = False, allow_bad_head = False):
+                 allow_conflicts = False, allow_bad_head = False,
+                 check_clean_iw = None):
         """Create a new L{StackTransaction}.
 
         @param discard_changes: Discard any changes in index+worktree
@@ -102,6 +103,8 @@ class StackTransaction(object):
         self.__temp_index = self.temp_index_tree = None
         if not allow_bad_head:
             self.__assert_head_top_equal()
+        if check_clean_iw:
+            self.__assert_index_worktree_clean(check_clean_iw)
     stack = property(lambda self: self.__stack)
     patches = property(lambda self: self.__patches)
     def __set_applied(self, val):
@@ -147,6 +150,11 @@ class StackTransaction(object):
                 'This can happen if you modify a branch with git.',
                 '"stg repair --help" explains more about what to do next.')
             self.__abort()
+    def __assert_index_worktree_clean(self, iw):
+        if not iw.worktree_clean() or \
+           not iw.index.is_clean(self.stack.head):
+            self.__halt('Repository not clean. Use "refresh" or '
+                        '"status --reset"')
     def __checkout(self, tree, iw, allow_bad_head):
         if not allow_bad_head:
             self.__assert_head_top_equal()
diff --git a/t/t2300-refresh-subdir.sh b/t/t2300-refresh-subdir.sh
index d731a11..89c95db 100755
--- a/t/t2300-refresh-subdir.sh
+++ b/t/t2300-refresh-subdir.sh
@@ -65,7 +65,7 @@ test_expect_success 'refresh -u -p <subdir>' '
 
 test_expect_success 'refresh an unapplied patch' '
     stg refresh -u &&
-    stg goto p0 &&
+    stg goto --keep p0 &&
     test "$(stg status)" = "M foo.txt" &&
     stg refresh -p p1 &&
     test "$(stg status)" = "" &&
diff --git a/t/t2800-goto-subdir.sh b/t/t2800-goto-subdir.sh
index 28b8292..855972b 100755
--- a/t/t2800-goto-subdir.sh
+++ b/t/t2800-goto-subdir.sh
@@ -25,7 +25,7 @@ cat > expected2.txt <<EOF
 bar
 EOF
 test_expect_success 'Goto in subdirectory (just pop)' '
-    (cd foo && stg goto p1) &&
+    (cd foo && stg goto --keep p1) &&
     cat foo/bar > actual.txt &&
     test_cmp expected1.txt actual.txt &&
     ls foo > actual.txt &&
@@ -48,7 +48,7 @@ cat > expected2.txt <<EOF
 bar
 EOF
 test_expect_success 'Goto in subdirectory (conflicting push)' '
-    (cd foo && stg goto p3) ;
+    (cd foo && stg goto --keep p3) ;
     [ $? -eq 3 ] &&
     cat foo/bar > actual.txt &&
     test_cmp expected1.txt actual.txt &&
diff --git a/t/t3000-dirty-merge.sh b/t/t3000-dirty-merge.sh
index f0f79d5..419d86e 100755
--- a/t/t3000-dirty-merge.sh
+++ b/t/t3000-dirty-merge.sh
@@ -26,7 +26,7 @@ test_expect_success 'Push with dirty worktree' '
     echo 4 > a &&
     [ "$(echo $(stg series --applied --noprefix))" = "p1" ] &&
     [ "$(echo $(stg series --unapplied --noprefix))" = "p2" ] &&
-    conflict stg goto p2 &&
+    conflict stg goto --keep p2 &&
     [ "$(echo $(stg series --applied --noprefix))" = "p1" ] &&
     [ "$(echo $(stg series --unapplied --noprefix))" = "p2" ] &&
     [ "$(echo $(cat a))" = "4" ]
Previous: Catalin MarinasNext: Karl Hasselström
Message 2 of 19 in “Various StGit patches”
  1. 0/5 Various StGit patchesCatalin Marinas, Mar 12, 2009
  2. 1/5 Check for local changes with "goto"Catalin Marinas, Mar 12, 2009
  3. Karl HasselströmMar 13, 2009
  4. Catalin MarinasMar 16, 2009
  5. Karl HasselströmMar 17, 2009
  6. Catalin MarinasMar 17, 2009
  7. Karl HasselströmMar 17, 2009
  8. 2/5 Add mergetool support to the classic StGit infrastructureCatalin Marinas, Mar 12, 2009
  9. Karl HasselströmMar 13, 2009
  10. 3/5 Add automatic git-mergetool invocation to the new infrastructureCatalin Marinas, Mar 12, 2009
  11. Karl HasselströmMar 13, 2009
  12. Catalin MarinasMar 16, 2009
  13. Karl HasselströmMar 17, 2009
  14. 4/5 Convert "sink" to the new infrastructureCatalin Marinas, Mar 12, 2009
  15. Karl HasselströmMar 13, 2009
  16. 5/5 Convert "float" to the lib infrastructureCatalin Marinas, Mar 12, 2009
  17. Karl HasselströmMar 13, 2009
  18. Catalin MarinasMar 16, 2009
  19. Karl HasselströmMar 17, 2009

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.