blob: b81cf0a8b1ee26f328c55834e0157ac5f44f040a [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',
David Pursehouse08671042020-02-12 13:52:31 +0900140 type='string', action='append', dest='reviewers',
Joe Onorato2896a792008-11-17 16:56:36 -0500141 help='Request reviews from these people.')
142 p.add_option('--cc',
David Pursehouse08671042020-02-12 13:52:31 +0900143 type='string', action='append', dest='cc',
Joe Onorato2896a792008-11-17 16:56:36 -0500144 help='Also send email to these email addresses.')
Mandeep Singh Bainesd6c93a22011-05-26 10:34:11 -0700145 p.add_option('--br',
David Pursehouse08671042020-02-12 13:52:31 +0900146 type='string', action='store', dest='branch',
Mandeep Singh Bainesd6c93a22011-05-26 10:34:11 -0700147 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.')
Mike Frysinger21c15752020-02-11 05:17:16 -0500171 p.add_option('--no-cert-checks',
172 dest='validate_certs', action='store_false', default=True,
173 help='Disable verifying ssl certs (unsafe).')
Shawn O. Pearcec99883f2008-11-11 17:12:43 -0800174
Doug Anderson37282b42011-03-04 11:54:18 -0800175 # Options relating to upload hook. Note that verify and no-verify are NOT
176 # opposites of each other, which is why they store to different locations.
177 # We are using them to match 'git commit' syntax.
178 #
179 # Combinations:
180 # - no-verify=False, verify=False (DEFAULT):
181 # If stdout is a tty, can prompt about running upload hooks if needed.
182 # If user denies running hooks, the upload is cancelled. If stdout is
183 # not a tty and we would need to prompt about upload hooks, upload is
184 # cancelled.
185 # - no-verify=False, verify=True:
186 # Always run upload hooks with no prompt.
187 # - no-verify=True, verify=False:
188 # Never run upload hooks, but upload anyway (AKA bypass hooks).
189 # - no-verify=True, verify=True:
190 # Invalid
Mike Frysinger21c15752020-02-11 05:17:16 -0500191 g = p.add_option_group('Upload hooks')
192 g.add_option('--no-verify',
Doug Anderson37282b42011-03-04 11:54:18 -0800193 dest='bypass_hooks', action='store_true',
194 help='Do not run the upload hook.')
Mike Frysinger21c15752020-02-11 05:17:16 -0500195 g.add_option('--verify',
Doug Anderson37282b42011-03-04 11:54:18 -0800196 dest='allow_all_hooks', action='store_true',
197 help='Run the upload hook without prompting.')
Mike Frysinger21c15752020-02-11 05:17:16 -0500198 g.add_option('--ignore-hooks',
199 dest='ignore_hooks', action='store_true',
200 help='Do not abort uploading if upload hooks fail.')
Doug Anderson37282b42011-03-04 11:54:18 -0800201
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700202 def _SingleBranch(self, opt, branch, people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700203 project = branch.project
204 name = branch.name
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700205 remote = project.GetBranch(name).remote
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700206
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700207 key = 'review.%s.autoupload' % remote.review
208 answer = project.config.GetBoolean(key)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700209
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700210 if answer is False:
211 _die("upload blocked by %s = false" % key)
212
213 if answer is None:
Shawn O. Pearce66bdd462009-04-17 18:47:22 -0700214 date = branch.date
David Pursehouse8a68ff92012-09-24 12:15:13 +0900215 commit_list = branch.commits
Shawn O. Pearce66bdd462009-04-17 18:47:22 -0700216
Chirayu Desai610d3c42013-06-24 14:02:12 +0530217 destination = opt.dest_branch or project.dest_branch or project.revisionExpr
Nicolas Cornub54343d2017-07-10 10:31:24 +0200218 print('Upload project %s/ to remote branch %s%s:' %
Jonathan Niederc94d6eb2017-08-08 18:34:53 +0000219 (project.relpath, destination, ' (draft)' if opt.draft else ''))
Sarah Owenscecd1d82012-11-01 22:59:27 -0700220 print(' branch %s (%2d commit%s, %s):' % (
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700221 name,
David Pursehouse8a68ff92012-09-24 12:15:13 +0900222 len(commit_list),
223 len(commit_list) != 1 and 's' or '',
Sarah Owenscecd1d82012-11-01 22:59:27 -0700224 date))
David Pursehouse8a68ff92012-09-24 12:15:13 +0900225 for commit in commit_list:
Sarah Owenscecd1d82012-11-01 22:59:27 -0700226 print(' %s' % commit)
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700227
Mike Frysingerab85fe72019-07-04 17:35:11 -0400228 print('to %s (y/N)? ' % remote.review, end='')
229 # TODO: When we require Python 3, use flush=True w/print above.
230 sys.stdout.flush()
David Pursehousefc241242012-11-14 09:19:39 +0900231 answer = sys.stdin.readline().strip().lower()
232 answer = answer in ('y', 'yes', '1', 'true', 't')
Shawn O. Pearcea608fb02009-04-17 12:11:24 -0700233
234 if answer:
Dan Morrill879a9a52010-05-04 16:56:07 -0700235 if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
236 answer = _ConfirmManyUploads()
237
238 if answer:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700239 self._UploadAndReport(opt, [branch], people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700240 else:
241 _die("upload aborted by user")
242
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700243 def _MultipleBranches(self, opt, pending, people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700244 projects = {}
245 branches = {}
246
247 script = []
248 script.append('# Uncomment the branches to upload:')
249 for project, avail in pending:
250 script.append('#')
251 script.append('# project %s/:' % project.relpath)
252
253 b = {}
254 for branch in avail:
Bryan Jacobs710d4b02013-05-31 15:28:05 -0400255 if branch is None:
256 continue
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700257 name = branch.name
258 date = branch.date
David Pursehouse8a68ff92012-09-24 12:15:13 +0900259 commit_list = branch.commits
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700260
261 if b:
262 script.append('#')
Bryan Jacobs691a7592013-05-31 15:45:28 -0400263 destination = opt.dest_branch or project.dest_branch or project.revisionExpr
Christer Fletcher6a1f7372011-04-28 14:13:14 +0200264 script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % (
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700265 name,
David Pursehouse8a68ff92012-09-24 12:15:13 +0900266 len(commit_list),
267 len(commit_list) != 1 and 's' or '',
Christer Fletcher6a1f7372011-04-28 14:13:14 +0200268 date,
Bryan Jacobs691a7592013-05-31 15:45:28 -0400269 destination))
David Pursehouse8a68ff92012-09-24 12:15:13 +0900270 for commit in commit_list:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700271 script.append('# %s' % commit)
272 b[name] = branch
273
274 projects[project.relpath] = project
275 branches[project.name] = b
276 script.append('')
277
278 script = Editor.EditString("\n".join(script)).split("\n")
279
280 project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$')
281 branch_re = re.compile(r'^\s*branch\s*([^\s(]+)\s*\(.*')
282
283 project = None
284 todo = []
285
286 for line in script:
287 m = project_re.match(line)
288 if m:
289 name = m.group(1)
290 project = projects.get(name)
291 if not project:
292 _die('project %s not available for upload', name)
293 continue
294
295 m = branch_re.match(line)
296 if m:
297 name = m.group(1)
298 if not project:
299 _die('project for branch %s not in script', name)
300 branch = branches[project.name].get(name)
301 if not branch:
302 _die('branch %s not in %s', name, project.relpath)
303 todo.append(branch)
304 if not todo:
305 _die("nothing uncommented for upload")
Dan Morrill879a9a52010-05-04 16:56:07 -0700306
307 many_commits = False
308 for branch in todo:
309 if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
310 many_commits = True
311 break
312 if many_commits:
313 if not _ConfirmManyUploads(multiple_branches=True):
314 _die("upload aborted by user")
315
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700316 self._UploadAndReport(opt, todo, people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700317
bijia093fdb62013-11-28 09:19:22 +0800318 def _AppendAutoList(self, branch, people):
Ben Komalo08a3f682010-07-15 16:03:02 -0700319 """
bijia093fdb62013-11-28 09:19:22 +0800320 Appends the list of reviewers in the git project's config.
Ben Komalo08a3f682010-07-15 16:03:02 -0700321 Appends the list of users in the CC list in the git project's config if a
322 non-empty reviewer list was found.
323 """
Ben Komalo08a3f682010-07-15 16:03:02 -0700324 name = branch.name
325 project = branch.project
bijia093fdb62013-11-28 09:19:22 +0800326
327 key = 'review.%s.autoreviewer' % project.GetBranch(name).remote.review
328 raw_list = project.config.GetString(key)
329 if not raw_list is None:
330 people[0].extend([entry.strip() for entry in raw_list.split(',')])
331
Ben Komalo08a3f682010-07-15 16:03:02 -0700332 key = 'review.%s.autocopy' % project.GetBranch(name).remote.review
333 raw_list = project.config.GetString(key)
334 if not raw_list is None and len(people[0]) > 0:
335 people[1].extend([entry.strip() for entry in raw_list.split(',')])
336
Ficus Kirkpatrickbc7ef672009-05-04 12:45:11 -0700337 def _FindGerritChange(self, branch):
338 last_pub = branch.project.WasPublished(branch.name)
339 if last_pub is None:
340 return ""
341
342 refs = branch.GetPublishedRefs()
343 try:
344 # refs/changes/XYZ/N --> XYZ
345 return refs.get(last_pub).split('/')[-2]
David Pursehouse1d947b32012-10-25 12:23:11 +0900346 except (AttributeError, IndexError):
Ficus Kirkpatrickbc7ef672009-05-04 12:45:11 -0700347 return ""
348
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700349 def _UploadAndReport(self, opt, todo, original_people):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700350 have_errors = False
351 for branch in todo:
352 try:
Ben Komalo08a3f682010-07-15 16:03:02 -0700353 people = copy.deepcopy(original_people)
bijia093fdb62013-11-28 09:19:22 +0800354 self._AppendAutoList(branch, people)
Ben Komalo08a3f682010-07-15 16:03:02 -0700355
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500356 # Check if there are local changes that may have been forgotten
Vadim Bendebury14e134d2014-10-05 15:40:30 -0700357 changes = branch.project.UncommitedFiles()
358 if changes:
David Pursehousec1b86a22012-11-14 11:36:51 +0900359 key = 'review.%s.autoupload' % branch.project.remote.review
360 answer = branch.project.config.GetBoolean(key)
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500361
David Pursehousec1b86a22012-11-14 11:36:51 +0900362 # if they want to auto upload, let's not ask because it could be automated
363 if answer is None:
Mike Frysingerab85fe72019-07-04 17:35:11 -0400364 print()
365 print('Uncommitted changes in %s (did you forget to amend?):'
366 % branch.project.name)
367 print('\n'.join(changes))
368 print('Continue uploading? (y/N) ', end='')
369 # TODO: When we require Python 3, use flush=True w/print above.
370 sys.stdout.flush()
David Pursehousec1b86a22012-11-14 11:36:51 +0900371 a = sys.stdin.readline().strip().lower()
372 if a not in ('y', 'yes', 't', 'true', 'on'):
373 print("skipping upload", file=sys.stderr)
374 branch.uploaded = False
375 branch.error = 'User aborted'
376 continue
Anthony Newnamcc50bac2010-04-08 10:28:59 -0500377
Anthony Russellod666e932012-06-01 00:48:22 -0400378 # Check if topic branches should be sent to the server during upload
379 if opt.auto_topic is not True:
David Pursehousec1b86a22012-11-14 11:36:51 +0900380 key = 'review.%s.uploadtopic' % branch.project.remote.review
381 opt.auto_topic = branch.project.config.GetBoolean(key)
Anthony Russellod666e932012-06-01 00:48:22 -0400382
Colin Cross59b31cb2013-10-08 23:10:52 -0700383 destination = opt.dest_branch or branch.project.dest_branch
Conley Owens3bfd7212013-09-30 15:54:38 -0700384
385 # Make sure our local branch is not setup to track a different remote branch
386 merge_branch = self._GetMergeBranch(branch.project)
Conley Owensfbd3f2a2013-10-15 12:59:00 -0700387 if destination:
388 full_dest = 'refs/heads/%s' % destination
389 if not opt.dest_branch and merge_branch and merge_branch != full_dest:
390 print('merge branch %s does not match destination branch %s'
391 % (merge_branch, full_dest))
392 print('skipping upload.')
393 print('Please use `--destination %s` if this is intentional'
394 % destination)
395 branch.uploaded = False
396 continue
Conley Owens3bfd7212013-09-30 15:54:38 -0700397
Changcheng Xiao87984c62017-08-02 16:55:03 +0200398 branch.UploadForReview(people,
399 auto_topic=opt.auto_topic,
Jonathan Niederc94d6eb2017-08-08 18:34:53 +0000400 draft=opt.draft,
Changcheng Xiao87984c62017-08-02 16:55:03 +0200401 private=opt.private,
Vadim Bendeburybd8f6582018-10-31 13:48:01 -0700402 notify=None if opt.notify else 'NONE',
Changcheng Xiao87984c62017-08-02 16:55:03 +0200403 wip=opt.wip,
Łukasz Gardońbed59ce2017-08-08 10:18:11 +0200404 dest_branch=destination,
Masaya Suzuki305a2d02017-11-13 10:48:34 -0800405 validate_certs=opt.validate_certs,
406 push_options=opt.push_options)
Łukasz Gardońbed59ce2017-08-08 10:18:11 +0200407
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700408 branch.uploaded = True
Sarah Owensa5be53f2012-09-09 15:37:57 -0700409 except UploadError as e:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700410 branch.error = e
411 branch.uploaded = False
412 have_errors = True
413
Sarah Owenscecd1d82012-11-01 22:59:27 -0700414 print(file=sys.stderr)
415 print('----------------------------------------------------------------------', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700416
417 if have_errors:
418 for branch in todo:
419 if not branch.uploaded:
Shawn O. Pearcef00e0ce2009-08-22 18:39:49 -0700420 if len(str(branch.error)) <= 30:
421 fmt = ' (%s)'
422 else:
423 fmt = '\n (%s)'
Sarah Owenscecd1d82012-11-01 22:59:27 -0700424 print(('[FAILED] %-15s %-15s' + fmt) % (
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700425 branch.project.relpath + '/', \
426 branch.name, \
Sarah Owenscecd1d82012-11-01 22:59:27 -0700427 str(branch.error)),
428 file=sys.stderr)
429 print()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700430
431 for branch in todo:
David Pursehousec1b86a22012-11-14 11:36:51 +0900432 if branch.uploaded:
433 print('[OK ] %-15s %s' % (
434 branch.project.relpath + '/',
435 branch.name),
436 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700437
438 if have_errors:
439 sys.exit(1)
440
Conley Owens3bfd7212013-09-30 15:54:38 -0700441 def _GetMergeBranch(self, project):
442 p = GitCommand(project,
443 ['rev-parse', '--abbrev-ref', 'HEAD'],
David Pursehousee5913ae2020-02-12 13:56:59 +0900444 capture_stdout=True,
445 capture_stderr=True)
Conley Owens3bfd7212013-09-30 15:54:38 -0700446 p.Wait()
447 local_branch = p.stdout.strip()
448 p = GitCommand(project,
449 ['config', '--get', 'branch.%s.merge' % local_branch],
David Pursehousee5913ae2020-02-12 13:56:59 +0900450 capture_stdout=True,
451 capture_stderr=True)
Conley Owens3bfd7212013-09-30 15:54:38 -0700452 p.Wait()
453 merge_branch = p.stdout.strip()
454 return merge_branch
455
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700456 def Execute(self, opt, args):
457 project_list = self.GetProjects(args)
458 pending = []
Joe Onorato2896a792008-11-17 16:56:36 -0500459 reviewers = []
460 cc = []
Mandeep Singh Bainesd6c93a22011-05-26 10:34:11 -0700461 branch = None
462
463 if opt.branch:
464 branch = opt.branch
Joe Onorato2896a792008-11-17 16:56:36 -0500465
Doug Anderson37282b42011-03-04 11:54:18 -0800466 for project in project_list:
Daniel Sandlere9d6b612012-04-06 10:39:32 -0400467 if opt.current_branch:
468 cbr = project.CurrentBranch
Warren Turkal011d4f42013-11-27 16:20:57 -0800469 up_branch = project.GetUploadableBranch(cbr)
470 if up_branch:
471 avail = [up_branch]
472 else:
473 avail = None
474 print('ERROR: Current branch (%s) not uploadable. '
475 'You may be able to type '
476 '"git branch --set-upstream-to m/master" to fix '
477 'your branch.' % str(cbr),
478 file=sys.stderr)
Daniel Sandlere9d6b612012-04-06 10:39:32 -0400479 else:
480 avail = project.GetUploadableBranches(branch)
Doug Anderson37282b42011-03-04 11:54:18 -0800481 if avail:
482 pending.append((project, avail))
483
Mike Frysinger163a3be2016-04-04 17:31:32 -0400484 if not pending:
485 print("no branches ready for upload", file=sys.stderr)
486 return
487
488 if not opt.bypass_hooks:
Doug Anderson37282b42011-03-04 11:54:18 -0800489 hook = RepoHook('pre-upload', self.manifest.repo_hooks_project,
Mike Frysinger40252c22016-08-15 21:23:44 -0400490 self.manifest.topdir,
491 self.manifest.manifestProject.GetRemote('origin').url,
492 abort_if_user_denies=True)
David Pursehouse3bcd3052017-07-10 22:42:22 +0900493 pending_proj_names = [project.name for (project, available) in pending]
494 pending_worktrees = [project.worktree for (project, available) in pending]
Mike Frysinger21c15752020-02-11 05:17:16 -0500495 passed = True
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)
Mike Frysinger21c15752020-02-11 05:17:16 -0500499 except SystemExit:
500 passed = False
501 if not opt.ignore_hooks:
502 raise
Sarah Owensa5be53f2012-09-09 15:37:57 -0700503 except HookError as e:
Mike Frysinger21c15752020-02-11 05:17:16 -0500504 passed = False
Sarah Owenscecd1d82012-11-01 22:59:27 -0700505 print("ERROR: %s" % str(e), file=sys.stderr)
Mike Frysinger21c15752020-02-11 05:17:16 -0500506
507 if not passed:
508 if opt.ignore_hooks:
509 print('\nWARNING: pre-upload hooks failed, but uploading anyways.',
510 file=sys.stderr)
511 else:
512 return
Doug Anderson37282b42011-03-04 11:54:18 -0800513
Joe Onorato2896a792008-11-17 16:56:36 -0500514 if opt.reviewers:
515 reviewers = _SplitEmails(opt.reviewers)
516 if opt.cc:
517 cc = _SplitEmails(opt.cc)
David Pursehouse8f62fb72012-11-14 12:09:38 +0900518 people = (reviewers, cc)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700519
Mike Frysinger163a3be2016-04-04 17:31:32 -0400520 if len(pending) == 1 and len(pending[0][1]) == 1:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700521 self._SingleBranch(opt, pending[0][1][0], people)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700522 else:
Shawn O. Pearcea5ece0e2010-07-15 16:52:42 -0700523 self._MultipleBranches(opt, pending, people)