"""
import sys, os, re, email
-from email.Header import decode_header, make_header
from mailbox import UnixMailbox
from StringIO import StringIO
from optparse import OptionParser, make_option
from stgit.commands.common import *
from stgit.utils import *
+from stgit.out import *
from stgit import stack, git
The patch description has to be separated from the data with a '---'
line."""
+directory = DirectoryHasRepository()
options = [make_option('-m', '--mail',
help = 'import the patch from a standard e-mail file',
action = 'store_true'),
make_option('--commname',
help = 'use COMMNAME as the committer name'),
make_option('--commemail',
- help = 'use COMMEMAIL as the committer e-mail')]
+ help = 'use COMMEMAIL as the committer e-mail')
+ ] + make_sign_options()
-def __end_descr(line):
- return re.match('---\s*$', line) or re.match('diff -', line) or \
- re.match('Index: ', line)
-
def __strip_patch_name(name):
stripped = re.sub('^[0-9]+-(.*)$', '\g<1>', name)
stripped = re.sub('^(.*)\.(diff|patch)$', '\g<1>', stripped)
return stripped
-def __parse_description(descr):
- """Parse the patch description and return the new description and
- author information (if any).
- """
- subject = body = ''
- authname = authemail = authdate = None
-
- descr_lines = [line.rstrip() for line in descr.split('\n')]
- if not descr_lines:
- raise CmdException, "Empty patch description"
-
- lasthdr = 0
- end = len(descr_lines)
-
- # Parse the patch header
- for pos in range(0, end):
- if not descr_lines[pos]:
- continue
- # check for a "From|Author:" line
- if re.match('\s*(?:from|author):\s+', descr_lines[pos], re.I):
- auth = re.findall('^.*?:\s+(.*)$', descr_lines[pos])[0]
- authname, authemail = name_email(auth)
- lasthdr = pos + 1
- continue
- # check for a "Date:" line
- if re.match('\s*date:\s+', descr_lines[pos], re.I):
- authdate = re.findall('^.*?:\s+(.*)$', descr_lines[pos])[0]
- lasthdr = pos + 1
- continue
- if subject:
- break
- # get the subject
- subject = descr_lines[pos]
- lasthdr = pos + 1
-
- # get the body
- if lasthdr < end:
- body = reduce(lambda x, y: x + '\n' + y, descr_lines[lasthdr:], '')
-
- return (subject + body, authname, authemail, authdate)
-
-def __parse_mail(msg):
- """Parse the message object and return (description, authname,
- authemail, authdate, diff)
- """
- def __decode_header(header):
- """Decode a qp-encoded e-mail header as per rfc2047"""
- try:
- words_enc = decode_header(header)
- hobj = make_header(words_enc)
- except Exception, ex:
- raise CmdException, 'header decoding error: %s' % str(ex)
- return unicode(hobj).encode('utf-8')
-
- # parse the headers
- if msg.has_key('from'):
- authname, authemail = name_email(__decode_header(msg['from']))
- else:
- authname = authemail = None
-
- # '\n\t' can be found on multi-line headers
- descr = __decode_header(msg['subject']).replace('\n\t', ' ')
- authdate = msg['date']
-
- # remove the '[*PATCH*]' expression in the subject
- if descr:
- descr = re.findall('^(\[.*?[Pp][Aa][Tt][Cc][Hh].*?\])?\s*(.*)$',
- descr)[0][1]
- descr += '\n\n'
- else:
- raise CmdException, 'Subject: line not found'
-
- # the rest of the message
- if msg.is_multipart():
- # this is assuming that the first part is the patch
- # description and the second part is the attached patch
- descr += msg.get_payload(0).get_payload(decode = True)
- diff = msg.get_payload(1).get_payload(decode = True)
- else:
- diff = msg.get_payload(decode = True)
-
- for line in diff.split('\n'):
- if __end_descr(line):
- break
- descr += line + '\n'
-
- descr.rstrip()
-
- # parse the description for author information
- descr, descr_authname, descr_authemail, descr_authdate = \
- __parse_description(descr)
- if descr_authname:
- authname = descr_authname
- if descr_authemail:
- authemail = descr_authemail
- if descr_authdate:
- authdate = descr_authdate
-
- return (descr, authname, authemail, authdate, diff)
-
-def __parse_patch(fobj):
- """Parse the input file and return (description, authname,
- authemail, authdate, diff)
- """
- descr = ''
- while True:
- line = fobj.readline()
- if not line:
- break
-
- if __end_descr(line):
- break
- else:
- descr += line
- descr.rstrip()
-
- diff = fobj.read()
-
- descr, authname, authemail, authdate = __parse_description(descr)
-
- # we don't yet have an agreed place for the creation date.
- # Just return None
- return (descr, authname, authemail, authdate, diff)
-
def __create_patch(filename, message, author_name, author_email,
author_date, diff, options):
"""Create a new patch on the stack
patch = __strip_patch_name(patch)
if not patch:
- patch = make_patch_name(message, crt_series.patch_exists,
- alternative = not (options.ignore
- or options.replace))
+ if options.ignore or options.replace:
+ unacceptable_name = lambda name: False
+ else:
+ unacceptable_name = crt_series.patch_exists
+ patch = make_patch_name(message, unacceptable_name)
else:
# fix possible invalid characters in the patch name
patch = re.sub('[^\w.]+', '-', patch).strip('-')
- if not diff:
- raise CmdException, 'No diff found inside the patch'
-
if options.ignore and patch in crt_series.get_applied():
- print 'Ignoring already applied patch "%s"' % patch
+ out.info('Ignoring already applied patch "%s"' % patch)
return
if options.replace and patch in crt_series.get_unapplied():
crt_series.delete_patch(patch)
committer_name = committer_name,
committer_email = committer_email)
- print 'Importing patch "%s"...' % patch,
- sys.stdout.flush()
-
- if options.base:
- git.apply_patch(diff = diff, base = git_id(options.base))
+ if not diff:
+ out.warn('No diff found, creating empty patch')
else:
- git.apply_patch(diff = diff)
-
- crt_series.refresh_patch(edit = options.edit,
- show_patch = options.showpatch)
-
- print 'done'
+ out.start('Importing patch "%s"' % patch)
+ if options.base:
+ git.apply_patch(diff = diff, base = git_id(options.base))
+ else:
+ git.apply_patch(diff = diff)
+ crt_series.refresh_patch(edit = options.edit,
+ show_patch = options.showpatch,
+ sign_str = options.sign_str)
+ out.done()
def __import_file(filename, options, patch = None):
"""Import a patch from a file or standard input
except Exception, ex:
raise CmdException, 'error parsing the e-mail file: %s' % str(ex)
message, author_name, author_email, author_date, diff = \
- __parse_mail(msg)
+ parse_mail(msg)
else:
message, author_name, author_email, author_date, diff = \
- __parse_patch(f)
+ parse_patch(f)
if filename:
f.close()
for msg in mbox:
message, author_name, author_email, author_date, diff = \
- __parse_mail(msg)
+ parse_mail(msg)
__create_patch(None, message, author_name, author_email,
author_date, diff, options)