"""
import sys, os
-from optparse import OptionParser, make_option
-
+from stgit.argparse import opt
from stgit.commands.common import *
from stgit.utils import *
from stgit.out import *
-from stgit import stack, git
+from stgit import argparse, stack, git
from stgit.stack import Series
-
-help = 'import a patch from a different branch or a commit object'
-usage = """%prog [options] ([<patch1>] [<patch2>] [<patch3>..<patch4>])|<commit>
-
+help = 'Import a patch from a different branch or a commit object'
+kind = 'patch'
+usage = ['[options] [--] ([<patch1>] [<patch2>] [<patch3>..<patch4>])|<commit>']
+description = """
Import one or more patches from a different branch or a commit object
into the current series. By default, the name of the imported patch is
used as the name of the current patch. It can be overridden with the
-'--name' option. A commit object can be reverted with the '--reverse'
+'--name' option. A commit object can be reverted with the '--revert'
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('-B', '--ref-branch',
- help = 'pick patches from BRANCH'),
- 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')]
+args = [argparse.patch_range(argparse.applied_patches,
+ argparse.unapplied_patches,
+ argparse.hidden_patches)]
+options = [
+ opt('-n', '--name',
+ short = 'Use NAME as the patch name'),
+ opt('-B', '--ref-branch', args = [argparse.stg_branches],
+ short = 'Pick patches from BRANCH'),
+ opt('-r', '--revert', action = 'store_true',
+ short = 'Revert the given commit object'),
+ opt('-p', '--parent', metavar = 'COMMITID', args = [argparse.commit],
+ short = 'Use COMMITID as parent'),
+ opt('-x', '--expose', action = 'store_true',
+ short = 'Append the imported commit id to the patch log'),
+ opt('--fold', action = 'store_true',
+ short = 'Fold the commit object into the current patch'),
+ opt('--update', action = 'store_true',
+ short = 'Like fold but only update the current patch files'),
+ opt('-f', '--file', action = 'append',
+ short = 'Only fold the given file (can be used multiple times)'),
+ opt('--unapplied', action = 'store_true',
+ short = 'Keep the patch unapplied')]
+
+directory = DirectoryGotoToplevel(log = True)
def __pick_commit(commit_id, patchname, options):
"""Pick a commit id.
if options.name:
patchname = options.name
+ elif patchname and options.revert:
+ patchname = 'revert-' + patchname
+ if patchname:
+ patchname = find_patch_name(patchname, crt_series.patch_exists)
if options.parent:
parent = git_id(crt_series, options.parent)
else:
parent = commit.get_parent()
- if not options.reverse:
+ if not options.revert:
bottom = parent
top = commit_id
else:
if options.fold:
out.start('Folding commit %s' % commit_id)
- # try a direct git-apply first
- if not git.apply_diff(bottom, top):
- git.merge_recursive(bottom, git.get_head(), top)
+ # try a direct git apply first
+ if not git.apply_diff(bottom, top, files = options.file):
+ if options.file:
+ raise CmdException('Patch folding failed')
+ else:
+ git.merge_recursive(bottom, git.get_head(), top)
out.done()
elif options.update:
- rev1 = git_id(crt_series, '//bottom')
- rev2 = git_id(crt_series, '//top')
+ rev1 = git_id(crt_series, 'HEAD^')
+ rev2 = git_id(crt_series, 'HEAD')
files = git.barefiles(rev1, rev2).split('\n')
out.start('Updating with commit %s' % commit_id)
out.done()
else:
message = commit.get_log()
- if options.expose:
+ if options.revert:
+ if message:
+ lines = message.splitlines()
+ subject = lines[0]
+ body = '\n'.join(lines[2:])
+ else:
+ subject = commit.get_id_hash()
+ body = ''
+ message = 'Revert "%s"\n\nThis reverts commit %s.\n\n%s\n' \
+ % (subject, commit.get_id_hash(), body)
+ elif options.expose:
message += '(imported from commit %s)\n' % commit.get_id_hash()
author_name, author_email, author_date = \
name_email_date(commit.get_author())
+ if options.revert:
+ author_name = author_email = None
out.start('Importing commit %s' % commit_id)
patchname = newpatch.get_name()
# find a patchlog to fork from
- (refpatchname, refbranchname, refpatchid) = parse_rev(patchname)
- if refpatchname and not refpatchid and \
- (not refpatchid or refpatchid == 'top'):
- # FIXME: should also support picking //top.old
+ refbranchname, refpatchname = parse_rev(patchname)
+ if refpatchname:
if refbranchname:
# assume the refseries is OK, since we already resolved
# commit_str to a git_id
if not args:
parser.error('incorrect number of arguments')
+ if options.file and not options.fold:
+ parser.error('--file can only be specified with --fold')
+
if not options.unapplied:
check_local_changes()
check_conflicts()
if options.parent:
raise CmdException, '--parent can only be specified with one patch'
- if (options.fold or options.update) and not crt_series.get_current():
+ if options.update and not crt_series.get_current():
raise CmdException, 'No patches applied'
if commit_id:
- __pick_commit(commit_id, None, options)
+ # Try to guess a patch name if the argument was <branch>:<patch>
+ try:
+ patchname = args[0].split(':')[1]
+ except IndexError:
+ patchname = None
+ __pick_commit(commit_id, patchname, options)
else:
if options.unapplied:
patches.reverse()