X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/stgit/blobdiff_plain/fff9bce57321720677a897e3c811538eea6a9cb6..7b601c9e979785f3521395a4f8b2abbe0b6408eb:/stgit/commands/pick.py diff --git a/stgit/commands/pick.py b/stgit/commands/pick.py index 1aa83d0..5b45434 100644 --- a/stgit/commands/pick.py +++ b/stgit/commands/pick.py @@ -20,7 +20,9 @@ from optparse import OptionParser, make_option from stgit.commands.common import * from stgit.utils import * +from stgit.out import * from stgit import stack, git +from stgit.stack import Series help = 'import a patch from a different branch or a commit object' @@ -32,16 +34,25 @@ the name of the current patch. It can be overridden with the '--name' option. A commit object can be reverted with the '--reverse' option. The log and author information are those of the commit object.""" +directory = DirectoryGotoToplevel() options = [make_option('-n', '--name', help = 'use NAME as the patch name'), make_option('-r', '--reverse', help = 'reverse the commit object before importing', action = 'store_true'), + make_option('-p', '--parent', metavar = 'COMMITID', + help = 'use COMMITID as parent'), + make_option('-x', '--expose', + help = 'append the imported commit id to the patch log', + action = 'store_true'), make_option('--fold', help = 'fold the commit object into the current patch', action = 'store_true'), make_option('--update', help = 'like fold but only update the current patch files', + action = 'store_true'), + make_option('--unapplied', + help = 'keep the patch unapplied', action = 'store_true')] @@ -51,12 +62,13 @@ def func(parser, options, args): if len(args) != 1: parser.error('incorrect number of arguments') - check_local_changes() - check_conflicts() - check_head_top_equal() + if not options.unapplied: + check_local_changes() + check_conflicts() + check_head_top_equal(crt_series) commit_str = args[0] - commit_id = git_id(commit_str) + commit_id = git_id(crt_series, commit_str) commit = git.Commit(commit_id) if options.fold or options.update: @@ -65,62 +77,90 @@ def func(parser, options, args): else: patch_branch = commit_str.split('@') if options.name: - patch = options.name + patchname = options.name elif len(patch_branch) == 2: - patch = patch_branch[0] + patchname = patch_branch[0] else: - patch = make_patch_name(commit.get_log()) - if not patch: - raise CmdException, 'Unknown patch name' + patchname = None + + if options.parent: + parent = git_id(crt_series, options.parent) + else: + parent = commit.get_parent() if not options.reverse: - bottom = commit.get_parent() + bottom = parent top = commit_id else: bottom = commit_id - top = commit.get_parent() + top = parent if options.fold: - print 'Folding commit %s...' % commit_id, - sys.stdout.flush() + out.start('Folding commit %s' % commit_id) # try a direct git-apply first if not git.apply_diff(bottom, top): - git.merge(bottom, git.get_head(), top) + git.merge(bottom, git.get_head(), top, recursive = True) - print 'done' + out.done() elif options.update: - rev1 = git_id('//bottom') - rev2 = git_id('//top') + rev1 = git_id(crt_series, '//bottom') + rev2 = git_id(crt_series, '//top') files = git.barefiles(rev1, rev2).split('\n') - print 'Updating with commit %s...' % commit_id, - sys.stdout.flush() + out.start('Updating with commit %s' % commit_id) if not git.apply_diff(bottom, top, files = files): raise CmdException, 'Patch updating failed' - print 'done' + out.done() else: message = commit.get_log() + if options.expose: + message += '(imported from commit %s)\n' % commit.get_id_hash() author_name, author_email, author_date = \ name_email_date(commit.get_author()) - print 'Importing commit %s...' % commit_id, - sys.stdout.flush() - - crt_series.new_patch(patch, message = message, can_edit = False, - unapplied = True, bottom = bottom, top = top, - author_name = author_name, - author_email = author_email, - author_date = author_date) - modified = crt_series.push_patch(patch) + out.start('Importing commit %s' % commit_id) + + newpatch = crt_series.new_patch(patchname, message = message, can_edit = False, + unapplied = True, bottom = bottom, top = top, + author_name = author_name, + author_email = author_email, + author_date = author_date) + # in case the patch name was automatically generated + patchname = newpatch.get_name() + + # find a patchlog to fork from + (refpatchname, refbranchname, refpatchid) = parse_rev(commit_str) + if refpatchname and not refpatchid and \ + (not refpatchid or refpatchid == 'top'): + # FIXME: should also support picking //top.old + if refbranchname: + # assume the refseries is OK, since we already resolved + # commit_str to a git_id + refseries = Series(refbranchname) + else: + refseries = crt_series + patch = refseries.get_patch(refpatchname) + if patch.get_log(): + out.info("Log was %s" % newpatch.get_log()) + out.info("Setting log to %s\n" % patch.get_log()) + newpatch.set_log(patch.get_log()) + out.info("Log is now %s" % newpatch.get_log()) + else: + out.info("No log for %s\n" % patchname) + + if not options.unapplied: + modified = crt_series.push_patch(patchname) + else: + modified = False - if crt_series.empty_patch(patch): - print 'done (empty patch)' + if crt_series.empty_patch(patchname): + out.done('empty patch') elif modified: - print 'done (modified)' + out.done('modified') else: - print 'done' - - print_crt_patch() + out.done() + + print_crt_patch(crt_series)