chiark / gitweb /
Check for local changes with "goto"
authorCatalin Marinas <catalin.marinas@arm.com>
Thu, 9 Apr 2009 20:40:58 +0000 (23:40 +0300)
committerCatalinMarinas <cmarinas@laptop.(none)>
Thu, 9 Apr 2009 20:40:58 +0000 (23:40 +0300)
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>
Acked-by: Karl Hasselström <kha@treskal.com>
examples/gitconfig
stgit/argparse.py
stgit/commands/goto.py
stgit/lib/git.py
stgit/lib/transaction.py
t/t2300-refresh-subdir.sh
t/t2800-goto-subdir.sh
t/t3000-dirty-merge.sh

index 9efc0898eb01fa8e09f8b0acc6190482515a2b84..2fc5f520d4dbcb92a206ac39de9d237c8d61e1c2 100644 (file)
        # -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
index 418a506d08a3ecf540cfea95931b82fb6ecfeab7..85ee6e3a2183df53aa11609fa79f3e1c3ed741a7 100644 (file)
@@ -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()
index 60a917ef7f3b25d37abac3cb1def5ddf0d4f1148..480266aa4cfb878a99f8f4fdd352bb640a986a72 100644 (file)
@@ -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)
index e2b42661edbfc4adffadd9aa60befc36ce368902..07079b8c7b3092d702a0e5caa5d6ccf171c5ad93 100644 (file)
@@ -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."""
index 54de1276fa43090a5c85f29047b2fae1f4fa3574..a88d289c6fea01b621076bf98694bfbbf8601a29 100644 (file)
@@ -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():
+            self.__halt('Worktree not clean. Use "refresh" or "status --reset"')
+        if not iw.index.is_clean(self.stack.head):
+            self.__halt('Index 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()
index d731a11a53a457176a23033638a0aa96447d67d6..89c95db6c8274829fad9d09b3faf7ea8ff97fbe4 100755 (executable)
@@ -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)" = "" &&
index 28b82924137e896ed80bbb231d30e3adb5b93aa6..855972b6669799bc5c95ad11f50dc0c556adebac 100755 (executable)
@@ -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 &&
index f0f79d5d6e740b6185151b96b831e5a0cb45827c..419d86ec1f314a46f66f1f4b8de947643c313f78 100755 (executable)
@@ -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" ]