Fixes for auto-generation of man pages
[stgit] / stgit / commands / pick.py
CommitLineData
0618ea9c
CM
1__copyright__ = """
2Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License version 2 as
6published by the Free Software Foundation.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16"""
17
18import sys, os
575bbdae 19from stgit.argparse import opt
0618ea9c
CM
20from stgit.commands.common import *
21from stgit.utils import *
5e888f30 22from stgit.out import *
0618ea9c 23from stgit import stack, git
8fce9909 24from stgit.stack import Series
0618ea9c 25
575bbdae 26help = 'Import a patch from a different branch or a commit object'
33ff9cdd 27kind = 'patch'
575bbdae
KH
28usage = ['[options] ([<patch1>] [<patch2>] [<patch3>..<patch4>])|<commit>']
29description = """
074f71bb
CM
30Import one or more patches from a different branch or a commit object
31into the current series. By default, the name of the imported patch is
32used as the name of the current patch. It can be overridden with the
33'--name' option. A commit object can be reverted with the '--reverse'
34option. The log and author information are those of the commit
35object."""
0618ea9c 36
575bbdae
KH
37options = [
38 opt('-n', '--name',
39 short = 'Use NAME as the patch name'),
40 opt('-B', '--ref-branch',
41 short = 'Pick patches from BRANCH'),
42 opt('-r', '--reverse', action = 'store_true',
43 short = 'Reverse the commit object before importing'),
44 opt('-p', '--parent', metavar = 'COMMITID',
45 short = 'Use COMMITID as parent'),
46 opt('-x', '--expose', action = 'store_true',
47 short = 'Append the imported commit id to the patch log'),
48 opt('--fold', action = 'store_true',
49 short = 'Fold the commit object into the current patch'),
50 opt('--update', action = 'store_true',
51 short = 'Like fold but only update the current patch files'),
52 opt('--unapplied', action = 'store_true',
53 short = 'Keep the patch unapplied')]
54
7b601c9e 55directory = DirectoryGotoToplevel()
0618ea9c 56
074f71bb
CM
57def __pick_commit(commit_id, patchname, options):
58 """Pick a commit id.
0618ea9c 59 """
fff9bce5 60 commit = git.Commit(commit_id)
0618ea9c 61
074f71bb
CM
62 if options.name:
63 patchname = options.name
0618ea9c 64
89e3bc51 65 if options.parent:
6972fd6b 66 parent = git_id(crt_series, options.parent)
89e3bc51
YD
67 else:
68 parent = commit.get_parent()
69
0618ea9c 70 if not options.reverse:
89e3bc51 71 bottom = parent
0618ea9c
CM
72 top = commit_id
73 else:
74 bottom = commit_id
89e3bc51 75 top = parent
0618ea9c 76
ba524d4c 77 if options.fold:
27ac2b7e 78 out.start('Folding commit %s' % commit_id)
0618ea9c 79
04b44217 80 # try a direct git apply first
d218d2f8 81 if not git.apply_diff(bottom, top):
fab69eac 82 git.merge_recursive(bottom, git.get_head(), top)
5f9ce587 83
27ac2b7e 84 out.done()
d0bfda1a 85 elif options.update:
e4560d7e
CM
86 rev1 = git_id(crt_series, 'HEAD^')
87 rev2 = git_id(crt_series, 'HEAD')
d0bfda1a
CM
88 files = git.barefiles(rev1, rev2).split('\n')
89
27ac2b7e 90 out.start('Updating with commit %s' % commit_id)
d0bfda1a
CM
91
92 if not git.apply_diff(bottom, top, files = files):
93 raise CmdException, 'Patch updating failed'
94
27ac2b7e 95 out.done()
ba524d4c
CM
96 else:
97 message = commit.get_log()
2ff25eb8
CM
98 if options.expose:
99 message += '(imported from commit %s)\n' % commit.get_id_hash()
ba524d4c
CM
100 author_name, author_email, author_date = \
101 name_email_date(commit.get_author())
102
27ac2b7e 103 out.start('Importing commit %s' % commit_id)
0618ea9c 104
8fce9909
YD
105 newpatch = crt_series.new_patch(patchname, message = message, can_edit = False,
106 unapplied = True, bottom = bottom, top = top,
107 author_name = author_name,
108 author_email = author_email,
109 author_date = author_date)
e2b1102c
CM
110 # in case the patch name was automatically generated
111 patchname = newpatch.get_name()
112
8fce9909 113 # find a patchlog to fork from
e4560d7e
CM
114 refbranchname, refpatchname = parse_rev(patchname)
115 if refpatchname:
8fce9909
YD
116 if refbranchname:
117 # assume the refseries is OK, since we already resolved
118 # commit_str to a git_id
119 refseries = Series(refbranchname)
120 else:
121 refseries = crt_series
122 patch = refseries.get_patch(refpatchname)
123 if patch.get_log():
27ac2b7e
KH
124 out.info("Log was %s" % newpatch.get_log())
125 out.info("Setting log to %s\n" % patch.get_log())
8fce9909 126 newpatch.set_log(patch.get_log())
27ac2b7e 127 out.info("Log is now %s" % newpatch.get_log())
8fce9909 128 else:
27ac2b7e
KH
129 out.info("No log for %s\n" % patchname)
130
7829d19d 131 if not options.unapplied:
2e88afce 132 modified = crt_series.push_patch(patchname)
7829d19d
CM
133 else:
134 modified = False
0618ea9c 135
2e88afce 136 if crt_series.empty_patch(patchname):
27ac2b7e 137 out.done('empty patch')
5f9ce587 138 elif modified:
27ac2b7e 139 out.done('modified')
5f9ce587 140 else:
27ac2b7e
KH
141 out.done()
142
074f71bb
CM
143
144def func(parser, options, args):
145 """Import a commit object as a new patch
146 """
147 if not args:
148 parser.error('incorrect number of arguments')
149
150 if not options.unapplied:
151 check_local_changes()
152 check_conflicts()
153 check_head_top_equal(crt_series)
154
155 if options.ref_branch:
156 remote_series = Series(options.ref_branch)
157 else:
158 remote_series = crt_series
159
160 applied = remote_series.get_applied()
161 unapplied = remote_series.get_unapplied()
162 try:
d3cb28ca 163 patches = parse_patches(args, applied + unapplied, len(applied))
074f71bb
CM
164 commit_id = None
165 except CmdException:
d714caa1 166 if len(args) > 1:
074f71bb
CM
167 raise
168 # no patches found, try a commit id
169 commit_id = git_id(remote_series, args[0])
170
d714caa1 171 if not commit_id and len(patches) > 1:
074f71bb
CM
172 if options.name:
173 raise CmdException, '--name can only be specified with one patch'
174 if options.parent:
175 raise CmdException, '--parent can only be specified with one patch'
176
177 if (options.fold or options.update) and not crt_series.get_current():
178 raise CmdException, 'No patches applied'
179
180 if commit_id:
181 __pick_commit(commit_id, None, options)
182 else:
183 if options.unapplied:
184 patches.reverse()
185 for patch in patches:
186 __pick_commit(git_id(remote_series, patch), patch, options)
187
6972fd6b 188 print_crt_patch(crt_series)