From: "Karl Hasselström" <kha@treskal.com>
To: Catalin Marinas <catalin.marinas@gmail.com>
Cc: git@vger.kernel.org
Subject: [StGit PATCH 2/2] New command: stg undo
Date: Fri, 09 May 2008 02:44:35 +0200 [thread overview]
Message-ID: <20080509004434.20312.14243.stgit@yoghurt> (raw)
In-Reply-To: <20080509003824.20312.17819.stgit@yoghurt>
Basically, this is just a user-friendly way to access a subset of the
functionality of "stg reset".
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/undo.py | 38 +++++++--------------
stgit/lib/log.py | 19 ++++++++++
stgit/main.py | 2 +
t/t3102-undo.sh | 86 +++++++++++++++++++++++++++++++++++++++++++++++
t/t3103-undo-hard.sh | 10 +++--
5 files changed, 125 insertions(+), 30 deletions(-)
copy stgit/commands/{reset.py => undo.py} (58%)
create mode 100755 t/t3102-undo.sh
copy t/{t3101-reset-hard.sh => t3103-undo-hard.sh} (82%)
diff --git a/stgit/commands/reset.py b/stgit/commands/undo.py
similarity index 58%
copy from stgit/commands/reset.py
copy to stgit/commands/undo.py
index 2bbac8b..b1d7de9 100644
--- a/stgit/commands/reset.py
+++ b/stgit/commands/undo.py
@@ -22,40 +22,28 @@ from stgit.commands import common
from stgit.lib import git, log, transaction
from stgit.out import out
-help = 'reset the patch stack to an earlier state'
-usage = """%prog [options] <state> [<patchnames>]
+help = 'undo the last operation'
+usage = """%prog [options]
-Reset the patch stack to an earlier state. The state is specified with
-a commit from a stack log; for a branch foo, StGit stores the stack
-log in foo.stgit^. So to undo the last N StGit commands, you would say
-
- stg reset foo.stgit^~N
-
-or, if you are not sure how many steps to undo, you can view the log
-with "git log" or gitk
-
- gitk foo.stgit^
-
-and then reset to any sha1 you see in the log.
-
-If one or more patch names are given, reset only those patches, and
-leave the rest alone."""
+Reset the patch stack to the previous state. Consecutive invocations
+of "stg undo" will take you ever further into the past."""
directory = common.DirectoryHasRepositoryLib()
-options = [make_option('--hard', action = 'store_true',
+options = [make_option('-n', '--number', type = 'int', metavar = 'N',
+ default = 1,
+ help = 'undo the last N commands'),
+ make_option('--hard', action = 'store_true',
help = 'discard changes in your index/worktree')]
def func(parser, options, args):
stack = directory.repository.current_stack
- if len(args) >= 1:
- ref, patches = args[0], args[1:]
- state = log.Log(stack.repository, ref, stack.repository.rev_parse(ref))
- else:
- raise common.CmdException('Wrong number of arguments')
- trans = transaction.StackTransaction(stack, 'reset',
+ if options.number < 1:
+ raise common.CmdException('Bad number of commands to undo')
+ state = log.undo_state(stack, options.number)
+ trans = transaction.StackTransaction(stack, 'undo %d' % options.number,
discard_changes = options.hard)
try:
- log.reset_stack(trans, stack.repository.default_iw, state, patches)
+ log.reset_stack(trans, stack.repository.default_iw, state, [])
except transaction.TransactionHalted:
pass
return trans.run(stack.repository.default_iw)
diff --git a/stgit/lib/log.py b/stgit/lib/log.py
index dfc2b9f..6d9fc6e 100644
--- a/stgit/lib/log.py
+++ b/stgit/lib/log.py
@@ -1,3 +1,4 @@
+import re
from stgit.lib import git, stack
from stgit import exception
from stgit.out import out
@@ -155,6 +156,9 @@ class Log(object):
self.base = self.patches[self.applied[0]].data.parent
else:
self.base = self.head
+ @property
+ def parents(self):
+ return self.commit.data.parents[2:]
class FullLog(Log):
full_log = property(lambda self: self.commit)
@@ -237,3 +241,18 @@ def reset_stack(trans, iw, state, only_patches):
else:
# Recreate the exact order specified by the goal state.
trans.reorder_patches(state.applied, state.unapplied, iw)
+
+def undo_state(stack, undo_steps):
+ ref = log_ref(stack.name)
+ log = Log(stack.repository, ref, stack.repository.refs.get(ref))
+ while undo_steps > 0:
+ msg = log.commit.data.message.strip()
+ m = re.match(r'^undo\s+(\d+)$', msg)
+ if m:
+ undo_steps += int(m.group(1))
+ else:
+ undo_steps -= 1
+ if not log.parents:
+ raise LogException('Not enough undo information available')
+ log = Log(stack.repository, log.parents[0].sha1, log.parents[0])
+ return log
diff --git a/stgit/main.py b/stgit/main.py
index 83e6b08..cf7b404 100644
--- a/stgit/main.py
+++ b/stgit/main.py
@@ -99,6 +99,7 @@ commands = Commands({
'top': 'top',
'unapplied': 'unapplied',
'uncommit': 'uncommit',
+ 'undo': 'undo',
'unhide': 'unhide'
})
@@ -129,6 +130,7 @@ stackcommands = (
'top',
'unapplied',
'uncommit',
+ 'undo',
'unhide',
)
patchcommands = (
diff --git a/t/t3102-undo.sh b/t/t3102-undo.sh
new file mode 100755
index 0000000..1093f70
--- /dev/null
+++ b/t/t3102-undo.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+test_description='Simple test cases for "stg undo"'
+
+. ./test-lib.sh
+
+# Ignore our own output files.
+cat > .git/info/exclude <<EOF
+/expected.txt
+EOF
+
+test_expect_success 'Initialize StGit stack with three patches' '
+ stg init &&
+ echo 000 >> a &&
+ git add a &&
+ git commit -m a &&
+ echo 111 >> a &&
+ git commit -a -m p1 &&
+ echo 222 >> a &&
+ git commit -a -m p2 &&
+ echo 333 >> a &&
+ git commit -a -m p3 &&
+ stg uncommit -n 3 &&
+ stg pop
+'
+
+cat > expected.txt <<EOF
+000
+111
+EOF
+test_expect_success 'Pop one patch ...' '
+ stg pop &&
+ test "$(echo $(stg applied))" = "p1" &&
+ test "$(echo $(stg unapplied))" = "p2 p3" &&
+ test_cmp expected.txt a
+'
+
+cat > expected.txt <<EOF
+000
+111
+222
+EOF
+test_expect_success '... and undo it' '
+ stg undo &&
+ test "$(echo $(stg applied))" = "p1 p2" &&
+ test "$(echo $(stg unapplied))" = "p3" &&
+ test_cmp expected.txt a
+'
+
+cat > expected.txt <<EOF
+000
+EOF
+test_expect_success 'Pop two patches ...' '
+ stg pop &&
+ stg pop &&
+ test "$(echo $(stg applied))" = "" &&
+ test "$(echo $(stg unapplied))" = "p1 p2 p3" &&
+ test_cmp expected.txt a
+'
+
+cat > expected.txt <<EOF
+000
+111
+222
+EOF
+test_expect_success '... and undo it' '
+ stg undo &&
+ stg undo &&
+ test "$(echo $(stg applied))" = "p1 p2" &&
+ test "$(echo $(stg unapplied))" = "p3" &&
+ test_cmp expected.txt a
+'
+
+cat > expected.txt <<EOF
+000
+111
+222
+EOF
+test_expect_success 'Undo past end of history' '
+ ! stg undo -n 100 &&
+ test "$(echo $(stg applied))" = "p1 p2" &&
+ test "$(echo $(stg unapplied))" = "p3" &&
+ test_cmp expected.txt a
+'
+
+test_done
diff --git a/t/t3101-reset-hard.sh b/t/t3103-undo-hard.sh
similarity index 82%
copy from t/t3101-reset-hard.sh
copy to t/t3103-undo-hard.sh
index 1e02805..21412f7 100755
--- a/t/t3101-reset-hard.sh
+++ b/t/t3103-undo-hard.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='Simple test cases for "stg reset"'
+test_description='Simple test cases for "stg undo"'
. ./test-lib.sh
@@ -35,8 +35,8 @@ test_expect_success 'Pop middle patch, creating a conflict' '
test "$(echo $(stg unapplied))" = "p2"
'
-test_expect_success 'Try to reset without --hard' '
- ! stg reset master.stgit^~1 &&
+test_expect_success 'Try to undo without --hard' '
+ ! stg undo &&
stg status a > actual.txt &&
test_cmp expected.txt actual.txt &&
test "$(echo $(stg applied))" = "p1 p3" &&
@@ -45,8 +45,8 @@ test_expect_success 'Try to reset without --hard' '
cat > expected.txt <<EOF
EOF
-test_expect_success 'Try to reset with --hard' '
- stg reset --hard master.stgit^~1 &&
+test_expect_success 'Try to undo with --hard' '
+ stg undo --hard &&
stg status a > actual.txt &&
test_cmp expected.txt actual.txt &&
test "$(echo $(stg applied))" = "p1" &&
prev parent reply other threads:[~2008-05-09 0:45 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-09 0:44 [StGit PATCH 0/2] stg undo Karl Hasselström
2008-05-09 0:44 ` [StGit PATCH 1/2] Move stack reset function to a shared location Karl Hasselström
2008-05-09 0:44 ` Karl Hasselström [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080509004434.20312.14243.stgit@yoghurt \
--to=kha@treskal.com \
--cc=catalin.marinas@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.