#!/usr/bin/env python3 """ Upload comments to gerrit. mph = "make Peter happy". Previously called mch ("make Casey happy"). """ import optparse import re import sys import codereview_parser try: import gerrit_util import git_cl except: print('depot_tools not found; try appending the module path to your' + ' python path') sys.exit(1) def DieWithError(message): print(message, file=sys.stderr) sys.exit(1) # These are additions to gerrit_util.py from depot_tools not yet ready to send # out for review. def CreateDraft(host, change, revision, path, line, msg=''): """Create a draft gerrit comment.""" path = 'changes/%s/revisions/%s/drafts' % (change, revision) body = {'path': path, 'line': line, 'message': msg, 'unresolved': True} conn = gerrit_util.CreateHttpConn(host, path, reqtype='PUT', body=body) return gerrit_util.ReadHttpJsonResponse(conn) def SetReview(host, change, revision, msg, lgtm, comments): """Sets a review in gerrit.""" path = 'changes/%s/revisions/%s/review' % (change, revision) body = {'message': msg, 'comments': comments} if lgtm: body['labels'] = {'code-review': 1} conn = gerrit_util.CreateHttpConn(host, path, reqtype='POST', body=body) return gerrit_util.ReadHttpJsonResponse(conn) class GerritParser(codereview_parser.Parser): def __init__(self, file): codereview_parser.Parser.__init__(self, file) self._HOST = 'chromium-review.googlesource.com' self._issue_number = 0 self._patchset = 0 self._change_id = '' self._revision_id = "" self._overall_comment = '' self._comments = {} def OnError(self, msg): DieWithError(msg) def OnPreambleLine(self, line): matcher = re.match('Issue: (\d+), patchset: (\d+)', line) if matcher: self._issue_number = int(matcher.groups()[0]) self._patchset = int(matcher.groups()[1]) self._change_id = gerrit_util.GetChange(self._HOST, self._issue_number)['change_id'] self._revision_id = gerrit_util.GetChangeCurrentRevision( self._HOST, self._change_id)[0]['current_revision'] def OnFinishPreamble(self): pass def OnOverallComment(self, comment): self._overall_comment = comment def OnFileComment(self, path, line, text, comment): if not path in self._comments: self._comments[path] = [] self._comments[path].append({ 'message': comment, 'line': line, 'unresolved': True }) def OnParseFinished(self): is_lg = re.match(".*lgtm.*", self._overall_comment, re.IGNORECASE) SetReview(self._HOST, self._change_id, self._revision_id, self._overall_comment, is_lg, self._comments) print('Done') def Parse(self): codereview_parser.Parser.Parse(self) self.OnParseFinished() def add_comment(self, issue, message, add_as_reviewer=False): max_message = 10000 tail = '...\n(message too large)' if len(message) > max_message: message = message[:max_message - len(tail)] + tail issue_props = self._rd.get_issue_properties(self._issue_number, None) reviewers = ','.join(issue_props['reviewers']) cc = ','.join(issue_props['cc']) self._rd.post('/%d/publish' % issue, [('xsrf_token', self._rd.xsrf_token()), ('message', message), ('message_only', 'False'), ('add_as_reviewer', str(bool(add_as_reviewer))), ('reviewers', reviewers), ('cc', cc), ('send_mail', 'True'), ('no_redirect', 'True')]) def ProcessFile(file): parser = GerritParser(file) parser.Parse() def main(argv): parser = optparse.OptionParser() parser.add_option('-f', '--file') options, args = parser.parse_args(argv) file_name = options.file if file_name is None: if len(argv) != 1: parser.print_help() DieWithError('Review file not specified') file_name = argv[0] with open(file_name) as file: ProcessFile(file) if __name__ == '__main__': main(sys.argv[1:])