git-mr-comment-list: initial implementation
authorFrantisek Hrbata <frantisek@hrbata.com>
Mon, 14 Dec 2020 17:08:25 +0000 (18:08 +0100)
committerFrantisek Hrbata <frantisek@hrbata.com>
Mon, 14 Dec 2020 17:08:25 +0000 (18:08 +0100)
Signed-off-by: Frantisek Hrbata <frantisek@hrbata.com>
git-mr-comment-list [new file with mode: 0755]

diff --git a/git-mr-comment-list b/git-mr-comment-list
new file mode 100755 (executable)
index 0000000..6cf01ad
--- /dev/null
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+
+# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
+
+"""
+Copyright © 2020 Frantisek Hrbata <frantisek@hrbata.com>
+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 os
+import string
+import mrlib
+import fcntl
+
+fmt = "{f:2.2} {m:.16} {c:.16} {s:70.70} {n:20.20} {d}"
+
+parser = argparse.ArgumentParser(description="List comments for MRs.")
+parser.add_argument("mr", nargs="*", default=["HEAD"], metavar="MR",
+        help="Merge request revisions for which comments will be listed (default: HEAD)")
+parser.add_argument("-A", "--all", action="store_true",
+        help="List comments for all MRs. MRs entered as positional arguments or on stdin are ignored.")
+parser.add_argument("-", "--stdin", action="store_true",
+        help="List comments for MRs from stdin. MRs entered as positional arguments are ignored.")
+parser.add_argument("--fmt", metavar="FMT", default=fmt,
+        help="Python's formatted string for comments.")
+parser.add_argument("--grep", metavar="PATTERN", action="append",
+        help="Limit the comments output to ones with message that matches the specified pattern. Can be used multiple times.")
+parser.add_argument("--all-match", action="store_true",
+        help="Limit the comments output to ones that match all given --grep.")
+parser.add_argument("-i", "--regexp-ignore-case", action="store_true",
+        help="Match the regular expression limiting patterns without regard to letter case.")
+parser.add_argument("-r", "--read-revs", metavar="FILE",
+        help="Read revs for previously read comments from FILE (default: $HOME/.gimrr/comment.revs).")
+
+class CFormatter(string.Formatter):
+    def __init__(self):
+        pass
+
+    def get_field(self, field, a, cargs):
+        if field not in cargs:
+            if field == "0":
+                value = "{}"
+            else:
+                value = "{{{}}}".format(field)
+        else:
+            value = cargs[field]
+
+        return (value, field)
+
+cfmt = CFormatter()
+def printc(fmt, cargs):
+    print(cfmt.vformat(fmt, None, cargs))
+
+args = parser.parse_args()
+user = mrlib.get_user()
+refs = mrlib.load_refs()
+revs = list()
+
+if args.read_revs:
+    revs_path = args.read_revs
+else:
+    revs_path = os.environ.get('HOME') + "/" + ".gimrr/comment.revs"
+
+if os.path.exists(revs_path):
+    with open(revs_path, "r") as fd:
+        fcntl.lockf(fd.fileno(), fcntl.LOCK_SH | fcntl.LOCK_NB)
+        revs = [r for r in fd.read().split("\n") if r]
+
+if args.all:
+    mrs = mrlib.filter_revs(refs, types=["head"])
+else:
+    if args.stdin:
+        mrs = sys.stdin.readlines()
+    else:
+        mrs = args.mr
+
+    mrs = mrlib.verify_mrs(mrs, refs)
+
+mboxes = mrlib.filter_revs(refs, mrs=mrs, types=["mbox"])
+
+stdin = "\n".join(mboxes)
+if not stdin:
+    sys.exit()
+
+cmd = ["git", "log", "--stdin", "--format=%H%x09%s%x09%an%x09%ae%x09%ad"]
+if args.grep:
+    for pattern in args.grep:
+        cmd += ["--grep", pattern]
+
+if args.all_match:
+    cmd += ["--all-match"]
+
+if args.regexp_ignore_case:
+    cmd += ["--regexp-ignore-case"]
+
+rv, out, err = mrlib.run(cmd, stdin=stdin)
+
+c2m = mrlib.comments2mrs(refs, mrs)
+cargs = dict()
+
+for line in reversed(out.split("\n")):
+    if not line:
+        continue
+    sha, subj, name, email, date = line.split("\t")
+    cargs["c"] = sha
+    cargs["s"] = subj
+    cargs["n"] = name
+    cargs["e"] = email
+    cargs["d"] = date
+    cargs["m"] = c2m[sha]
+    if sha in revs:
+        cargs["f"] = ""
+    else:
+        cargs["f"] = "N"
+
+    printc(args.fmt, cargs)