obmc-scripts: Add maintainers

maintainers is a python library and collection of scripts for
parsing and generating OpenBMC MAINTAINERS files. The culmination of the
effort is the `obmc-gerrit` git wrapper that automatically adds people
listed in the per-repository MAINTAINERS file as reviewers on changes
pushed to Gerrit.

Change-Id: I4a3c3efc5899b80a65836c1ad948ec1153dd6796
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/amboar/obmc-scripts/maintainers/obmc-gerrit b/amboar/obmc-scripts/maintainers/obmc-gerrit
new file mode 100755
index 0000000..a52abbc
--- /dev/null
+++ b/amboar/obmc-scripts/maintainers/obmc-gerrit
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (C) 2018 IBM Corp.
+#
+# Push changes to Gerrit, automatically adding reviewers to the patches by
+# parsing the OpenBMC-style MAINTAINERS file in the root of the repository (if
+# it exists).
+
+from obmc import maintainers
+from typing import cast, List, Optional
+import argparse
+import os
+import sh
+import sys
+
+git = sh.git.bake()
+
+def get_reviewers(root: Optional[str]=None, mname: str='MAINTAINERS') -> List[str]:
+    reviewers: List[str] = list()
+    if not root:
+        root = git('rev-parse', '--show-toplevel').strip()
+    mfile = os.path.join(root, mname)
+    with open(mfile, 'r') as mstream:
+        maintainers.trash_preamble(mstream)
+        block = maintainers.parse_block(mstream)
+        if not block:
+            return reviewers
+        mlist = cast(List[maintainers.Identity],
+                     block[maintainers.LineType.MAINTAINER])
+        reviewers.extend(i.email.address for i in mlist)
+        if maintainers.LineType.REVIEWER in block:
+            rlist = cast(List[maintainers.Identity],
+                         block[maintainers.LineType.REVIEWER])
+            reviewers.extend(i.email.address for i in rlist)
+    return reviewers
+
+def gerrit_refspec_args(reviewers: Optional[List[str]]=None) -> str:
+    args = ""
+    if reviewers:
+        args += ",".join("r={}".format(addr) for addr in reviewers)
+    return args
+
+def decorate_refspec(refspec: str) -> str:
+    gargs = gerrit_refspec_args(get_reviewers())
+    if '%' in refspec:
+        return "{},{}".format(refspec, gargs)
+    return "{}%{}".format(refspec, gargs)
+
+def do_push(args: argparse.Namespace) -> None:
+    git.push(args.remote, decorate_refspec(args.refspec),
+             _in=sys.stdin, _out=sys.stdout, _err=sys.stderr)
+
+parser = argparse.ArgumentParser()
+subbies = parser.add_subparsers(dest='subcommand')
+subbies.required = True
+push = subbies.add_parser("push", help="Push changes to Gerrit with reviewers")
+push.add_argument("remote")
+push.add_argument("refspec")
+push.set_defaults(func=do_push)
+
+args = parser.parse_args()
+args.func(args)