Skip to content

Commit e69e3e0

Browse files
authored
Merge pull request #1494 from pre-commit/normalize_slashes_more
normalize slashes even earlier on windows for filenames
2 parents 79359ed + 5fb721f commit e69e3e0

File tree

4 files changed

+30
-15
lines changed

4 files changed

+30
-15
lines changed

pre_commit/commands/run.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,7 @@ def filter_by_include_exclude(
7272

7373

7474
class Classifier:
75-
def __init__(self, filenames: Sequence[str]) -> None:
76-
# on windows we normalize all filenames to use forward slashes
77-
# this makes it easier to filter using the `files:` regex
78-
# this also makes improperly quoted shell-based hooks work better
79-
# see #1173
80-
if os.altsep == '/' and os.sep == '\\':
81-
filenames = [f.replace(os.sep, os.altsep) for f in filenames]
75+
def __init__(self, filenames: Collection[str]) -> None:
8276
self.filenames = [f for f in filenames if os.path.lexists(f)]
8377

8478
@functools.lru_cache(maxsize=None)
@@ -105,6 +99,22 @@ def filenames_for_hook(self, hook: Hook) -> Tuple[str, ...]:
10599
names = self.by_types(names, hook.types, hook.exclude_types)
106100
return tuple(names)
107101

102+
@classmethod
103+
def from_config(
104+
cls,
105+
filenames: Collection[str],
106+
include: str,
107+
exclude: str,
108+
) -> 'Classifier':
109+
# on windows we normalize all filenames to use forward slashes
110+
# this makes it easier to filter using the `files:` regex
111+
# this also makes improperly quoted shell-based hooks work better
112+
# see #1173
113+
if os.altsep == '/' and os.sep == '\\':
114+
filenames = [f.replace(os.sep, os.altsep) for f in filenames]
115+
filenames = filter_by_include_exclude(filenames, include, exclude)
116+
return Classifier(filenames)
117+
108118

109119
def _get_skips(environ: EnvironT) -> Set[str]:
110120
skips = environ.get('SKIP', '')
@@ -247,10 +257,9 @@ def _run_hooks(
247257
"""Actually run the hooks."""
248258
skips = _get_skips(environ)
249259
cols = _compute_cols(hooks)
250-
filenames = filter_by_include_exclude(
260+
classifier = Classifier.from_config(
251261
_all_filenames(args), config['files'], config['exclude'],
252262
)
253-
classifier = Classifier(filenames)
254263
retval = 0
255264
for hook in hooks:
256265
retval |= _run_single_hook(

pre_commit/meta_hooks/check_hooks_apply.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111

1212

1313
def check_all_hooks_match_files(config_file: str) -> int:
14-
classifier = Classifier(git.get_all_files())
14+
config = load_config(config_file)
15+
classifier = Classifier.from_config(
16+
git.get_all_files(), config['files'], config['exclude'],
17+
)
1518
retv = 0
1619

17-
for hook in all_hooks(load_config(config_file), Store()):
20+
for hook in all_hooks(config, Store()):
1821
if hook.always_run or hook.language == 'fail':
1922
continue
2023
elif not classifier.filenames_for_hook(hook):

pre_commit/meta_hooks/check_useless_excludes.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ def exclude_matches_any(
2828

2929
def check_useless_excludes(config_file: str) -> int:
3030
config = load_config(config_file)
31-
classifier = Classifier(git.get_all_files())
31+
filenames = git.get_all_files()
32+
classifier = Classifier.from_config(
33+
filenames, config['files'], config['exclude'],
34+
)
3235
retv = 0
3336

3437
exclude = config['exclude']
35-
if not exclude_matches_any(classifier.filenames, '', exclude):
38+
if not exclude_matches_any(filenames, '', exclude):
3639
print(
3740
f'The global exclude pattern {exclude!r} does not match any files',
3841
)

tests/commands/run_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,15 +939,15 @@ def test_classifier_normalizes_filenames_on_windows_to_forward_slashes(tmpdir):
939939
tmpdir.join('a/b/c').ensure()
940940
with mock.patch.object(os, 'altsep', '/'):
941941
with mock.patch.object(os, 'sep', '\\'):
942-
classifier = Classifier((r'a\b\c',))
942+
classifier = Classifier.from_config((r'a\b\c',), '', '^$')
943943
assert classifier.filenames == ['a/b/c']
944944

945945

946946
def test_classifier_does_not_normalize_backslashes_non_windows(tmpdir):
947947
with mock.patch.object(os.path, 'lexists', return_value=True):
948948
with mock.patch.object(os, 'altsep', None):
949949
with mock.patch.object(os, 'sep', '/'):
950-
classifier = Classifier((r'a/b\c',))
950+
classifier = Classifier.from_config((r'a/b\c',), '', '^$')
951951
assert classifier.filenames == [r'a/b\c']
952952

953953

0 commit comments

Comments
 (0)