Add --review and --cc flags to repo upload, so you can
assign reviewers when you upload changes.
diff --git a/codereview/__init__.py b/codereview/__init__.py
index 8221688..5883555 100644
--- a/codereview/__init__.py
+++ b/codereview/__init__.py
@@ -1 +1 @@
-__version__ = 'v1.0-99-g9cd3ea2f'
+__version__ = 'v1.0-112-gbcd4db5a'
diff --git a/codereview/upload_bundle_pb2.py b/codereview/upload_bundle_pb2.py
index 7cf2f86..ff91ee1 100644
--- a/codereview/upload_bundle_pb2.py
+++ b/codereview/upload_bundle_pb2.py
@@ -35,23 +35,27 @@
options=None,
type=None),
descriptor.EnumValueDescriptor(
- name='UNKNOWN_PROJECT', index=5, number=2,
+ name='UNKNOWN_EMAIL', index=5, number=11,
options=None,
type=None),
descriptor.EnumValueDescriptor(
- name='UNKNOWN_BRANCH', index=6, number=3,
+ name='UNKNOWN_PROJECT', index=6, number=2,
options=None,
type=None),
descriptor.EnumValueDescriptor(
- name='UNKNOWN_BUNDLE', index=7, number=5,
+ name='UNKNOWN_BRANCH', index=7, number=3,
options=None,
type=None),
descriptor.EnumValueDescriptor(
- name='NOT_BUNDLE_OWNER', index=8, number=6,
+ name='UNKNOWN_BUNDLE', index=8, number=5,
options=None,
type=None),
descriptor.EnumValueDescriptor(
- name='BUNDLE_CLOSED', index=9, number=8,
+ name='NOT_BUNDLE_OWNER', index=9, number=6,
+ options=None,
+ type=None),
+ descriptor.EnumValueDescriptor(
+ name='BUNDLE_CLOSED', index=10, number=8,
options=None,
type=None),
],
@@ -136,6 +140,20 @@
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
+ descriptor.FieldDescriptor(
+ name='reviewers', full_name='codereview.UploadBundleRequest.reviewers', index=6,
+ number=3, type=9, cpp_type=9, label=3,
+ default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ descriptor.FieldDescriptor(
+ name='cc', full_name='codereview.UploadBundleRequest.cc', index=7,
+ number=4, type=9, cpp_type=9, label=3,
+ default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
],
extensions=[
],
@@ -165,6 +183,20 @@
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
+ descriptor.FieldDescriptor(
+ name='invalid_reviewers', full_name='codereview.UploadBundleResponse.invalid_reviewers', index=2,
+ number=12, type=9, cpp_type=9, label=3,
+ default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ descriptor.FieldDescriptor(
+ name='invalid_cc', full_name='codereview.UploadBundleResponse.invalid_cc', index=3,
+ number=13, type=9, cpp_type=9, label=3,
+ default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
],
extensions=[
],
diff --git a/gerrit_upload.py b/gerrit_upload.py
index d3d4ff3..17112aa 100755
--- a/gerrit_upload.py
+++ b/gerrit_upload.py
@@ -75,6 +75,7 @@
dest_branch,
src_branch,
bases,
+ people,
replace_changes = None,
save_cookies=True):
@@ -112,6 +113,10 @@
req = UploadBundleRequest()
req.dest_project = str(dest_project)
req.dest_branch = str(dest_branch)
+ for e in people[0]:
+ req.reviewers.append(e)
+ for e in people[1]:
+ req.cc.append(e)
for c in revlist:
req.contained_object.append(c)
if replace_changes:
@@ -158,6 +163,10 @@
reason = 'invalid change id'
elif rsp.status_code == UploadBundleResponse.CHANGE_CLOSED:
reason = 'one or more changes are closed'
+ elif rsp.status_code == UploadBundleResponse.UNKNOWN_EMAIL:
+ emails = [x for x in rsp.invalid_reviewers] + [
+ x for x in rsp.invalid_cc]
+ reason = 'invalid email addresses: %s' % ", ".join(emails)
else:
reason = 'unknown error ' + str(rsp.status_code)
raise UploadError(reason)
diff --git a/project.py b/project.py
index 3955033..fe3ce34 100644
--- a/project.py
+++ b/project.py
@@ -142,9 +142,10 @@
R_HEADS + self.name,
'--')
- def UploadForReview(self):
+ def UploadForReview(self, people):
self.project.UploadForReview(self.name,
- self.replace_changes)
+ self.replace_changes,
+ people)
@property
def tip_url(self):
@@ -456,7 +457,7 @@
return rb
return None
- def UploadForReview(self, branch=None, replace_changes=None):
+ def UploadForReview(self, branch=None, replace_changes=None, people=([],[])):
"""Uploads the named branch for code review.
"""
if branch is None:
@@ -495,6 +496,7 @@
dest_branch = dest_branch,
src_branch = R_HEADS + branch.name,
bases = base_list,
+ people = people,
replace_changes = replace_changes)
except proto_client.ClientLoginError:
raise UploadError('Login failure')
diff --git a/subcmds/upload.py b/subcmds/upload.py
index 11f035d..49d0018 100644
--- a/subcmds/upload.py
+++ b/subcmds/upload.py
@@ -25,11 +25,17 @@
print >>sys.stderr, 'error: %s' % msg
sys.exit(1)
+def _SplitEmails(values):
+ result = []
+ for str in values:
+ result.extend([s.strip() for s in str.split(',')])
+ return result
+
class Upload(InteractiveCommand):
common = True
helpSummary = "Upload changes for code review"
helpUsage="""
-%prog {[<project>]... | --replace <project>}
+%prog [--re --cc] {[<project>]... | --replace <project>}
"""
helpDescription = """
The '%prog' command is used to send changes to the Gerrit code
@@ -44,14 +50,25 @@
by a relative or absolute path to the project's local directory. If
no projects are specified, '%prog' will search for uploadable
changes in all projects listed in the manifest.
+
+If the --reviewers or --cc options are passed, those emails are
+added to the respective list of users, and emails are sent to any
+new users. Users passed to --reviewers must be already registered
+with the code review system, or the upload will fail.
"""
def _Options(self, p):
p.add_option('--replace',
dest='replace', action='store_true',
help='Upload replacement patchesets from this branch')
+ p.add_option('--re', '--reviewers',
+ type='string', action='append', dest='reviewers',
+ help='Request reviews from these people.')
+ p.add_option('--cc',
+ type='string', action='append', dest='cc',
+ help='Also send email to these email addresses.')
- def _SingleBranch(self, branch):
+ def _SingleBranch(self, branch, people):
project = branch.project
name = branch.name
date = branch.date
@@ -69,11 +86,11 @@
sys.stdout.write('(y/n)? ')
answer = sys.stdin.readline().strip()
if answer in ('y', 'Y', 'yes', '1', 'true', 't'):
- self._UploadAndReport([branch])
+ self._UploadAndReport([branch], people)
else:
_die("upload aborted by user")
- def _MultipleBranches(self, pending):
+ def _MultipleBranches(self, pending, people):
projects = {}
branches = {}
@@ -132,7 +149,7 @@
todo.append(branch)
if not todo:
_die("nothing uncommented for upload")
- self._UploadAndReport(todo)
+ self._UploadAndReport(todo, people)
def _ReplaceBranch(self, project):
branch = project.CurrentBranch
@@ -176,13 +193,13 @@
sys.exit(1)
branch.replace_changes = to_replace
- self._UploadAndReport([branch])
+ self._UploadAndReport([branch], people)
- def _UploadAndReport(self, todo):
+ def _UploadAndReport(self, todo, people):
have_errors = False
for branch in todo:
try:
- branch.UploadForReview()
+ branch.UploadForReview(people)
branch.uploaded = True
except UploadError, e:
branch.error = e
@@ -216,6 +233,14 @@
def Execute(self, opt, args):
project_list = self.GetProjects(args)
pending = []
+ reviewers = []
+ cc = []
+
+ if opt.reviewers:
+ reviewers = _SplitEmails(opt.reviewers)
+ if opt.cc:
+ cc = _SplitEmails(opt.cc)
+ people = (reviewers,cc)
if opt.replace:
if len(project_list) != 1:
@@ -233,6 +258,6 @@
if not pending:
print >>sys.stdout, "no branches ready for upload"
elif len(pending) == 1 and len(pending[0][1]) == 1:
- self._SingleBranch(pending[0][1][0])
+ self._SingleBranch(pending[0][1][0], people)
else:
- self._MultipleBranches(pending)
+ self._MultipleBranches(pending, people)