Anthony Sottile | 8f61529 | 2022-01-15 19:24:05 -0500 | [diff] [blame] | 1 | from __future__ import annotations |
| 2 | |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 3 | import argparse |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 4 | import math |
| 5 | import os |
Alex Martani | 03a65ca | 2021-10-21 15:29:54 -0700 | [diff] [blame] | 6 | import subprocess |
Anthony Sottile | 030bfac | 2019-01-31 19:19:10 -0800 | [diff] [blame] | 7 | from typing import Sequence |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 8 | |
gkisel | c682b50 | 2015-01-07 14:07:32 -0800 | [diff] [blame] | 9 | from pre_commit_hooks.util import added_files |
Alex Martani | 03a65ca | 2021-10-21 15:29:54 -0700 | [diff] [blame] | 10 | from pre_commit_hooks.util import zsplit |
Anthony Sottile | 3f6f23d | 2015-12-25 09:25:14 -0800 | [diff] [blame] | 11 | |
| 12 | |
Anthony Sottile | 8f61529 | 2022-01-15 19:24:05 -0500 | [diff] [blame] | 13 | def filter_lfs_files(filenames: set[str]) -> None: # pragma: no cover (lfs) |
Alex Martani | 03a65ca | 2021-10-21 15:29:54 -0700 | [diff] [blame] | 14 | """Remove files tracked by git-lfs from the set.""" |
| 15 | if not filenames: |
| 16 | return |
Anthony Sottile | 3f6f23d | 2015-12-25 09:25:14 -0800 | [diff] [blame] | 17 | |
Alex Martani | 03a65ca | 2021-10-21 15:29:54 -0700 | [diff] [blame] | 18 | check_attr = subprocess.run( |
| 19 | ('git', 'check-attr', 'filter', '-z', '--stdin'), |
| 20 | stdout=subprocess.PIPE, |
| 21 | stderr=subprocess.DEVNULL, |
| 22 | encoding='utf-8', |
| 23 | check=True, |
| 24 | input='\0'.join(filenames), |
| 25 | ) |
| 26 | stdout = zsplit(check_attr.stdout) |
| 27 | for i in range(0, len(stdout), 3): |
| 28 | filename, filter_tag = stdout[i], stdout[i + 2] |
| 29 | if filter_tag == 'lfs': |
| 30 | filenames.remove(filename) |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 31 | |
| 32 | |
Marcus Shawcroft | 012bb06 | 2020-09-16 06:26:11 +0100 | [diff] [blame] | 33 | def find_large_added_files( |
| 34 | filenames: Sequence[str], |
| 35 | maxkb: int, |
| 36 | *, |
| 37 | enforce_all: bool = False, |
| 38 | ) -> int: |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 39 | # Find all added files that are also in the list of files pre-commit tells |
| 40 | # us about |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 41 | retv = 0 |
Alex Martani | 03a65ca | 2021-10-21 15:29:54 -0700 | [diff] [blame] | 42 | filenames_filtered = set(filenames) |
| 43 | filter_lfs_files(filenames_filtered) |
| 44 | |
Marcus Shawcroft | 012bb06 | 2020-09-16 06:26:11 +0100 | [diff] [blame] | 45 | if not enforce_all: |
| 46 | filenames_filtered &= added_files() |
| 47 | |
| 48 | for filename in filenames_filtered: |
Miroslav Šedivý | 2e4efef | 2023-09-21 19:54:38 +0200 | [diff] [blame] | 49 | kb = math.ceil(os.stat(filename).st_size / 1024) |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 50 | if kb > maxkb: |
Anthony Sottile | f5c42a0 | 2020-02-05 11:10:42 -0800 | [diff] [blame] | 51 | print(f'{filename} ({kb} KB) exceeds {maxkb} KB.') |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 52 | retv = 1 |
| 53 | |
| 54 | return retv |
| 55 | |
| 56 | |
Anthony Sottile | 8f61529 | 2022-01-15 19:24:05 -0500 | [diff] [blame] | 57 | def main(argv: Sequence[str] | None = None) -> int: |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 58 | parser = argparse.ArgumentParser() |
| 59 | parser.add_argument( |
| 60 | 'filenames', nargs='*', |
Anthony Sottile | 2a902e0 | 2017-07-12 18:35:24 -0700 | [diff] [blame] | 61 | help='Filenames pre-commit believes are changed.', |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 62 | ) |
| 63 | parser.add_argument( |
Marcus Shawcroft | 012bb06 | 2020-09-16 06:26:11 +0100 | [diff] [blame] | 64 | '--enforce-all', action='store_true', |
| 65 | help='Enforce all files are checked, not just staged files.', |
| 66 | ) |
| 67 | parser.add_argument( |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 68 | '--maxkb', type=int, default=500, |
Janosh Riebesell | 05a5297 | 2021-10-23 12:11:03 +0100 | [diff] [blame] | 69 | help='Maximum allowable KB for added files', |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 70 | ) |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 71 | args = parser.parse_args(argv) |
Marcus Shawcroft | 012bb06 | 2020-09-16 06:26:11 +0100 | [diff] [blame] | 72 | |
| 73 | return find_large_added_files( |
| 74 | args.filenames, |
| 75 | args.maxkb, |
| 76 | enforce_all=args.enforce_all, |
| 77 | ) |
Anthony Sottile | e0a6e66 | 2014-12-31 12:21:21 -0800 | [diff] [blame] | 78 | |
| 79 | |
| 80 | if __name__ == '__main__': |
Anthony Sottile | 39ab2ed | 2021-10-23 13:23:50 -0400 | [diff] [blame] | 81 | raise SystemExit(main()) |