mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
normalize slashes even earlier on windows for filenames
This commit is contained in:
parent
79359ed4e2
commit
5fb721f7a7
4 changed files with 30 additions and 15 deletions
|
|
@ -72,13 +72,7 @@ def filter_by_include_exclude(
|
||||||
|
|
||||||
|
|
||||||
class Classifier:
|
class Classifier:
|
||||||
def __init__(self, filenames: Sequence[str]) -> None:
|
def __init__(self, filenames: Collection[str]) -> None:
|
||||||
# on windows we normalize all filenames to use forward slashes
|
|
||||||
# this makes it easier to filter using the `files:` regex
|
|
||||||
# this also makes improperly quoted shell-based hooks work better
|
|
||||||
# see #1173
|
|
||||||
if os.altsep == '/' and os.sep == '\\':
|
|
||||||
filenames = [f.replace(os.sep, os.altsep) for f in filenames]
|
|
||||||
self.filenames = [f for f in filenames if os.path.lexists(f)]
|
self.filenames = [f for f in filenames if os.path.lexists(f)]
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
|
|
@ -105,6 +99,22 @@ class Classifier:
|
||||||
names = self.by_types(names, hook.types, hook.exclude_types)
|
names = self.by_types(names, hook.types, hook.exclude_types)
|
||||||
return tuple(names)
|
return tuple(names)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_config(
|
||||||
|
cls,
|
||||||
|
filenames: Collection[str],
|
||||||
|
include: str,
|
||||||
|
exclude: str,
|
||||||
|
) -> 'Classifier':
|
||||||
|
# on windows we normalize all filenames to use forward slashes
|
||||||
|
# this makes it easier to filter using the `files:` regex
|
||||||
|
# this also makes improperly quoted shell-based hooks work better
|
||||||
|
# see #1173
|
||||||
|
if os.altsep == '/' and os.sep == '\\':
|
||||||
|
filenames = [f.replace(os.sep, os.altsep) for f in filenames]
|
||||||
|
filenames = filter_by_include_exclude(filenames, include, exclude)
|
||||||
|
return Classifier(filenames)
|
||||||
|
|
||||||
|
|
||||||
def _get_skips(environ: EnvironT) -> Set[str]:
|
def _get_skips(environ: EnvironT) -> Set[str]:
|
||||||
skips = environ.get('SKIP', '')
|
skips = environ.get('SKIP', '')
|
||||||
|
|
@ -247,10 +257,9 @@ def _run_hooks(
|
||||||
"""Actually run the hooks."""
|
"""Actually run the hooks."""
|
||||||
skips = _get_skips(environ)
|
skips = _get_skips(environ)
|
||||||
cols = _compute_cols(hooks)
|
cols = _compute_cols(hooks)
|
||||||
filenames = filter_by_include_exclude(
|
classifier = Classifier.from_config(
|
||||||
_all_filenames(args), config['files'], config['exclude'],
|
_all_filenames(args), config['files'], config['exclude'],
|
||||||
)
|
)
|
||||||
classifier = Classifier(filenames)
|
|
||||||
retval = 0
|
retval = 0
|
||||||
for hook in hooks:
|
for hook in hooks:
|
||||||
retval |= _run_single_hook(
|
retval |= _run_single_hook(
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@ from pre_commit.store import Store
|
||||||
|
|
||||||
|
|
||||||
def check_all_hooks_match_files(config_file: str) -> int:
|
def check_all_hooks_match_files(config_file: str) -> int:
|
||||||
classifier = Classifier(git.get_all_files())
|
config = load_config(config_file)
|
||||||
|
classifier = Classifier.from_config(
|
||||||
|
git.get_all_files(), config['files'], config['exclude'],
|
||||||
|
)
|
||||||
retv = 0
|
retv = 0
|
||||||
|
|
||||||
for hook in all_hooks(load_config(config_file), Store()):
|
for hook in all_hooks(config, Store()):
|
||||||
if hook.always_run or hook.language == 'fail':
|
if hook.always_run or hook.language == 'fail':
|
||||||
continue
|
continue
|
||||||
elif not classifier.filenames_for_hook(hook):
|
elif not classifier.filenames_for_hook(hook):
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,14 @@ def exclude_matches_any(
|
||||||
|
|
||||||
def check_useless_excludes(config_file: str) -> int:
|
def check_useless_excludes(config_file: str) -> int:
|
||||||
config = load_config(config_file)
|
config = load_config(config_file)
|
||||||
classifier = Classifier(git.get_all_files())
|
filenames = git.get_all_files()
|
||||||
|
classifier = Classifier.from_config(
|
||||||
|
filenames, config['files'], config['exclude'],
|
||||||
|
)
|
||||||
retv = 0
|
retv = 0
|
||||||
|
|
||||||
exclude = config['exclude']
|
exclude = config['exclude']
|
||||||
if not exclude_matches_any(classifier.filenames, '', exclude):
|
if not exclude_matches_any(filenames, '', exclude):
|
||||||
print(
|
print(
|
||||||
f'The global exclude pattern {exclude!r} does not match any files',
|
f'The global exclude pattern {exclude!r} does not match any files',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -939,7 +939,7 @@ def test_classifier_normalizes_filenames_on_windows_to_forward_slashes(tmpdir):
|
||||||
tmpdir.join('a/b/c').ensure()
|
tmpdir.join('a/b/c').ensure()
|
||||||
with mock.patch.object(os, 'altsep', '/'):
|
with mock.patch.object(os, 'altsep', '/'):
|
||||||
with mock.patch.object(os, 'sep', '\\'):
|
with mock.patch.object(os, 'sep', '\\'):
|
||||||
classifier = Classifier((r'a\b\c',))
|
classifier = Classifier.from_config((r'a\b\c',), '', '^$')
|
||||||
assert classifier.filenames == ['a/b/c']
|
assert classifier.filenames == ['a/b/c']
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -947,7 +947,7 @@ def test_classifier_does_not_normalize_backslashes_non_windows(tmpdir):
|
||||||
with mock.patch.object(os.path, 'lexists', return_value=True):
|
with mock.patch.object(os.path, 'lexists', return_value=True):
|
||||||
with mock.patch.object(os, 'altsep', None):
|
with mock.patch.object(os, 'altsep', None):
|
||||||
with mock.patch.object(os, 'sep', '/'):
|
with mock.patch.object(os, 'sep', '/'):
|
||||||
classifier = Classifier((r'a/b\c',))
|
classifier = Classifier.from_config((r'a/b\c',), '', '^$')
|
||||||
assert classifier.filenames == [r'a/b\c']
|
assert classifier.filenames == [r'a/b\c']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue