--- /dev/null
+#!/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)