Skip to content

Commit

Permalink
Merge pull request #1494 from pre-commit/normalize_slashes_more
Browse files Browse the repository at this point in the history
normalize slashes even earlier on windows for filenames
  • Loading branch information
asottile committed Jun 8, 2020
2 parents 79359ed + 5fb721f commit e69e3e0
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 15 deletions.
27 changes: 18 additions & 9 deletions pre_commit/commands/run.py
Expand Up @@ -72,13 +72,7 @@ def filter_by_include_exclude(


class Classifier:
def __init__(self, filenames: Sequence[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]
def __init__(self, filenames: Collection[str]) -> None:
self.filenames = [f for f in filenames if os.path.lexists(f)]

@functools.lru_cache(maxsize=None)
Expand All @@ -105,6 +99,22 @@ def filenames_for_hook(self, hook: Hook) -> Tuple[str, ...]:
names = self.by_types(names, hook.types, hook.exclude_types)
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]:
skips = environ.get('SKIP', '')
Expand Down Expand Up @@ -247,10 +257,9 @@ def _run_hooks(
"""Actually run the hooks."""
skips = _get_skips(environ)
cols = _compute_cols(hooks)
filenames = filter_by_include_exclude(
classifier = Classifier.from_config(
_all_filenames(args), config['files'], config['exclude'],
)
classifier = Classifier(filenames)
retval = 0
for hook in hooks:
retval |= _run_single_hook(
Expand Down
7 changes: 5 additions & 2 deletions pre_commit/meta_hooks/check_hooks_apply.py
Expand Up @@ -11,10 +11,13 @@


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

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':
continue
elif not classifier.filenames_for_hook(hook):
Expand Down
7 changes: 5 additions & 2 deletions pre_commit/meta_hooks/check_useless_excludes.py
Expand Up @@ -28,11 +28,14 @@ def exclude_matches_any(

def check_useless_excludes(config_file: str) -> int:
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

exclude = config['exclude']
if not exclude_matches_any(classifier.filenames, '', exclude):
if not exclude_matches_any(filenames, '', exclude):
print(
f'The global exclude pattern {exclude!r} does not match any files',
)
Expand Down
4 changes: 2 additions & 2 deletions tests/commands/run_test.py
Expand Up @@ -939,15 +939,15 @@ def test_classifier_normalizes_filenames_on_windows_to_forward_slashes(tmpdir):
tmpdir.join('a/b/c').ensure()
with mock.patch.object(os, 'altsep', '/'):
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']


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, 'altsep', None):
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']


Expand Down

0 comments on commit e69e3e0

Please sign in to comment.