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'
-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):
- """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
- 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:
- 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')
- 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)