| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 errno | 10 import errno |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' | 49 DESCRIPTION_BACKUP_FILE = '~/.git_cl_description_backup' |
| 50 | 50 |
| 51 | 51 |
| 52 def DieWithError(message): | 52 def DieWithError(message): |
| 53 print >> sys.stderr, message | 53 print >> sys.stderr, message |
| 54 sys.exit(1) | 54 sys.exit(1) |
| 55 | 55 |
| 56 | 56 |
| 57 def Popen(cmd, **kwargs): | 57 def Popen(cmd, **kwargs): |
| 58 """Wrapper for subprocess.Popen() that logs and watch for cygwin issues""" | 58 """Wrapper for subprocess.Popen() that logs and watch for cygwin issues""" |
| 59 logging.info('Popen: ' + ' '.join(cmd)) | 59 logging.debug('Popen: ' + ' '.join(cmd)) |
| 60 try: | 60 try: |
| 61 return subprocess.Popen(cmd, **kwargs) | 61 return subprocess.Popen(cmd, **kwargs) |
| 62 except OSError, e: | 62 except OSError, e: |
| 63 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': | 63 if e.errno == errno.EAGAIN and sys.platform == 'cygwin': |
| 64 DieWithError( | 64 DieWithError( |
| 65 'Visit ' | 65 'Visit ' |
| 66 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure to ' | 66 'http://code.google.com/p/chromium/wiki/CygwinDllRemappingFailure to ' |
| 67 'learn how to fix this error; you need to rebase your cygwin dlls') | 67 'learn how to fix this error; you need to rebase your cygwin dlls') |
| 68 raise | 68 raise |
| 69 | 69 |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 | 803 |
| 804 | 804 |
| 805 def ConvertToInteger(inputval): | 805 def ConvertToInteger(inputval): |
| 806 """Convert a string to integer, but returns either an int or None.""" | 806 """Convert a string to integer, but returns either an int or None.""" |
| 807 try: | 807 try: |
| 808 return int(inputval) | 808 return int(inputval) |
| 809 except (TypeError, ValueError): | 809 except (TypeError, ValueError): |
| 810 return None | 810 return None |
| 811 | 811 |
| 812 | 812 |
| 813 def RunHook(committing, upstream_branch, rietveld_server, tbr, may_prompt): | 813 def RunHook(committing, upstream_branch, rietveld_server, tbr, may_prompt, |
| 814 verbose): |
| 814 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" | 815 """Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" |
| 815 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() | 816 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() |
| 816 if not root: | 817 if not root: |
| 817 root = '.' | 818 root = '.' |
| 818 absroot = os.path.abspath(root) | 819 absroot = os.path.abspath(root) |
| 819 if not root: | 820 if not root: |
| 820 raise Exception('Could not get root directory.') | 821 raise Exception('Could not get root directory.') |
| 821 | 822 |
| 822 # We use the sha1 of HEAD as a name of this change. | 823 # We use the sha1 of HEAD as a name of this change. |
| 823 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | 824 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() |
| (...skipping 12 matching lines...) Expand all Loading... |
| 836 '%s...' % (upstream_branch)]).strip() | 837 '%s...' % (upstream_branch)]).strip() |
| 837 change = presubmit_support.GitChange(name, description, absroot, files, | 838 change = presubmit_support.GitChange(name, description, absroot, files, |
| 838 issue, patchset) | 839 issue, patchset) |
| 839 | 840 |
| 840 # Apply watchlists on upload. | 841 # Apply watchlists on upload. |
| 841 if not committing: | 842 if not committing: |
| 842 watchlist = watchlists.Watchlists(change.RepositoryRoot()) | 843 watchlist = watchlists.Watchlists(change.RepositoryRoot()) |
| 843 files = [f.LocalPath() for f in change.AffectedFiles()] | 844 files = [f.LocalPath() for f in change.AffectedFiles()] |
| 844 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) | 845 cl.SetWatchers(watchlist.GetWatchersForPaths(files)) |
| 845 | 846 |
| 846 output = presubmit_support.DoPresubmitChecks(change, committing, | 847 try: |
| 847 verbose=False, output_stream=sys.stdout, input_stream=sys.stdin, | 848 output = presubmit_support.DoPresubmitChecks(change, committing, |
| 848 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, | 849 verbose=verbose, output_stream=sys.stdout, input_stream=sys.stdin, |
| 849 host_url=cl.GetRietveldServer()) | 850 default_presubmit=None, may_prompt=may_prompt, tbr=tbr, |
| 851 host_url=cl.GetRietveldServer()) |
| 852 except presubmit_support.PresubmitFailure, e: |
| 853 DieWithError( |
| 854 ('%s\nMaybe your depot_tools is out of date?\n' |
| 855 'If all fails, contact maruel@') % e) |
| 850 | 856 |
| 851 # TODO(dpranke): We should propagate the error out instead of calling exit(). | 857 # TODO(dpranke): We should propagate the error out instead of calling exit(). |
| 852 if not output.should_continue(): | 858 if not output.should_continue(): |
| 853 sys.exit(1) | 859 sys.exit(1) |
| 854 | 860 |
| 855 return output | 861 return output |
| 856 | 862 |
| 857 | 863 |
| 858 def CMDpresubmit(parser, args): | 864 def CMDpresubmit(parser, args): |
| 859 """run presubmit tests on the current changelist""" | 865 """run presubmit tests on the current changelist""" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 870 | 876 |
| 871 cl = Changelist() | 877 cl = Changelist() |
| 872 if args: | 878 if args: |
| 873 base_branch = args[0] | 879 base_branch = args[0] |
| 874 else: | 880 else: |
| 875 # Default to diffing against the "upstream" branch. | 881 # Default to diffing against the "upstream" branch. |
| 876 base_branch = cl.GetUpstreamBranch() | 882 base_branch = cl.GetUpstreamBranch() |
| 877 | 883 |
| 878 RunHook(committing=not options.upload, upstream_branch=base_branch, | 884 RunHook(committing=not options.upload, upstream_branch=base_branch, |
| 879 rietveld_server=cl.GetRietveldServer(), tbr=False, | 885 rietveld_server=cl.GetRietveldServer(), tbr=False, |
| 880 may_prompt=False) | 886 may_prompt=False, verbose=options.verbose) |
| 881 return 0 | 887 return 0 |
| 882 | 888 |
| 883 | 889 |
| 884 @usage('[args to "git diff"]') | 890 @usage('[args to "git diff"]') |
| 885 def CMDupload(parser, args): | 891 def CMDupload(parser, args): |
| 886 """upload the current changelist to codereview""" | 892 """upload the current changelist to codereview""" |
| 887 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 893 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
| 888 help='bypass upload presubmit hook') | 894 help='bypass upload presubmit hook') |
| 889 parser.add_option('-f', action='store_true', dest='force', | 895 parser.add_option('-f', action='store_true', dest='force', |
| 890 help="force yes to questions (don't prompt)") | 896 help="force yes to questions (don't prompt)") |
| (...skipping 23 matching lines...) Expand all Loading... |
| 914 if args: | 920 if args: |
| 915 base_branch = args[0] | 921 base_branch = args[0] |
| 916 else: | 922 else: |
| 917 # Default to diffing against the "upstream" branch. | 923 # Default to diffing against the "upstream" branch. |
| 918 base_branch = cl.GetUpstreamBranch() | 924 base_branch = cl.GetUpstreamBranch() |
| 919 args = [base_branch + "..."] | 925 args = [base_branch + "..."] |
| 920 | 926 |
| 921 if not options.bypass_hooks and not options.force: | 927 if not options.bypass_hooks and not options.force: |
| 922 hook_results = RunHook(committing=False, upstream_branch=base_branch, | 928 hook_results = RunHook(committing=False, upstream_branch=base_branch, |
| 923 rietveld_server=cl.GetRietveldServer(), tbr=False, | 929 rietveld_server=cl.GetRietveldServer(), tbr=False, |
| 924 may_prompt=True) | 930 may_prompt=True, verbose=options.verbose) |
| 925 if not options.reviewers and hook_results.reviewers: | 931 if not options.reviewers and hook_results.reviewers: |
| 926 options.reviewers = hook_results.reviewers | 932 options.reviewers = hook_results.reviewers |
| 927 | 933 |
| 928 | 934 |
| 929 # --no-ext-diff is broken in some versions of Git, so try to work around | 935 # --no-ext-diff is broken in some versions of Git, so try to work around |
| 930 # this by overriding the environment (but there is still a problem if the | 936 # this by overriding the environment (but there is still a problem if the |
| 931 # git config key "diff.external" is used). | 937 # git config key "diff.external" is used). |
| 932 env = os.environ.copy() | 938 env = os.environ.copy() |
| 933 if 'GIT_EXTERNAL_DIFF' in env: | 939 if 'GIT_EXTERNAL_DIFF' in env: |
| 934 del env['GIT_EXTERNAL_DIFF'] | 940 del env['GIT_EXTERNAL_DIFF'] |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1067 if extra_commits: | 1073 if extra_commits: |
| 1068 print ('This branch has %d additional commits not upstreamed yet.' | 1074 print ('This branch has %d additional commits not upstreamed yet.' |
| 1069 % len(extra_commits.splitlines())) | 1075 % len(extra_commits.splitlines())) |
| 1070 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' | 1076 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
| 1071 'before attempting to %s.' % (base_branch, cmd)) | 1077 'before attempting to %s.' % (base_branch, cmd)) |
| 1072 return 1 | 1078 return 1 |
| 1073 | 1079 |
| 1074 if not options.bypass_hooks and not options.force: | 1080 if not options.bypass_hooks and not options.force: |
| 1075 RunHook(committing=True, upstream_branch=base_branch, | 1081 RunHook(committing=True, upstream_branch=base_branch, |
| 1076 rietveld_server=cl.GetRietveldServer(), tbr=options.tbr, | 1082 rietveld_server=cl.GetRietveldServer(), tbr=options.tbr, |
| 1077 may_prompt=True) | 1083 may_prompt=True, verbose=options.verbose) |
| 1078 | 1084 |
| 1079 if cmd == 'dcommit': | 1085 if cmd == 'dcommit': |
| 1080 # Check the tree status if the tree status URL is set. | 1086 # Check the tree status if the tree status URL is set. |
| 1081 status = GetTreeStatus() | 1087 status = GetTreeStatus() |
| 1082 if 'closed' == status: | 1088 if 'closed' == status: |
| 1083 print ('The tree is closed. Please wait for it to reopen. Use ' | 1089 print ('The tree is closed. Please wait for it to reopen. Use ' |
| 1084 '"git cl dcommit -f" to commit on a closed tree.') | 1090 '"git cl dcommit -f" to commit on a closed tree.') |
| 1085 return 1 | 1091 return 1 |
| 1086 elif 'unknown' == status: | 1092 elif 'unknown' == status: |
| 1087 print ('Unable to determine tree status. Please verify manually and ' | 1093 print ('Unable to determine tree status. Please verify manually and ' |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 def main(argv): | 1406 def main(argv): |
| 1401 """Doesn't parse the arguments here, just find the right subcommand to | 1407 """Doesn't parse the arguments here, just find the right subcommand to |
| 1402 execute.""" | 1408 execute.""" |
| 1403 # Do it late so all commands are listed. | 1409 # Do it late so all commands are listed. |
| 1404 CMDhelp.usage_more = ('\n\nCommands are:\n' + '\n'.join([ | 1410 CMDhelp.usage_more = ('\n\nCommands are:\n' + '\n'.join([ |
| 1405 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) | 1411 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip()) |
| 1406 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) | 1412 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')])) |
| 1407 | 1413 |
| 1408 # Create the option parse and add --verbose support. | 1414 # Create the option parse and add --verbose support. |
| 1409 parser = optparse.OptionParser() | 1415 parser = optparse.OptionParser() |
| 1410 parser.add_option('-v', '--verbose', action='store_true') | 1416 parser.add_option( |
| 1417 '-v', '--verbose', action='count', default=0, |
| 1418 help='Use 2 times for more debugging info') |
| 1411 old_parser_args = parser.parse_args | 1419 old_parser_args = parser.parse_args |
| 1412 def Parse(args): | 1420 def Parse(args): |
| 1413 options, args = old_parser_args(args) | 1421 options, args = old_parser_args(args) |
| 1414 if options.verbose: | 1422 if options.verbose >= 2: |
| 1415 logging.basicConfig(level=logging.DEBUG) | 1423 logging.basicConfig(level=logging.DEBUG) |
| 1424 elif options.verbose: |
| 1425 logging.basicConfig(level=logging.INFO) |
| 1416 else: | 1426 else: |
| 1417 logging.basicConfig(level=logging.WARNING) | 1427 logging.basicConfig(level=logging.WARNING) |
| 1418 return options, args | 1428 return options, args |
| 1419 parser.parse_args = Parse | 1429 parser.parse_args = Parse |
| 1420 | 1430 |
| 1421 if argv: | 1431 if argv: |
| 1422 command = Command(argv[0]) | 1432 command = Command(argv[0]) |
| 1423 if command: | 1433 if command: |
| 1424 # "fix" the usage and the description now that we know the subcommand. | 1434 # "fix" the usage and the description now that we know the subcommand. |
| 1425 GenUsage(parser, argv[0]) | 1435 GenUsage(parser, argv[0]) |
| 1426 try: | 1436 try: |
| 1427 return command(parser, argv[1:]) | 1437 return command(parser, argv[1:]) |
| 1428 except urllib2.HTTPError, e: | 1438 except urllib2.HTTPError, e: |
| 1429 if e.code != 500: | 1439 if e.code != 500: |
| 1430 raise | 1440 raise |
| 1431 DieWithError( | 1441 DieWithError( |
| 1432 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 1442 ('AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 1433 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1443 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
| 1434 | 1444 |
| 1435 # Not a known command. Default to help. | 1445 # Not a known command. Default to help. |
| 1436 GenUsage(parser, 'help') | 1446 GenUsage(parser, 'help') |
| 1437 return CMDhelp(parser, argv) | 1447 return CMDhelp(parser, argv) |
| 1438 | 1448 |
| 1439 | 1449 |
| 1440 if __name__ == '__main__': | 1450 if __name__ == '__main__': |
| 1441 fix_encoding.fix_encoding() | 1451 fix_encoding.fix_encoding() |
| 1442 sys.exit(main(sys.argv[1:])) | 1452 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |