Commit | Line | Data |
---|---|---|
6a093bbb CM |
1 | __copyright__ = """ |
2 | Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com> | |
3 | ||
4 | This program is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License version 2 as | |
6 | published by the Free Software Foundation. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program; if not, write to the Free Software | |
15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
16 | """ | |
17 | ||
575bbdae | 18 | from stgit.argparse import opt |
3b0552a7 KH |
19 | from stgit.commands import common |
20 | from stgit.lib import transaction | |
5e888f30 | 21 | from stgit.out import * |
6c8a90e1 | 22 | from stgit import argparse |
6a093bbb | 23 | |
575bbdae | 24 | help = 'Permanently store the applied patches into the stack base' |
33ff9cdd | 25 | kind = 'stack' |
575bbdae | 26 | usage = ['', |
54239abf | 27 | '[--] <patchnames>', |
575bbdae KH |
28 | '-n NUM', |
29 | '--all'] | |
30 | description = """ | |
980bde6a KH |
31 | Merge one or more patches into the base of the current stack and |
32 | remove them from the series while advancing the base. This is the | |
33 | opposite of 'stg uncommit'. Use this command if you no longer want to | |
34 | manage a patch with StGIT. | |
6a093bbb | 35 | |
980bde6a KH |
36 | By default, the bottommost patch is committed. If patch names are |
37 | given, the stack is rearranged so that those patches are at the | |
38 | bottom, and then they are committed. | |
6a093bbb | 39 | |
980bde6a KH |
40 | The -n/--number option specifies the number of applied patches to |
41 | commit (counting from the bottom of the stack). If -a/--all is given, | |
42 | all applied patches are committed.""" | |
6a093bbb | 43 | |
6c8a90e1 KH |
44 | args = [argparse.patch_range(argparse.applied_patches, |
45 | argparse.unapplied_patches)] | |
575bbdae KH |
46 | options = [ |
47 | opt('-n', '--number', type = 'int', | |
48 | short = 'Commit the specified number of patches'), | |
49 | opt('-a', '--all', action = 'store_true', | |
50 | short = 'Commit all applied patches')] | |
51 | ||
980bde6a | 52 | directory = common.DirectoryHasRepositoryLib() |
6a093bbb CM |
53 | |
54 | def func(parser, options, args): | |
980bde6a | 55 | """Commit a number of patches.""" |
3b0552a7 | 56 | stack = directory.repository.current_stack |
d454cc06 | 57 | args = common.parse_patches(args, list(stack.patchorder.all_visible)) |
980bde6a KH |
58 | if len([x for x in [args, options.number != None, options.all] if x]) > 1: |
59 | parser.error('too many options') | |
60 | if args: | |
d454cc06 | 61 | patches = [pn for pn in stack.patchorder.all_visible if pn in args] |
980bde6a KH |
62 | bad = set(args) - set(patches) |
63 | if bad: | |
d454cc06 | 64 | raise common.CmdException('Nonexistent or hidden patch names: %s' |
980bde6a KH |
65 | % ', '.join(sorted(bad))) |
66 | elif options.number != None: | |
67 | if options.number <= len(stack.patchorder.applied): | |
68 | patches = stack.patchorder.applied[:options.number] | |
69 | else: | |
70 | raise common.CmdException('There are not that many applied patches') | |
71 | elif options.all: | |
72 | patches = stack.patchorder.applied | |
73 | else: | |
74 | patches = stack.patchorder.applied[:1] | |
3b0552a7 | 75 | if not patches: |
980bde6a KH |
76 | raise common.CmdException('No patches to commit') |
77 | ||
a0848ecf | 78 | iw = stack.repository.default_iw |
781e549a KH |
79 | def allow_conflicts(trans): |
80 | # As long as the topmost patch stays where it is, it's OK to | |
81 | # run "stg commit" with conflicts in the index. | |
82 | return len(trans.applied) >= 1 | |
83 | trans = transaction.StackTransaction(stack, 'commit', | |
84 | allow_conflicts = allow_conflicts) | |
980bde6a KH |
85 | try: |
86 | common_prefix = 0 | |
87 | for i in xrange(min(len(stack.patchorder.applied), len(patches))): | |
88 | if stack.patchorder.applied[i] == patches[i]: | |
89 | common_prefix += 1 | |
d8a700cf CM |
90 | else: |
91 | break | |
980bde6a | 92 | if common_prefix < len(patches): |
d8a700cf CM |
93 | to_push = [pn for pn in stack.patchorder.applied[common_prefix:] |
94 | if pn not in patches[common_prefix:]] | |
95 | # this pops all the applied patches from common_prefix | |
96 | trans.pop_patches(lambda pn: pn in to_push) | |
980bde6a KH |
97 | for pn in patches[common_prefix:]: |
98 | trans.push_patch(pn, iw) | |
99 | else: | |
100 | to_push = [] | |
101 | new_base = trans.patches[patches[-1]] | |
102 | for pn in patches: | |
103 | trans.patches[pn] = None | |
104 | trans.applied = [pn for pn in trans.applied if pn not in patches] | |
105 | trans.base = new_base | |
106 | out.info('Committed %d patch%s' % (len(patches), | |
107 | ['es', ''][len(patches) == 1])) | |
108 | for pn in to_push: | |
109 | trans.push_patch(pn, iw) | |
110 | except transaction.TransactionHalted: | |
111 | pass | |
112 | return trans.run(iw) |