Automatically generate patch names for uncommit
authorCatalin Marinas <catalin.marinas@gmail.com>
Fri, 14 Jul 2006 16:25:36 +0000 (17:25 +0100)
committerCatalin Marinas <catalin.marinas@gmail.com>
Fri, 14 Jul 2006 20:56:17 +0000 (21:56 +0100)
This is the same as in the pick or import commands, the patch name, if not
specified, is automatically generated from the first line of the patch
description.

Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
stgit/commands/common.py
stgit/commands/uncommit.py
t/t1300-uncommit.sh [new file with mode: 0755]

index 836884c..6843dcf 100644 (file)
@@ -241,5 +241,5 @@ def make_patch_name(msg):
     if not msg:
         return None
 
-    subject_line = msg.lstrip().split('\n', 1)[0]
+    subject_line = msg.lstrip().split('\n', 1)[0].lower()
     return re.sub('[\W]+', '-', subject_line).strip('-')
index 52ce5a8..45a2087 100644 (file)
@@ -24,20 +24,24 @@ 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> ... ]
+help = 'turn regular GIT commits into StGIT patches'
+usage = """%prog [options] [<patchname1> [<patchname2> ... ]]
 
 Take one or more git commits at the base of the current stack and turn
 them into StGIT patches. The new patches are created as applied patches
 at the bottom of the stack. This is the exact opposite of 'stg commit'.
 
-By default, the number of the patches to uncommit is determined by the
+By default, the number of patches to uncommit is determined by the
 number of patch names provided on the command line. First name is used
 for the first patch to uncommit, i.e. for the newest patch.
 
 The --number option specifies the number of patches to uncommit.  In
-this case, only one patch name may be specified. It is used as prefix to
-which the patch number is appended.
+this case, at most one patch name may be specified. It is used as
+prefix to which the patch number is appended.
+
+If no patch names are provided on the command line, StGIT
+automatically generates them based on the first line of the patch
+description.
 
 Only commits with exactly one parent can be uncommitted; in other
 words, you can't uncommit a merge."""
@@ -46,33 +50,57 @@ 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')
+    """Uncommit a number of patches.
+    """
     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)]
+        if options.number <= 0:
+            parser.error('invalid value passed to --number')
+
+        patch_nr = options.number
+
+        if len(args) == 0:
+            patchnames = None
+        elif len(args) == 1:
+            # prefix specified
+            patchnames = ['%s%d' % (args[0], i)
+                          for i in xrange(patch_nr, 0, -1)]
+        else:
+            parser.error('when using --number, specify at most one patch name')
+    elif len(args) == 0:
+        patchnames = None
+        patch_nr = 1
     else:
         patchnames = args
+        patch_nr = len(patchnames)
 
     if crt_series.get_protected():
-        raise CmdException, 'This branch is protected. Uncommit is not permitted'
+        raise CmdException, \
+              'This branch is protected. Uncommit is not permitted'
 
-    print 'Uncommitting %d patches...' % len(patchnames),
+    print 'Uncommitting %d patches...' % patch_nr,
     sys.stdout.flush()
 
-    for patchname in patchnames:
-        base_file = crt_series.get_base_file()
+    base_file = crt_series.get_base_file()
+
+    for n in xrange(0, patch_nr):
+        # retrieve the commit (only commits with a single parent are allowed)
         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())
+            raise CmdException, 'Commit %s does not have exactly one parent' \
+                  % commit_id
+        author_name, author_email, author_date = \
+                     name_email_date(commit.get_author())
+
+        if patchnames:
+            patchname = patchnames[n]
+        else:
+            patchname = make_patch_name(commit.get_log())
+        if not patchname:
+            raise CmdException, 'Unknown patch name for commit %s' % commit_id
+
         crt_series.new_patch(patchname,
                              can_edit = False, before_existing = True,
                              top = commit_id, bottom = parent,
diff --git a/t/t1300-uncommit.sh b/t/t1300-uncommit.sh
new file mode 100755 (executable)
index 0000000..497c354
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Catalin Marinas
+#
+
+test_description='Test the uncommit command.
+
+'
+
+. ./test-lib.sh
+
+test_expect_success \
+       'Initialize the StGIT repository' \
+       'stg init
+'
+
+test_expect_success \
+       'Create the first patch' \
+       '
+       stg new foo -m "Foo Patch" &&
+       echo foo > test &&
+       stg add test &&
+       stg refresh
+       '
+
+test_expect_success \
+       'Create the second patch' \
+       '
+       stg new bar -m "Bar Patch" &&
+       echo bar > test &&
+       stg add test &&
+       stg refresh
+       '
+
+test_expect_success \
+       'Commit the patches' \
+       '
+       stg commit
+       '
+
+test_expect_success \
+       'Uncommit the patches using names' \
+       '
+       stg uncommit bar foo &&
+       [ "$(stg id foo//top)" == "$(stg id bar//bottom)" ] &&
+       stg commit
+       '
+
+test_expect_success \
+       'Uncommit the patches using prefix' \
+       '
+       stg uncommit --number=2 foobar &&
+       [ "$(stg id foobar1//top)" == "$(stg id foobar2//bottom)" ] &&
+       stg commit
+       '
+
+test_expect_success \
+       'Uncommit the patches using auto names' \
+       '
+       stg uncommit --number=2 &&
+       [ "$(stg id foo-patch//top)" == "$(stg id bar-patch//bottom)" ] &&
+       stg commit
+       '
+
+test_expect_success \
+       'Uncommit the patches one by one' \
+       '
+       stg uncommit &&
+       stg uncommit &&
+       [ "$(stg id foo-patch//top)" == "$(stg id bar-patch//bottom)" ] &&
+       stg commit
+       '
+test_done