def func(parser, options, args): """Export a range of patches. """ stack = directory.repository.get_stack(options.branch) if options.dir: dirname = options.dir else: dirname = 'patches-%s' % stack.name directory.cd_to_topdir() if not options.branch and git.local_changes(): out.warn('Local changes in the tree;' ' you might want to commit them first') applied = stack.patchorder.applied unapplied = stack.patchorder.unapplied if len(args) != 0: patches = common.parse_patches(args, applied + unapplied, len(applied)) else: patches = applied num = len(patches) if num == 0: raise common.CmdException('No patches applied') zpadding = len(str(num)) if zpadding < 2: zpadding = 2 # get the template if options.template: with io.open(options.template, 'r') as f: tmpl = f.read() else: tmpl = templates.get_template('patchexport.tmpl') if not tmpl: tmpl = '' if not options.stdout: if not os.path.isdir(dirname): os.makedirs(dirname) series = io.open(os.path.join(dirname, 'series'), 'w') # note the base commit for this series base_commit = stack.base.sha1 print('# This series applies on GIT commit %s' % base_commit, file=series) for patch_no, p in enumerate(patches, 1): pname = p if options.patch: pname = '%s.patch' % pname elif options.extension: pname = '%s.%s' % (pname, options.extension) if options.numbered: pname = '%s-%s' % (str(patch_no).zfill(zpadding), pname) pfile = os.path.join(dirname, pname) if not options.stdout: print(pname, file=series) # get the patch description patch = stack.patches.get(p) cd = patch.commit.data descr = cd.message.strip() descr_lines = descr.split('\n') short_descr = descr_lines[0].rstrip() long_descr = '\n'.join(descr_lines[1:]).strip() diff = stack.repository.diff_tree(cd.parent.data.tree, cd.tree, options.diff_flags) tmpl_dict = { 'description': descr, 'shortdescr': short_descr, 'longdescr': long_descr, 'diffstat': gitlib.diffstat(diff).rstrip(), 'authname': cd.author.name, 'authemail': cd.author.email, 'authdate': cd.author.date.isoformat(), 'commname': cd.committer.name, 'commemail': cd.committer.email } try: descr = templates.specialize_template(tmpl, tmpl_dict) except KeyError as err: raise common.CmdException('Unknown patch template variable: %s' % err) except TypeError: raise common.CmdException('Only "%(name)s" variables are ' 'supported in the patch template') if options.stdout: if hasattr(sys.stdout, 'buffer'): f = sys.stdout.buffer else: f = sys.stdout else: f = io.open(pfile, 'wb') if options.stdout and num > 1: f.write('\n'.join(['-' * 79, patch.name, '-' * 79, '']).encode('utf-8')) f.write(descr) f.write(diff) if not options.stdout: f.close() if not options.stdout: series.close()
def __build_message(tmpl, msg_id, options, patch, patch_nr, total_nr, ref_id): """Build the message to be sent via SMTP """ repository = directory.repository stack = repository.current_stack p = stack.patches.get(patch) if p.commit.data.message: descr = p.commit.data.message.strip() else: # provide a place holder and force the edit message option on descr = '<empty message>' options.edit_patches = True descr_lines = descr.split('\n') short_descr = descr_lines[0].strip() long_descr = '\n'.join(l.rstrip() for l in descr_lines[1:]).lstrip('\n') author = p.commit.data.author committer = p.commit.data.committer sender = __get_sender() if author.name_email != sender: fromauth = 'From: %s\n\n' % author.name_email else: fromauth = '' if options.version: version_str = '%s' % options.version version_space = ' ' else: version_str = '' version_space = '' if options.prefix: prefix_str = options.prefix else: prefix_str = config.get('stgit.mail.prefix') if prefix_str: prefix_space = ' ' else: prefix_str = '' prefix_space = '' total_nr_str = text(total_nr) patch_nr_str = text(patch_nr).zfill(len(total_nr_str)) if not options.unrelated and total_nr > 1: number_str = '%s/%s' % (patch_nr_str, total_nr_str) number_space = ' ' else: number_str = '' number_space = '' diff = repository.diff_tree( p.commit.data.parent.data.tree, p.commit.data.tree, diff_opts=options.diff_flags, ) tmpl_dict = { 'patch': patch, 'sender': sender, 'maintainer': sender, # for backward template compatibility 'shortdescr': short_descr, 'longdescr': long_descr, 'endofheaders': '', # for backward template compatibility 'diff': diff, 'diffstat': diffstat(diff), 'date': '', # for backward template compatibility 'version': version_str, 'vspace': version_space, 'prefix': prefix_str, 'pspace': prefix_space, 'patchnr': patch_nr_str, 'totalnr': total_nr_str, 'number': number_str, 'nspace': number_space, 'snumber': number_str.strip(), 'fromauth': fromauth, 'authname': author.name, 'authemail': author.email, 'authdate': author.date.rfc2822_format(), 'commname': committer.name, 'commemail': committer.email, } try: msg_bytes = templates.specialize_template(tmpl, tmpl_dict) except KeyError as err: raise CmdException('Unknown patch template variable: %s' % err) except TypeError: raise CmdException('Only "%(name)s" variables are ' 'supported in the patch template') if options.edit_patches: msg_bytes = edit_bytes(msg_bytes, '.stgitmail.txt') # The Python email message try: msg = message_from_bytes(msg_bytes) except Exception as ex: raise CmdException('template parsing error: %s' % str(ex)) if options.auto: extra_cc = __get_signers_list(descr) else: extra_cc = [] if not options.git: __build_address_headers(msg, options, extra_cc) __build_extra_headers(msg, msg_id, ref_id) __encode_message(msg) return msg
def __build_cover(tmpl, msg_id, options, patches): """Build the cover message (series description) to be sent via SMTP """ sender = __get_sender() if options.version: version_str = '%s' % options.version version_space = ' ' else: version_str = '' version_space = '' if options.prefix: prefix_str = options.prefix else: prefix_str = config.get('stgit.mail.prefix') if prefix_str: prefix_space = ' ' else: prefix_str = '' prefix_space = '' total_nr_str = text(len(patches)) patch_nr_str = '0'.zfill(len(total_nr_str)) if len(patches) > 1: number_str = '%s/%s' % (patch_nr_str, total_nr_str) number_space = ' ' else: number_str = '' number_space = '' tmpl_dict = { 'sender': sender, # for backward template compatibility 'maintainer': sender, # for backward template compatibility 'endofheaders': '', # for backward template compatibility 'date': '', 'version': version_str, 'vspace': version_space, 'prefix': prefix_str, 'pspace': prefix_space, 'patchnr': patch_nr_str, 'totalnr': total_nr_str, 'number': number_str, 'nspace': number_space, 'snumber': number_str.strip(), 'shortlog': stack.shortlog(crt_series.get_patch(p) for p in reversed(patches)), 'diffstat': gitlib.diffstat( git.diff( rev1=git_id(crt_series, '%s^' % patches[0]), rev2=git_id(crt_series, '%s' % patches[-1]), diff_flags=options.diff_flags, )), } try: msg_bytes = templates.specialize_template(tmpl, tmpl_dict) except KeyError as err: raise CmdException('Unknown patch template variable: %s' % err) except TypeError: raise CmdException('Only "%(name)s" variables are ' 'supported in the patch template') if options.edit_cover: msg_bytes = edit_bytes(msg_bytes, '.stgitmail.txt') # The Python email message try: msg = message_from_bytes(msg_bytes) except Exception as ex: raise CmdException('template parsing error: %s' % str(ex)) extra_cc = [] if options.auto: for patch in patches: p = crt_series.get_patch(patch) if p.get_description(): descr = p.get_description().strip() extra_cc.extend(__get_signers_list(descr)) extra_cc = list(set(extra_cc)) if not options.git: __build_address_headers(msg, options, extra_cc) __build_extra_headers(msg, msg_id, options.in_reply_to) __encode_message(msg) return msg
def __build_cover(tmpl, msg_id, options, patches): """Build the cover message (series description) to be sent via SMTP """ sender = __get_sender() if options.version: version_str = '%s' % options.version version_space = ' ' else: version_str = '' version_space = '' if options.prefix: prefix_str = options.prefix else: prefix_str = config.get('stgit.mail.prefix') if prefix_str: prefix_space = ' ' else: prefix_str = '' prefix_space = '' total_nr_str = text(len(patches)) patch_nr_str = '0'.zfill(len(total_nr_str)) if len(patches) > 1: number_str = '%s/%s' % (patch_nr_str, total_nr_str) number_space = ' ' else: number_str = '' number_space = '' repository = directory.repository stack = repository.current_stack tmpl_dict = { 'sender': sender, # for backward template compatibility 'maintainer': sender, # for backward template compatibility 'endofheaders': '', # for backward template compatibility 'date': '', 'version': version_str, 'vspace': version_space, 'prefix': prefix_str, 'pspace': prefix_space, 'patchnr': patch_nr_str, 'totalnr': total_nr_str, 'number': number_str, 'nspace': number_space, 'snumber': number_str.strip(), 'shortlog': __shortlog(stack, patches), 'diffstat': repository.diff_tree( stack.base.data.tree, stack.top.data.tree, diff_opts=options.diff_flags, stat=True, ), } try: msg_bytes = templates.specialize_template(tmpl, tmpl_dict) except KeyError as err: raise CmdException('Unknown patch template variable: %s' % err) except TypeError: raise CmdException('Only "%(name)s" variables are ' 'supported in the patch template') if options.edit_cover: msg_bytes = edit_bytes(msg_bytes, '.stgitmail.txt') # The Python email message try: msg = message_from_bytes(msg_bytes) except Exception as ex: raise CmdException('template parsing error: %s' % str(ex)) extra_cc = [] if options.auto: for pn in patches: p = stack.patches.get(pn) if p.commit.data.message: descr = p.commit.data.message.strip() extra_cc.extend(__get_signers_list(descr)) extra_cc = list(set(extra_cc)) if not options.git: __build_address_headers(msg, options, extra_cc) __build_extra_headers(msg, msg_id, options.in_reply_to) __encode_message(msg) return msg
def __build_message(tmpl, msg_id, options, patch, patch_nr, total_nr, ref_id): """Build the message to be sent via SMTP """ p = crt_series.get_patch(patch) if p.get_description(): descr = p.get_description().strip() else: # provide a place holder and force the edit message option on descr = '<empty message>' options.edit_patches = True descr_lines = descr.split('\n') short_descr = descr_lines[0].strip() long_descr = '\n'.join(l.rstrip() for l in descr_lines[1:]).lstrip('\n') authname = p.get_authname() authemail = p.get_authemail() commname = p.get_commname() commemail = p.get_commemail() sender = __get_sender() fromauth = '%s <%s>' % (authname, authemail) if fromauth != sender: fromauth = 'From: %s\n\n' % fromauth else: fromauth = '' if options.version: version_str = '%s' % options.version version_space = ' ' else: version_str = '' version_space = '' if options.prefix: prefix_str = options.prefix else: prefix_str = config.get('stgit.mail.prefix') if prefix_str: prefix_space = ' ' else: prefix_str = '' prefix_space = '' total_nr_str = text(total_nr) patch_nr_str = text(patch_nr).zfill(len(total_nr_str)) if not options.unrelated and total_nr > 1: number_str = '%s/%s' % (patch_nr_str, total_nr_str) number_space = ' ' else: number_str = '' number_space = '' diff = git.diff(rev1=git_id(crt_series, '%s^' % patch), rev2=git_id(crt_series, '%s' % patch), diff_flags=options.diff_flags) tmpl_dict = { 'patch': patch, 'sender': sender, # for backward template compatibility 'maintainer': sender, 'shortdescr': short_descr, 'longdescr': long_descr, # for backward template compatibility 'endofheaders': '', 'diff': diff, 'diffstat': gitlib.diffstat(diff), # for backward template compatibility 'date': '', 'version': version_str, 'vspace': version_space, 'prefix': prefix_str, 'pspace': prefix_space, 'patchnr': patch_nr_str, 'totalnr': total_nr_str, 'number': number_str, 'nspace': number_space, 'snumber': number_str.strip(), 'fromauth': fromauth, 'authname': authname, 'authemail': authemail, 'authdate': p.get_authdate(), 'commname': commname, 'commemail': commemail } try: msg_bytes = templates.specialize_template(tmpl, tmpl_dict) except KeyError as err: raise CmdException('Unknown patch template variable: %s' % err) except TypeError: raise CmdException('Only "%(name)s" variables are ' 'supported in the patch template') if options.edit_patches: msg_bytes = edit_bytes(msg_bytes, '.stgitmail.txt') # The Python email message try: msg = message_from_bytes(msg_bytes) except Exception as ex: raise CmdException('template parsing error: %s' % str(ex)) if options.auto: extra_cc = __get_signers_list(descr) else: extra_cc = [] if not options.git: __build_address_headers(msg, options, extra_cc) __build_extra_headers(msg, msg_id, ref_id) __encode_message(msg) return msg