chiark / gitweb /
Make "stg commit" fancier
authorKarl Hasselström <kha@treskal.com>
Wed, 12 Dec 2007 22:48:56 +0000 (23:48 +0100)
committerKarl Hasselström <kha@treskal.com>
Wed, 9 Jan 2008 23:37:13 +0000 (00:37 +0100)
Allow the user to commit any patch. Changed behavior: with no
parameters, commit one applied patch, not all applied patches -- this
is what uncommit does.

Signed-off-by: Karl Hasselström <kha@treskal.com>
stgit/commands/commit.py
stgit/commands/uncommit.py
stgit/lib/transaction.py
t/t1300-uncommit.sh

index f82218176aa9667eb9ff17a7316f79f3eb439af9..1d741b36beffd7642bb5b7cbebc1b7bf0c4e9c03 100644 (file)
@@ -15,39 +15,82 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
+from optparse import make_option
 from stgit.commands import common
 from stgit.lib import transaction
 from stgit.out import *
 
 help = 'permanently store the applied patches into stack base'
 from stgit.commands import common
 from stgit.lib import transaction
 from stgit.out import *
 
 help = 'permanently store the applied patches into stack base'
-usage = """%prog [options]
+usage = """%prog [<patchnames>] | -n NUM | --all
 
 
-Merge the applied patches into the base of the current stack and
-remove them from the series while advancing the base.
+Merge one or more patches into the base of the current stack and
+remove them from the series while advancing the base. This is the
+opposite of 'stg uncommit'. Use this command if you no longer want to
+manage a patch with StGIT.
 
 
-Use this command only if you want to permanently store the applied
-patches and no longer manage them with StGIT."""
+By default, the bottommost patch is committed. If patch names are
+given, the stack is rearranged so that those patches are at the
+bottom, and then they are committed.
 
 
-directory = common.DirectoryHasRepositoryLib()
-options = []
+The -n/--number option specifies the number of applied patches to
+commit (counting from the bottom of the stack). If -a/--all is given,
+all applied patches are committed."""
 
 
+directory = common.DirectoryHasRepositoryLib()
+options = [make_option('-n', '--number', type = 'int',
+                       help = 'commit the specified number of patches'),
+           make_option('-a', '--all', action = 'store_true',
+                       help = 'commit all applied patches')]
 
 def func(parser, options, args):
 
 def func(parser, options, args):
-    """Merge the applied patches into the base of the current stack
-       and remove them from the series while advancing the base
-    """
-    if len(args) != 0:
-        parser.error('incorrect number of arguments')
-
+    """Commit a number of patches."""
     stack = directory.repository.current_stack
     stack = directory.repository.current_stack
-    patches = stack.patchorder.applied
+    args = common.parse_patches(args, (list(stack.patchorder.applied)
+                                       + list(stack.patchorder.unapplied)))
+    if len([x for x in [args, options.number != None, options.all] if x]) > 1:
+        parser.error('too many options')
+    if args:
+        patches = [pn for pn in (stack.patchorder.applied
+                                 + stack.patchorder.unapplied) if pn in args]
+        bad = set(args) - set(patches)
+        if bad:
+            raise common.CmdException('Bad patch names: %s'
+                                      % ', '.join(sorted(bad)))
+    elif options.number != None:
+        if options.number <= len(stack.patchorder.applied):
+            patches = stack.patchorder.applied[:options.number]
+        else:
+            raise common.CmdException('There are not that many applied patches')
+    elif options.all:
+        patches = stack.patchorder.applied
+    else:
+        patches = stack.patchorder.applied[:1]
     if not patches:
     if not patches:
-        raise CmdException('No patches to commit')
-    out.start('Committing %d patches' % len(patches))
+        raise common.CmdException('No patches to commit')
+
+    iw = stack.repository.default_iw()
     trans = transaction.StackTransaction(stack, 'stg commit')
     trans = transaction.StackTransaction(stack, 'stg commit')
-    for pn in patches:
-        trans.patches[pn] = None
-    trans.applied = []
-    trans.base = stack.head
-    trans.run()
-    out.done()
+    try:
+        common_prefix = 0
+        for i in xrange(min(len(stack.patchorder.applied), len(patches))):
+            if stack.patchorder.applied[i] == patches[i]:
+                common_prefix += 1
+        if common_prefix < len(patches):
+            to_push = trans.pop_patches(
+                lambda pn: pn in stack.patchorder.applied[common_prefix:])
+            for pn in patches[common_prefix:]:
+                trans.push_patch(pn, iw)
+        else:
+            to_push = []
+        new_base = trans.patches[patches[-1]]
+        for pn in patches:
+            trans.patches[pn] = None
+        trans.applied = [pn for pn in trans.applied if pn not in patches]
+        trans.base = new_base
+        out.info('Committed %d patch%s' % (len(patches),
+                                           ['es', ''][len(patches) == 1]))
+        for pn in to_push:
+            trans.push_patch(pn, iw)
+    except transaction.TransactionHalted:
+        pass
+    return trans.run(iw)
index 842295296bbc76922508825a0226c3d372932803..933ec60adf0f4ccf942efa5fcfe59b606d06771a 100644 (file)
@@ -28,7 +28,7 @@ usage = """%prog [<patchnames>] | -n NUM [<prefix>]] | -t <committish> [-x]
 
 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
 
 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'.
+at the bottom of the stack. This is the opposite of 'stg commit'.
 
 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
 
 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
index a7c4f7e890aaa4d85023b5e1a3e17c8f360e8781..a60c5ff62b2de498cc2ca00df3f49b5a03838ce5 100644 (file)
@@ -51,7 +51,8 @@ class StackTransaction(object):
         self.__unapplied = list(val)
     unapplied = property(lambda self: self.__unapplied, __set_unapplied)
     def __set_base(self, val):
         self.__unapplied = list(val)
     unapplied = property(lambda self: self.__unapplied, __set_unapplied)
     def __set_base(self, val):
-        assert not self.__applied
+        assert (not self.__applied
+                or self.patches[self.applied[0]].data.parent == val)
         self.__base = val
     base = property(lambda self: self.__base, __set_base)
     def __checkout(self, tree, iw):
         self.__base = val
     base = property(lambda self: self.__base, __set_base)
     def __checkout(self, tree, iw):
index 85408fdce8e8759219b5a44efca0598dac7b1327..d86e579382a805cdb994e3eb27825da855120148 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success \
 test_expect_success \
        'Commit the patches' \
        '
 test_expect_success \
        'Commit the patches' \
        '
-       stg commit
+       stg commit --all
        '
 
 test_expect_success \
        '
 
 test_expect_success \
@@ -43,7 +43,7 @@ test_expect_success \
        '
        stg uncommit bar foo &&
        [ "$(stg id foo//top)" = "$(stg id bar//bottom)" ] &&
        '
        stg uncommit bar foo &&
        [ "$(stg id foo//top)" = "$(stg id bar//bottom)" ] &&
-       stg commit
+       stg commit --all
        '
 
 test_expect_success \
        '
 
 test_expect_success \
@@ -51,7 +51,7 @@ test_expect_success \
        '
        stg uncommit --number=2 foobar &&
        [ "$(stg id foobar1//top)" = "$(stg id foobar2//bottom)" ] &&
        '
        stg uncommit --number=2 foobar &&
        [ "$(stg id foobar1//top)" = "$(stg id foobar2//bottom)" ] &&
-       stg commit
+       stg commit --all
        '
 
 test_expect_success \
        '
 
 test_expect_success \
@@ -59,7 +59,7 @@ test_expect_success \
        '
        stg uncommit --number=2 &&
        [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
        '
        stg uncommit --number=2 &&
        [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
-       stg commit
+       stg commit --all
        '
 
 test_expect_success \
        '
 
 test_expect_success \
@@ -68,14 +68,14 @@ test_expect_success \
        stg uncommit &&
        stg uncommit &&
        [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
        stg uncommit &&
        stg uncommit &&
        [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
-       stg commit
+       stg commit --all
        '
 
 test_expect_success \
     'Uncommit the patches with --to' '
     stg uncommit --to HEAD^ &&
     [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
        '
 
 test_expect_success \
     'Uncommit the patches with --to' '
     stg uncommit --to HEAD^ &&
     [ "$(stg id foo-patch//top)" = "$(stg id bar-patch//bottom)" ] &&
-    stg commit
+    stg commit --all
 '
 
 test_done
 '
 
 test_done