def patch_desc(repo, cd, append_diff, diff_flags, replacement_diff): """Return a description text for the patch, suitable for editing and/or reimporting with L{update_patch_description()}. @param cd: The L{CommitData<stgit.lib.git.CommitData>} to generate a description of @param append_diff: Whether to append the patch diff to the description @type append_diff: C{bool} @param diff_flags: Extra parameters to pass to C{git diff} @param replacement_diff: Diff text to use; or C{None} if it should be computed from C{cd} @type replacement_diff: C{str} or C{None}""" desc = ['From: %s <%s>' % (cd.author.name, cd.author.email), 'Date: %s' % cd.author.date.isoformat(), '', cd.message] if append_diff: if replacement_diff: diff = replacement_diff else: just_diff = repo.diff_tree(cd.parent.data.tree, cd.tree, diff_flags) diff = '\n'.join([git.diffstat(just_diff), just_diff]) desc += ['---', '', diff] return '\n'.join(desc)
def patch_desc(repo, cd, append_diff, diff_flags, replacement_diff): """Return a description text for the patch, suitable for editing and/or reimporting with L{update_patch_description()}. @param cd: The L{CommitData<stgit.lib.git.CommitData>} to generate a description of @param append_diff: Whether to append the patch diff to the description @type append_diff: C{bool} @param diff_flags: Extra parameters to pass to C{git diff} @param replacement_diff: Diff text to use; or C{None} if it should be computed from C{cd} @type replacement_diff: C{str} or C{None}""" desc = '\n'.join([ 'From: %s <%s>' % (cd.author.name, cd.author.email), 'Date: %s' % cd.author.date.isoformat(), '', cd.message, ]).encode('utf-8') if append_diff: desc += b'\n---\n' if replacement_diff: desc += b'\n' + replacement_diff else: diff = repo.diff_tree(cd.parent.data.tree, cd.tree, diff_flags) if diff: desc += b'\n'.join([b'', diffstat(diff).encode('utf-8'), diff]) return desc
def func(parser, options, args): """Show commit log and diff """ if options.applied: patches = crt_series.get_applied() elif options.unapplied: patches = crt_series.get_unapplied() elif len(args) == 0: patches = ['HEAD'] elif '..' in ' '.join(args): # patch ranges applied = crt_series.get_applied() unapplied = crt_series.get_unapplied() patches = parse_patches(args, applied + unapplied + \ crt_series.get_hidden(), len(applied)) else: # individual patches or commit ids patches = args if not options.stat: options.diff_flags.extend(color_diff_flags()) commit_ids = [git_id(crt_series, patch) for patch in patches] commit_str = '\n'.join([ git.pretty_commit(commit_id, flags=options.diff_flags) for commit_id in commit_ids ]) if options.stat: commit_str = gitlib.diffstat(commit_str) if commit_str: pager(commit_str)
def func(parser, options, args): """Show the tree diff """ args = git.ls_files(args) directory.cd_to_topdir() if options.revs: rev_list = options.revs.split('..') rev_list_len = len(rev_list) if rev_list_len == 1: rev1 = rev_list[0] rev2 = None elif rev_list_len == 2: rev1 = rev_list[0] rev2 = rev_list[1] else: parser.error('incorrect parameters to -r') else: rev1 = 'HEAD' rev2 = None if not options.stat: options.diff_flags.extend(color_diff_flags()) diff_str = git.diff(args, rev1 and git_id(crt_series, rev1), rev2 and git_id(crt_series, rev2), diff_flags = options.diff_flags) if options.stat: out.stdout_raw(gitlib.diffstat(diff_str) + '\n') else: if diff_str: pager(diff_str)
def func(parser, options, args): """Show commit log and diff """ if options.applied: patches = crt_series.get_applied() elif options.unapplied: patches = crt_series.get_unapplied() elif len(args) == 0: patches = ['HEAD'] elif '..' in ' '.join(args): # patch ranges applied = crt_series.get_applied() unapplied = crt_series.get_unapplied() patches = parse_patches(args, applied + unapplied + \ crt_series.get_hidden(), len(applied)) else: # individual patches or commit ids patches = args if not options.stat: options.diff_flags.extend(color_diff_flags()) commit_ids = [git_id(crt_series, patch) for patch in patches] commit_str = '\n'.join([git.pretty_commit(commit_id, flags = options.diff_flags) for commit_id in commit_ids]) if options.stat: commit_str = gitlib.diffstat(commit_str) if commit_str: pager(commit_str)
def func(parser, options, args): """Show the files modified by a patch (or the current patch) """ if options.bare and options.stat: raise CmdException('Cannot specify both --bare and --stat') if len(args) == 0: patch = 'HEAD' elif len(args) == 1: patch = args[0] else: parser.error('incorrect number of arguments') rev1 = git_id(crt_series, '%s^' % patch) rev2 = git_id(crt_series, '%s' % patch) if options.stat: output = gitlib.diffstat( git.diff(rev1=rev1, rev2=rev2, diff_flags=options.diff_flags)) elif options.bare: output = git.barefiles(rev1, rev2) else: output = git.files(rev1, rev2, diff_flags=options.diff_flags) if output: if not output.endswith('\n'): output += '\n' out.stdout_raw(output)
def func(parser, options, args): """Show the tree diff """ args = git.ls_files(args) directory.cd_to_topdir() if options.revs: rev_list = options.revs.split('..') rev_list_len = len(rev_list) if rev_list_len == 1: rev1 = rev_list[0] rev2 = None elif rev_list_len == 2: rev1 = rev_list[0] rev2 = rev_list[1] else: parser.error('incorrect parameters to -r') else: rev1 = 'HEAD' rev2 = None if not options.stat: options.diff_flags.extend(color_diff_flags()) diff_str = git.diff(args, rev1 and git_id(crt_series, rev1), rev2 and git_id(crt_series, rev2), diff_flags=options.diff_flags) if options.stat: out.stdout_raw(gitlib.diffstat(diff_str) + '\n') else: if diff_str: pager(diff_str)
def func(parser, options, args): """Show commit log and diff """ if options.applied: patches = crt_series.get_applied() elif options.unapplied: patches = crt_series.get_unapplied() elif len(args) == 0: patches = ['HEAD'] elif '..' in ' '.join(args): # patch ranges applied = crt_series.get_applied() unapplied = crt_series.get_unapplied() patches = parse_patches(args, applied + unapplied + \ crt_series.get_hidden(), len(applied)) else: # individual patches or commit ids patches = args if not options.stat: options.diff_flags.extend(color_diff_flags()) commit_ids = [git_id(crt_series, patch) for patch in patches] commit_bytes = b'\n'.join( (Run('git', 'show', *(options.diff_flags + [commit_id])).decoding(None).raw_output()) for commit_id in commit_ids) if options.stat: commit_bytes = git.diffstat(commit_bytes).encode('utf-8') if commit_bytes: pager(commit_bytes)
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 = str(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_string = tmpl % tmpl_dict except KeyError, err: raise CmdException, 'Unknown patch template variable: %s' \ % err
def func(parser, options, args): """Show the files modified by a patch (or the current patch) """ if len(args) == 0: patch = 'HEAD' elif len(args) == 1: patch = args[0] else: parser.error('incorrect number of arguments') rev1 = git_id(crt_series, '%s^' % patch) rev2 = git_id(crt_series, '%s' % patch) if options.stat: output = gitlib.diffstat(git.diff(rev1 = rev1, rev2 = rev2, diff_flags = options.diff_flags)) elif options.bare: output = git.barefiles(rev1, rev2) else: output = git.files(rev1, rev2, diff_flags = options.diff_flags) if output: if not output.endswith('\n'): output += '\n' out.stdout_raw(output)
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': 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 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') if not options.stdout: if not os.path.isdir(dirname): os.makedirs(dirname) series = file(os.path.join(dirname, 'series'), 'w+') 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: tmpl = file(options.template).read() else: tmpl = templates.get_template('patchexport.tmpl') if not tmpl: tmpl = '' # note the base commit for this series if not options.stdout: base_commit = stack.patches.get(patches[0]).commit.sha1 print >> series, '# This series applies on GIT commit %s' % base_commit patch_no = 1; for p in patches: 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 >> series, pname # 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 = reduce(lambda x, y: x + '\n' + y, 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} for key in tmpl_dict: if not tmpl_dict[key]: tmpl_dict[key] = '' try: descr = tmpl % tmpl_dict except KeyError, 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'
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 = str(total_nr) patch_nr_str = str(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} # change None to '' for key in tmpl_dict: if not tmpl_dict[key]: tmpl_dict[key] = '' try: msg_string = tmpl % tmpl_dict except KeyError, err: raise CmdException, 'Unknown patch template variable: %s' \ % err
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} # change None to '' for key in tmpl_dict: if not tmpl_dict[key]: tmpl_dict[key] = '' try: msg_string = 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_string = __edit_message(msg_string) # The Python email message try: msg = email.message_from_string(msg_string) 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_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 } # change None to '' for key in tmpl_dict: if not tmpl_dict[key]: tmpl_dict[key] = '' try: msg_string = 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_string = __edit_message(msg_string) # The Python email message try: msg = email.message_from_string(msg_string) 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_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 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_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_string = 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_string = __edit_message(msg_string) # The Python email message try: msg = email.message_from_string(msg_string) 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