chiark / gitweb /
218075b63a518dd904252778daca508d7f0146ec
[stgit] / stgit / commands / refresh.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 import sys, os
20 from optparse import OptionParser, make_option
21
22 from stgit.commands.common import *
23 from stgit.utils import *
24 from stgit.out import *
25 from stgit import stack, git
26 from stgit.config import config
27
28
29 help = 'generate a new commit for the current patch'
30 usage = """%prog [options] [<files...>]
31
32 Include the latest tree changes in the current patch. This command
33 generates a new GIT commit object with the patch details, the previous
34 one no longer being visible. The patch attributes like author,
35 committer and description can be changed with the command line
36 options. The '--force' option is useful when a commit object was
37 created with a different tool but the changes need to be included in
38 the current patch."""
39
40 options = [make_option('-f', '--force',
41                        help = 'force the refresh even if HEAD and '\
42                        'top differ',
43                        action = 'store_true'),
44            make_option('-e', '--edit',
45                        help = 'invoke an editor for the patch '\
46                        'description',
47                        action = 'store_true'),
48            make_option('-s', '--showpatch',
49                        help = 'show the patch content in the editor buffer',
50                        action = 'store_true'),
51            make_option('--update',
52                        help = 'only update the current patch files',
53                        action = 'store_true'),
54            make_option('--undo',
55                        help = 'revert the commit generated by the last refresh',
56                        action = 'store_true'),
57            make_option('-m', '--message',
58                        help = 'use MESSAGE as the patch ' \
59                        'description'),
60            make_option('-a', '--annotate', metavar = 'NOTE',
61                        help = 'annotate the patch log entry'),
62            make_option('--author', metavar = '"NAME <EMAIL>"',
63                        help = 'use "NAME <EMAIL>" as the author details'),
64            make_option('--authname',
65                        help = 'use AUTHNAME as the author name'),
66            make_option('--authemail',
67                        help = 'use AUTHEMAIL as the author e-mail'),
68            make_option('--authdate',
69                        help = 'use AUTHDATE as the author date'),
70            make_option('--commname',
71                        help = 'use COMMNAME as the committer name'),
72            make_option('--commemail',
73                        help = 'use COMMEMAIL as the committer ' \
74                        'e-mail'),
75            make_option('-p', '--patch',
76                        help = 'refresh (applied) PATCH instead of the top one'),
77            make_option('--sign',
78                        help = 'add Signed-off-by line',
79                        action = 'store_true'),
80            make_option('--ack',
81                        help = 'add Acked-by line',
82                        action = 'store_true')]
83
84
85 def func(parser, options, args):
86     autoresolved = config.get('stgit.autoresolved')
87
88     if autoresolved != 'yes':
89         check_conflicts()
90
91     if options.patch:
92         if args or options.update:
93             raise CmdException, \
94                   'Only full refresh is available with the --patch option'
95         patch = options.patch
96         if not crt_series.patch_applied(patch):
97             raise CmdException, 'Patches "%s" not applied' % patch
98     else:
99         patch = crt_series.get_current()
100         if not patch:
101             raise CmdException, 'No patches applied'
102
103     if not options.force:
104         check_head_top_equal()
105
106     if options.undo:
107         out.start('Undoing the refresh of "%s"' % patch)
108         crt_series.undo_refresh()
109         out.done()
110         return
111
112     if options.author:
113         options.authname, options.authemail = name_email(options.author)
114
115     if options.sign:
116         sign_str = 'Signed-off-by'
117         if options.ack:
118             raise CmdException, '--ack and --sign were both specified'
119     elif options.ack:
120         sign_str = 'Acked-by'
121     else:
122         sign_str = None
123
124     files = [x[1] for x in git.tree_status(verbose = True)]
125     if args:
126         files = [f for f in files if f in args]
127
128     if files or not crt_series.head_top_equal() \
129            or options.edit or options.message \
130            or options.authname or options.authemail or options.authdate \
131            or options.commname or options.commemail \
132            or options.sign or options.ack:
133
134         if options.patch:
135             applied = crt_series.get_applied()
136             between = applied[:applied.index(patch):-1]
137             pop_patches(between, keep = True)
138         elif options.update:
139             rev1 = git_id('//bottom')
140             rev2 = git_id('//top')
141             patch_files = git.barefiles(rev1, rev2).split('\n')
142             files = [f for f in files if f in patch_files]
143             if not files:
144                 out.info('No modified files for updating patch "%s"' % patch)
145                 return
146
147         out.start('Refreshing patch "%s"' % patch)
148
149         if autoresolved == 'yes':
150             resolved_all()
151         crt_series.refresh_patch(files = files,
152                                  message = options.message,
153                                  edit = options.edit,
154                                  show_patch = options.showpatch,
155                                  author_name = options.authname,
156                                  author_email = options.authemail,
157                                  author_date = options.authdate,
158                                  committer_name = options.commname,
159                                  committer_email = options.commemail,
160                                  backup = True, sign_str = sign_str,
161                                  notes = options.annotate)
162
163         if crt_series.empty_patch(patch):
164             out.done('empty patch')
165         else:
166             out.done()
167
168         if options.patch:
169             between.reverse()
170             push_patches(between)
171     elif options.annotate:
172         # only annotate the top log entry as there is no need to
173         # refresh the patch and generate a full commit
174         crt_series.log_patch(crt_series.get_patch(patch), None,
175                              notes = options.annotate)
176     else:
177         out.info('Patch "%s" is already up to date' % patch)