[PATCH 2/2] Add 'stg uncommit' command
Add an uncommit command, which is exactly the opposite of 'stg commit'.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/commit.py | 5 ++-
stgit/commands/uncommit.py | 80 ++++++++++++++++++++++++++++++++++++++++++++
stgit/main.py | 2 +
stgit/stack.py | 12 +++++--
4 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/stgit/commands/commit.py b/stgit/commands/commit.py
index a3b7277..ed9a0b3 100644
--- a/stgit/commands/commit.py
+++ b/stgit/commands/commit.py
@@ -28,8 +28,9 @@ usage = """%prog [options]
Merge the applied patches into the base of the current stack and
remove them from the series while advancing the base.
-Use this command only if you want to permanently store the applied
-patches and no longer manage them with StGIT."""
+Use this command if you want to permanently store the applied patches
+and no longer manage them with StGIT. If you should change your mind
+later, use 'stg uncommit'."""
options = []
diff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py
new file mode 100644
index 0000000..4ac0dfb
--- /dev/null
+++ b/stgit/commands/uncommit.py
@@ -0,0 +1,80 @@
+__copyright__ = """
+Copyright (C) 2006, Catalin Marinas <catalin.marinas@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+import sys, os
+from optparse import OptionParser, make_option
+
+from stgit.commands.common import *
+from stgit.utils import *
+from stgit import stack, git
+
+help = 'turn regular git commits into StGIT patches'
+usage = """%prog [options] <patchname1> [<patchname2> ... ]
+
+Takes one or more git commits at the base of the current stack, and
+turns them into StGIT patches. These new patches are alreay applied,
+at the bottom of the stack. This is the exact opposite of 'stg
+commit'.
+
+You can either give one patch name for each commit you wish to
+uncommit, or use the --number option and exactly one patch name; StGIT
+will then create numbered patches with the given patch name as prefix.
+
+Only commits with exactly one parent can be uncommitted; in other
+words, you can't uncommmit a merge."""
+
+options = [make_option('-n', '--number', type = 'int',
+ help = 'uncommit the specified number of commits')]
+
+def func(parser, options, args):
+ if len(args) == 0:
+ parser.error('you must specify at least one patch name')
+ if options.number:
+ if len(args) != 1:
+ parser.error('when using --number, specify exactly one patch name')
+ patchnames = ['%s%d' % (args[0], i)
+ for i in xrange(options.number - 1, -1, -1)]
+ else:
+ patchnames = args
+
+ if crt_series.get_protected():
+ raise CmdException, 'This branch is protected. Uncommit is not permitted'
+
+ print 'Uncommitting %d patches...' % len(patchnames),
+ sys.stdout.flush()
+
+ for patchname in patchnames:
+ base_file = crt_series.get_base_file()
+ commit_id = read_string(base_file)
+ commit = git.Commit(commit_id)
+ try:
+ parent, = commit.get_parents()
+ except ValueError:
+ raise CmdException, ('Commit %s does not have exactly one parent'
+ % commit_id)
+ author_name, author_email, author_date = name_email_date(
+ commit.get_author())
+ crt_series.new_patch(patchname,
+ can_edit = False, before_existing = True,
+ top = commit_id, bottom = parent,
+ message = commit.get_log(),
+ author_name = author_name,
+ author_email = author_email,
+ author_date = author_date)
+ write_string(base_file, parent)
+
+ print 'done'
diff --git a/stgit/main.py b/stgit/main.py
index 6d86ee4..4a48668 100644
--- a/stgit/main.py
+++ b/stgit/main.py
@@ -57,6 +57,7 @@ import stgit.commands.series
import stgit.commands.status
import stgit.commands.top
import stgit.commands.unapplied
+import stgit.commands.uncommit
#
@@ -92,6 +93,7 @@ commands = {
'status': stgit.commands.status,
'top': stgit.commands.top,
'unapplied':stgit.commands.unapplied,
+ 'uncommit': stgit.commands.uncommit,
}
def print_help():
diff --git a/stgit/stack.py b/stgit/stack.py
index bc39d14..05389bb 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -621,7 +621,8 @@ class Series:
unapplied = False, show_patch = False,
top = None, bottom = None,
author_name = None, author_email = None, author_date = None,
- committer_name = None, committer_email = None):
+ committer_name = None, committer_email = None,
+ before_existing = False):
"""Creates a new patch
"""
if self.__patch_applied(name) or self.__patch_unapplied(name):
@@ -664,8 +665,13 @@ class Series:
f.writelines([line + '\n' for line in patches])
f.close()
else:
- append_string(self.__applied_file, patch.get_name())
- self.__set_current(name)
+ if before_existing:
+ insert_string(self.__applied_file, patch.get_name())
+ if not self.get_current():
+ self.__set_current(name)
+ else:
+ append_string(self.__applied_file, patch.get_name())
+ self.__set_current(name)
def delete_patch(self, name):
"""Deletes a patch