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

Side by Side Diff: git_cl.py

Issue 1585923004: 5X speed up of 'git cl format', which also speeds up 'git cl upload' (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Update comment Created 4 years, 11 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
« 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 from distutils.version import LooseVersion 10 from distutils.version import LooseVersion
(...skipping 3403 matching lines...) Expand 10 before | Expand all | Expand 10 after
3414 3414
3415 change = cl.GetChange(base_branch, None) 3415 change = cl.GetChange(base_branch, None)
3416 return owners_finder.OwnersFinder( 3416 return owners_finder.OwnersFinder(
3417 [f.LocalPath() for f in 3417 [f.LocalPath() for f in
3418 cl.GetChange(base_branch, None).AffectedFiles()], 3418 cl.GetChange(base_branch, None).AffectedFiles()],
3419 change.RepositoryRoot(), author, 3419 change.RepositoryRoot(), author,
3420 fopen=file, os_path=os.path, glob=glob.glob, 3420 fopen=file, os_path=os.path, glob=glob.glob,
3421 disable_color=options.no_color).run() 3421 disable_color=options.no_color).run()
3422 3422
3423 3423
3424 def BuildGitDiffCmd(diff_type, upstream_commit, args, extensions): 3424 def BuildGitDiffCmd(diff_type, upstream_commit, args):
3425 """Generates a diff command.""" 3425 """Generates a diff command."""
3426 # Generate diff for the current branch's changes. 3426 # Generate diff for the current branch's changes.
3427 diff_cmd = ['diff', '--no-ext-diff', '--no-prefix', diff_type, 3427 diff_cmd = ['diff', '--no-ext-diff', '--no-prefix', diff_type,
3428 upstream_commit, '--' ] 3428 upstream_commit, '--' ]
3429 3429
3430 if args: 3430 if args:
3431 for arg in args: 3431 for arg in args:
3432 if os.path.isdir(arg): 3432 if os.path.isdir(arg) or os.path.isfile(arg):
3433 diff_cmd.extend(os.path.join(arg, '*' + ext) for ext in extensions)
3434 elif os.path.isfile(arg):
3435 diff_cmd.append(arg) 3433 diff_cmd.append(arg)
3436 else: 3434 else:
3437 DieWithError('Argument "%s" is not a file or a directory' % arg) 3435 DieWithError('Argument "%s" is not a file or a directory' % arg)
3438 else:
3439 diff_cmd.extend('*' + ext for ext in extensions)
3440 3436
3441 return diff_cmd 3437 return diff_cmd
3442 3438
3439 def MatchingFileType(file_name, extensions):
3440 """Returns true if the file name ends with one of the given extensions."""
3441 return bool([ext for ext in extensions if file_name.lower().endswith(ext)])
3443 3442
3444 @subcommand.usage('[files or directories to diff]') 3443 @subcommand.usage('[files or directories to diff]')
3445 def CMDformat(parser, args): 3444 def CMDformat(parser, args):
3446 """Runs auto-formatting tools (clang-format etc.) on the diff.""" 3445 """Runs auto-formatting tools (clang-format etc.) on the diff."""
3447 CLANG_EXTS = ['.cc', '.cpp', '.h', '.mm', '.proto', '.java'] 3446 CLANG_EXTS = ['.cc', '.cpp', '.h', '.mm', '.proto', '.java']
3448 parser.add_option('--full', action='store_true', 3447 parser.add_option('--full', action='store_true',
3449 help='Reformat the full content of all touched files') 3448 help='Reformat the full content of all touched files')
3450 parser.add_option('--dry-run', action='store_true', 3449 parser.add_option('--dry-run', action='store_true',
3451 help='Don\'t modify any file on disk.') 3450 help='Don\'t modify any file on disk.')
3452 parser.add_option('--python', action='store_true', 3451 parser.add_option('--python', action='store_true',
(...skipping 16 matching lines...) Expand all
3469 cl = Changelist() 3468 cl = Changelist()
3470 upstream_branch = cl.GetUpstreamBranch() 3469 upstream_branch = cl.GetUpstreamBranch()
3471 if upstream_branch: 3470 if upstream_branch:
3472 upstream_commit = RunGit(['merge-base', 'HEAD', upstream_branch]) 3471 upstream_commit = RunGit(['merge-base', 'HEAD', upstream_branch])
3473 upstream_commit = upstream_commit.strip() 3472 upstream_commit = upstream_commit.strip()
3474 3473
3475 if not upstream_commit: 3474 if not upstream_commit:
3476 DieWithError('Could not find base commit for this branch. ' 3475 DieWithError('Could not find base commit for this branch. '
3477 'Are you in detached state?') 3476 'Are you in detached state?')
3478 3477
3479 if opts.full: 3478 changed_files_cmd = BuildGitDiffCmd('--name-only', upstream_commit, args)
3480 # Only list the names of modified files. 3479 diff_output = RunGit(changed_files_cmd)
3481 diff_type = '--name-only' 3480 diff_files = diff_output.splitlines()
3482 else:
3483 # Only generate context-less patches.
3484 diff_type = '-U0'
3485 3481
3486 diff_cmd = BuildGitDiffCmd(diff_type, upstream_commit, args, CLANG_EXTS) 3482 clang_diff_files = [x for x in diff_files if MatchingFileType(x, CLANG_EXTS)]
3487 diff_output = RunGit(diff_cmd) 3483 python_diff_files = [x for x in diff_files if MatchingFileType(x, ['.py'])]
3484 dart_diff_files = [x for x in diff_files if MatchingFileType(x, ['.dart'])]
3488 3485
3489 top_dir = os.path.normpath( 3486 top_dir = os.path.normpath(
3490 RunGit(["rev-parse", "--show-toplevel"]).rstrip('\n')) 3487 RunGit(["rev-parse", "--show-toplevel"]).rstrip('\n'))
3491 3488
3492 # Locate the clang-format binary in the checkout 3489 # Locate the clang-format binary in the checkout
3493 try: 3490 try:
3494 clang_format_tool = clang_format.FindClangFormatToolInChromiumTree() 3491 clang_format_tool = clang_format.FindClangFormatToolInChromiumTree()
3495 except clang_format.NotFoundError, e: 3492 except clang_format.NotFoundError, e:
3496 DieWithError(e) 3493 DieWithError(e)
3497 3494
3498 # Set to 2 to signal to CheckPatchFormatted() that this patch isn't 3495 # Set to 2 to signal to CheckPatchFormatted() that this patch isn't
3499 # formatted. This is used to block during the presubmit. 3496 # formatted. This is used to block during the presubmit.
3500 return_value = 0 3497 return_value = 0
3501 3498
3502 if opts.full: 3499 if opts.full:
3503 # diff_output is a list of files to send to clang-format. 3500 if clang_diff_files:
3504 files = diff_output.splitlines()
3505 if files:
3506 cmd = [clang_format_tool] 3501 cmd = [clang_format_tool]
3507 if not opts.dry_run and not opts.diff: 3502 if not opts.dry_run and not opts.diff:
3508 cmd.append('-i') 3503 cmd.append('-i')
3509 stdout = RunCommand(cmd + files, cwd=top_dir) 3504 stdout = RunCommand(cmd + clang_diff_files, cwd=top_dir)
3510 if opts.diff: 3505 if opts.diff:
3511 sys.stdout.write(stdout) 3506 sys.stdout.write(stdout)
3512 else: 3507 else:
3513 env = os.environ.copy() 3508 env = os.environ.copy()
3514 env['PATH'] = str(os.path.dirname(clang_format_tool)) 3509 env['PATH'] = str(os.path.dirname(clang_format_tool))
3515 # diff_output is a patch to send to clang-format-diff.py
3516 try: 3510 try:
3517 script = clang_format.FindClangFormatScriptInChromiumTree( 3511 script = clang_format.FindClangFormatScriptInChromiumTree(
3518 'clang-format-diff.py') 3512 'clang-format-diff.py')
3519 except clang_format.NotFoundError, e: 3513 except clang_format.NotFoundError, e:
3520 DieWithError(e) 3514 DieWithError(e)
3521 3515
3522 cmd = [sys.executable, script, '-p0'] 3516 cmd = [sys.executable, script, '-p0']
3523 if not opts.dry_run and not opts.diff: 3517 if not opts.dry_run and not opts.diff:
3524 cmd.append('-i') 3518 cmd.append('-i')
3525 3519
3520 diff_cmd = BuildGitDiffCmd('-U0', upstream_commit, clang_diff_files)
3521 diff_output = RunGit(diff_cmd)
3522
3526 stdout = RunCommand(cmd, stdin=diff_output, cwd=top_dir, env=env) 3523 stdout = RunCommand(cmd, stdin=diff_output, cwd=top_dir, env=env)
3527 if opts.diff: 3524 if opts.diff:
3528 sys.stdout.write(stdout) 3525 sys.stdout.write(stdout)
3529 if opts.dry_run and len(stdout) > 0: 3526 if opts.dry_run and len(stdout) > 0:
3530 return_value = 2 3527 return_value = 2
3531 3528
3532 # Similar code to above, but using yapf on .py files rather than clang-format 3529 # Similar code to above, but using yapf on .py files rather than clang-format
3533 # on C/C++ files 3530 # on C/C++ files
3534 if opts.python: 3531 if opts.python:
3535 diff_cmd = BuildGitDiffCmd(diff_type, upstream_commit, args, ['.py'])
3536 diff_output = RunGit(diff_cmd)
3537 yapf_tool = gclient_utils.FindExecutable('yapf') 3532 yapf_tool = gclient_utils.FindExecutable('yapf')
3538 if yapf_tool is None: 3533 if yapf_tool is None:
3539 DieWithError('yapf not found in PATH') 3534 DieWithError('yapf not found in PATH')
3540 3535
3541 if opts.full: 3536 if opts.full:
3542 files = diff_output.splitlines() 3537 if python_diff_files:
3543 if files:
3544 cmd = [yapf_tool] 3538 cmd = [yapf_tool]
3545 if not opts.dry_run and not opts.diff: 3539 if not opts.dry_run and not opts.diff:
3546 cmd.append('-i') 3540 cmd.append('-i')
3547 stdout = RunCommand(cmd + files, cwd=top_dir) 3541 stdout = RunCommand(cmd + python_diff_files, cwd=top_dir)
3548 if opts.diff: 3542 if opts.diff:
3549 sys.stdout.write(stdout) 3543 sys.stdout.write(stdout)
3550 else: 3544 else:
3551 # TODO(sbc): yapf --lines mode still has some issues. 3545 # TODO(sbc): yapf --lines mode still has some issues.
3552 # https://github.com/google/yapf/issues/154 3546 # https://github.com/google/yapf/issues/154
3553 DieWithError('--python currently only works with --full') 3547 DieWithError('--python currently only works with --full')
3554 3548
3555 # Build a diff command that only operates on dart files. dart's formatter 3549 # Dart's formatter does not have the nice property of only operating on
3556 # does not have the nice property of only operating on modified chunks, so 3550 # modified chunks, so hard code full.
3557 # hard code full. 3551 if dart_diff_files:
3558 dart_diff_cmd = BuildGitDiffCmd('--name-only', upstream_commit,
3559 args, ['.dart'])
3560 dart_diff_output = RunGit(dart_diff_cmd)
3561 if dart_diff_output:
3562 try: 3552 try:
3563 command = [dart_format.FindDartFmtToolInChromiumTree()] 3553 command = [dart_format.FindDartFmtToolInChromiumTree()]
3564 if not opts.dry_run and not opts.diff: 3554 if not opts.dry_run and not opts.diff:
3565 command.append('-w') 3555 command.append('-w')
3566 command.extend(dart_diff_output.splitlines()) 3556 command.extend(dart_diff_files)
3567 3557
3568 stdout = RunCommand(command, cwd=top_dir, env=env) 3558 stdout = RunCommand(command, cwd=top_dir, env=env)
3569 if opts.dry_run and stdout: 3559 if opts.dry_run and stdout:
3570 return_value = 2 3560 return_value = 2
3571 except dart_format.NotFoundError as e: 3561 except dart_format.NotFoundError as e:
3572 print ('Warning: Unable to check Dart code formatting. Dart SDK not ' + 3562 print ('Warning: Unable to check Dart code formatting. Dart SDK not ' +
3573 'found in this checkout. Files in other languages are still ' + 3563 'found in this checkout. Files in other languages are still ' +
3574 'formatted.') 3564 'formatted.')
3575 3565
3576 return return_value 3566 return return_value
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
3672 if __name__ == '__main__': 3662 if __name__ == '__main__':
3673 # These affect sys.stdout so do it outside of main() to simplify mocks in 3663 # These affect sys.stdout so do it outside of main() to simplify mocks in
3674 # unit testing. 3664 # unit testing.
3675 fix_encoding.fix_encoding() 3665 fix_encoding.fix_encoding()
3676 colorama.init() 3666 colorama.init()
3677 try: 3667 try:
3678 sys.exit(main(sys.argv[1:])) 3668 sys.exit(main(sys.argv[1:]))
3679 except KeyboardInterrupt: 3669 except KeyboardInterrupt:
3680 sys.stderr.write('interrupted\n') 3670 sys.stderr.write('interrupted\n')
3681 sys.exit(1) 3671 sys.exit(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