From ee11a2896d0815d1530c5dc2a7e4719409b7833f Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 9 Apr 2009 23:40:58 +0300 Subject: [PATCH] Check for local changes with "goto" MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Acked-by: Karl Hasselström --- 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..480266a 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..a88d289 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(): + 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() 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 ' ' 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 < actual.txt && test_cmp expected1.txt actual.txt && ls foo > actual.txt && @@ -48,7 +48,7 @@ cat > expected2.txt < 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" ] -- 2.11.0