summaryrefslogtreecommitdiffstats
path: root/pre_commit
diff options
context:
space:
mode:
Diffstat (limited to 'pre_commit')
-rw-r--r--pre_commit/clientlib.py68
-rw-r--r--pre_commit/commands/hook_impl.py19
-rw-r--r--pre_commit/commands/run.py5
-rw-r--r--pre_commit/constants.py13
-rw-r--r--pre_commit/languages/conda.py3
-rw-r--r--pre_commit/languages/python.py4
-rw-r--r--pre_commit/languages/rust.py1
-rw-r--r--pre_commit/main.py19
-rw-r--r--pre_commit/util.py2
9 files changed, 106 insertions, 28 deletions
diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py
index 9ff38c6..d0651ca 100644
--- a/pre_commit/clientlib.py
+++ b/pre_commit/clientlib.py
@@ -6,6 +6,7 @@ import re
import shlex
import sys
from typing import Any
+from typing import NamedTuple
from typing import Sequence
import cfgv
@@ -20,6 +21,21 @@ logger = logging.getLogger('pre_commit')
check_string_regex = cfgv.check_and(cfgv.check_string, cfgv.check_regex)
+HOOK_TYPES = (
+ 'commit-msg',
+ 'post-checkout',
+ 'post-commit',
+ 'post-merge',
+ 'post-rewrite',
+ 'pre-commit',
+ 'pre-merge-commit',
+ 'pre-push',
+ 'pre-rebase',
+ 'prepare-commit-msg',
+)
+# `manual` is not invoked by any installed git hook. See #719
+STAGES = (*HOOK_TYPES, 'manual')
+
def check_type_tag(tag: str) -> None:
if tag not in ALL_TAGS:
@@ -43,6 +59,46 @@ def check_min_version(version: str) -> None:
)
+_STAGES = {
+ 'commit': 'pre-commit',
+ 'merge-commit': 'pre-merge-commit',
+ 'push': 'pre-push',
+}
+
+
+def transform_stage(stage: str) -> str:
+ return _STAGES.get(stage, stage)
+
+
+class StagesMigrationNoDefault(NamedTuple):
+ key: str
+ default: Sequence[str]
+
+ def check(self, dct: dict[str, Any]) -> None:
+ if self.key not in dct:
+ return
+
+ val = dct[self.key]
+ cfgv.check_array(cfgv.check_any)(val)
+
+ val = [transform_stage(v) for v in val]
+ cfgv.check_array(cfgv.check_one_of(STAGES))(val)
+
+ def apply_default(self, dct: dict[str, Any]) -> None:
+ if self.key not in dct:
+ return
+ dct[self.key] = [transform_stage(v) for v in dct[self.key]]
+
+ def remove_default(self, dct: dict[str, Any]) -> None:
+ raise NotImplementedError
+
+
+class StagesMigration(StagesMigrationNoDefault):
+ def apply_default(self, dct: dict[str, Any]) -> None:
+ dct.setdefault(self.key, self.default)
+ super().apply_default(dct)
+
+
MANIFEST_HOOK_DICT = cfgv.Map(
'Hook', 'id',
@@ -70,7 +126,7 @@ MANIFEST_HOOK_DICT = cfgv.Map(
cfgv.Optional('log_file', cfgv.check_string, ''),
cfgv.Optional('minimum_pre_commit_version', cfgv.check_string, '0'),
cfgv.Optional('require_serial', cfgv.check_bool, False),
- cfgv.Optional('stages', cfgv.check_array(cfgv.check_one_of(C.STAGES)), []),
+ StagesMigration('stages', []),
cfgv.Optional('verbose', cfgv.check_bool, False),
)
MANIFEST_SCHEMA = cfgv.Array(MANIFEST_HOOK_DICT)
@@ -241,7 +297,9 @@ CONFIG_HOOK_DICT = cfgv.Map(
cfgv.OptionalNoDefault(item.key, item.check_fn)
for item in MANIFEST_HOOK_DICT.items
if item.key != 'id'
+ if item.key != 'stages'
),
+ StagesMigrationNoDefault('stages', []),
OptionalSensibleRegexAtHook('files', cfgv.check_string),
OptionalSensibleRegexAtHook('exclude', cfgv.check_string),
)
@@ -290,17 +348,13 @@ CONFIG_SCHEMA = cfgv.Map(
cfgv.RequiredRecurse('repos', cfgv.Array(CONFIG_REPO_DICT)),
cfgv.Optional(
'default_install_hook_types',
- cfgv.check_array(cfgv.check_one_of(C.HOOK_TYPES)),
+ cfgv.check_array(cfgv.check_one_of(HOOK_TYPES)),
['pre-commit'],
),
cfgv.OptionalRecurse(
'default_language_version', DEFAULT_LANGUAGE_VERSION, {},
),
- cfgv.Optional(
- 'default_stages',
- cfgv.check_array(cfgv.check_one_of(C.STAGES)),
- C.STAGES,
- ),
+ StagesMigration('default_stages', STAGES),
cfgv.Optional('files', check_string_regex, ''),
cfgv.Optional('exclude', check_string_regex, '^$'),
cfgv.Optional('fail_fast', cfgv.check_bool, False),
diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py
index f5995e9..dab2135 100644
--- a/pre_commit/commands/hook_impl.py
+++ b/pre_commit/commands/hook_impl.py
@@ -73,6 +73,8 @@ def _ns(
local_branch: str | None = None,
from_ref: str | None = None,
to_ref: str | None = None,
+ pre_rebase_upstream: str | None = None,
+ pre_rebase_branch: str | None = None,
remote_name: str | None = None,
remote_url: str | None = None,
commit_msg_filename: str | None = None,
@@ -84,11 +86,13 @@ def _ns(
) -> argparse.Namespace:
return argparse.Namespace(
color=color,
- hook_stage=hook_type.replace('pre-', ''),
+ hook_stage=hook_type,
remote_branch=remote_branch,
local_branch=local_branch,
from_ref=from_ref,
to_ref=to_ref,
+ pre_rebase_upstream=pre_rebase_upstream,
+ pre_rebase_branch=pre_rebase_branch,
remote_name=remote_name,
remote_url=remote_url,
commit_msg_filename=commit_msg_filename,
@@ -185,6 +189,12 @@ def _check_args_length(hook_type: str, args: Sequence[str]) -> None:
f'hook-impl for {hook_type} expected 1, 2, or 3 arguments '
f'but got {len(args)}: {args}',
)
+ elif hook_type == 'pre-rebase':
+ if len(args) < 1 or len(args) > 2:
+ raise SystemExit(
+ f'hook-impl for {hook_type} expected 1 or 2 arguments '
+ f'but got {len(args)}: {args}',
+ )
elif hook_type in _EXPECTED_ARG_LENGTH_BY_HOOK:
expected = _EXPECTED_ARG_LENGTH_BY_HOOK[hook_type]
if len(args) != expected:
@@ -231,6 +241,13 @@ def _run_ns(
return _ns(hook_type, color, is_squash_merge=args[0])
elif hook_type == 'post-rewrite':
return _ns(hook_type, color, rewrite_command=args[0])
+ elif hook_type == 'pre-rebase' and len(args) == 1:
+ return _ns(hook_type, color, pre_rebase_upstream=args[0])
+ elif hook_type == 'pre-rebase' and len(args) == 2:
+ return _ns(
+ hook_type, color, pre_rebase_upstream=args[0],
+ pre_rebase_branch=args[1],
+ )
else:
raise AssertionError(f'unexpected hook type: {hook_type}')
diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py
index c9bc55b..c867799 100644
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -254,6 +254,7 @@ def _all_filenames(args: argparse.Namespace) -> Collection[str]:
# these hooks do not operate on files
if args.hook_stage in {
'post-checkout', 'post-commit', 'post-merge', 'post-rewrite',
+ 'pre-rebase',
}:
return ()
elif args.hook_stage in {'prepare-commit-msg', 'commit-msg'}:
@@ -389,6 +390,10 @@ def run(
environ['PRE_COMMIT_FROM_REF'] = args.from_ref
environ['PRE_COMMIT_TO_REF'] = args.to_ref
+ if args.pre_rebase_upstream and args.pre_rebase_branch:
+ environ['PRE_COMMIT_PRE_REBASE_UPSTREAM'] = args.pre_rebase_upstream
+ environ['PRE_COMMIT_PRE_REBASE_BRANCH'] = args.pre_rebase_branch
+
if (
args.remote_name and args.remote_url and
args.remote_branch and args.local_branch
diff --git a/pre_commit/constants.py b/pre_commit/constants.py
index 3f03cee..79a9bb6 100644
--- a/pre_commit/constants.py
+++ b/pre_commit/constants.py
@@ -10,17 +10,4 @@ LOCAL_REPO_VERSION = '1'
VERSION = importlib.metadata.version('pre_commit')
-# `manual` is not invoked by any installed git hook. See #719
-STAGES = (
- 'commit', 'merge-commit', 'prepare-commit-msg', 'commit-msg',
- 'post-commit', 'manual', 'post-checkout', 'push', 'post-merge',
- 'post-rewrite',
-)
-
-HOOK_TYPES = (
- 'pre-commit', 'pre-merge-commit', 'pre-push', 'prepare-commit-msg',
- 'commit-msg', 'post-commit', 'post-checkout', 'post-merge',
- 'post-rewrite',
-)
-
DEFAULT = 'default'
diff --git a/pre_commit/languages/conda.py b/pre_commit/languages/conda.py
index 05f1d29..41c355e 100644
--- a/pre_commit/languages/conda.py
+++ b/pre_commit/languages/conda.py
@@ -2,6 +2,7 @@ from __future__ import annotations
import contextlib
import os
+import sys
from typing import Generator
from typing import Sequence
@@ -26,7 +27,7 @@ def get_env_patch(env: str) -> PatchesT:
# $CONDA_PREFIX/Scripts and $CONDA_PREFIX. Whereas the latter only
# seems to be used for python.exe.
path: SubstitutionT = (os.path.join(env, 'bin'), os.pathsep, Var('PATH'))
- if os.name == 'nt': # pragma: no cover (platform specific)
+ if sys.platform == 'win32': # pragma: win32 cover
path = (env, os.pathsep, *path)
path = (os.path.join(env, 'Scripts'), os.pathsep, *path)
path = (os.path.join(env, 'Library', 'bin'), os.pathsep, *path)
diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py
index 976674e..3ef3436 100644
--- a/pre_commit/languages/python.py
+++ b/pre_commit/languages/python.py
@@ -48,7 +48,7 @@ def _read_pyvenv_cfg(filename: str) -> dict[str, str]:
def bin_dir(venv: str) -> str:
"""On windows there's a different directory for the virtualenv"""
- bin_part = 'Scripts' if os.name == 'nt' else 'bin'
+ bin_part = 'Scripts' if sys.platform == 'win32' else 'bin'
return os.path.join(venv, bin_part)
@@ -137,7 +137,7 @@ def norm_version(version: str) -> str | None:
elif _sys_executable_matches(version): # virtualenv defaults to our exe
return None
- if os.name == 'nt': # pragma: no cover (windows)
+ if sys.platform == 'win32': # pragma: no cover (windows)
version_exec = _find_by_py_launcher(version)
if version_exec:
return version_exec
diff --git a/pre_commit/languages/rust.py b/pre_commit/languages/rust.py
index af5f483..a1f4dbe 100644
--- a/pre_commit/languages/rust.py
+++ b/pre_commit/languages/rust.py
@@ -50,7 +50,6 @@ def _rust_toolchain(language_version: str) -> str:
def get_env_patch(target_dir: str, version: str) -> PatchesT:
return (
- ('CARGO_HOME', target_dir),
('PATH', (os.path.join(target_dir, 'bin'), os.pathsep, Var('PATH'))),
# Only set RUSTUP_TOOLCHAIN if we don't want use the system's default
# toolchain
diff --git a/pre_commit/main.py b/pre_commit/main.py
index 3915993..9615c5e 100644
--- a/pre_commit/main.py
+++ b/pre_commit/main.py
@@ -7,6 +7,7 @@ import sys
from typing import Sequence
import pre_commit.constants as C
+from pre_commit import clientlib
from pre_commit import git
from pre_commit.color import add_color_option
from pre_commit.commands.autoupdate import autoupdate
@@ -52,7 +53,7 @@ def _add_config_option(parser: argparse.ArgumentParser) -> None:
def _add_hook_type_option(parser: argparse.ArgumentParser) -> None:
parser.add_argument(
'-t', '--hook-type',
- choices=C.HOOK_TYPES, action='append', dest='hook_types',
+ choices=clientlib.HOOK_TYPES, action='append', dest='hook_types',
)
@@ -73,7 +74,10 @@ def _add_run_options(parser: argparse.ArgumentParser) -> None:
help='When hooks fail, run `git diff` directly afterward.',
)
parser.add_argument(
- '--hook-stage', choices=C.STAGES, default='commit',
+ '--hook-stage',
+ choices=clientlib.STAGES,
+ type=clientlib.transform_stage,
+ default='pre-commit',
help='The stage during which the hook is fired. One of %(choices)s',
)
parser.add_argument(
@@ -104,6 +108,17 @@ def _add_run_options(parser: argparse.ArgumentParser) -> None:
),
)
parser.add_argument(
+ '--pre-rebase-upstream', help=(
+ 'The upstream from which the series was forked.'
+ ),
+ )
+ parser.add_argument(
+ '--pre-rebase-branch', help=(
+ 'The branch being rebased, and is not set when '
+ 'rebasing the current branch.'
+ ),
+ )
+ parser.add_argument(
'--commit-msg-filename',
help='Filename to check when running during `commit-msg`',
)
diff --git a/pre_commit/util.py b/pre_commit/util.py
index ea0d4f5..4f8e835 100644
--- a/pre_commit/util.py
+++ b/pre_commit/util.py
@@ -119,7 +119,7 @@ def cmd_output(*cmd: str, **kwargs: Any) -> tuple[int, str, str | None]:
return returncode, stdout, stderr
-if os.name != 'nt': # pragma: win32 no cover
+if sys.platform != 'win32': # pragma: win32 no cover
from os import openpty
import termios