blob: 8ea4df4d1bf28ee13229af60e109c0b77e908ed9 [file] [log] [blame]
Josip Sokcevic84434e82021-06-09 22:48:43 +00001#!/usr/bin/env vpython3
dimu833c94c2017-01-18 17:36:15 -08002# Copyright 2017 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Simple client for the Gerrit REST API.
7
8Example usage:
Michael Moss5eebf6f2021-07-16 13:18:34 +00009 ./gerrit_client.py [command] [args]
dimu833c94c2017-01-18 17:36:15 -080010"""
11
dimu833c94c2017-01-18 17:36:15 -080012import json
13import logging
14import optparse
15import subcommand
16import sys
Gavin Makb5c7f4b2023-08-24 18:35:41 +000017import urllib.parse
dimu833c94c2017-01-18 17:36:15 -080018
dimu833c94c2017-01-18 17:36:15 -080019import fix_encoding
20import gerrit_util
21import setup_color
22
23__version__ = '0.1'
dimu833c94c2017-01-18 17:36:15 -080024
25
26def write_result(result, opt):
27 if opt.json_file:
28 with open(opt.json_file, 'w') as json_file:
29 json_file.write(json.dumps(result))
30
31
32@subcommand.usage('[args ...]')
Josip Sokcevicc39ab992020-09-24 20:09:15 +000033def CMDmovechanges(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +000034 """Move changes to a different destination branch."""
Josip Sokcevicc39ab992020-09-24 20:09:15 +000035 parser.add_option('-p', '--param', dest='params', action='append',
36 help='repeatable query parameter, format: -p key=value')
37 parser.add_option('--destination_branch', dest='destination_branch',
38 help='where to move changes to')
39
40 (opt, args) = parser.parse_args(args)
41 assert opt.destination_branch, "--destination_branch not defined"
Mike Frysinger8820ab82020-11-25 00:52:31 +000042 for p in opt.params:
43 assert '=' in p, '--param is key=value, not "%s"' % p
Gavin Makb5c7f4b2023-08-24 18:35:41 +000044 host = urllib.parse.urlparse(opt.host).netloc
Josip Sokcevicc39ab992020-09-24 20:09:15 +000045
46 limit = 100
47 while True:
48 result = gerrit_util.QueryChanges(
49 host,
50 list(tuple(p.split('=', 1)) for p in opt.params),
51 limit=limit,
52 )
53 for change in result:
54 gerrit_util.MoveChange(host, change['id'], opt.destination_branch)
55
56 if len(result) < limit:
57 break
58 logging.info("Done")
59
60
61@subcommand.usage('[args ...]')
dimu833c94c2017-01-18 17:36:15 -080062def CMDbranchinfo(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +000063 """Get information on a gerrit branch."""
dimu833c94c2017-01-18 17:36:15 -080064 parser.add_option('--branch', dest='branch', help='branch name')
65
66 (opt, args) = parser.parse_args(args)
Gavin Makb5c7f4b2023-08-24 18:35:41 +000067 host = urllib.parse.urlparse(opt.host).netloc
68 project = urllib.parse.quote_plus(opt.project)
69 branch = urllib.parse.quote_plus(opt.branch)
dimu833c94c2017-01-18 17:36:15 -080070 result = gerrit_util.GetGerritBranch(host, project, branch)
71 logging.info(result)
72 write_result(result, opt)
73
Quinten Yearsleyd9cbe7a2019-09-03 16:49:11 +000074
dimu833c94c2017-01-18 17:36:15 -080075@subcommand.usage('[args ...]')
Michael Moss9c28af42021-10-25 16:59:05 +000076def CMDrawapi(parser, args):
77 """Call an arbitrary Gerrit REST API endpoint."""
78 parser.add_option('--path', dest='path', help='HTTP path of the API endpoint')
79 parser.add_option('--method', dest='method',
80 help='HTTP method for the API (default: GET)')
81 parser.add_option('--body', dest='body', help='API JSON body contents')
82 parser.add_option('--accept_status',
83 dest='accept_status',
84 help='Comma-delimited list of status codes for success.')
85
86 (opt, args) = parser.parse_args(args)
87 assert opt.path, "--path not defined"
88
Gavin Makb5c7f4b2023-08-24 18:35:41 +000089 host = urllib.parse.urlparse(opt.host).netloc
Michael Moss9c28af42021-10-25 16:59:05 +000090 kwargs = {}
91 if opt.method:
92 kwargs['reqtype'] = opt.method.upper()
93 if opt.body:
94 kwargs['body'] = json.loads(opt.body)
95 if opt.accept_status:
96 kwargs['accept_statuses'] = [int(x) for x in opt.accept_status.split(',')]
97 result = gerrit_util.CallGerritApi(host, opt.path, **kwargs)
98 logging.info(result)
99 write_result(result, opt)
100
101
102@subcommand.usage('[args ...]')
dimu833c94c2017-01-18 17:36:15 -0800103def CMDbranch(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000104 """Create a branch in a gerrit project."""
dimu833c94c2017-01-18 17:36:15 -0800105 parser.add_option('--branch', dest='branch', help='branch name')
106 parser.add_option('--commit', dest='commit', help='commit hash')
Xinan Lindbcecc92023-05-03 18:29:00 +0000107 parser.add_option('--allow-existent-branch',
108 action='store_true',
109 help=('Accept that the branch alread exists as long as the'
110 ' branch head points the given commit'))
dimu833c94c2017-01-18 17:36:15 -0800111
112 (opt, args) = parser.parse_args(args)
Josip Sokcevicc99efb22020-03-17 00:35:34 +0000113 assert opt.project, "--project not defined"
114 assert opt.branch, "--branch not defined"
115 assert opt.commit, "--commit not defined"
dimu833c94c2017-01-18 17:36:15 -0800116
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000117 project = urllib.parse.quote_plus(opt.project)
118 host = urllib.parse.urlparse(opt.host).netloc
119 branch = urllib.parse.quote_plus(opt.branch)
Xinan Lindbcecc92023-05-03 18:29:00 +0000120 result = gerrit_util.GetGerritBranch(host, project, branch)
121 if result:
122 if not opt.allow_existent_branch:
123 raise gerrit_util.GerritError(200, 'Branch already exists')
124 if result.get('revision') != opt.commit:
125 raise gerrit_util.GerritError(
126 200, ('Branch already exists but '
127 'the branch head is not at the given commit'))
128 else:
129 try:
130 result = gerrit_util.CreateGerritBranch(host, project, branch, opt.commit)
131 except gerrit_util.GerritError as e:
132 result = gerrit_util.GetGerritBranch(host, project, branch)
133 if not result:
134 raise e
135 # If reached here, we hit a real conflict error, because the
136 # branch just created is pointing a different commit.
137 if result.get('revision') != opt.commit:
138 raise gerrit_util.GerritError(
139 200, ('Conflict: branch was created but '
140 'the branch head is not at the given commit'))
dimu833c94c2017-01-18 17:36:15 -0800141 logging.info(result)
142 write_result(result, opt)
143
144
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200145@subcommand.usage('[args ...]')
Michael Mossb6ce2442021-10-20 04:36:24 +0000146def CMDtag(parser, args):
147 """Create a tag in a gerrit project."""
148 parser.add_option('--tag', dest='tag', help='tag name')
149 parser.add_option('--commit', dest='commit', help='commit hash')
150
151 (opt, args) = parser.parse_args(args)
152 assert opt.project, "--project not defined"
153 assert opt.tag, "--tag not defined"
154 assert opt.commit, "--commit not defined"
155
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000156 project = urllib.parse.quote_plus(opt.project)
157 host = urllib.parse.urlparse(opt.host).netloc
158 tag = urllib.parse.quote_plus(opt.tag)
Michael Moss5c9e8b42021-10-26 16:54:16 +0000159 result = gerrit_util.CreateGerritTag(host, project, tag, opt.commit)
Michael Mossb6ce2442021-10-20 04:36:24 +0000160 logging.info(result)
161 write_result(result, opt)
162
163
164@subcommand.usage('[args ...]')
Josip Sokcevicdf9a8022020-12-08 00:10:19 +0000165def CMDhead(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000166 """Update which branch the project HEAD points to."""
Josip Sokcevicdf9a8022020-12-08 00:10:19 +0000167 parser.add_option('--branch', dest='branch', help='branch name')
168
169 (opt, args) = parser.parse_args(args)
170 assert opt.project, "--project not defined"
171 assert opt.branch, "--branch not defined"
172
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000173 project = urllib.parse.quote_plus(opt.project)
174 host = urllib.parse.urlparse(opt.host).netloc
175 branch = urllib.parse.quote_plus(opt.branch)
Josip Sokcevicdf9a8022020-12-08 00:10:19 +0000176 result = gerrit_util.UpdateHead(host, project, branch)
177 logging.info(result)
178 write_result(result, opt)
179
180
181@subcommand.usage('[args ...]')
182def CMDheadinfo(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000183 """Retrieves the current HEAD of the project."""
Josip Sokcevicdf9a8022020-12-08 00:10:19 +0000184
185 (opt, args) = parser.parse_args(args)
186 assert opt.project, "--project not defined"
187
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000188 project = urllib.parse.quote_plus(opt.project)
189 host = urllib.parse.urlparse(opt.host).netloc
Josip Sokcevicdf9a8022020-12-08 00:10:19 +0000190 result = gerrit_util.GetHead(host, project)
191 logging.info(result)
192 write_result(result, opt)
193
194
195@subcommand.usage('[args ...]')
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200196def CMDchanges(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000197 """Queries gerrit for matching changes."""
Mike Frysinger98d3bb22023-06-22 21:35:59 +0000198 parser.add_option('-p',
199 '--param',
200 dest='params',
201 action='append',
202 default=[],
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200203 help='repeatable query parameter, format: -p key=value')
Mike Frysinger98d3bb22023-06-22 21:35:59 +0000204 parser.add_option('--query', help='raw gerrit search query string')
Paweł Hajdan, Jr24025d32017-07-11 16:38:21 +0200205 parser.add_option('-o', '--o-param', dest='o_params', action='append',
206 help='gerrit output parameters, e.g. ALL_REVISIONS')
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200207 parser.add_option('--limit', dest='limit', type=int,
208 help='maximum number of results to return')
209 parser.add_option('--start', dest='start', type=int,
210 help='how many changes to skip '
211 '(starting with the most recent)')
212
213 (opt, args) = parser.parse_args(args)
Mike Frysinger98d3bb22023-06-22 21:35:59 +0000214 assert opt.params or opt.query, '--param or --query required'
Mike Frysinger8820ab82020-11-25 00:52:31 +0000215 for p in opt.params:
216 assert '=' in p, '--param is key=value, not "%s"' % p
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200217
218 result = gerrit_util.QueryChanges(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000219 urllib.parse.urlparse(opt.host).netloc,
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200220 list(tuple(p.split('=', 1)) for p in opt.params),
Mike Frysinger98d3bb22023-06-22 21:35:59 +0000221 first_param=opt.query,
222 start=opt.start, # Default: None
223 limit=opt.limit, # Default: None
Paweł Hajdan, Jr24025d32017-07-11 16:38:21 +0200224 o_params=opt.o_params, # Default: None
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200225 )
226 logging.info('Change query returned %d changes.', len(result))
227 write_result(result, opt)
228
229
LaMont Jones9eed4232021-04-02 16:29:49 +0000230@subcommand.usage('[args ...]')
Marco Georgaklis85557a02021-06-03 15:56:54 +0000231def CMDrelatedchanges(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000232 """Gets related changes for a given change and revision."""
Marco Georgaklis85557a02021-06-03 15:56:54 +0000233 parser.add_option('-c', '--change', type=str, help='change id')
234 parser.add_option('-r', '--revision', type=str, help='revision id')
235
236 (opt, args) = parser.parse_args(args)
237
238 result = gerrit_util.GetRelatedChanges(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000239 urllib.parse.urlparse(opt.host).netloc,
Marco Georgaklis85557a02021-06-03 15:56:54 +0000240 change=opt.change,
241 revision=opt.revision,
242 )
243 logging.info(result)
244 write_result(result, opt)
245
246
247@subcommand.usage('[args ...]')
LaMont Jones9eed4232021-04-02 16:29:49 +0000248def CMDcreatechange(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000249 """Create a new change in gerrit."""
LaMont Jones9eed4232021-04-02 16:29:49 +0000250 parser.add_option('-s', '--subject', help='subject for change')
251 parser.add_option('-b',
252 '--branch',
253 default='main',
254 help='target branch for change')
255 parser.add_option(
256 '-p',
257 '--param',
258 dest='params',
259 action='append',
260 help='repeatable field value parameter, format: -p key=value')
261
Xinan Lin91d2a5d2022-02-04 21:18:32 +0000262 parser.add_option('--cc',
263 dest='cc_list',
264 action='append',
265 help='CC address to notify, format: --cc foo@example.com')
266
LaMont Jones9eed4232021-04-02 16:29:49 +0000267 (opt, args) = parser.parse_args(args)
268 for p in opt.params:
269 assert '=' in p, '--param is key=value, not "%s"' % p
270
Xinan Lin91d2a5d2022-02-04 21:18:32 +0000271 params = list(tuple(p.split('=', 1)) for p in opt.params)
272
273 if opt.cc_list:
274 params.append(('notify_details', {'CC': {'accounts': opt.cc_list}}))
275
LaMont Jones9eed4232021-04-02 16:29:49 +0000276 result = gerrit_util.CreateChange(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000277 urllib.parse.urlparse(opt.host).netloc,
LaMont Jones9eed4232021-04-02 16:29:49 +0000278 opt.project,
279 branch=opt.branch,
280 subject=opt.subject,
Xinan Lin91d2a5d2022-02-04 21:18:32 +0000281 params=params,
LaMont Jones9eed4232021-04-02 16:29:49 +0000282 )
283 logging.info(result)
284 write_result(result, opt)
285
286
287@subcommand.usage('[args ...]')
288def CMDchangeedit(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000289 """Puts content of a file into a change edit."""
LaMont Jones9eed4232021-04-02 16:29:49 +0000290 parser.add_option('-c', '--change', type=int, help='change number')
291 parser.add_option('--path', help='path for file')
292 parser.add_option('--file', help='file to place at |path|')
293
294 (opt, args) = parser.parse_args(args)
295
296 with open(opt.file) as f:
297 data = f.read()
298 result = gerrit_util.ChangeEdit(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000299 urllib.parse.urlparse(opt.host).netloc, opt.change, opt.path, data)
LaMont Jones9eed4232021-04-02 16:29:49 +0000300 logging.info(result)
301 write_result(result, opt)
302
303
304@subcommand.usage('[args ...]')
305def CMDpublishchangeedit(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000306 """Publish a Gerrit change edit."""
LaMont Jones9eed4232021-04-02 16:29:49 +0000307 parser.add_option('-c', '--change', type=int, help='change number')
308 parser.add_option('--notify', help='whether to notify')
309
310 (opt, args) = parser.parse_args(args)
311
312 result = gerrit_util.PublishChangeEdit(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000313 urllib.parse.urlparse(opt.host).netloc, opt.change, opt.notify)
LaMont Jones9eed4232021-04-02 16:29:49 +0000314 logging.info(result)
315 write_result(result, opt)
316
317
Xinan Lin6ec7cd82021-07-21 00:53:42 +0000318@subcommand.usage('[args ...]')
319def CMDsubmitchange(parser, args):
320 """Submit a Gerrit change."""
321 parser.add_option('-c', '--change', type=int, help='change number')
Xinan Lin6ec7cd82021-07-21 00:53:42 +0000322 (opt, args) = parser.parse_args(args)
Xinan Lin1bd4ffa2021-07-28 00:54:22 +0000323 result = gerrit_util.SubmitChange(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000324 urllib.parse.urlparse(opt.host).netloc, opt.change)
Xinan Lin6ec7cd82021-07-21 00:53:42 +0000325 logging.info(result)
326 write_result(result, opt)
327
328
Xinan Linc2fb26a2021-07-27 18:01:55 +0000329@subcommand.usage('[args ...]')
Xinan Lin2b4ec952021-08-20 17:35:29 +0000330def CMDchangesubmittedtogether(parser, args):
331 """Get all changes submitted with the given one."""
332 parser.add_option('-c', '--change', type=int, help='change number')
333 (opt, args) = parser.parse_args(args)
334 result = gerrit_util.GetChangesSubmittedTogether(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000335 urllib.parse.urlparse(opt.host).netloc, opt.change)
Xinan Lin2b4ec952021-08-20 17:35:29 +0000336 logging.info(result)
337 write_result(result, opt)
338
339
340@subcommand.usage('[args ...]')
Xinan Linc2fb26a2021-07-27 18:01:55 +0000341def CMDgetcommitincludedin(parser, args):
342 """Retrieves the branches and tags for a given commit."""
343 parser.add_option('--commit', dest='commit', help='commit hash')
344 (opt, args) = parser.parse_args(args)
345 result = gerrit_util.GetCommitIncludedIn(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000346 urllib.parse.urlparse(opt.host).netloc, opt.project, opt.commit)
Xinan Linc2fb26a2021-07-27 18:01:55 +0000347 logging.info(result)
348 write_result(result, opt)
349
350
Xinan Lin0b0738d2021-07-27 19:13:49 +0000351@subcommand.usage('[args ...]')
352def CMDsetbotcommit(parser, args):
353 """Sets bot-commit+1 to a bot generated change."""
354 parser.add_option('-c', '--change', type=int, help='change number')
355 (opt, args) = parser.parse_args(args)
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000356 result = gerrit_util.SetReview(urllib.parse.urlparse(opt.host).netloc,
357 opt.change,
358 labels={'Bot-Commit': 1},
359 ready=True)
Xinan Lin0b0738d2021-07-27 19:13:49 +0000360 logging.info(result)
361 write_result(result, opt)
362
363
Ben Pastene281edf72021-10-06 01:23:24 +0000364@subcommand.usage('[args ...]')
365def CMDsetlabel(parser, args):
366 """Sets a label to a specific value on a given change."""
367 parser.add_option('-c', '--change', type=int, help='change number')
368 parser.add_option('-l',
369 '--label',
370 nargs=2,
371 metavar=('label_name', 'label_value'))
372 (opt, args) = parser.parse_args(args)
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000373 result = gerrit_util.SetReview(urllib.parse.urlparse(opt.host).netloc,
Ben Pastene281edf72021-10-06 01:23:24 +0000374 opt.change,
375 labels={opt.label[0]: opt.label[1]})
376 logging.info(result)
377 write_result(result, opt)
378
379
Sergiy Belozorovfe347232019-02-27 15:07:33 +0000380@subcommand.usage('')
381def CMDabandon(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000382 """Abandons a Gerrit change."""
Sergiy Belozorovfe347232019-02-27 15:07:33 +0000383 parser.add_option('-c', '--change', type=int, help='change number')
384 parser.add_option('-m', '--message', default='', help='reason for abandoning')
385
386 (opt, args) = parser.parse_args(args)
Josip Sokcevicc99efb22020-03-17 00:35:34 +0000387 assert opt.change, "-c not defined"
Sergiy Belozorovfe347232019-02-27 15:07:33 +0000388 result = gerrit_util.AbandonChange(
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000389 urllib.parse.urlparse(opt.host).netloc, opt.change, opt.message)
Sergiy Belozorovfe347232019-02-27 15:07:33 +0000390 logging.info(result)
391 write_result(result, opt)
392
393
Michael Moss5eebf6f2021-07-16 13:18:34 +0000394@subcommand.usage('')
Josip Sokcevice1a98942021-04-07 21:35:29 +0000395def CMDmass_abandon(parser, args):
Michael Moss5eebf6f2021-07-16 13:18:34 +0000396 """Mass abandon changes
397
398 Abandons CLs that match search criteria provided by user. Before any change is
399 actually abandoned, user is presented with a list of CLs that will be affected
400 if user confirms. User can skip confirmation by passing --force parameter.
401
402 The script can abandon up to 100 CLs per invocation.
403
404 Examples:
405 gerrit_client.py mass-abandon --host https://HOST -p 'project=repo2'
406 gerrit_client.py mass-abandon --host https://HOST -p 'message=testing'
407 gerrit_client.py mass-abandon --host https://HOST -p 'is=wip' -p 'age=1y'
408 """
Josip Sokcevice1a98942021-04-07 21:35:29 +0000409 parser.add_option('-p',
410 '--param',
411 dest='params',
412 action='append',
413 default=[],
414 help='repeatable query parameter, format: -p key=value')
415 parser.add_option('-m', '--message', default='', help='reason for abandoning')
416 parser.add_option('-f',
417 '--force',
418 action='store_true',
419 help='Don\'t prompt for confirmation')
420
421 opt, args = parser.parse_args(args)
422
423 for p in opt.params:
424 assert '=' in p, '--param is key=value, not "%s"' % p
425 search_query = list(tuple(p.split('=', 1)) for p in opt.params)
426 if not any(t for t in search_query if t[0] == 'owner'):
427 # owner should always be present when abandoning changes
428 search_query.append(('owner', 'me'))
429 search_query.append(('status', 'open'))
430 logging.info("Searching for: %s" % search_query)
431
Gavin Makb5c7f4b2023-08-24 18:35:41 +0000432 host = urllib.parse.urlparse(opt.host).netloc
Josip Sokcevice1a98942021-04-07 21:35:29 +0000433
434 result = gerrit_util.QueryChanges(
435 host,
436 search_query,
437 # abandon at most 100 changes as not all Gerrit instances support
438 # unlimited results.
439 limit=100,
440 )
441 if len(result) == 0:
Nico Weber6b33f852023-06-21 17:14:24 +0000442 logging.warning("Nothing to abandon")
Josip Sokcevice1a98942021-04-07 21:35:29 +0000443 return
444
Nico Weber6b33f852023-06-21 17:14:24 +0000445 logging.warning("%s CLs match search query: " % len(result))
Josip Sokcevice1a98942021-04-07 21:35:29 +0000446 for change in result:
Nico Weber6b33f852023-06-21 17:14:24 +0000447 logging.warning("[ID: %d] %s" % (change['_number'], change['subject']))
Josip Sokcevice1a98942021-04-07 21:35:29 +0000448
449 if not opt.force:
Josip Sokcevic284fbdd2021-10-08 18:26:30 +0000450 q = input(
Josip Sokcevice1a98942021-04-07 21:35:29 +0000451 'Do you want to move forward with abandoning? [y to confirm] ').strip()
452 if q not in ['y', 'Y']:
Nico Weber6b33f852023-06-21 17:14:24 +0000453 logging.warning("Aborting...")
Josip Sokcevice1a98942021-04-07 21:35:29 +0000454 return
455
456 for change in result:
457 logging.warning("Abandoning: %s" % change['subject'])
458 gerrit_util.AbandonChange(host, change['id'], opt.message)
459
460 logging.warning("Done")
461
462
dimu833c94c2017-01-18 17:36:15 -0800463class OptionParser(optparse.OptionParser):
464 """Creates the option parse and add --verbose support."""
465 def __init__(self, *args, **kwargs):
Josip Sokcevicc99efb22020-03-17 00:35:34 +0000466 optparse.OptionParser.__init__(self, *args, version=__version__, **kwargs)
dimu833c94c2017-01-18 17:36:15 -0800467 self.add_option(
468 '--verbose', action='count', default=0,
469 help='Use 2 times for more debugging info')
470 self.add_option('--host', dest='host', help='Url of host.')
471 self.add_option('--project', dest='project', help='project name')
472 self.add_option(
473 '--json_file', dest='json_file', help='output json filepath')
474
475 def parse_args(self, args=None, values=None):
476 options, args = optparse.OptionParser.parse_args(self, args, values)
Josip Sokcevicc99efb22020-03-17 00:35:34 +0000477 # Host is always required
478 assert options.host, "--host not defined."
dimu833c94c2017-01-18 17:36:15 -0800479 levels = [logging.WARNING, logging.INFO, logging.DEBUG]
480 logging.basicConfig(level=levels[min(options.verbose, len(levels) - 1)])
481 return options, args
482
483
484def main(argv):
485 if sys.hexversion < 0x02060000:
486 print('\nYour python version %s is unsupported, please upgrade.\n'
Quinten Yearsleyd9cbe7a2019-09-03 16:49:11 +0000487 % (sys.version.split(' ', 1)[0],),
dimu833c94c2017-01-18 17:36:15 -0800488 file=sys.stderr)
489 return 2
490 dispatcher = subcommand.CommandDispatcher(__name__)
491 return dispatcher.execute(OptionParser(), argv)
492
493
494if __name__ == '__main__':
495 # These affect sys.stdout so do it outside of main() to simplify mocks in
496 # unit testing.
497 fix_encoding.fix_encoding()
498 setup_color.init()
499 try:
500 sys.exit(main(sys.argv[1:]))
501 except KeyboardInterrupt:
502 sys.stderr.write('interrupted\n')
Michael Achenbach6fbf12f2017-07-06 10:54:11 +0200503 sys.exit(1)