Add Runner interface.

This commit is contained in:
Anthony Sottile 2014-03-23 16:22:24 -07:00
parent ae1d1681b2
commit 88686d298f
25 changed files with 282 additions and 148 deletions

View file

@ -57,7 +57,7 @@ def validate_config_extra(config):
)
validate_config = get_validator(
load_config = get_validator(
C.CONFIG_FILE,
CONFIG_JSON_SCHEMA,
InvalidConfigError,
@ -69,25 +69,28 @@ validate_config = get_validator(
def run(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
'filename',
nargs='?', default=None,
help='Config filename. Defaults to {0} at root of git repo'.format(
'filenames',
nargs='*', default=None,
help='Config filenames. Defaults to {0} at root of git repo'.format(
C.CONFIG_FILE,
)
)
args = parser.parse_args(argv)
try:
validate_config(args.filename)
except InvalidConfigError as e:
print(e.args[0])
# If we have more than one exception argument print the stringified
# version
if len(e.args) > 1:
print(str(e.args[1]))
return 1
filenames = args.filenames or [C.CONFIG_FILE]
retval = 0
return 0
for filename in filenames:
try:
load_config(filename)
except InvalidConfigError as e:
print(e.args[0])
# If we have more than one exception argument print the stringified
# version
if len(e.args) > 1:
print(str(e.args[1]))
retval = 1
return retval
if __name__ == '__main__':

View file

@ -46,7 +46,7 @@ def additional_manifest_check(obj):
)
validate_manifest = get_validator(
load_manifest = get_validator(
C.MANIFEST_FILE,
MANIFEST_JSON_SCHEMA,
InvalidManifestError,
@ -58,25 +58,28 @@ validate_manifest = get_validator(
def run(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
'filename',
nargs='?', default=None,
help='Manifest filename. Defaults to {0} at root of git repo'.format(
'filenames',
nargs='*', default=None,
help='Manifest filenames. Defaults to {0} at root of git repo'.format(
C.MANIFEST_FILE,
)
)
args = parser.parse_args(argv)
try:
validate_manifest(args.filename)
except InvalidManifestError as e:
print(e.args[0])
# If we have more than one exception argument print the stringified
# version
if len(e.args) > 1:
print(str(e.args[1]))
return 1
filenames = args.filenames or [C.MANIFEST_FILE]
retval = 0
return 0
for filename in filenames:
try:
load_manifest(filename)
except InvalidManifestError as e:
print(e.args[0])
# If we have more than one exception argument print the stringified
# version
if len(e.args) > 1:
print(str(e.args[1]))
retval = 1
return retval
if __name__ == '__main__':

View file

@ -3,7 +3,7 @@ import contextlib
from plumbum import local
import pre_commit.constants as C
from pre_commit.clientlib.validate_manifest import validate_manifest
from pre_commit.clientlib.validate_manifest import load_manifest
from pre_commit.hooks_workspace import in_hooks_workspace
from pre_commit.languages.all import languages
from pre_commit.ordereddict import OrderedDict
@ -40,7 +40,7 @@ class Repository(object):
with self.in_checkout():
return dict(
(hook['id'], hook)
for hook in validate_manifest(C.MANIFEST_FILE)
for hook in load_manifest(C.MANIFEST_FILE)
)
@contextlib.contextmanager

View file

@ -5,8 +5,7 @@ import subprocess
import sys
from pre_commit import git
from pre_commit.clientlib.validate_config import validate_config
from pre_commit.repository import Repository
from pre_commit.runner import Runner
from pre_commit.util import entry
@ -15,6 +14,8 @@ GREEN = '\033[42m'
NORMAL = '\033[0m'
COLS = int(subprocess.Popen(['tput', 'cols'], stdout=subprocess.PIPE).communicate()[0])
PASS_FAIL_LENGTH = 6
def _run_single_hook(repository, hook_id, run_all_the_things=False):
repository.install()
@ -26,6 +27,13 @@ def _run_single_hook(repository, hook_id, run_all_the_things=False):
hook = repository.hooks[hook_id]
# Print the hook and the dots first in case the hook takes hella long to
# run.
print '{0}{1}'.format(
hook['name'],
'.' * (COLS - len(hook['name']) - PASS_FAIL_LENGTH - 6),
),
retcode, stdout, stderr = repository.run_hook(
hook_id,
map(os.path.abspath, get_filenames(hook['files'])),
@ -43,13 +51,7 @@ def _run_single_hook(repository, hook_id, run_all_the_things=False):
pass_fail = 'Passed'
print '{0}{1}{2}{3}{4}'.format(
hook['name'],
'.' * (COLS - len(hook['name']) - len(pass_fail) - 6),
color,
pass_fail,
NORMAL,
)
print '{0}{1}{2}'.format(color, pass_fail, NORMAL)
if output:
print
@ -63,9 +65,8 @@ def run_hooks(run_all_the_things=False):
"""Actually run the hooks."""
retval = 0
configs = validate_config([])
for config in configs:
repo = Repository(config)
runner = Runner.create()
for repo in runner.repositories:
for hook_id in repo.hooks:
retval |= _run_single_hook(
repo,
@ -76,10 +77,9 @@ def run_hooks(run_all_the_things=False):
return retval
def run_single_hook(hook_id, configs=None, run_all_the_things=False):
configs = configs or validate_config([])
for config in configs:
repo = Repository(config)
def run_single_hook(hook_id, run_all_the_things=False):
runner = Runner.create()
for repo in runner.repositories:
if hook_id in repo.hooks:
return _run_single_hook(
repo,

42
pre_commit/runner.py Normal file
View file

@ -0,0 +1,42 @@
import os
import os.path
import pre_commit.constants as C
from pre_commit import git
from pre_commit.clientlib.validate_config import load_config
from pre_commit.repository import Repository
from pre_commit.util import cached_property
class Runner(object):
"""A `Runner` represents the execution context of the hooks. Notably the
repository under test.
"""
def __init__(self, git_root):
self.git_root = git_root
@classmethod
def create(cls):
"""Creates a PreCommitRunner by doing the following:
- Finds the root of the current git repository
- chdirs to that directory
"""
root = git.get_root()
os.chdir(root)
return cls(root)
@cached_property
def hooks_workspace_path(self):
return os.path.join(self.git_root, C.HOOKS_WORKSPACE)
@cached_property
def config_file_path(self):
return os.path.join(self.git_root, C.CONFIG_FILE)
@cached_property
def repositories(self):
"""Returns a tuple of the configured repositories."""
config = load_config(self.config_file_path)
return tuple(map(Repository, config))