{"thread":{"id":"17698","subject":"[StGit PATCH] Check for local changes with \"goto\"","startedAt":"2009-02-10T14:11:51Z","lastAt":"2009-02-11T09:05:35Z","messageCount":2,"participants":["Catalin Marinas","Karl Hasselström"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"104009","messageId":"20090210141039.28782.50452.stgit@pc1117.cambridge.arm.com","threadId":"17698","inReplyTo":null,"subject":"[StGit PATCH] Check for local changes with \"goto\"","fromName":"Catalin Marinas","fromEmail":"catalin.marinas@arm.com","sentAt":"2009-02-10T14:11:51Z","receivedAt":"2009-02-10T14:11:51Z","isPatch":true,"sender":{"key":"catalin.marinas@arm.com","avatar":null},"body":"This is done by default, unless the --keep option is passed, for\nconsistency with the \"pop\" command. The index is checked in the\nTransaction.run() function so that other commands could benefit from\nthis feature (off by default).\n\nSigned-off-by: Catalin Marinas <catalin.marinas@gmail.com>\n---\n\nThis is hopefully the final variant of what was discussed in a previous\nthread. The next step is to have the --keep behaviour configurable via\n.gitconfig.\n\n stgit/commands/goto.py    |   13 +++++++++++--\n stgit/lib/git.py          |   14 ++++++++++++--\n stgit/lib/transaction.py  |   10 +++++++++-\n t/t2300-refresh-subdir.sh |    2 +-\n t/t2800-goto-subdir.sh    |    4 ++--\n t/t3000-dirty-merge.sh    |    2 +-\n 6 files changed, 36 insertions(+), 9 deletions(-)\n\ndiff --git a/stgit/commands/goto.py b/stgit/commands/goto.py\nindex 60a917e..4f6274f 100644\n--- a/stgit/commands/goto.py\n+++ b/stgit/commands/goto.py\n@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n from stgit.commands import common\n from stgit.lib import transaction\n from stgit import argparse\n+from stgit.argparse import opt\n \n help = 'Push or pop patches to the given one'\n kind = 'stack'\n@@ -27,7 +28,10 @@ Push/pop patches to/from the stack until the one given on the command\n line becomes current.\"\"\"\n \n args = [argparse.other_applied_patches, argparse.unapplied_patches]\n-options = []\n+options = [\n+    opt('-k', '--keep', action = 'store_true',\n+        short = 'Keep the local changes')\n+]\n \n directory = common.DirectoryHasRepositoryLib()\n \n@@ -38,7 +42,12 @@ def func(parser, options, args):\n \n     stack = directory.repository.current_stack\n     iw = stack.repository.default_iw\n-    trans = transaction.StackTransaction(stack, 'goto')\n+    if not options.keep:\n+        check_clean_iw = iw\n+    else:\n+        check_clean_iw = None\n+    trans = transaction.StackTransaction(stack, 'goto',\n+                                         check_clean_iw = check_clean_iw)\n     if patch in trans.applied:\n         to_pop = set(trans.applied[trans.applied.index(patch)+1:])\n         assert not trans.pop_patches(lambda pn: pn in to_pop)\ndiff --git a/stgit/lib/git.py b/stgit/lib/git.py\nindex e2b4266..07079b8 100644\n--- a/stgit/lib/git.py\n+++ b/stgit/lib/git.py\n@@ -706,9 +706,11 @@ class Index(RunWithEnv):\n                     ).output_one_line())\n         except run.RunException:\n             raise MergeException('Conflicting merge')\n-    def is_clean(self):\n+    def is_clean(self, tree):\n+        \"\"\"Check whether the index is clean relative to the given treeish.\"\"\"\n         try:\n-            self.run(['git', 'update-index', '--refresh']).discard_output()\n+            self.run(['git', 'diff-index', '--quiet', '--cached', tree.sha1]\n+                    ).discard_output()\n         except run.RunException:\n             return False\n         else:\n@@ -858,6 +860,14 @@ class IndexAndWorktree(RunWithEnvCwd):\n         cmd = ['git', 'update-index', '--remove']\n         self.run(cmd + ['-z', '--stdin']\n                  ).input_nulterm(paths).discard_output()\n+    def worktree_clean(self):\n+        \"\"\"Check whether the worktree is clean relative to index.\"\"\"\n+        try:\n+            self.run(['git', 'update-index', '--refresh']).discard_output()\n+        except run.RunException:\n+            return False\n+        else:\n+            return True\n \n class Branch(object):\n     \"\"\"Represents a Git branch.\"\"\"\ndiff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py\nindex 54de127..5a81f9d 100644\n--- a/stgit/lib/transaction.py\n+++ b/stgit/lib/transaction.py\n@@ -75,7 +75,8 @@ class StackTransaction(object):\n       your refs and index+worktree, or fail without having done\n       anything.\"\"\"\n     def __init__(self, stack, msg, discard_changes = False,\n-                 allow_conflicts = False, allow_bad_head = False):\n+                 allow_conflicts = False, allow_bad_head = False,\n+                 check_clean_iw = None):\n         \"\"\"Create a new L{StackTransaction}.\n \n         @param discard_changes: Discard any changes in index+worktree\n@@ -102,6 +103,8 @@ class StackTransaction(object):\n         self.__temp_index = self.temp_index_tree = None\n         if not allow_bad_head:\n             self.__assert_head_top_equal()\n+        if check_clean_iw:\n+            self.__assert_index_worktree_clean(check_clean_iw)\n     stack = property(lambda self: self.__stack)\n     patches = property(lambda self: self.__patches)\n     def __set_applied(self, val):\n@@ -147,6 +150,11 @@ class StackTransaction(object):\n                 'This can happen if you modify a branch with git.',\n                 '\"stg repair --help\" explains more about what to do next.')\n             self.__abort()\n+    def __assert_index_worktree_clean(self, iw):\n+        if not iw.worktree_clean() or \\\n+           not iw.index.is_clean(self.stack.head):\n+            self.__halt('Repository not clean. Use \"refresh\" or '\n+                        '\"status --reset\"')\n     def __checkout(self, tree, iw, allow_bad_head):\n         if not allow_bad_head:\n             self.__assert_head_top_equal()\ndiff --git a/t/t2300-refresh-subdir.sh b/t/t2300-refresh-subdir.sh\nindex d731a11..89c95db 100755\n--- a/t/t2300-refresh-subdir.sh\n+++ b/t/t2300-refresh-subdir.sh\n@@ -65,7 +65,7 @@ test_expect_success 'refresh -u -p <subdir>' '\n \n test_expect_success 'refresh an unapplied patch' '\n     stg refresh -u &&\n-    stg goto p0 &&\n+    stg goto --keep p0 &&\n     test \"$(stg status)\" = \"M foo.txt\" &&\n     stg refresh -p p1 &&\n     test \"$(stg status)\" = \"\" &&\ndiff --git a/t/t2800-goto-subdir.sh b/t/t2800-goto-subdir.sh\nindex 28b8292..855972b 100755\n--- a/t/t2800-goto-subdir.sh\n+++ b/t/t2800-goto-subdir.sh\n@@ -25,7 +25,7 @@ cat > expected2.txt <<EOF\n bar\n EOF\n test_expect_success 'Goto in subdirectory (just pop)' '\n-    (cd foo && stg goto p1) &&\n+    (cd foo && stg goto --keep p1) &&\n     cat foo/bar > actual.txt &&\n     test_cmp expected1.txt actual.txt &&\n     ls foo > actual.txt &&\n@@ -48,7 +48,7 @@ cat > expected2.txt <<EOF\n bar\n EOF\n test_expect_success 'Goto in subdirectory (conflicting push)' '\n-    (cd foo && stg goto p3) ;\n+    (cd foo && stg goto --keep p3) ;\n     [ $? -eq 3 ] &&\n     cat foo/bar > actual.txt &&\n     test_cmp expected1.txt actual.txt &&\ndiff --git a/t/t3000-dirty-merge.sh b/t/t3000-dirty-merge.sh\nindex f0f79d5..419d86e 100755\n--- a/t/t3000-dirty-merge.sh\n+++ b/t/t3000-dirty-merge.sh\n@@ -26,7 +26,7 @@ test_expect_success 'Push with dirty worktree' '\n     echo 4 > a &&\n     [ \"$(echo $(stg series --applied --noprefix))\" = \"p1\" ] &&\n     [ \"$(echo $(stg series --unapplied --noprefix))\" = \"p2\" ] &&\n-    conflict stg goto p2 &&\n+    conflict stg goto --keep p2 &&\n     [ \"$(echo $(stg series --applied --noprefix))\" = \"p1\" ] &&\n     [ \"$(echo $(stg series --unapplied --noprefix))\" = \"p2\" ] &&\n     [ \"$(echo $(cat a))\" = \"4\" ]\n"},{"id":"104153","messageId":"20090211090535.GB26136@diana.vm.bytemark.co.uk","threadId":"17698","inReplyTo":"20090210141039.28782.50452.stgit@pc1117.cambridge.arm.com","subject":"Re: [StGit PATCH] Check for local changes with \"goto\"","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2009-02-11T09:05:35Z","receivedAt":"2009-02-11T09:05:35Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2009-02-10 14:11:51 +0000, Catalin Marinas wrote:\n\n> This is hopefully the final variant of what was discussed in a\n> previous thread. The next step is to have the --keep behaviour\n> configurable via .gitconfig.\n\nYeah, I can't find anything more to complain about. :-)\n\nAcked-by: Karl Hasselström <kha@treskal.com>\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"}]}