blob: d0dd383764331534f7df8b864c241e7675826c8a [file] [log] [blame]
Mike Frysingerf6013762019-06-13 02:30:51 -04001# -*- coding:utf-8 -*-
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07002#
3# Copyright (C) 2008 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Sarah Owenscecd1d82012-11-01 22:59:27 -070017from __future__ import print_function
Ben Komalo08a3f682010-07-15 16:03:02 -070018import copy
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070019import re
20import sys
21
22from command import InteractiveCommand
23from editor import Editor
Doug Anderson37282b42011-03-04 11:54:18 -080024from error import HookError, UploadError
Conley Owens3bfd7212013-09-30 15:54:38 -070025from git_command import GitCommand
Doug Anderson37282b42011-03-04 11:54:18 -080026from project import RepoHook
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070027
David Pursehouse59bbb582013-05-17 10:49:33 +090028from pyversion import is_python3
29if not is_python3():
Chirayu Desai217ea7d2013-03-01 19:14:38 +053030 input = raw_input
Anthony Kingd792f792014-05-05 22:01:07 +010031else:
32 unicode = str
Chirayu Desai217ea7d2013-03-01 19:14:38 +053033
Dan Morrillf0a9a1a2010-05-05 08:18:35 -070034UNUSUAL_COMMIT_THRESHOLD = 5
Dan Morrill879a9a52010-05-04 16:56:07 -070035
36def _ConfirmManyUploads(multiple_branches=False):
37 if multiple_branches:
David Pursehouse2f9e7e42013-03-05 17:26:46 +090038 print('ATTENTION: One or more branches has an unusually high number '
Sarah Owenscecd1d82012-11-01 22:59:27 -070039 'of commits.')
Dan Morrill879a9a52010-05-04 16:56:07 -070040 else:
Sarah Owenscecd1d82012-11-01 22:59:27 -070041 print('ATTENTION: You are uploading an unusually high number of commits.')
David Pursehouse2f9e7e42013-03-05 17:26:46 +090042 print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across '
Sarah Owenscecd1d82012-11-01 22:59:27 -070043 'branches?)')
Chirayu Desai217ea7d2013-03-01 19:14:38 +053044 answer = input("If you are sure you intend to do this, type 'yes': ").strip()
Dan Morrill879a9a52010-05-04 16:56:07 -070045 return answer == "yes"
46
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070047def _die(fmt, *args):
48 msg = fmt % args
Sarah Owenscecd1d82012-11-01 22:59:27 -070049 print('error: %s' % msg, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070050 sys.exit(1)
51
Joe Onorato2896a792008-11-17 16:56:36 -050052def _SplitEmails(values):
53 result = []
David Pursehouse8a68ff92012-09-24 12:15:13 +090054 for value in values:
55 result.extend([s.strip() for s in value.split(',')])
Joe Onorato2896a792008-11-17 16:56:36 -050056 return result
57
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070058class Upload(InteractiveCommand):
59 common = True
60 helpSummary = "Upload changes for code review"
David Pursehouse8f62fb72012-11-14 12:09:38 +090061 helpUsage = """
Ficus Kirkpatricka0de6e82010-10-22 13:06:47 -070062%prog [--re --cc] [<project>]...
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070063"""
64 helpDescription = """
Shawn O. Pearce337fb9c2009-04-18 10:59:33 -070065The '%prog' command is used to send changes to the Gerrit Code
66Review system. It searches for topic branches in local projects
67that have not yet been published for review. If multiple topic
68branches are found, '%prog' opens an editor to allow the user to
69select which branches to upload.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070070
Shawn O. Pearce337fb9c2009-04-18 10:59:33 -070071'%prog' searches for uploadable changes in all projects listed at
72the command line. Projects can be specified either by name, or by
73a relative or absolute path to the project's local directory. If no
74projects are specified, '%prog' will search for uploadable changes
75in all projects listed in the manifest.
Joe Onorato2896a792008-11-17 16:56:36 -050076
77If the --reviewers or --cc options are passed, those emails are
78added to the respective list of users, and emails are sent to any
Shawn O. Pearce337fb9c2009-04-18 10:59:33 -070079new users. Users passed as --reviewers must already be registered
Joe Onorato2896a792008-11-17 16:56:36 -050080with the code review system, or the upload will fail.
Shawn O. Pearcea6df7d22008-12-12 08:04:07 -080081
Mike Frysingerb8f7bb02018-10-10 01:05:11 -040082# Configuration
Shawn O. Pearcea608fb02009-04-17 12:11:24 -070083
84review.URL.autoupload:
85
Mike Frysingere9311272011-08-11 15:46:43 -040086To disable the "Upload ... (y/N)?" prompt, you can set a per-project
Shawn O. Pearcea608fb02009-04-17 12:11:24 -070087or global Git configuration option. If review.URL.autoupload is set
88to "true" then repo will assume you always answer "y" at the prompt,
89and will not prompt you further. If it is set to "false" then repo
90will assume you always answer "n", and will abort.
91
bijia093fdb62013-11-28 09:19:22 +080092review.URL.autoreviewer:
93
94To automatically append a user or mailing list to reviews, you can set
95a per-project or global Git option to do so.
96
Ben Komalo08a3f682010-07-15 16:03:02 -070097review.URL.autocopy:
98
99To automatically copy a user or mailing list to all uploaded reviews,
100you can set a per-project or global Git option to do so. Specifically,
101review.URL.autocopy can be set to a comma separated list of reviewers
102who you always want copied on all uploads with a non-empty --re
103argument.
104
Shawn O. Pearce3575b8f2010-07-15 17:00:14 -0700105review.URL.username:
106
107Override the username used to connect to Gerrit Code Review.
108By default the local part of the email address is used.
109
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700110The URL must match the review URL listed in the manifest XML file,
111or in the .git/config within the project. For example:
112
113 [remote "origin"]
114 url = git://git.example.com/project.git
115 review = http://review.example.com/
116
117 [review "http://review.example.com/"]
118 autoupload = true
Ben Komalo08a3f682010-07-15 16:03:02 -0700119 autocopy = johndoe@company.com,my-team-alias@company.com
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700120
Anthony Russellod666e932012-06-01 00:48:22 -0400121review.URL.uploadtopic:
122
123To add a topic branch whenever uploading a commit, you can set a
124per-project or global Git option to do so. If review.URL.uploadtopic
125is set to "true" then repo will assume you always want the equivalent
126of the -t option to the repo command. If unset or set to "false" then
127repo will make use of only the command line option.
128
Mike Frysingerb8f7bb02018-10-10 01:05:11 -0400129# References
Shawn O. Pearce337fb9c2009-04-18 10:59:33 -0700130
Mike Frysinger3b24e7b2018-10-10 00:57:44 -0400131Gerrit Code Review: https://www.gerritcodereview.com/
Shawn O. Pearce337fb9c2009-04-18 10:59:33 -0700132
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700133"""
134
Shawn O. Pearcec99883f2008-11-11 17:12:43 -0800135 def _Options(self, p):
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700136 p.add_option('-t',
137 dest='auto_topic', action='store_true',
138 help='Send local branch name to Gerrit Code Review')
Joe Onorato2896a792008-11-17 16:56:36 -0500139 p.add_option('--re', '--reviewers',
140 type='string', action='append', dest='reviewers',
141 help='Request reviews from these people.')
142 p.add_option('--cc',
143 type='string', action='append', dest='cc',
144 help='Also send email to these email addresses.')
Mandeep Singh Bainesd6c93a22011-05-26 10:34:11 -0700145 p.add_option('--br',
146 type='string', action='store', dest='branch',
147 help='Branch to upload.')
Daniel Sandlere9d6b612012-04-06 10:39:32 -0400148 p.add_option('--cbr', '--current-branch',
149 dest='current_branch', action='store_true',
150 help='Upload current git branch.')
Brian Harring435370c2012-07-28 15:37:04 -0700151 p.add_option('-d', '--draft',
Jonathan Niederc94d6eb2017-08-08 18:34:53 +0000152 action='store_true', dest='draft', default=False,
153 help='If specified, upload as a draft.')
Vadim Bendeburybd8f6582018-10-31 13:48:01 -0700154 p.add_option('--ne', '--no-emails',
155 action='store_false', dest='notify', default=True,
156 help='If specified, do not send emails on upload.')
Changcheng Xiao87984c62017-08-02 16:55:03 +0200157 p.add_option('-p', '--private',
158 action='store_true', dest='private', default=False,
159 help='If specified, upload as a private change.')
160 p.add_option('-w', '--wip',
161 action='store_true', dest='wip', default=False,
162 help='If specified, upload as a work-in-progress change.')
Masaya Suzuki305a2d02017-11-13 10:48:34 -0800163 p.add_option('-o', '--push-option',
164 type='string', action='append', dest='push_options',
165 default=[],
166 help='Additional push options to transmit')
Bryan Jacobsf609f912013-05-06 13:36:24 -0400167 p.add_option('-D', '--destination', '--dest',
168 type='string', action='store', dest='dest_branch',
169 metavar='BRANCH',
170 help='Submit for review on this target branch.')
Shawn O. Pearcec99883f2008-11-11 17:12:43 -0800171
Doug Anderson37282b42011-03-04 11:54:18 -0800172 # Options relating to upload hook. Note that verify and no-verify are NOT
173 # opposites of each other, which is why they store to different locations.
174 # We are using them to match 'git commit' syntax.
175 #
176 # Combinations:
177 # - no-verify=False, verify=False (DEFAULT):
178 # If stdout is a tty, can prompt about running upload hooks if needed.
179 # If user denies running hooks, the upload is cancelled. If stdout is
180 # not a tty and we would need to prompt about upload hooks, upload is
181 # cancelled.
182 # - no-verify=False, verify=True:
183 # Always run upload hooks with no prompt.
184 # - no-verify=True, verify=False:
185 # Never run upload hooks, but upload anyway (AKA bypass hooks).
186 # - no-verify=True, verify=True:
187 # Invalid
Łukasz Gardońbed59ce2017-08-08 10:18:11 +0200188 p.add_option('--no-cert-checks',
189 dest='validate_certs', action='store_false', default=True,
190 help='Disable verifying ssl certs (unsafe).')
Doug Anderson37282b42011-03-04 11:54:18 -0800191 p.add_option('--no-verify',
192 dest='bypass_hooks', action='store_true',
193 help='Do not run the upload hook.')
194 p.add_option('--verify',
195 dest='allow_all_hooks', action='store_true',
196 help='Run the upload hook without prompting.')
197
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700198 def _SingleBranch(self, opt, branch, people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700199 project = branch.project
200 name = branch.name
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700201 remote = project.GetBranch(name).remote
202
203 key = 'review.%s.autoupload' % remote.review
204 answer = project.config.GetBoolean(key)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700205
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700206 if answer is False:
207 _die("upload blocked by %s = false" % key)
208
209 if answer is None:
Shawn O. Pearce66bdd462009-04-17 18:47:22 -0700210 date = branch.date
David Pursehouse8a68ff92012-09-24 12:15:13 +0900211 commit_list = branch.commits
Shawn O. Pearce66bdd462009-04-17 18:47:22 -0700212
Chirayu Desai610d3c42013-06-24 14:02:12 +0530213 destination = opt.dest_branch or project.dest_branch or project.revisionExpr
Nicolas Cornub54343d2017-07-10 10:31:24 +0200214 print('Upload project %s/ to remote branch %s%s:' %
Jonathan Niederc94d6eb2017-08-08 18:34:53 +0000215 (project.relpath, destination, ' (draft)' if opt.draft else ''))
Sarah Owenscecd1d82012-11-01 22:59:27 -0700216 print(' branch %s (%2d commit%s, %s):' % (
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700217 name,
David Pursehouse8a68ff92012-09-24 12:15:13 +0900218 len(commit_list),
219 len(commit_list) != 1 and 's' or '',
Sarah Owenscecd1d82012-11-01 22:59:27 -0700220 date))
David Pursehouse8a68ff92012-09-24 12:15:13 +0900221 for commit in commit_list:
Sarah Owenscecd1d82012-11-01 22:59:27 -0700222 print(' %s' % commit)
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700223
Mike Frysingerab85fe72019-07-04 17:35:11 -0400224 print('to %s (y/N)? ' % remote.review, end='')
225 # TODO: When we require Python 3, use flush=True w/print above.
226 sys.stdout.flush()
David Pursehousefc241242012-11-14 09:19:39 +0900227 answer = sys.stdin.readline().strip().lower()
228 answer = answer in ('y', 'yes', '1', 'true', 't')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700229
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700230 if answer:
Dan Morrill879a9a52010-05-04 16:56:07 -0700231 if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
232 answer = _ConfirmManyUploads()
233
234 if answer:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700235 self._UploadAndReport(opt, [branch], people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700236 else:
237 _die("upload aborted by user")
238
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700239 def _MultipleBranches(self, opt, pending, people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700240 projects = {}
241 branches = {}
242
243 script = []
244 script.append('# Uncomment the branches to upload:')
245 for project, avail in pending:
246 script.append('#')
247 script.append('# project %s/:' % project.relpath)
248
249 b = {}
250 for branch in avail:
Bryan Jacobs710d4b02013-05-31 15:28:05 -0400251 if branch is None:
252 continue
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700253 name = branch.name
254 date = branch.date
David Pursehouse8a68ff92012-09-24 12:15:13 +0900255 commit_list = branch.commits
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700256
257 if b:
258 script.append('#')
Bryan Jacobs691a7592013-05-31 15:45:28 -0400259 destination = opt.dest_branch or project.dest_branch or project.revisionExpr
Christer Fletcher6a1f7372011-04-28 14:13:14 +0200260 script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % (
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700261 name,
David Pursehouse8a68ff92012-09-24 12:15:13 +0900262 len(commit_list),
263 len(commit_list) != 1 and 's' or '',
Christer Fletcher6a1f7372011-04-28 14:13:14 +0200264 date,
Bryan Jacobs691a7592013-05-31 15:45:28 -0400265 destination))
David Pursehouse8a68ff92012-09-24 12:15:13 +0900266 for commit in commit_list:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700267 script.append('# %s' % commit)
268 b[name] = branch
269
270 projects[project.relpath] = project
271 branches[project.name] = b
272 script.append('')
273
chenguodong605a9a42011-08-22 18:42:47 +0800274 script = [ x.encode('utf-8')
275 if issubclass(type(x), unicode)
276 else x
277 for x in script ]
278
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700279 script = Editor.EditString("\n".join(script)).split("\n")
280
281 project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$')
282 branch_re = re.compile(r'^\s*branch\s*([^\s(]+)\s*\(.*')
283
284 project = None
285 todo = []
286
287 for line in script:
288 m = project_re.match(line)
289 if m:
290 name = m.group(1)
291 project = projects.get(name)
292 if not project:
293 _die('project %s not available for upload', name)
294 continue
295
296 m = branch_re.match(line)
297 if m:
298 name = m.group(1)
299 if not project:
300 _die('project for branch %s not in script', name)
301 branch = branches[project.name].get(name)
302 if not branch:
303 _die('branch %s not in %s', name, project.relpath)
304 todo.append(branch)
305 if not todo:
306 _die("nothing uncommented for upload")
Dan Morrill879a9a52010-05-04 16:56:07 -0700307
308 many_commits = False
309 for branch in todo:
310 if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
311 many_commits = True
312 break
313 if many_commits:
314 if not _ConfirmManyUploads(multiple_branches=True):
315 _die("upload aborted by user")
316
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700317 self._UploadAndReport(opt, todo, people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700318
bijia093fdb62013-11-28 09:19:22 +0800319 def _AppendAutoList(self, branch, people):
Ben Komalo08a3f682010-07-15 16:03:02 -0700320 """
bijia093fdb62013-11-28 09:19:22 +0800321 Appends the list of reviewers in the git project's config.
Ben Komalo08a3f682010-07-15 16:03:02 -0700322 Appends the list of users in the CC list in the git project's config if a
323 non-empty reviewer list was found.
324 """
Ben Komalo08a3f682010-07-15 16:03:02 -0700325 name = branch.name
326 project = branch.project
bijia093fdb62013-11-28 09:19:22 +0800327
328 key = 'review.%s.autoreviewer' % project.GetBranch(name).remote.review
329 raw_list = project.config.GetString(key)
330 if not raw_list is None:
331 people[0].extend([entry.strip() for entry in raw_list.split(',')])
332
Ben Komalo08a3f682010-07-15 16:03:02 -0700333 key = 'review.%s.autocopy' % project.GetBranch(name).remote.review
334 raw_list = project.config.GetString(key)
335 if not raw_list is None and len(people[0]) > 0:
336 people[1].extend([entry.strip() for entry in raw_list.split(',')])
337
Ficus Kirkpatrickbc7ef672009-05-04 12:45:11 -0700338 def _FindGerritChange(self, branch):
339 last_pub = branch.project.WasPublished(branch.name)
340 if last_pub is None:
341 return ""
342
343 refs = branch.GetPublishedRefs()
344 try:
345 # refs/changes/XYZ/N --> XYZ
346 return refs.get(last_pub).split('/')[-2]
David Pursehouse1d947b32012-10-25 12:23:11 +0900347 except (AttributeError, IndexError):
Ficus Kirkpatrickbc7ef672009-05-04 12:45:11 -0700348 return ""
349
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700350 def _UploadAndReport(self, opt, todo, original_people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700351 have_errors = False
352 for branch in todo:
353 try:
Ben Komalo08a3f682010-07-15 16:03:02 -0700354 people = copy.deepcopy(original_people)
bijia093fdb62013-11-28 09:19:22 +0800355 self._AppendAutoList(branch, people)
Ben Komalo08a3f682010-07-15 16:03:02 -0700356
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500357 # Check if there are local changes that may have been forgotten
Vadim Bendebury14e134d2014-10-05 15:40:30 -0700358 changes = branch.project.UncommitedFiles()
359 if changes:
David Pursehousec1b86a22012-11-14 11:36:51 +0900360 key = 'review.%s.autoupload' % branch.project.remote.review
361 answer = branch.project.config.GetBoolean(key)
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500362
David Pursehousec1b86a22012-11-14 11:36:51 +0900363 # if they want to auto upload, let's not ask because it could be automated
364 if answer is None:
Mike Frysingerab85fe72019-07-04 17:35:11 -0400365 print()
366 print('Uncommitted changes in %s (did you forget to amend?):'
367 % branch.project.name)
368 print('\n'.join(changes))
369 print('Continue uploading? (y/N) ', end='')
370 # TODO: When we require Python 3, use flush=True w/print above.
371 sys.stdout.flush()
David Pursehousec1b86a22012-11-14 11:36:51 +0900372 a = sys.stdin.readline().strip().lower()
373 if a not in ('y', 'yes', 't', 'true', 'on'):
374 print("skipping upload", file=sys.stderr)
375 branch.uploaded = False
376 branch.error = 'User aborted'
377 continue
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500378
Anthony Russellod666e932012-06-01 00:48:22 -0400379 # Check if topic branches should be sent to the server during upload
380 if opt.auto_topic is not True:
David Pursehousec1b86a22012-11-14 11:36:51 +0900381 key = 'review.%s.uploadtopic' % branch.project.remote.review
382 opt.auto_topic = branch.project.config.GetBoolean(key)
Anthony Russellod666e932012-06-01 00:48:22 -0400383
Colin Cross59b31cb2013-10-08 23:10:52 -0700384 destination = opt.dest_branch or branch.project.dest_branch
Conley Owens3bfd7212013-09-30 15:54:38 -0700385
386 # Make sure our local branch is not setup to track a different remote branch
387 merge_branch = self._GetMergeBranch(branch.project)
Conley Owensfbd3f2a2013-10-15 12:59:00 -0700388 if destination:
389 full_dest = 'refs/heads/%s' % destination
390 if not opt.dest_branch and merge_branch and merge_branch != full_dest:
391 print('merge branch %s does not match destination branch %s'
392 % (merge_branch, full_dest))
393 print('skipping upload.')
394 print('Please use `--destination %s` if this is intentional'
395 % destination)
396 branch.uploaded = False
397 continue
Conley Owens3bfd7212013-09-30 15:54:38 -0700398
Changcheng Xiao87984c62017-08-02 16:55:03 +0200399 branch.UploadForReview(people,
400 auto_topic=opt.auto_topic,
Jonathan Niederc94d6eb2017-08-08 18:34:53 +0000401 draft=opt.draft,
Changcheng Xiao87984c62017-08-02 16:55:03 +0200402 private=opt.private,
Vadim Bendeburybd8f6582018-10-31 13:48:01 -0700403 notify=None if opt.notify else 'NONE',
Changcheng Xiao87984c62017-08-02 16:55:03 +0200404 wip=opt.wip,
Łukasz Gardońbed59ce2017-08-08 10:18:11 +0200405 dest_branch=destination,
Masaya Suzuki305a2d02017-11-13 10:48:34 -0800406 validate_certs=opt.validate_certs,
407 push_options=opt.push_options)
Łukasz Gardońbed59ce2017-08-08 10:18:11 +0200408
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700409 branch.uploaded = True
Sarah Owensa5be53f2012-09-09 15:37:57 -0700410 except UploadError as e:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700411 branch.error = e
412 branch.uploaded = False
413 have_errors = True
414
Sarah Owenscecd1d82012-11-01 22:59:27 -0700415 print(file=sys.stderr)
416 print('----------------------------------------------------------------------', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700417
418 if have_errors:
419 for branch in todo:
420 if not branch.uploaded:
Shawn O. Pearcef00e0ce2009-08-22 18:39:49 -0700421 if len(str(branch.error)) <= 30:
422 fmt = ' (%s)'
423 else:
424 fmt = '\n (%s)'
Sarah Owenscecd1d82012-11-01 22:59:27 -0700425 print(('[FAILED] %-15s %-15s' + fmt) % (
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700426 branch.project.relpath + '/', \
427 branch.name, \
Sarah Owenscecd1d82012-11-01 22:59:27 -0700428 str(branch.error)),
429 file=sys.stderr)
430 print()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700431
432 for branch in todo:
David Pursehousec1b86a22012-11-14 11:36:51 +0900433 if branch.uploaded:
434 print('[OK ] %-15s %s' % (
435 branch.project.relpath + '/',
436 branch.name),
437 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700438
439 if have_errors:
440 sys.exit(1)
441
Conley Owens3bfd7212013-09-30 15:54:38 -0700442 def _GetMergeBranch(self, project):
443 p = GitCommand(project,
444 ['rev-parse', '--abbrev-ref', 'HEAD'],
445 capture_stdout = True,
446 capture_stderr = True)
447 p.Wait()
448 local_branch = p.stdout.strip()
449 p = GitCommand(project,
450 ['config', '--get', 'branch.%s.merge' % local_branch],
451 capture_stdout = True,
452 capture_stderr = True)
453 p.Wait()
454 merge_branch = p.stdout.strip()
455 return merge_branch
456
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700457 def Execute(self, opt, args):
458 project_list = self.GetProjects(args)
459 pending = []
Joe Onorato2896a792008-11-17 16:56:36 -0500460 reviewers = []
461 cc = []
Mandeep Singh Bainesd6c93a22011-05-26 10:34:11 -0700462 branch = None
463
464 if opt.branch:
465 branch = opt.branch
Joe Onorato2896a792008-11-17 16:56:36 -0500466
Doug Anderson37282b42011-03-04 11:54:18 -0800467 for project in project_list:
Daniel Sandlere9d6b612012-04-06 10:39:32 -0400468 if opt.current_branch:
469 cbr = project.CurrentBranch
Warren Turkal011d4f42013-11-27 16:20:57 -0800470 up_branch = project.GetUploadableBranch(cbr)
471 if up_branch:
472 avail = [up_branch]
473 else:
474 avail = None
475 print('ERROR: Current branch (%s) not uploadable. '
476 'You may be able to type '
477 '"git branch --set-upstream-to m/master" to fix '
478 'your branch.' % str(cbr),
479 file=sys.stderr)
Daniel Sandlere9d6b612012-04-06 10:39:32 -0400480 else:
481 avail = project.GetUploadableBranches(branch)
Doug Anderson37282b42011-03-04 11:54:18 -0800482 if avail:
483 pending.append((project, avail))
484
Mike Frysinger163a3be2016-04-04 17:31:32 -0400485 if not pending:
486 print("no branches ready for upload", file=sys.stderr)
487 return
488
489 if not opt.bypass_hooks:
Doug Anderson37282b42011-03-04 11:54:18 -0800490 hook = RepoHook('pre-upload', self.manifest.repo_hooks_project,
Mike Frysinger40252c22016-08-15 21:23:44 -0400491 self.manifest.topdir,
492 self.manifest.manifestProject.GetRemote('origin').url,
493 abort_if_user_denies=True)
David Pursehouse3bcd3052017-07-10 22:42:22 +0900494 pending_proj_names = [project.name for (project, available) in pending]
495 pending_worktrees = [project.worktree for (project, available) in pending]
Doug Anderson37282b42011-03-04 11:54:18 -0800496 try:
David James8d201162013-10-11 17:03:19 -0700497 hook.Run(opt.allow_all_hooks, project_list=pending_proj_names,
498 worktree_list=pending_worktrees)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700499 except HookError as e:
Sarah Owenscecd1d82012-11-01 22:59:27 -0700500 print("ERROR: %s" % str(e), file=sys.stderr)
Doug Anderson37282b42011-03-04 11:54:18 -0800501 return
502
Joe Onorato2896a792008-11-17 16:56:36 -0500503 if opt.reviewers:
504 reviewers = _SplitEmails(opt.reviewers)
505 if opt.cc:
506 cc = _SplitEmails(opt.cc)
David Pursehouse8f62fb72012-11-14 12:09:38 +0900507 people = (reviewers, cc)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700508
Mike Frysinger163a3be2016-04-04 17:31:32 -0400509 if len(pending) == 1 and len(pending[0][1]) == 1:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700510 self._SingleBranch(opt, pending[0][1][0], people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700511 else:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700512 self._MultipleBranches(opt, pending, people)