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 # 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 Loading... |
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 Loading... |
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 Loading... |
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) |
OLD | NEW |