mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Refactor pre_commit.repository and factor out cached-property
This commit is contained in:
parent
7448e588ff
commit
c577ed92e7
14 changed files with 390 additions and 446 deletions
|
|
@ -1,8 +1,8 @@
|
|||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os.path
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
import six
|
||||
from aspy.yaml import ordered_dump
|
||||
|
|
@ -16,8 +16,8 @@ from pre_commit.clientlib import InvalidManifestError
|
|||
from pre_commit.clientlib import is_local_repo
|
||||
from pre_commit.clientlib import is_meta_repo
|
||||
from pre_commit.clientlib import load_config
|
||||
from pre_commit.clientlib import load_manifest
|
||||
from pre_commit.commands.migrate_config import migrate_config
|
||||
from pre_commit.repository import Repository
|
||||
from pre_commit.util import CalledProcessError
|
||||
from pre_commit.util import cmd_output
|
||||
|
||||
|
|
@ -52,24 +52,24 @@ def _update_repo(repo_config, store, tags_only):
|
|||
if rev == repo_config['rev']:
|
||||
return repo_config
|
||||
|
||||
# Construct a new config with the head rev
|
||||
new_config = OrderedDict(repo_config)
|
||||
new_config['rev'] = rev
|
||||
|
||||
try:
|
||||
new_hooks = Repository.create(new_config, store).manifest_hooks
|
||||
path = store.clone(repo_config['repo'], rev)
|
||||
manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
|
||||
except InvalidManifestError as e:
|
||||
raise RepositoryCannotBeUpdatedError(six.text_type(e))
|
||||
|
||||
# See if any of our hooks were deleted with the new commits
|
||||
hooks = {hook['id'] for hook in repo_config['hooks']}
|
||||
hooks_missing = hooks - set(new_hooks)
|
||||
hooks_missing = hooks - {hook['id'] for hook in manifest}
|
||||
if hooks_missing:
|
||||
raise RepositoryCannotBeUpdatedError(
|
||||
'Cannot update because the tip of master is missing these hooks:\n'
|
||||
'{}'.format(', '.join(sorted(hooks_missing))),
|
||||
)
|
||||
|
||||
# Construct a new config with the head rev
|
||||
new_config = repo_config.copy()
|
||||
new_config['rev'] = rev
|
||||
return new_config
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ from pre_commit import git
|
|||
from pre_commit import output
|
||||
from pre_commit.clientlib import load_config
|
||||
from pre_commit.languages import python
|
||||
from pre_commit.repository import repositories
|
||||
from pre_commit.repository import all_hooks
|
||||
from pre_commit.repository import install_hook_envs
|
||||
from pre_commit.util import cmd_output
|
||||
from pre_commit.util import make_executable
|
||||
from pre_commit.util import mkdirp
|
||||
|
|
@ -116,8 +117,7 @@ def install(
|
|||
|
||||
|
||||
def install_hooks(config_file, store):
|
||||
for repository in repositories(load_config(config_file), store):
|
||||
repository.require_installed()
|
||||
install_hook_envs(all_hooks(load_config(config_file), store), store)
|
||||
|
||||
|
||||
def uninstall(hook_type='pre-commit'):
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ from pre_commit import git
|
|||
from pre_commit import output
|
||||
from pre_commit.clientlib import load_config
|
||||
from pre_commit.output import get_hook_message
|
||||
from pre_commit.repository import repositories
|
||||
from pre_commit.repository import all_hooks
|
||||
from pre_commit.repository import install_hook_envs
|
||||
from pre_commit.staged_files_only import staged_files_only
|
||||
from pre_commit.util import cmd_output
|
||||
from pre_commit.util import memoize_by_cwd
|
||||
|
|
@ -32,9 +33,7 @@ def _get_skips(environ):
|
|||
|
||||
|
||||
def _hook_msg_start(hook, verbose):
|
||||
return '{}{}'.format(
|
||||
'[{}] '.format(hook['id']) if verbose else '', hook['name'],
|
||||
)
|
||||
return '{}{}'.format('[{}] '.format(hook.id) if verbose else '', hook.name)
|
||||
|
||||
|
||||
def _filter_by_include_exclude(filenames, include, exclude):
|
||||
|
|
@ -63,21 +62,21 @@ SKIPPED = 'Skipped'
|
|||
NO_FILES = '(no files to check)'
|
||||
|
||||
|
||||
def _run_single_hook(filenames, hook, repo, args, skips, cols):
|
||||
include, exclude = hook['files'], hook['exclude']
|
||||
def _run_single_hook(filenames, hook, args, skips, cols):
|
||||
include, exclude = hook.files, hook.exclude
|
||||
filenames = _filter_by_include_exclude(filenames, include, exclude)
|
||||
types, exclude_types = hook['types'], hook['exclude_types']
|
||||
types, exclude_types = hook.types, hook.exclude_types
|
||||
filenames = _filter_by_types(filenames, types, exclude_types)
|
||||
|
||||
if hook['language'] == 'pcre':
|
||||
if hook.language == 'pcre':
|
||||
logger.warning(
|
||||
'`{}` (from {}) uses the deprecated pcre language.\n'
|
||||
'The pcre language is scheduled for removal in pre-commit 2.x.\n'
|
||||
'The pygrep language is a more portable (and usually drop-in) '
|
||||
'replacement.'.format(hook['id'], repo.repo_config['repo']),
|
||||
'replacement.'.format(hook.id, hook.src),
|
||||
)
|
||||
|
||||
if hook['id'] in skips or hook['alias'] in skips:
|
||||
if hook.id in skips or hook.alias in skips:
|
||||
output.write(get_hook_message(
|
||||
_hook_msg_start(hook, args.verbose),
|
||||
end_msg=SKIPPED,
|
||||
|
|
@ -86,7 +85,7 @@ def _run_single_hook(filenames, hook, repo, args, skips, cols):
|
|||
cols=cols,
|
||||
))
|
||||
return 0
|
||||
elif not filenames and not hook['always_run']:
|
||||
elif not filenames and not hook.always_run:
|
||||
output.write(get_hook_message(
|
||||
_hook_msg_start(hook, args.verbose),
|
||||
postfix=NO_FILES,
|
||||
|
|
@ -107,8 +106,8 @@ def _run_single_hook(filenames, hook, repo, args, skips, cols):
|
|||
diff_before = cmd_output(
|
||||
'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,
|
||||
)
|
||||
retcode, stdout, stderr = repo.run_hook(
|
||||
hook, tuple(filenames) if hook['pass_filenames'] else (),
|
||||
retcode, stdout, stderr = hook.run(
|
||||
tuple(filenames) if hook.pass_filenames else (),
|
||||
)
|
||||
diff_after = cmd_output(
|
||||
'git', 'diff', '--no-ext-diff', retcode=None, encoding=None,
|
||||
|
|
@ -133,9 +132,9 @@ def _run_single_hook(filenames, hook, repo, args, skips, cols):
|
|||
|
||||
if (
|
||||
(stdout or stderr or file_modifications) and
|
||||
(retcode or args.verbose or hook['verbose'])
|
||||
(retcode or args.verbose or hook.verbose)
|
||||
):
|
||||
output.write_line('hookid: {}\n'.format(hook['id']))
|
||||
output.write_line('hookid: {}\n'.format(hook.id))
|
||||
|
||||
# Print a message if failing due to file modifications
|
||||
if file_modifications:
|
||||
|
|
@ -149,7 +148,7 @@ def _run_single_hook(filenames, hook, repo, args, skips, cols):
|
|||
for out in (stdout, stderr):
|
||||
assert type(out) is bytes, type(out)
|
||||
if out.strip():
|
||||
output.write_line(out.strip(), logfile_name=hook['log_file'])
|
||||
output.write_line(out.strip(), logfile_name=hook.log_file)
|
||||
output.write_line()
|
||||
|
||||
return retcode
|
||||
|
|
@ -189,15 +188,15 @@ def _all_filenames(args):
|
|||
return git.get_staged_files()
|
||||
|
||||
|
||||
def _run_hooks(config, repo_hooks, args, environ):
|
||||
def _run_hooks(config, hooks, args, environ):
|
||||
"""Actually run the hooks."""
|
||||
skips = _get_skips(environ)
|
||||
cols = _compute_cols([hook for _, hook in repo_hooks], args.verbose)
|
||||
cols = _compute_cols(hooks, args.verbose)
|
||||
filenames = _all_filenames(args)
|
||||
filenames = _filter_by_include_exclude(filenames, '', config['exclude'])
|
||||
retval = 0
|
||||
for repo, hook in repo_hooks:
|
||||
retval |= _run_single_hook(filenames, hook, repo, args, skips, cols)
|
||||
for hook in hooks:
|
||||
retval |= _run_single_hook(filenames, hook, args, skips, cols)
|
||||
if retval and config['fail_fast']:
|
||||
break
|
||||
if (
|
||||
|
|
@ -252,28 +251,18 @@ def run(config_file, store, args, environ=os.environ):
|
|||
ctx = staged_files_only(store.directory)
|
||||
|
||||
with ctx:
|
||||
repo_hooks = []
|
||||
config = load_config(config_file)
|
||||
for repo in repositories(config, store):
|
||||
for _, hook in repo.hooks:
|
||||
if (
|
||||
(
|
||||
not args.hook or
|
||||
hook['id'] == args.hook or
|
||||
hook['alias'] == args.hook
|
||||
) and
|
||||
(
|
||||
not hook['stages'] or
|
||||
args.hook_stage in hook['stages']
|
||||
)
|
||||
):
|
||||
repo_hooks.append((repo, hook))
|
||||
hooks = [
|
||||
hook
|
||||
for hook in all_hooks(config, store)
|
||||
if not args.hook or hook.id == args.hook or hook.alias == args.hook
|
||||
if not hook.stages or args.hook_stage in hook.stages
|
||||
]
|
||||
|
||||
if args.hook and not repo_hooks:
|
||||
if args.hook and not hooks:
|
||||
output.write_line('No hook with id `{}`'.format(args.hook))
|
||||
return 1
|
||||
|
||||
for repo in {repo for repo, _ in repo_hooks}:
|
||||
repo.require_installed()
|
||||
install_hook_envs(hooks, store)
|
||||
|
||||
return _run_hooks(config, repo_hooks, args, environ)
|
||||
return _run_hooks(config, hooks, args, environ)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue