push/pop: Allow "-n0" to do nothing
[stgit] / stgit / commands / push.py
... / ...
CommitLineData
1
2__copyright__ = """
3Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License version 2 as
7published by the Free Software Foundation.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17"""
18
19from stgit.commands import common
20from stgit.lib import transaction
21from stgit import argparse
22from stgit.argparse import opt
23
24help = 'Push one or more patches onto the stack'
25kind = 'stack'
26usage = ['[options] [<patch1>] [<patch2>] [<patch3>..<patch4>]']
27description = """
28Push one or more patches (defaulting to the first unapplied one) onto
29the stack. The 'push' operation allows patch reordering by commuting
30them with the three-way merge algorithm. If there are conflicts while
31pushing a patch, those conflicts are written to the work tree, and the
32command halts. Conflicts raised during the push operation have to be
33fixed and the 'git add --update' command run (alternatively, you may
34undo the conflicting push with 'stg undo').
35
36The command also notifies when the patch becomes empty (fully merged
37upstream) or is modified (three-way merged) by the 'push' operation."""
38
39args = [argparse.patch_range(argparse.unapplied_patches)]
40options = [
41 opt('-a', '--all', action = 'store_true',
42 short = 'Push all the unapplied patches'),
43 opt('-n', '--number', type = 'int',
44 short = 'Push the specified number of patches', long = '''
45 Push the specified number of patches.
46
47 With a negative number, push all but that many patches.'''),
48 opt('--reverse', action = 'store_true',
49 short = 'Push the patches in reverse order'),
50 opt('--set-tree', action = 'store_true',
51 short = 'Push the patch with the original tree', long = """
52 Push the patches, but don't perform a merge. Instead, the
53 resulting tree will be identical to the tree that the patch
54 previously created.
55
56 This can be useful when splitting a patch by first popping the
57 patch and creating a new patch with some of the
58 changes. Pushing the original patch with '--set-tree' will
59 avoid conflicts and only the remaining changes will be in the
60 patch.""")
61 ] + argparse.keep_option() + argparse.merged_option()
62
63directory = common.DirectoryHasRepositoryLib()
64
65def func(parser, options, args):
66 """Pushes the given patches or the first unapplied onto the stack."""
67 stack = directory.repository.current_stack
68 iw = stack.repository.default_iw
69 clean_iw = (not options.keep and iw) or None
70 trans = transaction.StackTransaction(stack, 'pop',
71 check_clean_iw = clean_iw)
72
73 if options.number == 0:
74 # explicitly allow this without any warning/error message
75 return
76
77 if not trans.unapplied:
78 raise common.CmdException('No patches to push')
79
80 if options.all:
81 patches = list(trans.unapplied)
82 elif options.number is not None:
83 patches = trans.unapplied[:options.number]
84 elif not args:
85 patches = [trans.unapplied[0]]
86 else:
87 patches = common.parse_patches(args, trans.unapplied)
88
89 if not patches:
90 raise common.CmdException('No patches to push')
91
92 if options.reverse:
93 patches.reverse()
94
95 if options.set_tree:
96 for pn in patches:
97 trans.push_tree(pn)
98 else:
99 try:
100 if options.merged:
101 merged = set(trans.check_merged(patches))
102 else:
103 merged = set()
104 for pn in patches:
105 trans.push_patch(pn, iw, allow_interactive = True,
106 already_merged = pn in merged)
107 except transaction.TransactionHalted:
108 pass
109 return trans.run(iw)