Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Applies an issue from Rietveld. | 6 """Applies an issue from Rietveld. |
| 7 """ | 7 """ |
| 8 import getpass | 8 import getpass |
| 9 import json | 9 import json |
| 10 import logging | 10 import logging |
| 11 import optparse | 11 import optparse |
| 12 import os | 12 import os |
| 13 import subprocess | 13 import subprocess |
| 14 import sys | 14 import sys |
| 15 import urllib2 | 15 import urllib2 |
| 16 | 16 |
| 17 import breakpad # pylint: disable=W0611 | 17 import breakpad # pylint: disable=W0611 |
| 18 | 18 |
| 19 import annotated_gclient | 19 import annotated_gclient |
| 20 import auth | 20 import auth |
| 21 import checkout | 21 import checkout |
| 22 import fix_encoding | 22 import fix_encoding |
| 23 import gclient_utils | 23 import gclient_utils |
| 24 import rietveld | 24 import rietveld |
| 25 import scm | 25 import scm |
| 26 | 26 |
| 27 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | 27 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 28 | 28 |
| 29 | 29 |
| 30 RETURN_CODE_ARG_PARSER = 2 # default in python. | 30 RETURN_CODE_OK = 0 # any other failure, likely patch apply one. |
|
Sergey Berezin
2015/10/05 19:06:58
drive-by nit: that's not a failure :-)
| |
| 31 RETURN_CODE_INFRA_FAILURE = 3 # considered as infra failure. | 31 RETURN_CODE_OTHER_FAILURE = 1 # any other failure, likely patch apply one. |
| 32 RETURN_CODE_OTHERWISE = 1 # any other failure, likely patch apply one. | 32 RETURN_CODE_ARGPARSE_FAILURE = 2 # default in python. |
| 33 RETURN_CODE_INFRA_FAILURE = 3 # considered as infra failure. | |
| 33 | 34 |
| 34 | 35 |
| 35 class Unbuffered(object): | 36 class Unbuffered(object): |
| 36 """Disable buffering on a file object.""" | 37 """Disable buffering on a file object.""" |
| 37 def __init__(self, stream): | 38 def __init__(self, stream): |
| 38 self.stream = stream | 39 self.stream = stream |
| 39 | 40 |
| 40 def write(self, data): | 41 def write(self, data): |
| 41 self.stream.write(data) | 42 self.stream.write(data) |
| 42 self.stream.flush() | 43 self.stream.flush() |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 except rietveld.upload.ClientLoginError as e: | 172 except rietveld.upload.ClientLoginError as e: |
| 172 # Fine, we'll do proper authentication. | 173 # Fine, we'll do proper authentication. |
| 173 pass | 174 pass |
| 174 if properties is None: | 175 if properties is None: |
| 175 rietveld_obj = rietveld.Rietveld(options.server, auth_config, | 176 rietveld_obj = rietveld.Rietveld(options.server, auth_config, |
| 176 options.email) | 177 options.email) |
| 177 try: | 178 try: |
| 178 properties = rietveld_obj.get_issue_properties(options.issue, False) | 179 properties = rietveld_obj.get_issue_properties(options.issue, False) |
| 179 except rietveld.upload.ClientLoginError as e: | 180 except rietveld.upload.ClientLoginError as e: |
| 180 print('Accessing the issue requires proper credentials.') | 181 print('Accessing the issue requires proper credentials.') |
| 181 return RETURN_CODE_OTHERWISE | 182 return RETURN_CODE_OTHER_FAILURE |
| 182 except urllib2.URLError: | 183 except urllib2.URLError: |
| 183 logging.exception('failed to fetch issue properties') | 184 logging.exception('failed to fetch issue properties') |
| 184 return RETURN_CODE_INFRA_FAILURE | 185 return RETURN_CODE_INFRA_FAILURE |
| 185 | 186 |
| 186 if not options.patchset: | 187 if not options.patchset: |
| 187 options.patchset = properties['patchsets'][-1] | 188 options.patchset = properties['patchsets'][-1] |
| 188 print('No patchset specified. Using patchset %d' % options.patchset) | 189 print('No patchset specified. Using patchset %d' % options.patchset) |
| 189 | 190 |
| 190 issues_patchsets_to_apply = [(options.issue, options.patchset)] | 191 issues_patchsets_to_apply = [(options.issue, options.patchset)] |
| 191 try: | 192 try: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 try: | 235 try: |
| 235 patchset = rietveld_obj.get_patch(issue_to_apply, patchset_to_apply) | 236 patchset = rietveld_obj.get_patch(issue_to_apply, patchset_to_apply) |
| 236 except urllib2.HTTPError: | 237 except urllib2.HTTPError: |
| 237 print( | 238 print( |
| 238 'Failed to fetch the patch for issue %d, patchset %d.\n' | 239 'Failed to fetch the patch for issue %d, patchset %d.\n' |
| 239 'Try visiting %s/%d') % ( | 240 'Try visiting %s/%d') % ( |
| 240 issue_to_apply, patchset_to_apply, | 241 issue_to_apply, patchset_to_apply, |
| 241 options.server, issue_to_apply) | 242 options.server, issue_to_apply) |
| 242 # If we got this far, then this is likely missing patchset. | 243 # If we got this far, then this is likely missing patchset. |
| 243 # Thus, it's not infra failure. | 244 # Thus, it's not infra failure. |
| 244 return RETURN_CODE_OTHERWISE | 245 return RETURN_CODE_OTHER_FAILURE |
| 245 except urllib2.URLError: | 246 except urllib2.URLError: |
| 246 logging.exception( | 247 logging.exception( |
| 247 'Failed to fetch the patch for issue %d, patchset %d', | 248 'Failed to fetch the patch for issue %d, patchset %d', |
| 248 issue_to_apply, patchset_to_apply) | 249 issue_to_apply, patchset_to_apply) |
| 249 return RETURN_CODE_INFRA_FAILURE | 250 return RETURN_CODE_INFRA_FAILURE |
| 250 if options.whitelist: | 251 if options.whitelist: |
| 251 patchset.patches = [patch for patch in patchset.patches | 252 patchset.patches = [patch for patch in patchset.patches |
| 252 if patch.filename in options.whitelist] | 253 if patch.filename in options.whitelist] |
| 253 if options.blacklist: | 254 if options.blacklist: |
| 254 patchset.patches = [patch for patch in patchset.patches | 255 patchset.patches = [patch for patch in patchset.patches |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 275 # chromium_commands.py?view=markup | 276 # chromium_commands.py?view=markup |
| 276 open('.buildbot-patched', 'w').close() | 277 open('.buildbot-patched', 'w').close() |
| 277 | 278 |
| 278 print('\nApplying the patch from %s' % issue_url) | 279 print('\nApplying the patch from %s' % issue_url) |
| 279 try: | 280 try: |
| 280 scm_obj.apply_patch(patchset, verbose=True) | 281 scm_obj.apply_patch(patchset, verbose=True) |
| 281 except checkout.PatchApplicationFailed as e: | 282 except checkout.PatchApplicationFailed as e: |
| 282 print(str(e)) | 283 print(str(e)) |
| 283 print('CWD=%s' % os.getcwd()) | 284 print('CWD=%s' % os.getcwd()) |
| 284 print('Checkout path=%s' % scm_obj.project_path) | 285 print('Checkout path=%s' % scm_obj.project_path) |
| 285 return RETURN_CODE_OTHERWISE | 286 return RETURN_CODE_OTHER_FAILURE |
| 286 | 287 |
| 287 if ('DEPS' in map(os.path.basename, patchset.filenames) | 288 if ('DEPS' in map(os.path.basename, patchset.filenames) |
| 288 and not options.ignore_deps): | 289 and not options.ignore_deps): |
| 289 gclient_root = gclient_utils.FindGclientRoot(full_dir) | 290 gclient_root = gclient_utils.FindGclientRoot(full_dir) |
| 290 if gclient_root and scm_type: | 291 if gclient_root and scm_type: |
| 291 print( | 292 print( |
| 292 'A DEPS file was updated inside a gclient checkout, running gclient ' | 293 'A DEPS file was updated inside a gclient checkout, running gclient ' |
| 293 'sync.') | 294 'sync.') |
| 294 gclient_path = os.path.join(BASE_DIR, 'gclient') | 295 gclient_path = os.path.join(BASE_DIR, 'gclient') |
| 295 if sys.platform == 'win32': | 296 if sys.platform == 'win32': |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 306 cmd.extend(['--output-json', f]) | 307 cmd.extend(['--output-json', f]) |
| 307 | 308 |
| 308 retcode = subprocess.call(cmd, cwd=gclient_root) | 309 retcode = subprocess.call(cmd, cwd=gclient_root) |
| 309 | 310 |
| 310 if retcode == 0 and options.revision_mapping: | 311 if retcode == 0 and options.revision_mapping: |
| 311 revisions = annotated_gclient.parse_got_revision( | 312 revisions = annotated_gclient.parse_got_revision( |
| 312 f, options.revision_mapping) | 313 f, options.revision_mapping) |
| 313 annotated_gclient.emit_buildprops(revisions) | 314 annotated_gclient.emit_buildprops(revisions) |
| 314 | 315 |
| 315 return retcode | 316 return retcode |
| 316 return 0 | 317 return RETURN_CODE_OK |
| 317 | 318 |
| 318 | 319 |
| 319 if __name__ == "__main__": | 320 if __name__ == "__main__": |
| 320 fix_encoding.fix_encoding() | 321 fix_encoding.fix_encoding() |
| 321 try: | 322 try: |
| 322 sys.exit(main()) | 323 sys.exit(main()) |
| 323 except KeyboardInterrupt: | 324 except KeyboardInterrupt: |
| 324 sys.stderr.write('interrupted\n') | 325 sys.stderr.write('interrupted\n') |
| 325 sys.exit(RETURN_CODE_OTHERWISE) | 326 sys.exit(RETURN_CODE_OTHER_FAILURE) |
| OLD | NEW |