diff options
author | Joe Onorato <joeo@android.com> | 2008-11-17 16:56:36 -0500 |
---|---|---|
committer | Joe Onorato <joeo@android.com> | 2008-11-19 11:55:06 -0500 |
commit | 2896a79120fe1de65472736f756c47b558b44db1 (patch) | |
tree | 73a105ae2e3138575b82e9840a69c8b2eca0dd1e | |
parent | 8c6eef4713db36a2063dd5a68b3d37a5e4276508 (diff) | |
download | git-repo-2896a79120fe1de65472736f756c47b558b44db1.tar.gz |
Add --review and --cc flags to repo upload, so you can
assign reviewers when you upload changes.
-rw-r--r-- | codereview/__init__.py | 2 | ||||
-rw-r--r-- | codereview/upload_bundle_pb2.py | 42 | ||||
-rwxr-xr-x | gerrit_upload.py | 9 | ||||
-rw-r--r-- | project.py | 8 | ||||
-rw-r--r-- | subcmds/upload.py | 47 |
5 files changed, 88 insertions, 20 deletions
diff --git a/codereview/__init__.py b/codereview/__init__.py index 82216880..58835553 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 7cf2f86e..ff91ee1f 100644 --- a/codereview/upload_bundle_pb2.py +++ b/codereview/upload_bundle_pb2.py | |||
@@ -35,23 +35,27 @@ _UPLOADBUNDLERESPONSE_CODETYPE = descriptor.EnumDescriptor( | |||
35 | options=None, | 35 | options=None, |
36 | type=None), | 36 | type=None), |
37 | descriptor.EnumValueDescriptor( | 37 | descriptor.EnumValueDescriptor( |
38 | name='UNKNOWN_PROJECT', index=5, number=2, | 38 | name='UNKNOWN_EMAIL', index=5, number=11, |
39 | options=None, | 39 | options=None, |
40 | type=None), | 40 | type=None), |
41 | descriptor.EnumValueDescriptor( | 41 | descriptor.EnumValueDescriptor( |
42 | name='UNKNOWN_BRANCH', index=6, number=3, | 42 | name='UNKNOWN_PROJECT', index=6, number=2, |
43 | options=None, | 43 | options=None, |
44 | type=None), | 44 | type=None), |
45 | descriptor.EnumValueDescriptor( | 45 | descriptor.EnumValueDescriptor( |
46 | name='UNKNOWN_BUNDLE', index=7, number=5, | 46 | name='UNKNOWN_BRANCH', index=7, number=3, |
47 | options=None, | 47 | options=None, |
48 | type=None), | 48 | type=None), |
49 | descriptor.EnumValueDescriptor( | 49 | descriptor.EnumValueDescriptor( |
50 | name='NOT_BUNDLE_OWNER', index=8, number=6, | 50 | name='UNKNOWN_BUNDLE', index=8, number=5, |
51 | options=None, | 51 | options=None, |
52 | type=None), | 52 | type=None), |
53 | descriptor.EnumValueDescriptor( | 53 | descriptor.EnumValueDescriptor( |
54 | name='BUNDLE_CLOSED', index=9, number=8, | 54 | name='NOT_BUNDLE_OWNER', index=9, number=6, |
55 | options=None, | ||
56 | type=None), | ||
57 | descriptor.EnumValueDescriptor( | ||
58 | name='BUNDLE_CLOSED', index=10, number=8, | ||
55 | options=None, | 59 | options=None, |
56 | type=None), | 60 | type=None), |
57 | ], | 61 | ], |
@@ -136,6 +140,20 @@ _UPLOADBUNDLEREQUEST = descriptor.Descriptor( | |||
136 | message_type=None, enum_type=None, containing_type=None, | 140 | message_type=None, enum_type=None, containing_type=None, |
137 | is_extension=False, extension_scope=None, | 141 | is_extension=False, extension_scope=None, |
138 | options=None), | 142 | options=None), |
143 | descriptor.FieldDescriptor( | ||
144 | name='reviewers', full_name='codereview.UploadBundleRequest.reviewers', index=6, | ||
145 | number=3, type=9, cpp_type=9, label=3, | ||
146 | default_value=[], | ||
147 | message_type=None, enum_type=None, containing_type=None, | ||
148 | is_extension=False, extension_scope=None, | ||
149 | options=None), | ||
150 | descriptor.FieldDescriptor( | ||
151 | name='cc', full_name='codereview.UploadBundleRequest.cc', index=7, | ||
152 | number=4, type=9, cpp_type=9, label=3, | ||
153 | default_value=[], | ||
154 | message_type=None, enum_type=None, containing_type=None, | ||
155 | is_extension=False, extension_scope=None, | ||
156 | options=None), | ||
139 | ], | 157 | ], |
140 | extensions=[ | 158 | extensions=[ |
141 | ], | 159 | ], |
@@ -165,6 +183,20 @@ _UPLOADBUNDLERESPONSE = descriptor.Descriptor( | |||
165 | message_type=None, enum_type=None, containing_type=None, | 183 | message_type=None, enum_type=None, containing_type=None, |
166 | is_extension=False, extension_scope=None, | 184 | is_extension=False, extension_scope=None, |
167 | options=None), | 185 | options=None), |
186 | descriptor.FieldDescriptor( | ||
187 | name='invalid_reviewers', full_name='codereview.UploadBundleResponse.invalid_reviewers', index=2, | ||
188 | number=12, type=9, cpp_type=9, label=3, | ||
189 | default_value=[], | ||
190 | message_type=None, enum_type=None, containing_type=None, | ||
191 | is_extension=False, extension_scope=None, | ||
192 | options=None), | ||
193 | descriptor.FieldDescriptor( | ||
194 | name='invalid_cc', full_name='codereview.UploadBundleResponse.invalid_cc', index=3, | ||
195 | number=13, type=9, cpp_type=9, label=3, | ||
196 | default_value=[], | ||
197 | message_type=None, enum_type=None, containing_type=None, | ||
198 | is_extension=False, extension_scope=None, | ||
199 | options=None), | ||
168 | ], | 200 | ], |
169 | extensions=[ | 201 | extensions=[ |
170 | ], | 202 | ], |
diff --git a/gerrit_upload.py b/gerrit_upload.py index d3d4ff3e..17112aac 100755 --- a/gerrit_upload.py +++ b/gerrit_upload.py | |||
@@ -75,6 +75,7 @@ def UploadBundle(project, | |||
75 | dest_branch, | 75 | dest_branch, |
76 | src_branch, | 76 | src_branch, |
77 | bases, | 77 | bases, |
78 | people, | ||
78 | replace_changes = None, | 79 | replace_changes = None, |
79 | save_cookies=True): | 80 | save_cookies=True): |
80 | 81 | ||
@@ -112,6 +113,10 @@ def UploadBundle(project, | |||
112 | req = UploadBundleRequest() | 113 | req = UploadBundleRequest() |
113 | req.dest_project = str(dest_project) | 114 | req.dest_project = str(dest_project) |
114 | req.dest_branch = str(dest_branch) | 115 | req.dest_branch = str(dest_branch) |
116 | for e in people[0]: | ||
117 | req.reviewers.append(e) | ||
118 | for e in people[1]: | ||
119 | req.cc.append(e) | ||
115 | for c in revlist: | 120 | for c in revlist: |
116 | req.contained_object.append(c) | 121 | req.contained_object.append(c) |
117 | if replace_changes: | 122 | if replace_changes: |
@@ -158,6 +163,10 @@ def UploadBundle(project, | |||
158 | reason = 'invalid change id' | 163 | reason = 'invalid change id' |
159 | elif rsp.status_code == UploadBundleResponse.CHANGE_CLOSED: | 164 | elif rsp.status_code == UploadBundleResponse.CHANGE_CLOSED: |
160 | reason = 'one or more changes are closed' | 165 | reason = 'one or more changes are closed' |
166 | elif rsp.status_code == UploadBundleResponse.UNKNOWN_EMAIL: | ||
167 | emails = [x for x in rsp.invalid_reviewers] + [ | ||
168 | x for x in rsp.invalid_cc] | ||
169 | reason = 'invalid email addresses: %s' % ", ".join(emails) | ||
161 | else: | 170 | else: |
162 | reason = 'unknown error ' + str(rsp.status_code) | 171 | reason = 'unknown error ' + str(rsp.status_code) |
163 | raise UploadError(reason) | 172 | raise UploadError(reason) |
@@ -142,9 +142,10 @@ class ReviewableBranch(object): | |||
142 | R_HEADS + self.name, | 142 | R_HEADS + self.name, |
143 | '--') | 143 | '--') |
144 | 144 | ||
145 | def UploadForReview(self): | 145 | def UploadForReview(self, people): |
146 | self.project.UploadForReview(self.name, | 146 | self.project.UploadForReview(self.name, |
147 | self.replace_changes) | 147 | self.replace_changes, |
148 | people) | ||
148 | 149 | ||
149 | @property | 150 | @property |
150 | def tip_url(self): | 151 | def tip_url(self): |
@@ -456,7 +457,7 @@ class Project(object): | |||
456 | return rb | 457 | return rb |
457 | return None | 458 | return None |
458 | 459 | ||
459 | def UploadForReview(self, branch=None, replace_changes=None): | 460 | def UploadForReview(self, branch=None, replace_changes=None, people=([],[])): |
460 | """Uploads the named branch for code review. | 461 | """Uploads the named branch for code review. |
461 | """ | 462 | """ |
462 | if branch is None: | 463 | if branch is None: |
@@ -495,6 +496,7 @@ class Project(object): | |||
495 | dest_branch = dest_branch, | 496 | dest_branch = dest_branch, |
496 | src_branch = R_HEADS + branch.name, | 497 | src_branch = R_HEADS + branch.name, |
497 | bases = base_list, | 498 | bases = base_list, |
499 | people = people, | ||
498 | replace_changes = replace_changes) | 500 | replace_changes = replace_changes) |
499 | except proto_client.ClientLoginError: | 501 | except proto_client.ClientLoginError: |
500 | raise UploadError('Login failure') | 502 | raise UploadError('Login failure') |
diff --git a/subcmds/upload.py b/subcmds/upload.py index 11f035d7..49d00187 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py | |||
@@ -25,11 +25,17 @@ def _die(fmt, *args): | |||
25 | print >>sys.stderr, 'error: %s' % msg | 25 | print >>sys.stderr, 'error: %s' % msg |
26 | sys.exit(1) | 26 | sys.exit(1) |
27 | 27 | ||
28 | def _SplitEmails(values): | ||
29 | result = [] | ||
30 | for str in values: | ||
31 | result.extend([s.strip() for s in str.split(',')]) | ||
32 | return result | ||
33 | |||
28 | class Upload(InteractiveCommand): | 34 | class Upload(InteractiveCommand): |
29 | common = True | 35 | common = True |
30 | helpSummary = "Upload changes for code review" | 36 | helpSummary = "Upload changes for code review" |
31 | helpUsage=""" | 37 | helpUsage=""" |
32 | %prog {[<project>]... | --replace <project>} | 38 | %prog [--re --cc] {[<project>]... | --replace <project>} |
33 | """ | 39 | """ |
34 | helpDescription = """ | 40 | helpDescription = """ |
35 | The '%prog' command is used to send changes to the Gerrit code | 41 | The '%prog' command is used to send changes to the Gerrit code |
@@ -44,14 +50,25 @@ at the command line. Projects can be specified either by name, or | |||
44 | by a relative or absolute path to the project's local directory. If | 50 | by a relative or absolute path to the project's local directory. If |
45 | no projects are specified, '%prog' will search for uploadable | 51 | no projects are specified, '%prog' will search for uploadable |
46 | changes in all projects listed in the manifest. | 52 | changes in all projects listed in the manifest. |
53 | |||
54 | If the --reviewers or --cc options are passed, those emails are | ||
55 | added to the respective list of users, and emails are sent to any | ||
56 | new users. Users passed to --reviewers must be already registered | ||
57 | with the code review system, or the upload will fail. | ||
47 | """ | 58 | """ |
48 | 59 | ||
49 | def _Options(self, p): | 60 | def _Options(self, p): |
50 | p.add_option('--replace', | 61 | p.add_option('--replace', |
51 | dest='replace', action='store_true', | 62 | dest='replace', action='store_true', |
52 | help='Upload replacement patchesets from this branch') | 63 | help='Upload replacement patchesets from this branch') |
53 | 64 | p.add_option('--re', '--reviewers', | |
54 | def _SingleBranch(self, branch): | 65 | type='string', action='append', dest='reviewers', |
66 | help='Request reviews from these people.') | ||
67 | p.add_option('--cc', | ||
68 | type='string', action='append', dest='cc', | ||
69 | help='Also send email to these email addresses.') | ||
70 | |||
71 | def _SingleBranch(self, branch, people): | ||
55 | project = branch.project | 72 | project = branch.project |
56 | name = branch.name | 73 | name = branch.name |
57 | date = branch.date | 74 | date = branch.date |
@@ -69,11 +86,11 @@ changes in all projects listed in the manifest. | |||
69 | sys.stdout.write('(y/n)? ') | 86 | sys.stdout.write('(y/n)? ') |
70 | answer = sys.stdin.readline().strip() | 87 | answer = sys.stdin.readline().strip() |
71 | if answer in ('y', 'Y', 'yes', '1', 'true', 't'): | 88 | if answer in ('y', 'Y', 'yes', '1', 'true', 't'): |
72 | self._UploadAndReport([branch]) | 89 | self._UploadAndReport([branch], people) |
73 | else: | 90 | else: |
74 | _die("upload aborted by user") | 91 | _die("upload aborted by user") |
75 | 92 | ||
76 | def _MultipleBranches(self, pending): | 93 | def _MultipleBranches(self, pending, people): |
77 | projects = {} | 94 | projects = {} |
78 | branches = {} | 95 | branches = {} |
79 | 96 | ||
@@ -132,7 +149,7 @@ changes in all projects listed in the manifest. | |||
132 | todo.append(branch) | 149 | todo.append(branch) |
133 | if not todo: | 150 | if not todo: |
134 | _die("nothing uncommented for upload") | 151 | _die("nothing uncommented for upload") |
135 | self._UploadAndReport(todo) | 152 | self._UploadAndReport(todo, people) |
136 | 153 | ||
137 | def _ReplaceBranch(self, project): | 154 | def _ReplaceBranch(self, project): |
138 | branch = project.CurrentBranch | 155 | branch = project.CurrentBranch |
@@ -176,13 +193,13 @@ changes in all projects listed in the manifest. | |||
176 | sys.exit(1) | 193 | sys.exit(1) |
177 | 194 | ||
178 | branch.replace_changes = to_replace | 195 | branch.replace_changes = to_replace |
179 | self._UploadAndReport([branch]) | 196 | self._UploadAndReport([branch], people) |
180 | 197 | ||
181 | def _UploadAndReport(self, todo): | 198 | def _UploadAndReport(self, todo, people): |
182 | have_errors = False | 199 | have_errors = False |
183 | for branch in todo: | 200 | for branch in todo: |
184 | try: | 201 | try: |
185 | branch.UploadForReview() | 202 | branch.UploadForReview(people) |
186 | branch.uploaded = True | 203 | branch.uploaded = True |
187 | except UploadError, e: | 204 | except UploadError, e: |
188 | branch.error = e | 205 | branch.error = e |
@@ -216,6 +233,14 @@ changes in all projects listed in the manifest. | |||
216 | def Execute(self, opt, args): | 233 | def Execute(self, opt, args): |
217 | project_list = self.GetProjects(args) | 234 | project_list = self.GetProjects(args) |
218 | pending = [] | 235 | pending = [] |
236 | reviewers = [] | ||
237 | cc = [] | ||
238 | |||
239 | if opt.reviewers: | ||
240 | reviewers = _SplitEmails(opt.reviewers) | ||
241 | if opt.cc: | ||
242 | cc = _SplitEmails(opt.cc) | ||
243 | people = (reviewers,cc) | ||
219 | 244 | ||
220 | if opt.replace: | 245 | if opt.replace: |
221 | if len(project_list) != 1: | 246 | if len(project_list) != 1: |
@@ -233,6 +258,6 @@ changes in all projects listed in the manifest. | |||
233 | if not pending: | 258 | if not pending: |
234 | print >>sys.stdout, "no branches ready for upload" | 259 | print >>sys.stdout, "no branches ready for upload" |
235 | elif len(pending) == 1 and len(pending[0][1]) == 1: | 260 | elif len(pending) == 1 and len(pending[0][1]) == 1: |
236 | self._SingleBranch(pending[0][1][0]) | 261 | self._SingleBranch(pending[0][1][0], people) |
237 | else: | 262 | else: |
238 | self._MultipleBranches(pending) | 263 | self._MultipleBranches(pending, people) |