blob: db6bcfe0586282990e73b4fb55e9319326c26c64 [file] [log] [blame]
Patrick Williams45c70172021-03-04 20:25:26 -06001#!/usr/bin/env -S python3 -B
Andrew Jefferyf4019fe2018-05-18 16:42:18 +09302#
3# SPDX-License-Identifier: Apache-2.0
4# Copyright (C) 2018 IBM Corp.
5#
6# Push changes to Gerrit, automatically adding reviewers to the patches by
7# parsing the OpenBMC-style MAINTAINERS file in the root of the repository (if
8# it exists).
9
10from obmc import maintainers
Patrick Williams404d3012021-06-21 15:33:11 -050011from typing import cast, Callable, List, Optional, Tuple
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093012import argparse
13import os
Patrick Williams2deb2e32021-06-21 15:15:20 -050014import sh # type: ignore
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093015import sys
16
Patrick Williams2deb2e32021-06-21 15:15:20 -050017git: Callable[..., str] = sh.git.bake()
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093018
Patrick Williams9a014392021-06-21 14:57:29 -050019
Patrick Williams404d3012021-06-21 15:33:11 -050020def get_reviewers(
21 root: Optional[str] = None, mname: str = "MAINTAINERS"
22) -> Tuple[List[str], List[str]]:
23 maints: List[str] = list()
Patrick Williams2deb2e32021-06-21 15:15:20 -050024 reviewers: List[str] = list()
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093025 if not root:
Patrick Williams9a014392021-06-21 14:57:29 -050026 root = git("rev-parse", "--show-toplevel").strip()
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093027 mfile = os.path.join(root, mname)
Andrew Jeffery39654b12018-05-22 12:38:53 +093028 if not os.path.exists(mfile):
Patrick Williams404d3012021-06-21 15:33:11 -050029 return (maints, reviewers)
Patrick Williams9a014392021-06-21 14:57:29 -050030 with open(mfile, "r") as mstream:
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093031 maintainers.trash_preamble(mstream)
32 block = maintainers.parse_block(mstream)
33 if not block:
Patrick Williams404d3012021-06-21 15:33:11 -050034 return (maints, reviewers)
Patrick Williams9a014392021-06-21 14:57:29 -050035 mlist = cast(
36 List[maintainers.Identity], block[maintainers.LineType.MAINTAINER]
37 )
Patrick Williams404d3012021-06-21 15:33:11 -050038 maints.extend(i.email.address for i in mlist)
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093039 if maintainers.LineType.REVIEWER in block:
Patrick Williams9a014392021-06-21 14:57:29 -050040 rlist = cast(
41 List[maintainers.Identity], block[maintainers.LineType.REVIEWER]
42 )
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093043 reviewers.extend(i.email.address for i in rlist)
Patrick Williams404d3012021-06-21 15:33:11 -050044 return (maints, reviewers)
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093045
Patrick Williams9a014392021-06-21 14:57:29 -050046
47def gerrit_refspec_args(
Patrick Williams404d3012021-06-21 15:33:11 -050048 maintainers: Optional[List[str]] = None,
49 reviewers: Optional[List[str]] = None,
50 topic: str = None,
Patrick Williams9a014392021-06-21 14:57:29 -050051) -> str:
Patrick Williams2deb2e32021-06-21 15:15:20 -050052 argl: List[str] = []
Patrick Williams404d3012021-06-21 15:33:11 -050053 if maintainers:
54 argl.extend("r={}".format(addr) for addr in maintainers)
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093055 if reviewers:
Patrick Williams404d3012021-06-21 15:33:11 -050056 argl.extend("cc={}".format(addr) for addr in reviewers)
Andrew Jeffery3512b932020-06-15 13:09:16 +093057 if topic:
Lei YU8e56c312020-07-30 10:14:47 +000058 argl.append("topic={}".format(topic))
Andrew Jeffery3512b932020-06-15 13:09:16 +093059 return ",".join(argl)
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093060
Patrick Williams9a014392021-06-21 14:57:29 -050061
Andrew Jeffery3512b932020-06-15 13:09:16 +093062def decorate_refspec(refspec: str, topic: str) -> str:
Patrick Williams404d3012021-06-21 15:33:11 -050063 (maintainers, reviewers) = get_reviewers()
64 gargs = gerrit_refspec_args(maintainers, reviewers, topic)
Andrew Jeffery39654b12018-05-22 12:38:53 +093065 if not gargs:
66 return refspec
Patrick Williams9a014392021-06-21 14:57:29 -050067 if "%" in refspec:
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093068 return "{},{}".format(refspec, gargs)
69 return "{}%{}".format(refspec, gargs)
70
Patrick Williams9a014392021-06-21 14:57:29 -050071
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093072def do_push(args: argparse.Namespace) -> None:
Patrick Williams2deb2e32021-06-21 15:15:20 -050073 git(
74 "push",
Patrick Williams9a014392021-06-21 14:57:29 -050075 args.remote,
76 decorate_refspec(args.refspec, args.topic),
77 _in=sys.stdin,
78 _out=sys.stdout,
79 _err=sys.stderr,
80 )
81
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093082
Patrick Williams2d198342021-06-21 15:35:50 -050083def do_reviewers(args: argparse.Namespace) -> None:
84 (maintainers, reviewers) = get_reviewers()
85 print(gerrit_refspec_args(maintainers, reviewers))
86
87
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093088parser = argparse.ArgumentParser()
Patrick Williams9a014392021-06-21 14:57:29 -050089subbies = parser.add_subparsers(dest="subcommand")
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093090subbies.required = True
Patrick Williams2d198342021-06-21 15:35:50 -050091
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093092push = subbies.add_parser("push", help="Push changes to Gerrit with reviewers")
93push.add_argument("remote")
94push.add_argument("refspec")
Patrick Williams9a014392021-06-21 14:57:29 -050095push.add_argument("topic", nargs="?", default=None)
Andrew Jefferyf4019fe2018-05-18 16:42:18 +093096push.set_defaults(func=do_push)
97
Patrick Williams2d198342021-06-21 15:35:50 -050098reviewers = subbies.add_parser("reviewers", help="Get the reviewer list.")
99reviewers.set_defaults(func=do_reviewers)
100
Andrew Jefferyf4019fe2018-05-18 16:42:18 +0930101args = parser.parse_args()
102args.func(args)