Skip to content

Commit a5259ab

Browse files
LCMLCM
authored andcommitted
Preparatory work & clean-up for #219
clientlib/validate_config.py: moving "sha" field requirement out of JSON schema commands/run.py: code simplification runner.py: made .config a cached_property
1 parent aec1c55 commit a5259ab

3 files changed

Lines changed: 45 additions & 34 deletions

File tree

‎pre_commit/clientlib/validate_config.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class InvalidConfigError(FatalError):
3737
}
3838
}
3939
},
40-
'required': ['repo', 'sha', 'hooks'],
40+
'required': ['repo', 'hooks'],
4141
}
4242
}
4343

@@ -53,6 +53,9 @@ def try_regex(repo, hook, value, field_name):
5353

5454
def validate_config_extra(config):
5555
for repo in config:
56+
if 'sha' not in repo:
57+
raise InvalidConfigError('Missing "sha" field'
58+
'for repository {0}'.format(repo['repo']))
5659
for hook in repo['hooks']:
5760
try_regex(repo, hook['id'], hook.get('files', ''), 'files')
5861
try_regex(repo, hook['id'], hook['exclude'], 'exclude')

‎pre_commit/commands/run.py‎

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
logger = logging.getLogger('pre_commit')
1919

2020

21+
class HookExecuter(object):
22+
def __init__(self, hook, invoker):
23+
self.hook = hook
24+
self._invoker = invoker
25+
26+
def invoke(self, filenames):
27+
return self._invoker(self.hook, filenames)
28+
29+
2130
def _get_skips(environ):
2231
skips = environ.get('SKIP', '')
2332
return set(skip.strip() for skip in skips.split(',') if skip.strip())
@@ -55,21 +64,25 @@ def get_changed_files(new, old):
5564
)[1].splitlines()
5665

5766

58-
def _run_single_hook(runner, repository, hook, args, write, skips=set()):
67+
def get_filenames(args, include_expr, exclude_expr):
5968
if args.origin and args.source:
60-
get_filenames = git.get_files_matching(
69+
getter = git.get_files_matching(
6170
lambda: get_changed_files(args.origin, args.source),
6271
)
6372
elif args.files:
64-
get_filenames = git.get_files_matching(lambda: args.files)
73+
getter = git.get_files_matching(lambda: args.files)
6574
elif args.all_files:
66-
get_filenames = git.get_all_files_matching
75+
getter = git.get_all_files_matching
6776
elif git.is_in_merge_conflict():
68-
get_filenames = git.get_conflicted_files_matching
77+
getter = git.get_conflicted_files_matching
6978
else:
70-
get_filenames = git.get_staged_files_matching
79+
getter = git.get_staged_files_matching
80+
return getter(include_expr, exclude_expr)
7181

72-
filenames = get_filenames(hook['files'], hook['exclude'])
82+
83+
def _run_single_hook(hook_executer, args, write, skips=frozenset()):
84+
hook = hook_executer.hook
85+
filenames = get_filenames(args, hook['files'], hook['exclude'])
7386
if hook['id'] in skips:
7487
_print_user_skipped(hook, write, args)
7588
return 0
@@ -82,7 +95,7 @@ def _run_single_hook(runner, repository, hook, args, write, skips=set()):
8295
write(get_hook_message(_hook_msg_start(hook, args.verbose), end_len=6))
8396
sys.stdout.flush()
8497

85-
retcode, stdout, stderr = repository.run_hook(hook, filenames)
98+
retcode, stdout, stderr = hook_executer.invoke(filenames)
8699

87100
if retcode != hook['expected_return_value']:
88101
retcode = 1
@@ -106,32 +119,19 @@ def _run_single_hook(runner, repository, hook, args, write, skips=set()):
106119
return retcode
107120

108121

109-
def _run_hooks(runner, args, write, environ):
122+
def _run_hooks(hook_executers, args, write, environ):
110123
"""Actually run the hooks."""
111-
retval = 0
112-
113124
skips = _get_skips(environ)
114-
115-
for repo in runner.repositories:
116-
for _, hook in repo.hooks:
117-
retval |= _run_single_hook(
118-
runner, repo, hook, args, write, skips=skips,
119-
)
120-
125+
retval = 0
126+
for hook_executer in hook_executers:
127+
retval |= _run_single_hook(hook_executer, args, write, skips)
121128
return retval
122129

123130

124-
def _run_hook(runner, args, write):
125-
hook_id = args.hook
131+
def get_hook_executers(runner):
126132
for repo in runner.repositories:
127-
for hook_id_in_repo, hook in repo.hooks:
128-
if hook_id == hook_id_in_repo:
129-
return _run_single_hook(
130-
runner, repo, hook, args, write=write,
131-
)
132-
else:
133-
write('No hook with id `{0}`\n'.format(hook_id))
134-
return 1
133+
for _, repo_hook in repo.hooks:
134+
yield HookExecuter(repo_hook, repo.run_hook)
135135

136136

137137
def _has_unmerged_paths(runner):
@@ -159,7 +159,11 @@ def run(runner, args, write=sys_stdout_write_wrapper, environ=os.environ):
159159
ctx = staged_files_only(runner.cmd_runner)
160160

161161
with ctx:
162+
hook_executers = list(get_hook_executers(runner))
162163
if args.hook:
163-
return _run_hook(runner, args, write=write)
164-
else:
165-
return _run_hooks(runner, args, write=write, environ=environ)
164+
hook_executers = [he for he in hook_executers
165+
if he.hook['id'] == args.hook]
166+
if not hook_executers:
167+
write('No hook with id `{0}`\n'.format(args.hook))
168+
return 1
169+
return _run_hooks(hook_executers, args, write, environ)

‎pre_commit/runner.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ def create(cls):
3434
def config_file_path(self):
3535
return os.path.join(self.git_root, C.CONFIG_FILE)
3636

37+
@cached_property
38+
def config(self):
39+
return load_config(self.config_file_path)
40+
3741
@cached_property
3842
def repositories(self):
3943
"""Returns a tuple of the configured repositories."""
40-
config = load_config(self.config_file_path)
41-
repositories = tuple(Repository.create(x, self.store) for x in config)
44+
repositories = tuple(Repository.create(hook, self.store)
45+
for hook in self.config)
4246
for repository in repositories:
4347
repository.require_installed()
4448
return repositories

0 commit comments

Comments
 (0)