Beispiel #1
0
def __import_mail_path(mail_path, filename, options):
    with open(mail_path, 'rb') as f:
        mail = f.read()

    msg_path = mail_path + '-msg'
    patch_path = mail_path + '-patch'

    mailinfo_lines = Run(
        'git', 'mailinfo', msg_path, patch_path
    ).encoding(None).decoding(None).raw_input(mail).output_lines(b'\n')

    mailinfo = dict(line.split(b': ', 1) for line in mailinfo_lines if line)

    with open(msg_path, 'rb') as f:
        msg_body = f.read()

    msg_bytes = mailinfo[b'Subject'] + b'\n\n' + msg_body

    with open(patch_path, 'rb') as f:
        diff = f.read()

    __create_patch(
        None if options.mbox else filename,
        decode_utf8_with_latin1(msg_bytes),
        mailinfo[b'Author'].decode('utf-8'),
        mailinfo[b'Email'].decode('utf-8'),
        mailinfo[b'Date'].decode('utf-8'),
        diff,
        options,
    )
Beispiel #2
0
def __import_mail_path(mail_path, filename, options):
    with open(mail_path, 'rb') as f:
        mail = f.read()

    msg_path = mail_path + '-msg'
    patch_path = mail_path + '-patch'

    mailinfo_cmd = ['git', 'mailinfo']
    if options.message_id or config.getbool('stgit.import.message-id'):
        mailinfo_cmd.append('--message-id')
    mailinfo_cmd.extend([msg_path, patch_path])

    mailinfo_lines = (Run(*mailinfo_cmd).encoding(None).decoding(
        None).raw_input(mail).output_lines(b'\n'))

    mailinfo = dict(line.split(b': ', 1) for line in mailinfo_lines if line)

    with open(msg_path, 'rb') as f:
        msg_body = f.read()

    msg_bytes = mailinfo[b'Subject'] + b'\n\n' + msg_body

    with open(patch_path, 'rb') as f:
        diff = f.read()

    __create_patch(
        None if options.mbox else filename,
        decode_utf8_with_latin1(msg_bytes),
        None,
        mailinfo[b'Author'].decode('utf-8'),
        mailinfo[b'Email'].decode('utf-8'),
        mailinfo[b'Date'].decode('utf-8'),
        diff,
        options,
    )
def parse_patch(patch_data, contains_diff, fail_on_empty_description=True):
    """Parse patch data.

    Returns (description, patch_name, authname, authemail, authdate, diff)

    """
    assert isinstance(patch_data, bytes)
    if contains_diff:
        (descr, diff) = __split_descr_diff(patch_data)
    else:
        descr = patch_data
        diff = None
    (descr, patch_name, authname, authemail,
     authdate) = __parse_description(decode_utf8_with_latin1(descr),
                                     fail_on_empty_description)

    return (descr, patch_name, authname, authemail, authdate, diff)
Beispiel #4
0
def parse_patch(patch_data, contains_diff):
    """Parse patch data.

    Returns (description, authname, authemail, authdate, diff)

    """
    assert isinstance(patch_data, bytes)
    if contains_diff:
        (descr, diff) = __split_descr_diff(patch_data)
    else:
        descr = patch_data
        diff = None
    (descr, authname, authemail,
     authdate) = __parse_description(decode_utf8_with_latin1(descr))

    # we don't yet have an agreed place for the creation date.
    # Just return None
    return (descr, authname, authemail, authdate, diff)
Beispiel #5
0
def parse_mail(msg):
    """Parse the message object and return (description, authname,
    authemail, authdate, diff)
    """
    import email.header
    if sys.version_info[0] <= 2:
        # Python 2's decode_header() fails to decode encoded words if they are
        # quoted. This does not match the behavior of Python3 or `git
        # mailinfo`. For example, Python2 does not handle this header
        # correctly:
        #
        #    From: "=?UTF-8?q?Christian=20K=C3=B6nig?=" <*****@*****.**>
        #
        # By replacing the encoded words regex in the email.header module, we
        # can bless Python2 with the same behavior as Python3.
        email.header.ecre = re.compile((r'=\? (?P<charset>[^?]*?)'
                                        r' \? (?P<encoding>[QqBb])'
                                        r' \? (?P<encoded>.*?)'
                                        r' \?='), re.VERBOSE | re.MULTILINE)

    def __decode_header(header):
        """Decode a qp-encoded e-mail header as per rfc2047"""
        try:
            decoded_words = email.header.decode_header(header)
            return text(email.header.make_header(decoded_words))
        except Exception as ex:
            raise CmdException('header decoding error: %s' % str(ex))

    # parse the headers
    if 'from' in msg:
        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'])
    descr = re.sub('\n[ \t]*', ' ', descr)
    authdate = msg['date']

    # remove the '[*PATCH*]' expression in the subject
    if descr:
        descr = re.findall(r'^(\[.*?[Pp][Aa][Tt][Cc][Hh].*?\])?\s*(.*)$',
                           descr)[0][1]
    else:
        raise CmdException('Subject: line not found')

    # the rest of the message
    msg_data = b''
    for part in msg.walk():
        if part.get_content_type() in [
                'text/plain', 'application/octet-stream'
        ]:
            payload = part.get_payload(decode=True)
            msg_data += payload

    rem_descr, diff = __split_descr_diff(msg_data)
    if rem_descr:
        descr += '\n\n' + decode_utf8_with_latin1(rem_descr)

    # 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)