forked from pre-commit/pre-commit-hooks
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
5 changed files
with
151 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import argparse | ||
import os.path | ||
from pathlib import Path | ||
from typing import Iterable, Iterator, Optional, Sequence, Set | ||
|
||
from pre_commit_hooks.util import added_files | ||
|
||
|
||
def lower_set(iterable: Iterable[str]) -> Set[str]: | ||
return {x.lower() for x in iterable} | ||
|
||
|
||
def parents(file: str) -> Iterator[str]: | ||
file = os.path.dirname(file) | ||
while file: | ||
yield file | ||
file = os.path.dirname(file) | ||
|
||
|
||
def directories_for(files: Set[str]) -> Set[str]: | ||
return {parent for file in files for parent in parents(file)} | ||
|
||
|
||
# https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file | ||
ILLEGAL_NAMES = { | ||
"CON", | ||
"PRN", | ||
"AUX", | ||
"NUL", | ||
*(f"COM{i}" for i in range(1, 10)), | ||
*(f"LPT{i}" for i in range(1, 10)), | ||
} | ||
|
||
|
||
def find_illegal_windows_names(filenames: Sequence[str]) -> int: | ||
relevant_files = set(filenames) | added_files() | ||
relevant_files |= directories_for(relevant_files) | ||
retv = 0 | ||
|
||
for filename in relevant_files: | ||
root = Path(filename) | ||
while root.suffix: | ||
root = root.with_suffix("") | ||
if root.name.lower() in lower_set(ILLEGAL_NAMES): | ||
print(f"Illegal name {filename}") | ||
retv = 1 | ||
|
||
return retv | ||
|
||
|
||
def main(argv: Optional[Sequence[str]] = None) -> int: | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"filenames", | ||
nargs="*", | ||
help="Filenames pre-commit believes are changed.", | ||
) | ||
|
||
args = parser.parse_args(argv) | ||
return find_illegal_windows_names(args.filenames) | ||
|
||
|
||
if __name__ == "__main__": | ||
exit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import sys | ||
|
||
import pytest | ||
|
||
from pre_commit_hooks.check_illegal_windows_names import ( | ||
find_illegal_windows_names, | ||
main, | ||
parents, | ||
) | ||
from pre_commit_hooks.util import cmd_output | ||
|
||
skip_win32 = pytest.mark.skipif( | ||
sys.platform == "win32", | ||
reason="case conflicts between directories and files", | ||
) | ||
|
||
|
||
def test_parents(): | ||
assert set(parents("a")) == set() | ||
assert set(parents("a/b")) == {"a"} | ||
assert set(parents("a/b/c")) == {"a/b", "a"} | ||
assert set(parents("a/b/c/d")) == {"a/b/c", "a/b", "a"} | ||
|
||
|
||
def test_nothing_added(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
assert find_illegal_windows_names(["f.py"]) == 0 | ||
|
||
|
||
def test_adding_something(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
temp_git_dir.join("f.py").write("print('hello world')") | ||
cmd_output("git", "add", "f.py") | ||
|
||
assert find_illegal_windows_names(["f.py"]) == 0 | ||
|
||
|
||
@skip_win32 # pragma: win32 no cover | ||
def test_adding_something_with_illegal_filename(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
temp_git_dir.join("CoM3.py").write("print('hello world')") | ||
cmd_output("git", "add", "CoM3.py") | ||
|
||
assert find_illegal_windows_names(["CoM3.py"]) == 1 | ||
|
||
|
||
@skip_win32 # pragma: win32 no cover | ||
def test_adding_files_with_illegal_directory(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
temp_git_dir.mkdir("lpt2").join("x").write("foo") | ||
cmd_output("git", "add", "-A") | ||
|
||
assert find_illegal_windows_names([]) == 1 | ||
|
||
|
||
@skip_win32 # pragma: win32 no cover | ||
def test_adding_files_with_illegal_deep_directories(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
temp_git_dir.mkdir("x").mkdir("y").join("pRn").write("foo") | ||
cmd_output("git", "add", "-A") | ||
|
||
assert find_illegal_windows_names([]) == 1 | ||
|
||
|
||
@skip_win32 # pragma: win32 no cover | ||
def test_integration(temp_git_dir): | ||
with temp_git_dir.as_cwd(): | ||
assert main(argv=[]) == 0 | ||
|
||
temp_git_dir.join("f.py").write("print('hello world')") | ||
cmd_output("git", "add", "f.py") | ||
|
||
assert main(argv=["f.py"]) == 0 | ||
|
||
temp_git_dir.join("CON.py").write("print('hello world')") | ||
cmd_output("git", "add", "CON.py") | ||
|
||
assert main(argv=["CON.py"]) == 1 |