diff options
Diffstat (limited to 'pre_commit')
-rw-r--r-- | pre_commit/commands/hook_impl.py | 18 | ||||
-rw-r--r-- | pre_commit/commands/run.py | 10 | ||||
-rw-r--r-- | pre_commit/languages/helpers.py | 5 | ||||
-rw-r--r-- | pre_commit/languages/ruby.py | 1 | ||||
-rw-r--r-- | pre_commit/main.py | 97 | ||||
-rw-r--r-- | pre_commit/parse_shebang.py | 5 | ||||
-rw-r--r-- | pre_commit/util.py | 4 |
7 files changed, 79 insertions, 61 deletions
diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py index f315c04..f5995e9 100644 --- a/pre_commit/commands/hook_impl.py +++ b/pre_commit/commands/hook_impl.py @@ -76,6 +76,8 @@ def _ns( remote_name: str | None = None, remote_url: str | None = None, commit_msg_filename: str | None = None, + prepare_commit_message_source: str | None = None, + commit_object_name: str | None = None, checkout_type: str | None = None, is_squash_merge: str | None = None, rewrite_command: str | None = None, @@ -90,6 +92,8 @@ def _ns( remote_name=remote_name, remote_url=remote_url, commit_msg_filename=commit_msg_filename, + prepare_commit_message_source=prepare_commit_message_source, + commit_object_name=commit_object_name, all_files=all_files, checkout_type=checkout_type, is_squash_merge=is_squash_merge, @@ -202,8 +206,20 @@ def _run_ns( _check_args_length(hook_type, args) if hook_type == 'pre-push': return _pre_push_ns(color, args, stdin) - elif hook_type in {'commit-msg', 'prepare-commit-msg'}: + elif hook_type in 'commit-msg': return _ns(hook_type, color, commit_msg_filename=args[0]) + elif hook_type == 'prepare-commit-msg' and len(args) == 1: + return _ns(hook_type, color, commit_msg_filename=args[0]) + elif hook_type == 'prepare-commit-msg' and len(args) == 2: + return _ns( + hook_type, color, commit_msg_filename=args[0], + prepare_commit_message_source=args[1], + ) + elif hook_type == 'prepare-commit-msg' and len(args) == 3: + return _ns( + hook_type, color, commit_msg_filename=args[0], + prepare_commit_message_source=args[1], commit_object_name=args[2], + ) elif hook_type in {'post-commit', 'pre-merge-commit', 'pre-commit'}: return _ns(hook_type, color) elif hook_type == 'post-checkout': diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py index 37f989b..ad3d766 100644 --- a/pre_commit/commands/run.py +++ b/pre_commit/commands/run.py @@ -361,6 +361,16 @@ def run( ): return 0 + # Expose prepare_commit_message_source / commit_object_name + # as environment variables for the hooks + if args.prepare_commit_message_source: + environ['PRE_COMMIT_COMMIT_MSG_SOURCE'] = ( + args.prepare_commit_message_source + ) + + if args.commit_object_name: + environ['PRE_COMMIT_COMMIT_OBJECT_NAME'] = args.commit_object_name + # Expose from-ref / to-ref as environment variables for hooks to consume if args.from_ref and args.to_ref: # legacy names diff --git a/pre_commit/languages/helpers.py b/pre_commit/languages/helpers.py index 05a7165..0be08b5 100644 --- a/pre_commit/languages/helpers.py +++ b/pre_commit/languages/helpers.py @@ -5,9 +5,9 @@ import os import random import re from typing import Any +from typing import NoReturn from typing import overload from typing import Sequence -from typing import TYPE_CHECKING import pre_commit.constants as C from pre_commit import parse_shebang @@ -16,9 +16,6 @@ from pre_commit.prefix import Prefix from pre_commit.util import cmd_output_b from pre_commit.xargs import xargs -if TYPE_CHECKING: - from typing import NoReturn - FIXED_RANDOM_SEED = 1542676187 SHIMS_RE = re.compile(r'[/\\]shims[/\\]') diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index 6c5cff2..8955dd0 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -138,6 +138,7 @@ def install_environment( ( 'gem', 'install', '--no-document', '--no-format-executable', + '--no-user-install', *prefix.star('.gem'), *additional_dependencies, ), ) diff --git a/pre_commit/main.py b/pre_commit/main.py index 6d2814b..b4fa966 100644 --- a/pre_commit/main.py +++ b/pre_commit/main.py @@ -108,6 +108,20 @@ def _add_run_options(parser: argparse.ArgumentParser) -> None: help='Filename to check when running during `commit-msg`', ) parser.add_argument( + '--prepare-commit-message-source', + help=( + 'Source of the commit message ' + '(typically the second argument to .git/hooks/prepare-commit-msg)' + ), + ) + parser.add_argument( + '--commit-object-name', + help=( + 'Commit object name ' + '(typically the third argument to .git/hooks/prepare-commit-msg)' + ), + ) + parser.add_argument( '--remote-name', help='Remote name used by `git push`.', ) parser.add_argument('--remote-url', help='Remote url used by `git push`.') @@ -167,11 +181,15 @@ def main(argv: Sequence[str] | None = None) -> int: subparsers = parser.add_subparsers(dest='command') - autoupdate_parser = subparsers.add_parser( + def _add_cmd(name: str, *, help: str) -> argparse.ArgumentParser: + parser = subparsers.add_parser(name, help=help) + add_color_option(parser) + return parser + + autoupdate_parser = _add_cmd( 'autoupdate', help="Auto-update pre-commit config to the latest repos' versions.", ) - add_color_option(autoupdate_parser) _add_config_option(autoupdate_parser) autoupdate_parser.add_argument( '--bleeding-edge', action='store_true', @@ -189,34 +207,17 @@ def main(argv: Sequence[str] | None = None) -> int: help='Only update this repository -- may be specified multiple times.', ) - clean_parser = subparsers.add_parser( - 'clean', help='Clean out pre-commit files.', - ) - add_color_option(clean_parser) - _add_config_option(clean_parser) - - hook_impl_parser = subparsers.add_parser('hook-impl') - add_color_option(hook_impl_parser) - _add_config_option(hook_impl_parser) - hook_impl_parser.add_argument('--hook-type') - hook_impl_parser.add_argument('--hook-dir') - hook_impl_parser.add_argument( - '--skip-on-missing-config', action='store_true', - ) - hook_impl_parser.add_argument(dest='rest', nargs=argparse.REMAINDER) + _add_cmd('clean', help='Clean out pre-commit files.') - gc_parser = subparsers.add_parser('gc', help='Clean unused cached repos.') - add_color_option(gc_parser) - _add_config_option(gc_parser) + _add_cmd('gc', help='Clean unused cached repos.') - init_templatedir_parser = subparsers.add_parser( + init_templatedir_parser = _add_cmd( 'init-templatedir', help=( 'Install hook script in a directory intended for use with ' '`git config init.templateDir`.' ), ) - add_color_option(init_templatedir_parser) _add_config_option(init_templatedir_parser) init_templatedir_parser.add_argument( 'directory', help='The directory in which to write the hook script.', @@ -229,10 +230,7 @@ def main(argv: Sequence[str] | None = None) -> int: ) _add_hook_type_option(init_templatedir_parser) - install_parser = subparsers.add_parser( - 'install', help='Install the pre-commit script.', - ) - add_color_option(install_parser) + install_parser = _add_cmd('install', help='Install the pre-commit script.') _add_config_option(install_parser) install_parser.add_argument( '-f', '--overwrite', action='store_true', @@ -254,7 +252,7 @@ def main(argv: Sequence[str] | None = None) -> int: ), ) - install_hooks_parser = subparsers.add_parser( + install_hooks_parser = _add_cmd( 'install-hooks', help=( 'Install hook environments for all environments in the config ' @@ -262,32 +260,24 @@ def main(argv: Sequence[str] | None = None) -> int: 'useful.' ), ) - add_color_option(install_hooks_parser) _add_config_option(install_hooks_parser) - migrate_config_parser = subparsers.add_parser( + migrate_config_parser = _add_cmd( 'migrate-config', help='Migrate list configuration to new map configuration.', ) - add_color_option(migrate_config_parser) _add_config_option(migrate_config_parser) - run_parser = subparsers.add_parser('run', help='Run hooks.') - add_color_option(run_parser) + run_parser = _add_cmd('run', help='Run hooks.') _add_config_option(run_parser) _add_run_options(run_parser) - sample_config_parser = subparsers.add_parser( - 'sample-config', help=f'Produce a sample {C.CONFIG_FILE} file', - ) - add_color_option(sample_config_parser) - _add_config_option(sample_config_parser) + _add_cmd('sample-config', help=f'Produce a sample {C.CONFIG_FILE} file') - try_repo_parser = subparsers.add_parser( + try_repo_parser = _add_cmd( 'try-repo', help='Try the hooks in a repository, useful for developing new hooks.', ) - add_color_option(try_repo_parser) _add_config_option(try_repo_parser) try_repo_parser.add_argument( 'repo', help='Repository to source hooks from.', @@ -301,32 +291,39 @@ def main(argv: Sequence[str] | None = None) -> int: ) _add_run_options(try_repo_parser) - uninstall_parser = subparsers.add_parser( + uninstall_parser = _add_cmd( 'uninstall', help='Uninstall the pre-commit script.', ) - add_color_option(uninstall_parser) _add_config_option(uninstall_parser) _add_hook_type_option(uninstall_parser) - validate_config_parser = subparsers.add_parser( + validate_config_parser = _add_cmd( 'validate-config', help='Validate .pre-commit-config.yaml files', ) - add_color_option(validate_config_parser) - _add_config_option(validate_config_parser) validate_config_parser.add_argument('filenames', nargs='*') - validate_manifest_parser = subparsers.add_parser( + validate_manifest_parser = _add_cmd( 'validate-manifest', help='Validate .pre-commit-hooks.yaml files', ) - add_color_option(validate_manifest_parser) - _add_config_option(validate_manifest_parser) validate_manifest_parser.add_argument('filenames', nargs='*') + # does not use `_add_cmd` because it doesn't use `--color` help = subparsers.add_parser( 'help', help='Show help for a specific command.', ) help.add_argument('help_cmd', nargs='?', help='Command to show help for.') + # not intended for users to call this directly + hook_impl_parser = subparsers.add_parser('hook-impl') + add_color_option(hook_impl_parser) + _add_config_option(hook_impl_parser) + hook_impl_parser.add_argument('--hook-type') + hook_impl_parser.add_argument('--hook-dir') + hook_impl_parser.add_argument( + '--skip-on-missing-config', action='store_true', + ) + hook_impl_parser.add_argument(dest='rest', nargs=argparse.REMAINDER) + # argparse doesn't really provide a way to use a `default` subparser if len(argv) == 0: argv = ['run'] @@ -340,11 +337,11 @@ def main(argv: Sequence[str] | None = None) -> int: with error_handler(), logging_handler(args.color): git.check_for_cygwin_mismatch() + store = Store() + if args.command not in COMMANDS_NO_GIT: _adjust_args_and_chdir(args) - - store = Store() - store.mark_config_used(args.config) + store.mark_config_used(args.config) if args.command == 'autoupdate': return autoupdate( diff --git a/pre_commit/parse_shebang.py b/pre_commit/parse_shebang.py index 3fd3129..3ac933c 100644 --- a/pre_commit/parse_shebang.py +++ b/pre_commit/parse_shebang.py @@ -2,13 +2,10 @@ from __future__ import annotations import os.path from typing import Mapping -from typing import TYPE_CHECKING +from typing import NoReturn from identify.identify import parse_shebang_from_file -if TYPE_CHECKING: - from typing import NoReturn - class ExecutableNotFoundError(OSError): def to_output(self) -> tuple[int, bytes, None]: diff --git a/pre_commit/util.py b/pre_commit/util.py index 40c53e5..8c296f4 100644 --- a/pre_commit/util.py +++ b/pre_commit/util.py @@ -168,10 +168,10 @@ if os.name != 'nt': # pragma: win32 no cover self.r, self.w = openpty() # tty flags normally change \n to \r\n - attrs = termios.tcgetattr(self.r) + attrs = termios.tcgetattr(self.w) assert isinstance(attrs[1], int) attrs[1] &= ~(termios.ONLCR | termios.OPOST) - termios.tcsetattr(self.r, termios.TCSANOW, attrs) + termios.tcsetattr(self.w, termios.TCSANOW, attrs) return self |