chiark / gitweb /
Generate command lists automatically
[stgit] / stgit / commands / series.py
1
2 __copyright__ = """
3 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 """
18
19 from stgit.argparse import opt
20 from stgit.commands import common
21 from stgit.commands.common import parse_patches
22 from stgit.out import out
23 from stgit.config import config
24
25 help = 'Print the patch series'
26 kind = 'stack'
27 usage = ['[options] [<patch-range>]']
28 description = """
29 Show all the patches in the series or just those in the given
30 range. The applied patches are prefixed with a '+', the unapplied ones
31 with a '-' and the hidden ones with a '!'. The current patch is
32 prefixed with a '>'. Empty patches are prefixed with a '0'."""
33
34 options = [
35     opt('-b', '--branch',
36         short = 'Use BRANCH instead of the default branch'),
37     opt('-a', '--all', action = 'store_true',
38         short = 'Show all patches, including the hidden ones'),
39     opt('-A', '--applied', action = 'store_true',
40         short = 'Show the applied patches only'),
41     opt('-U', '--unapplied', action = 'store_true',
42         short = 'Show the unapplied patches only'),
43     opt('-H', '--hidden', action = 'store_true',
44         short = 'Show the hidden patches only'),
45     opt('-m', '--missing', metavar = 'BRANCH',
46         short = 'Show patches in BRANCH missing in current'),
47     opt('-c', '--count', action = 'store_true',
48         short = 'Print the number of patches in the series'),
49     opt('-d', '--description', action = 'store_true',
50         short = 'Show a short description for each patch'),
51     opt('--author', action = 'store_true',
52         short = 'Show the author name for each patch'),
53     opt('-e', '--empty', action = 'store_true',
54         short = 'Check whether patches are empty'),
55     opt('--showbranch', action = 'store_true',
56         short = 'Append the branch name to the listed patches'),
57     opt('--noprefix', action = 'store_true',
58         short = 'Do not show the patch status prefix'),
59     opt('-s', '--short', action = 'store_true',
60         short = 'List just the patches around the topmost patch')]
61
62 directory = common.DirectoryHasRepositoryLib()
63
64 def __get_description(stack, patch):
65     """Extract and return a patch's short description
66     """
67     cd = stack.patches.get(patch).commit.data
68     descr = cd.message.strip()
69     descr_lines = descr.split('\n')
70     return descr_lines[0].rstrip()
71
72 def __get_author(stack, patch):
73     """Extract and return a patch's short description
74     """
75     cd = stack.patches.get(patch).commit.data
76     return cd.author.name
77
78 def __print_patch(stack, patch, branch_str, prefix, empty_prefix, length, options):
79     """Print a patch name, description and various markers.
80     """
81     if options.noprefix:
82         prefix = ''
83     elif options.empty and stack.patches.get(patch).is_empty():
84         prefix = empty_prefix
85
86     patch_str = branch_str + patch
87
88     if options.description or options.author:
89         patch_str = patch_str.ljust(length)
90
91     if options.description:
92         out.stdout(prefix + patch_str + ' # ' + __get_description(stack, patch))
93     elif options.author:
94         out.stdout(prefix + patch_str + ' # ' + __get_author(stack, patch))
95     else:
96         out.stdout(prefix + patch_str)
97
98 def func(parser, options, args):
99     """Show the patch series
100     """
101     if options.all and options.short:
102         raise common.CmdException, 'combining --all and --short is meaningless'
103
104     stack = directory.repository.get_stack(options.branch)
105     if options.missing:
106         cmp_stack = stack
107         stack = directory.repository.get_stack(options.missing)
108
109     # current series patches
110     applied = unapplied = hidden = ()
111     if options.applied or options.unapplied or options.hidden:
112         if options.all:
113             raise common.CmdException, \
114                 '--all cannot be used with --applied/unapplied/hidden'
115         if options.applied:
116             applied = stack.patchorder.applied
117         if options.unapplied:
118             unapplied = stack.patchorder.unapplied
119         if options.hidden:
120             hidden = stack.patchorder.hidden
121     elif options.all:
122         applied = stack.patchorder.applied
123         unapplied = stack.patchorder.unapplied
124         hidden = stack.patchorder.hidden
125     else:
126         applied = stack.patchorder.applied
127         unapplied = stack.patchorder.unapplied
128
129     if options.missing:
130         cmp_patches = cmp_stack.patchorder.all
131     else:
132         cmp_patches = ()
133
134     # the filtering range covers the whole series
135     if args:
136         show_patches = parse_patches(args, applied + unapplied + hidden,
137                                      len(applied))
138     else:
139         show_patches = applied + unapplied + hidden
140
141     # missing filtering
142     show_patches = [p for p in show_patches if p not in cmp_patches]
143
144     # filter the patches
145     applied = [p for p in applied if p in show_patches]
146     unapplied = [p for p in unapplied if p in show_patches]
147     hidden = [p for p in hidden if p in show_patches]
148
149     if options.short:
150         nr = int(config.get('stgit.shortnr'))
151         if len(applied) > nr:
152             applied = applied[-(nr+1):]
153         n = len(unapplied)
154         if n > nr:
155             unapplied = unapplied[:nr]
156         elif n < nr:
157             hidden = hidden[:nr-n]
158
159     patches = applied + unapplied + hidden
160
161     if options.count:
162         out.stdout(len(patches))
163         return
164
165     if not patches:
166         return
167
168     if options.showbranch:
169         branch_str = stack.name + ':'
170     else:
171         branch_str = ''
172
173     max_len = 0
174     if len(patches) > 0:
175         max_len = max([len(i + branch_str) for i in patches])
176
177     if applied:
178         for p in applied[:-1]:
179             __print_patch(stack, p, branch_str, '+ ', '0 ', max_len, options)
180         __print_patch(stack, applied[-1], branch_str, '> ', '0>', max_len,
181                       options)
182
183     for p in unapplied:
184         __print_patch(stack, p, branch_str, '- ', '0 ', max_len, options)
185
186     for p in hidden:
187         __print_patch(stack, p, branch_str, '! ', '! ', max_len, options)