From 9e7cd9f13abb29ff8458407b905d522548eaf5c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Fri, 8 Jan 2021 17:27:16 +0200 Subject: [PATCH] Refactor check_executables_have_shebangs for git ls-files reuse --- .../check_executables_have_shebangs.py | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/pre_commit_hooks/check_executables_have_shebangs.py b/pre_commit_hooks/check_executables_have_shebangs.py index 19f7ed2..e271c66 100644 --- a/pre_commit_hooks/check_executables_have_shebangs.py +++ b/pre_commit_hooks/check_executables_have_shebangs.py @@ -2,7 +2,9 @@ import argparse import shlex import sys +from typing import Generator from typing import List +from typing import NamedTuple from typing import Optional from typing import Sequence from typing import Set @@ -19,29 +21,38 @@ def check_executables(paths: List[str]) -> int: else: # pragma: win32 no cover retv = 0 for path in paths: - if not _check_has_shebang(path): + if not has_shebang(path): _message(path) retv = 1 return retv -def _check_git_filemode(paths: Sequence[str]) -> int: - outs = cmd_output('git', 'ls-files', '-z', '--stage', '--', *paths) - seen: Set[str] = set() - for out in zsplit(outs): - metadata, path = out.split('\t') - tagmode = metadata.split(' ', 1)[0] +class GitLsFile(NamedTuple): + mode: str + filename: str - is_executable = any(b in EXECUTABLE_VALUES for b in tagmode[-3:]) - if is_executable and not _check_has_shebang(path): - _message(path) - seen.add(path) + +def git_ls_files(paths: Sequence[str]) -> Generator[GitLsFile, None, None]: + outs = cmd_output('git', 'ls-files', '-z', '--stage', '--', *paths) + for out in zsplit(outs): + metadata, filename = out.split('\t') + mode, _, _ = metadata.split() + yield GitLsFile(mode, filename) + + +def _check_git_filemode(paths: Sequence[str]) -> int: + seen: Set[str] = set() + for ls_file in git_ls_files(paths): + is_executable = any(b in EXECUTABLE_VALUES for b in ls_file.mode[-3:]) + if is_executable and not has_shebang(ls_file.filename): + _message(ls_file.filename) + seen.add(ls_file.filename) return int(bool(seen)) -def _check_has_shebang(path: str) -> int: +def has_shebang(path: str) -> int: with open(path, 'rb') as f: first_bytes = f.read(2)