Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: git_cl.py

Issue 10894019: Enforce coherent type handling in git_cl.py (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 # Copyright (C) 2008 Evan Martin <martine@danga.com> 6 # Copyright (C) 2008 Evan Martin <martine@danga.com>
7 7
8 """A git-command for integrating reviews on Rietveld.""" 8 """A git-command for integrating reviews on Rietveld."""
9 9
10 import json 10 import json
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 429
430 def GetRemoteUrl(self): 430 def GetRemoteUrl(self):
431 """Return the configured remote URL, e.g. 'git://example.org/foo.git/'. 431 """Return the configured remote URL, e.g. 'git://example.org/foo.git/'.
432 432
433 Returns None if there is no remote. 433 Returns None if there is no remote.
434 """ 434 """
435 remote = self.GetRemote() 435 remote = self.GetRemote()
436 return RunGit(['config', 'remote.%s.url' % remote], error_ok=True).strip() 436 return RunGit(['config', 'remote.%s.url' % remote], error_ok=True).strip()
437 437
438 def GetIssue(self): 438 def GetIssue(self):
439 """Returns the issue number as a int or None if not set."""
439 if not self.has_issue: 440 if not self.has_issue:
440 issue = RunGit(['config', self._IssueSetting()], error_ok=True).strip() 441 issue = RunGit(['config', self._IssueSetting()], error_ok=True).strip()
441 if issue: 442 if issue:
442 self.issue = issue 443 self.issue = int(issue)
443 else: 444 else:
444 self.issue = None 445 self.issue = None
445 self.has_issue = True 446 self.has_issue = True
446 return self.issue 447 return self.issue
447 448
448 def GetRietveldServer(self): 449 def GetRietveldServer(self):
449 if not self.rietveld_server: 450 if not self.rietveld_server:
450 # If we're on a branch then get the server potentially associated 451 # If we're on a branch then get the server potentially associated
451 # with that branch. 452 # with that branch.
452 if self.GetIssue(): 453 if self.GetIssue():
453 self.rietveld_server = gclient_utils.UpgradeToHttps(RunGit( 454 self.rietveld_server = gclient_utils.UpgradeToHttps(RunGit(
454 ['config', self._RietveldServer()], error_ok=True).strip()) 455 ['config', self._RietveldServer()], error_ok=True).strip())
455 if not self.rietveld_server: 456 if not self.rietveld_server:
456 self.rietveld_server = settings.GetDefaultServerUrl() 457 self.rietveld_server = settings.GetDefaultServerUrl()
457 return self.rietveld_server 458 return self.rietveld_server
458 459
459 def GetIssueURL(self): 460 def GetIssueURL(self):
460 """Get the URL for a particular issue.""" 461 """Get the URL for a particular issue."""
461 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue()) 462 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue())
462 463
463 def GetDescription(self, pretty=False): 464 def GetDescription(self, pretty=False):
464 if not self.has_description: 465 if not self.has_description:
465 if self.GetIssue(): 466 if self.GetIssue():
466 issue = int(self.GetIssue()) 467 issue = self.GetIssue()
467 try: 468 try:
468 self.description = self.RpcServer().get_description(issue).strip() 469 self.description = self.RpcServer().get_description(issue).strip()
469 except urllib2.HTTPError, e: 470 except urllib2.HTTPError, e:
470 if e.code == 404: 471 if e.code == 404:
471 DieWithError( 472 DieWithError(
472 ('\nWhile fetching the description for issue %d, received a ' 473 ('\nWhile fetching the description for issue %d, received a '
473 '404 (not found)\n' 474 '404 (not found)\n'
474 'error. It is likely that you deleted this ' 475 'error. It is likely that you deleted this '
475 'issue on the server. If this is the\n' 476 'issue on the server. If this is the\n'
476 'case, please run\n\n' 477 'case, please run\n\n'
477 ' git cl issue 0\n\n' 478 ' git cl issue 0\n\n'
478 'to clear the association with the deleted issue. Then run ' 479 'to clear the association with the deleted issue. Then run '
479 'this command again.') % issue) 480 'this command again.') % issue)
480 else: 481 else:
481 DieWithError( 482 DieWithError(
482 '\nFailed to fetch issue description. HTTP error ' + e.code) 483 '\nFailed to fetch issue description. HTTP error ' + e.code)
483 self.has_description = True 484 self.has_description = True
484 if pretty: 485 if pretty:
485 wrapper = textwrap.TextWrapper() 486 wrapper = textwrap.TextWrapper()
486 wrapper.initial_indent = wrapper.subsequent_indent = ' ' 487 wrapper.initial_indent = wrapper.subsequent_indent = ' '
487 return wrapper.fill(self.description) 488 return wrapper.fill(self.description)
488 return self.description 489 return self.description
489 490
490 def GetPatchset(self): 491 def GetPatchset(self):
492 """Returns the patchset number as a int or None if not set."""
491 if not self.has_patchset: 493 if not self.has_patchset:
492 patchset = RunGit(['config', self._PatchsetSetting()], 494 patchset = RunGit(['config', self._PatchsetSetting()],
493 error_ok=True).strip() 495 error_ok=True).strip()
494 if patchset: 496 if patchset:
495 self.patchset = patchset 497 self.patchset = int(patchset)
496 else: 498 else:
497 self.patchset = None 499 self.patchset = None
498 self.has_patchset = True 500 self.has_patchset = True
499 return self.patchset 501 return self.patchset
500 502
501 def SetPatchset(self, patchset): 503 def SetPatchset(self, patchset):
502 """Set this branch's patchset. If patchset=0, clears the patchset.""" 504 """Set this branch's patchset. If patchset=0, clears the patchset."""
503 if patchset: 505 if patchset:
504 RunGit(['config', self._PatchsetSetting(), str(patchset)]) 506 RunGit(['config', self._PatchsetSetting(), str(patchset)])
505 else: 507 else:
(...skipping 29 matching lines...) Expand all
535 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) 537 files = scm.GIT.CaptureStatus([root], '.', upstream_branch)
536 except subprocess2.CalledProcessError: 538 except subprocess2.CalledProcessError:
537 DieWithError( 539 DieWithError(
538 ('\nFailed to diff against upstream branch %s!\n\n' 540 ('\nFailed to diff against upstream branch %s!\n\n'
539 'This branch probably doesn\'t exist anymore. To reset the\n' 541 'This branch probably doesn\'t exist anymore. To reset the\n'
540 'tracking branch, please run\n' 542 'tracking branch, please run\n'
541 ' git branch --set-upstream %s trunk\n' 543 ' git branch --set-upstream %s trunk\n'
542 'replacing trunk with origin/master or the relevant branch') % 544 'replacing trunk with origin/master or the relevant branch') %
543 (upstream_branch, self.GetBranch())) 545 (upstream_branch, self.GetBranch()))
544 546
545 issue = ConvertToInteger(self.GetIssue()) 547 issue = self.GetIssue()
546 patchset = ConvertToInteger(self.GetPatchset()) 548 patchset = self.GetPatchset()
547 if issue: 549 if issue:
548 description = self.GetDescription() 550 description = self.GetDescription()
549 else: 551 else:
550 # If the change was never uploaded, use the log messages of all commits 552 # If the change was never uploaded, use the log messages of all commits
551 # up to the branch point, as git cl upload will prefill the description 553 # up to the branch point, as git cl upload will prefill the description
552 # with these log messages. 554 # with these log messages.
553 description = RunCommand(['git', 'log', '--pretty=format:%s%n%n%b', 555 description = RunCommand(['git', 'log', '--pretty=format:%s%n%n%b',
554 '%s...' % (upstream_branch)]).strip() 556 '%s...' % (upstream_branch)]).strip()
555 557
556 if not author: 558 if not author:
(...skipping 22 matching lines...) Expand all
579 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, 581 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin,
580 default_presubmit=None, may_prompt=may_prompt, 582 default_presubmit=None, may_prompt=may_prompt,
581 rietveld_obj=self.RpcServer()) 583 rietveld_obj=self.RpcServer())
582 except presubmit_support.PresubmitFailure, e: 584 except presubmit_support.PresubmitFailure, e:
583 DieWithError( 585 DieWithError(
584 ('%s\nMaybe your depot_tools is out of date?\n' 586 ('%s\nMaybe your depot_tools is out of date?\n'
585 'If all fails, contact maruel@') % e) 587 'If all fails, contact maruel@') % e)
586 588
587 def CloseIssue(self): 589 def CloseIssue(self):
588 """Updates the description and closes the issue.""" 590 """Updates the description and closes the issue."""
589 issue = int(self.GetIssue()) 591 issue = self.GetIssue()
590 self.RpcServer().update_description(issue, self.description) 592 self.RpcServer().update_description(issue, self.description)
591 return self.RpcServer().close_issue(issue) 593 return self.RpcServer().close_issue(issue)
592 594
593 def SetFlag(self, flag, value): 595 def SetFlag(self, flag, value):
594 """Patchset must match.""" 596 """Patchset must match."""
595 if not self.GetPatchset(): 597 if not self.GetPatchset():
596 DieWithError('The patchset needs to match. Send another patchset.') 598 DieWithError('The patchset needs to match. Send another patchset.')
597 try: 599 try:
598 return self.RpcServer().set_flag( 600 return self.RpcServer().set_flag(
599 int(self.GetIssue()), int(self.GetPatchset()), flag, value) 601 self.GetIssue(), self.GetPatchset(), flag, value)
600 except urllib2.HTTPError, e: 602 except urllib2.HTTPError, e:
601 if e.code == 404: 603 if e.code == 404:
602 DieWithError('The issue %s doesn\'t exist.' % self.GetIssue()) 604 DieWithError('The issue %s doesn\'t exist.' % self.GetIssue())
603 if e.code == 403: 605 if e.code == 403:
604 DieWithError( 606 DieWithError(
605 ('Access denied to issue %s. Maybe the patchset %s doesn\'t ' 607 ('Access denied to issue %s. Maybe the patchset %s doesn\'t '
606 'match?') % (self.GetIssue(), self.GetPatchset())) 608 'match?') % (self.GetIssue(), self.GetPatchset()))
607 raise 609 raise
608 610
609 def RpcServer(self): 611 def RpcServer(self):
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 url = cl.GetIssueURL() 859 url = cl.GetIssueURL()
858 if url: 860 if url:
859 print url 861 print url
860 else: 862 else:
861 print 863 print
862 print 'Current branch:', 864 print 'Current branch:',
863 if not cl.GetIssue(): 865 if not cl.GetIssue():
864 print 'no issue assigned.' 866 print 'no issue assigned.'
865 return 0 867 return 0
866 print cl.GetBranch() 868 print cl.GetBranch()
867 print 'Issue number:', cl.GetIssue(), '(%s)' % cl.GetIssueURL() 869 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL())
868 print 'Issue description:' 870 print 'Issue description:'
869 print cl.GetDescription(pretty=True) 871 print cl.GetDescription(pretty=True)
870 return 0 872 return 0
871 873
872 874
873 @usage('[issue_number]') 875 @usage('[issue_number]')
874 def CMDissue(parser, args): 876 def CMDissue(parser, args):
875 """Set or display the current code review issue number. 877 """Set or display the current code review issue number.
876 878
877 Pass issue number 0 to clear the current issue. 879 Pass issue number 0 to clear the current issue.
878 """ 880 """
879 _, args = parser.parse_args(args) 881 _, args = parser.parse_args(args)
880 882
881 cl = Changelist() 883 cl = Changelist()
882 if len(args) > 0: 884 if len(args) > 0:
883 try: 885 try:
884 issue = int(args[0]) 886 issue = int(args[0])
885 except ValueError: 887 except ValueError:
886 DieWithError('Pass a number to set the issue or none to list it.\n' 888 DieWithError('Pass a number to set the issue or none to list it.\n'
887 'Maybe you want to run git cl status?') 889 'Maybe you want to run git cl status?')
888 cl.SetIssue(issue) 890 cl.SetIssue(issue)
889 print 'Issue number:', cl.GetIssue(), '(%s)' % cl.GetIssueURL() 891 print 'Issue number: %s (%s)' % (cl.GetIssue(), cl.GetIssueURL())
890 return 0 892 return 0
891 893
892 894
893 def CMDcomments(parser, args): 895 def CMDcomments(parser, args):
894 """show review comments of the current changelist""" 896 """show review comments of the current changelist"""
895 (_, args) = parser.parse_args(args) 897 (_, args) = parser.parse_args(args)
896 if args: 898 if args:
897 parser.error('Unsupported argument: %s' % args) 899 parser.error('Unsupported argument: %s' % args)
898 900
899 cl = Changelist() 901 cl = Changelist()
(...skipping 13 matching lines...) Expand all
913 log_args = [args[0] + '..'] 915 log_args = [args[0] + '..']
914 elif len(args) == 1 and args[0].endswith('...'): 916 elif len(args) == 1 and args[0].endswith('...'):
915 log_args = [args[0][:-1]] 917 log_args = [args[0][:-1]]
916 elif len(args) == 2: 918 elif len(args) == 2:
917 log_args = [args[0] + '..' + args[1]] 919 log_args = [args[0] + '..' + args[1]]
918 else: 920 else:
919 log_args = args[:] # Hope for the best! 921 log_args = args[:] # Hope for the best!
920 return RunGit(['log', '--pretty=format:%s\n\n%b'] + log_args) 922 return RunGit(['log', '--pretty=format:%s\n\n%b'] + log_args)
921 923
922 924
923 def ConvertToInteger(inputval):
924 """Convert a string to integer, but returns either an int or None."""
925 try:
926 return int(inputval)
927 except (TypeError, ValueError):
928 return None
929
930
931 def CMDpresubmit(parser, args): 925 def CMDpresubmit(parser, args):
932 """run presubmit tests on the current changelist""" 926 """run presubmit tests on the current changelist"""
933 parser.add_option('--upload', action='store_true', 927 parser.add_option('--upload', action='store_true',
934 help='Run upload hook instead of the push/dcommit hook') 928 help='Run upload hook instead of the push/dcommit hook')
935 (options, args) = parser.parse_args(args) 929 (options, args) = parser.parse_args(args)
936 930
937 # Make sure index is up-to-date before running diff-index. 931 # Make sure index is up-to-date before running diff-index.
938 RunGit(['update-index', '--refresh', '-q'], error_ok=True) 932 RunGit(['update-index', '--refresh', '-q'], error_ok=True)
939 if RunGit(['diff-index', 'HEAD']): 933 if RunGit(['diff-index', 'HEAD']):
940 # TODO(maruel): Is this really necessary? 934 # TODO(maruel): Is this really necessary?
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 change_desc = None 998 change_desc = None
1005 999
1006 if cl.GetIssue(): 1000 if cl.GetIssue():
1007 if options.title: 1001 if options.title:
1008 upload_args.extend(['--title', options.title]) 1002 upload_args.extend(['--title', options.title])
1009 elif options.message: 1003 elif options.message:
1010 # TODO(rogerta): for now, the -m option will also set the --title option 1004 # TODO(rogerta): for now, the -m option will also set the --title option
1011 # for upload.py. Soon this will be changed to set the --message option. 1005 # for upload.py. Soon this will be changed to set the --message option.
1012 # Will wait until people are used to typing -t instead of -m. 1006 # Will wait until people are used to typing -t instead of -m.
1013 upload_args.extend(['--title', options.message]) 1007 upload_args.extend(['--title', options.message])
1014 upload_args.extend(['--issue', cl.GetIssue()]) 1008 upload_args.extend(['--issue', str(cl.GetIssue())])
1015 print ("This branch is associated with issue %s. " 1009 print ("This branch is associated with issue %s. "
1016 "Adding patch to that issue." % cl.GetIssue()) 1010 "Adding patch to that issue." % cl.GetIssue())
1017 else: 1011 else:
1018 if options.title: 1012 if options.title:
1019 upload_args.extend(['--title', options.title]) 1013 upload_args.extend(['--title', options.title])
1020 message = options.message or CreateDescriptionFromLog(args) 1014 message = options.message or CreateDescriptionFromLog(args)
1021 change_desc = ChangeDescription(message, options.reviewers) 1015 change_desc = ChangeDescription(message, options.reviewers)
1022 if not options.force: 1016 if not options.force:
1023 change_desc.Prompt() 1017 change_desc.Prompt()
1024 change_desc.ParseDescription() 1018 change_desc.ParseDescription()
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1398 help="don't commit after patch applies") 1392 help="don't commit after patch applies")
1399 (options, args) = parser.parse_args(args) 1393 (options, args) = parser.parse_args(args)
1400 if len(args) != 1: 1394 if len(args) != 1:
1401 parser.print_help() 1395 parser.print_help()
1402 return 1 1396 return 1
1403 issue_arg = args[0] 1397 issue_arg = args[0]
1404 1398
1405 # TODO(maruel): Use apply_issue.py 1399 # TODO(maruel): Use apply_issue.py
1406 # TODO(ukai): use gerrit-cherry-pick for gerrit repository? 1400 # TODO(ukai): use gerrit-cherry-pick for gerrit repository?
1407 1401
1408 if re.match(r'\d+', issue_arg): 1402 if issue_arg.isdigit():
1409 # Input is an issue id. Figure out the URL. 1403 # Input is an issue id. Figure out the URL.
1410 issue = issue_arg 1404 issue = int(issue_arg)
1411 patch_data = Changelist().GetPatchSetDiff(issue) 1405 patch_data = Changelist().GetPatchSetDiff(issue)
1412 else: 1406 else:
1413 # Assume it's a URL to the patch. Default to https. 1407 # Assume it's a URL to the patch. Default to https.
1414 issue_url = gclient_utils.UpgradeToHttps(issue_arg) 1408 issue_url = gclient_utils.UpgradeToHttps(issue_arg)
1415 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url) 1409 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url)
1416 if not match: 1410 if not match:
1417 DieWithError('Must pass an issue ID or full URL for ' 1411 DieWithError('Must pass an issue ID or full URL for '
1418 '\'Download raw patch set\'') 1412 '\'Download raw patch set\'')
1419 issue = match.group(1) 1413 issue = int(match.group(1))
1420 patch_data = urllib2.urlopen(issue_arg).read() 1414 patch_data = urllib2.urlopen(issue_arg).read()
1421 1415
1422 if options.newbranch: 1416 if options.newbranch:
1423 if options.force: 1417 if options.force:
1424 RunGit(['branch', '-D', options.newbranch], 1418 RunGit(['branch', '-D', options.newbranch],
1425 stderr=subprocess2.PIPE, error_ok=True) 1419 stderr=subprocess2.PIPE, error_ok=True)
1426 RunGit(['checkout', '-b', options.newbranch, 1420 RunGit(['checkout', '-b', options.newbranch,
1427 Changelist().GetUpstreamBranch()]) 1421 Changelist().GetUpstreamBranch()])
1428 1422
1429 # Switch up to the top-level directory, if necessary, in preparation for 1423 # Switch up to the top-level directory, if necessary, in preparation for
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1617 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) 1611 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)))
1618 1612
1619 # Not a known command. Default to help. 1613 # Not a known command. Default to help.
1620 GenUsage(parser, 'help') 1614 GenUsage(parser, 'help')
1621 return CMDhelp(parser, argv) 1615 return CMDhelp(parser, argv)
1622 1616
1623 1617
1624 if __name__ == '__main__': 1618 if __name__ == '__main__':
1625 fix_encoding.fix_encoding() 1619 fix_encoding.fix_encoding()
1626 sys.exit(main(sys.argv[1:])) 1620 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698