1 from stgit
.argparse
import opt
, patch_range
2 from stgit
.commands
.common
import (
13 from stgit
.config
import config
14 from stgit
.lib
.git
import CommitData
, MergeConflictException
, MergeException
, Person
15 from stgit
.lib
.transaction
import StackTransaction
, TransactionHalted
16 from stgit
.out
import out
17 from stgit
.run
import Run
18 from stgit
.utils
import STGIT_CONFLICT
, STGIT_SUCCESS
21 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
23 This program is free software; you can redistribute it and/or modify
24 it under the terms of the GNU General Public License version 2 as
25 published by the Free Software Foundation.
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, see http://www.gnu.org/licenses/.
36 help = 'Import a patch from a different branch or a commit object'
38 usage
= ['[options] [--] ([<patch1>] [<patch2>] [<patch3>..<patch4>])|<commit>']
40 Import one or more patches from a different branch or a commit object
41 into the current series. By default, the name of the imported patch is
42 used as the name of the current patch. It can be overridden with the
43 '--name' option. A commit object can be reverted with the '--revert'
44 option. The log and author information are those of the commit
47 When using the '--expose' option, the format of the commit message is
48 determined by the 'stgit.pick.expose-format' configuration option. This option
49 is a format string as may supplied as the '--pretty' option to
50 linkgit:git-show[1]. The default is "format:%B%n(imported from commit %H)",
51 which appends the commit hash of the picked commit to the patch's commit
55 args
= [patch_range('applied_patches', 'unapplied_patches', 'hidden_patches')]
60 short
='Use NAME as the patch name',
65 args
=['stg_branches'],
66 short
='Pick patches from BRANCH',
72 short
='Revert the given commit object',
79 short
='Use COMMITID as parent',
85 short
='Append the imported commit id to the patch log',
90 short
='Fold the commit object into the current patch',
95 short
='Like fold but only update the current patch files',
101 short
='Only fold the given file (can be used multiple times)',
106 short
='Keep the patch unapplied',
110 directory
= DirectoryGotoTopLevel()
113 def __pick_commit(stack
, ref_stack
, iw
, commit
, patchname
, options
):
115 repository
= stack
.repository
118 patchname
= options
.name
119 elif patchname
and options
.revert
:
120 patchname
= 'revert-' + patchname
123 patchname
= stack
.patches
.make_name(patchname
, lower
=False)
125 patchname
= stack
.patches
.make_name(commit
.data
.message_str
)
128 parent
= git_commit(options
.parent
, repository
, ref_stack
.name
)
130 parent
= commit
.data
.parent
132 if not options
.revert
:
140 out
.start('Folding commit %s' % commit
.sha1
)
142 diff
= repository
.diff_tree(
143 bottom
.data
.tree
, top
.data
.tree
, pathlimits
=options
.file
148 # try a direct git apply first
149 iw
.apply(diff
, quiet
=True)
150 except MergeException
:
152 out
.done('conflict(s)')
153 out
.error('%s does not apply cleanly' % patchname
)
154 return STGIT_CONFLICT
159 stack
.head
.data
.tree
,
162 except MergeConflictException
as e
:
163 out
.done('%s conflicts' % len(e
.conflicts
))
164 out
.error('%s does not apply cleanly' % patchname
, *e
.conflicts
)
165 return STGIT_CONFLICT
168 out
.done('no changes')
173 for _
, _
, _
, _
, _
, fn1
, fn2
in repository
.diff_tree_files(
174 stack
.top
.data
.parent
.data
.tree
, stack
.top
.data
.tree
178 diff
= repository
.diff_tree(bottom
.data
.tree
, top
.data
.tree
, pathlimits
=files
)
180 out
.start('Updating with commit %s' % commit
.sha1
)
183 iw
.apply(diff
, quiet
=True)
184 except MergeException
:
185 out
.done('conflict(s)')
186 out
.error('%s does not apply cleanly' % patchname
)
187 return STGIT_CONFLICT
192 author
= commit
.data
.author
193 message
= commit
.data
.message_str
196 author
= Person
.author()
198 lines
= message
.splitlines()
200 body
= '\n'.join(lines
[2:])
202 subject
= commit
.sha1
204 message
= 'Revert "%s"\n\nThis reverts commit %s.\n\n%s\n' % (
210 fmt
= config
.get('stgit.pick.expose-format')
212 'git', 'show', '--no-patch', '--pretty=' + fmt
, commit
.sha1
214 message
= message
.rstrip() + '\n'
216 out
.start('Importing commit %s' % commit
.sha1
)
218 new_commit
= repository
.commit(
227 trans
= StackTransaction(stack
, 'pick %s from %s' % (patchname
, ref_stack
.name
))
228 trans
.patches
[patchname
] = new_commit
230 trans
.unapplied
.append(patchname
)
231 if not options
.unapplied
:
233 trans
.push_patch(patchname
, iw
, allow_interactive
=True)
234 except TransactionHalted
:
237 retval
= trans
.run(iw
, print_current_patch
=False)
239 if retval
== STGIT_CONFLICT
:
240 out
.done('conflict(s)')
241 elif stack
.patches
.get(patchname
).is_empty():
242 out
.done('empty patch')
249 def func(parser
, options
, args
):
250 """Import a commit object as a new patch"""
252 parser
.error('incorrect number of arguments')
254 if options
.file and not options
.fold
:
255 parser
.error('--file can only be specified with --fold')
257 repository
= directory
.repository
258 stack
= repository
.get_stack()
259 iw
= repository
.default_iw
261 if not options
.unapplied
:
262 check_local_changes(repository
)
264 check_head_top_equal(stack
)
266 if options
.ref_branch
:
267 ref_stack
= repository
.get_stack(options
.ref_branch
)
272 patches
= parse_patches(
274 ref_stack
.patchorder
.all_visible
,
275 len(ref_stack
.patchorder
.applied
),
282 branch
, patch
= parse_rev(args
[0])
285 commit
= git_commit(patch
, repository
, options
.ref_branch
)
288 ref_stack
= repository
.get_stack(branch
)
289 patches
= parse_patches(
291 ref_stack
.patchorder
.all_visible
,
292 len(ref_stack
.patchorder
.applied
),
296 if not commit
and len(patches
) > 1:
298 raise CmdException('--name can only be specified with one patch')
300 raise CmdException('--parent can only be specified with one patch')
302 if options
.update
and not stack
.patchorder
.applied
:
303 raise CmdException('No patches applied')
307 retval
= __pick_commit(stack
, ref_stack
, iw
, commit
, patchname
, options
)
309 if options
.unapplied
:
311 for patchname
in patches
:
312 commit
= git_commit(patchname
, repository
, ref_stack
.name
)
313 retval
= __pick_commit(stack
, ref_stack
, iw
, commit
, patchname
, options
)
314 if retval
!= STGIT_SUCCESS
:
317 if retval
== STGIT_SUCCESS
:
318 print_current_patch(stack
)