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