From 3d53b6d6c17faf922a1fe4550ebc6d5c03af1ce3 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Wed, 16 Dec 2020 10:58:18 +0100 Subject: [PATCH] git-mr-reply: initial implementation Signed-off-by: Frantisek Hrbata --- git-mr-reply | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100755 git-mr-reply diff --git a/git-mr-reply b/git-mr-reply new file mode 100755 index 0000000..4197647 --- /dev/null +++ b/git-mr-reply @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 + +""" +Copyright © 2020 Frantisek Hrbata +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. +""" + +import argparse +import sys +import mrlib +from email.utils import formatdate +import os +import fcntl + +parser = argparse.ArgumentParser(description="Reply to comment, patch or MR.") +parser.add_argument("rev", nargs="?", metavar="REV", + help="Comment or patch revision.") +parser.add_argument("-m", "--mr", default="HEAD", + help="MR revision.") +parser.add_argument("-w", "--write-revs", metavar="FILE", + help="Append comment rev as read comment to FILE (default: $HOME/.gimrr/comment.revs).") + +args = parser.parse_args() +refs = mrlib.load_refs() +rev_comment = False + +if not args.rev: + mr = mrlib.verify_mrs([args.mr], refs)[0] + rev = mrlib.rev_zero + tags = mrlib.load_tags([mr], refs=refs, commits=False) + mrtags = mrlib.get_commit_tags(tags, mr, mrlib.rev_zero) + an = mrlib.get_tag_value(mrtags, "AN") + ae = mrlib.get_tag_value(mrtags, "AE") + at = mrlib.get_tag_value(mrtags, "AT") + subj = mrlib.get_tag_value(mrtags, "S") + body = mrlib.get_tag_value(mrtags, "D").replace("\\n", "\n") +else: + rev = mrlib.verify_rev(args.rev) + c2m = mrlib.comments2mrs(refs) + if rev in c2m: + mr = c2m[rev] + rev_comment = True + else: + p2m = mrlib.patches2mrs(refs) + if rev not in p2m: + sys.exit("Revision '{}' is not comment nor patch.".format(rev)) + + if len(p2m[rev]) > 1: + mr = mrlib.verify_mrs([args.mr], refs)[0] + if mr not in p2m[rev]: + sys.exit("Patch '{}' included in more MRs '{}'. Use -m option.".format(rev, " ".join(p2m[rev]))) + else: + mr = p2m[rev][0] + + rv, out, err = mrlib.run(["git", "show", "--no-patch", "--format=%s%x09%an%x09%ae%x09%at", rev]) + subj, an, ae, at = out.strip().split("\t") + rv, body, err = mrlib.run(["git", "show", "--format=%b", rev]) + +if not subj.startswith("Re: "): + subj = "Re: " + subj + +ad = formatdate(int(at)) +qbody = "" +for line in body.split("\n"): + qbody += "> {}\n".format(line) + +msg = """To: {an} <{ae}> +Subject: {s} +In-Reply-To: <{mr}.{rev}@localhost> + +On {ad}, {an} wrote: +{b}""".format(an=an, ae=ae, s=subj, mr=mr, rev=rev, ad=ad, b=qbody) + +msg = mrlib.editor(msg) + +rv, out, err = mrlib.run(["git", "mr-sendmail"], stdin=msg) + +if not rev_comment: + sys.exit() + +if args.write_revs: + revs_path = args.read_revs +else: + revs_path = os.environ.get('HOME') + "/" + ".gimrr/comment.revs" + +fd = open(revs_path, "a+") +fd.seek(0) +fcntl.lockf(fd.fileno(), fcntl.LOCK_SH | fcntl.LOCK_NB) +oldrevs = [r for r in fd.read().split("\n") if r] +if rev in oldrevs: + sys.exit() + +try: + pos = fd.tell() + fd.write("{}\n".format(rev)) + fd.flush() +except: + fd.truncate(pos) + raise -- 1.7.10.4