Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os, re, email
+import sys, os, re, email, tarfile
from mailbox import UnixMailbox
from StringIO import StringIO
from stgit.argparse import opt
opt('-M', '--mbox', action = 'store_true',
short = 'Import a series of patches from an mbox file'),
opt('-s', '--series', action = 'store_true',
- short = 'Import a series of patches'),
+ short = 'Import a series of patches', long = """
+ Import a series of patches from a series file or a tar archive."""),
opt('-u', '--url', action = 'store_true',
short = 'Import a patch from a URL'),
opt('-n', '--name',
short = 'Use NAME as the patch name'),
- opt('-t', '--strip', action = 'store_true',
+ opt('-p', '--strip', type = 'int', metavar = 'N',
+ short = 'Remove N leading slashes from diff paths (default 1)'),
+ opt('-t', '--stripname', action = 'store_true',
short = 'Strip numbering and extension from patch name'),
opt('-i', '--ignore', action = 'store_true',
short = 'Ignore the applied patches in the series'),
short = 'Replace the unapplied patches in the series'),
opt('-b', '--base', args = [argparse.commit],
short = 'Use BASE instead of HEAD for file importing'),
+ opt('--reject', action = 'store_true',
+ short = 'leave the rejected hunks in corresponding *.rej files'),
opt('-e', '--edit', action = 'store_true',
short = 'Invoke an editor for the patch description'),
- opt('-p', '--showpatch', action = 'store_true',
+ opt('-d', '--showdiff', action = 'store_true',
short = 'Show the patch content in the editor buffer'),
opt('-a', '--author', metavar = '"NAME <EMAIL>"',
short = 'Use "NAME <EMAIL>" as the author details'),
short = 'Use AUTHEMAIL as the author e-mail'),
opt('--authdate',
short = 'Use AUTHDATE as the author date'),
- opt('--commname',
- short = 'Use COMMNAME as the committer name'),
- opt('--commemail',
- short = 'Use COMMEMAIL as the committer e-mail'),
] + argparse.sign_options()
directory = DirectoryHasRepository(log = True)
patch = os.path.basename(filename)
else:
patch = ''
- if options.strip:
+ if options.stripname:
patch = __strip_patch_name(patch)
if not patch:
if not message:
can_edit = False
- committer_name = committer_email = None
-
if options.author:
options.authname, options.authemail = name_email(options.author)
author_email = options.authemail
if options.authdate:
author_date = options.authdate
- if options.commname:
- committer_name = options.commname
- if options.commemail:
- committer_email = options.commemail
crt_series.new_patch(patch, message = message, can_edit = False,
author_name = author_name,
author_email = author_email,
- author_date = author_date,
- committer_name = committer_name,
- committer_email = committer_email)
+ author_date = author_date)
if not diff:
out.warn('No diff found, creating empty patch')
else:
out.start('Importing patch "%s"' % patch)
if options.base:
- git.apply_patch(diff = diff,
- base = git_id(crt_series, options.base))
+ base = git_id(crt_series, options.base)
else:
- git.apply_patch(diff = diff)
+ base = None
+ git.apply_patch(diff = diff, base = base, reject = options.reject,
+ strip = options.strip)
crt_series.refresh_patch(edit = options.edit,
- show_patch = options.showpatch,
+ show_patch = options.showdiff,
+ author_date = author_date,
sign_str = options.sign_str,
backup = False)
out.done()
applied = crt_series.get_applied()
if filename:
+ if tarfile.is_tarfile(filename):
+ __import_tarfile(filename, options)
+ return
f = file(filename)
patchdir = os.path.dirname(filename)
else:
import tempfile
if not url:
- parser.error('URL argument required')
+ raise CmdException('URL argument required')
patch = os.path.basename(urllib.unquote(url))
filename = os.path.join(tempfile.gettempdir(), patch)
urllib.urlretrieve(url, filename)
__import_file(filename, options)
+def __import_tarfile(tar, options):
+ """Import patch series from a tar archive
+ """
+ import tempfile
+ import shutil
+
+ if not tarfile.is_tarfile(tar):
+ raise CmdException, "%s is not a tarfile!" % tar
+
+ t = tarfile.open(tar, 'r')
+ names = t.getnames()
+
+ # verify paths in the tarfile are safe
+ for n in names:
+ if n.startswith('/'):
+ raise CmdException, "Absolute path found in %s" % tar
+ if n.find("..") > -1:
+ raise CmdException, "Relative path found in %s" % tar
+
+ # find the series file
+ seriesfile = '';
+ for m in names:
+ if m.endswith('/series') or m == 'series':
+ seriesfile = m
+ break
+ if seriesfile == '':
+ raise CmdException, "no 'series' file found in %s" % tar
+
+ # unpack into a tmp dir
+ tmpdir = tempfile.mkdtemp('.stg')
+ t.extractall(tmpdir)
+
+ # apply the series
+ __import_series(os.path.join(tmpdir, seriesfile), options)
+
+ # cleanup the tmpdir
+ shutil.rmtree(tmpdir)
+
def func(parser, options, args):
"""Import a GNU diff file as a new patch
"""
else:
filename = None
- if filename:
+ if not options.url and filename:
filename = os.path.abspath(filename)
directory.cd_to_topdir()