Skip to content

Commit 88686d2

Browse files
committed
Add Runner interface.
1 parent ae1d168 commit 88686d2

25 files changed

+284
-150
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
sha: 47b7ca44ed1fcaa83464ed00cef72049ae22c33d
1818
hooks:
1919
- id: validate_manifest
20-
files: /manifest.yaml
20+
files: '^manifest.yaml$'
2121
- id: validate_config
22-
files: /\.pre-commit-config.yaml
22+
files: '^\.pre-commit-config.yaml$'

manifest.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
- id: validate_manifest
32
name: Validate Pre-Commit Manifest
43
description: This validator validates a pre-commit hooks manifest file

pre_commit/clientlib/validate_config.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def validate_config_extra(config):
5757
)
5858

5959

60-
validate_config = get_validator(
60+
load_config = get_validator(
6161
C.CONFIG_FILE,
6262
CONFIG_JSON_SCHEMA,
6363
InvalidConfigError,
@@ -69,25 +69,28 @@ def validate_config_extra(config):
6969
def run(argv):
7070
parser = argparse.ArgumentParser()
7171
parser.add_argument(
72-
'filename',
73-
nargs='?', default=None,
74-
help='Config filename. Defaults to {0} at root of git repo'.format(
72+
'filenames',
73+
nargs='*', default=None,
74+
help='Config filenames. Defaults to {0} at root of git repo'.format(
7575
C.CONFIG_FILE,
7676
)
7777
)
7878
args = parser.parse_args(argv)
7979

80-
try:
81-
validate_config(args.filename)
82-
except InvalidConfigError as e:
83-
print(e.args[0])
84-
# If we have more than one exception argument print the stringified
85-
# version
86-
if len(e.args) > 1:
87-
print(str(e.args[1]))
88-
return 1
89-
90-
return 0
80+
filenames = args.filenames or [C.CONFIG_FILE]
81+
retval = 0
82+
83+
for filename in filenames:
84+
try:
85+
load_config(filename)
86+
except InvalidConfigError as e:
87+
print(e.args[0])
88+
# If we have more than one exception argument print the stringified
89+
# version
90+
if len(e.args) > 1:
91+
print(str(e.args[1]))
92+
retval = 1
93+
return retval
9194

9295

9396
if __name__ == '__main__':

pre_commit/clientlib/validate_manifest.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def additional_manifest_check(obj):
4646
)
4747

4848

49-
validate_manifest = get_validator(
49+
load_manifest = get_validator(
5050
C.MANIFEST_FILE,
5151
MANIFEST_JSON_SCHEMA,
5252
InvalidManifestError,
@@ -58,25 +58,28 @@ def additional_manifest_check(obj):
5858
def run(argv):
5959
parser = argparse.ArgumentParser()
6060
parser.add_argument(
61-
'filename',
62-
nargs='?', default=None,
63-
help='Manifest filename. Defaults to {0} at root of git repo'.format(
61+
'filenames',
62+
nargs='*', default=None,
63+
help='Manifest filenames. Defaults to {0} at root of git repo'.format(
6464
C.MANIFEST_FILE,
6565
)
6666
)
6767
args = parser.parse_args(argv)
6868

69-
try:
70-
validate_manifest(args.filename)
71-
except InvalidManifestError as e:
72-
print(e.args[0])
73-
# If we have more than one exception argument print the stringified
74-
# version
75-
if len(e.args) > 1:
76-
print(str(e.args[1]))
77-
return 1
78-
79-
return 0
69+
filenames = args.filenames or [C.MANIFEST_FILE]
70+
retval = 0
71+
72+
for filename in filenames:
73+
try:
74+
load_manifest(filename)
75+
except InvalidManifestError as e:
76+
print(e.args[0])
77+
# If we have more than one exception argument print the stringified
78+
# version
79+
if len(e.args) > 1:
80+
print(str(e.args[1]))
81+
retval = 1
82+
return retval
8083

8184

8285
if __name__ == '__main__':

pre_commit/repository.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from plumbum import local
44

55
import pre_commit.constants as C
6-
from pre_commit.clientlib.validate_manifest import validate_manifest
6+
from pre_commit.clientlib.validate_manifest import load_manifest
77
from pre_commit.hooks_workspace import in_hooks_workspace
88
from pre_commit.languages.all import languages
99
from pre_commit.ordereddict import OrderedDict
@@ -40,7 +40,7 @@ def manifest(self):
4040
with self.in_checkout():
4141
return dict(
4242
(hook['id'], hook)
43-
for hook in validate_manifest(C.MANIFEST_FILE)
43+
for hook in load_manifest(C.MANIFEST_FILE)
4444
)
4545

4646
@contextlib.contextmanager

pre_commit/run.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import sys
66

77
from pre_commit import git
8-
from pre_commit.clientlib.validate_config import validate_config
9-
from pre_commit.repository import Repository
8+
from pre_commit.runner import Runner
109
from pre_commit.util import entry
1110

1211

@@ -15,6 +14,8 @@
1514
NORMAL = '\033[0m'
1615
COLS = int(subprocess.Popen(['tput', 'cols'], stdout=subprocess.PIPE).communicate()[0])
1716

17+
PASS_FAIL_LENGTH = 6
18+
1819

1920
def _run_single_hook(repository, hook_id, run_all_the_things=False):
2021
repository.install()
@@ -26,6 +27,13 @@ def _run_single_hook(repository, hook_id, run_all_the_things=False):
2627

2728
hook = repository.hooks[hook_id]
2829

30+
# Print the hook and the dots first in case the hook takes hella long to
31+
# run.
32+
print '{0}{1}'.format(
33+
hook['name'],
34+
'.' * (COLS - len(hook['name']) - PASS_FAIL_LENGTH - 6),
35+
),
36+
2937
retcode, stdout, stderr = repository.run_hook(
3038
hook_id,
3139
map(os.path.abspath, get_filenames(hook['files'])),
@@ -43,13 +51,7 @@ def _run_single_hook(repository, hook_id, run_all_the_things=False):
4351
pass_fail = 'Passed'
4452

4553

46-
print '{0}{1}{2}{3}{4}'.format(
47-
hook['name'],
48-
'.' * (COLS - len(hook['name']) - len(pass_fail) - 6),
49-
color,
50-
pass_fail,
51-
NORMAL,
52-
)
54+
print '{0}{1}{2}'.format(color, pass_fail, NORMAL)
5355

5456
if output:
5557
print
@@ -63,9 +65,8 @@ def run_hooks(run_all_the_things=False):
6365
"""Actually run the hooks."""
6466
retval = 0
6567

66-
configs = validate_config([])
67-
for config in configs:
68-
repo = Repository(config)
68+
runner = Runner.create()
69+
for repo in runner.repositories:
6970
for hook_id in repo.hooks:
7071
retval |= _run_single_hook(
7172
repo,
@@ -76,10 +77,9 @@ def run_hooks(run_all_the_things=False):
7677
return retval
7778

7879

79-
def run_single_hook(hook_id, configs=None, run_all_the_things=False):
80-
configs = configs or validate_config([])
81-
for config in configs:
82-
repo = Repository(config)
80+
def run_single_hook(hook_id, run_all_the_things=False):
81+
runner = Runner.create()
82+
for repo in runner.repositories:
8383
if hook_id in repo.hooks:
8484
return _run_single_hook(
8585
repo,

pre_commit/runner.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
import os
3+
import os.path
4+
5+
import pre_commit.constants as C
6+
from pre_commit import git
7+
from pre_commit.clientlib.validate_config import load_config
8+
from pre_commit.repository import Repository
9+
from pre_commit.util import cached_property
10+
11+
12+
class Runner(object):
13+
"""A `Runner` represents the execution context of the hooks. Notably the
14+
repository under test.
15+
"""
16+
17+
def __init__(self, git_root):
18+
self.git_root = git_root
19+
20+
@classmethod
21+
def create(cls):
22+
"""Creates a PreCommitRunner by doing the following:
23+
- Finds the root of the current git repository
24+
- chdirs to that directory
25+
"""
26+
root = git.get_root()
27+
os.chdir(root)
28+
return cls(root)
29+
30+
@cached_property
31+
def hooks_workspace_path(self):
32+
return os.path.join(self.git_root, C.HOOKS_WORKSPACE)
33+
34+
@cached_property
35+
def config_file_path(self):
36+
return os.path.join(self.git_root, C.CONFIG_FILE)
37+
38+
@cached_property
39+
def repositories(self):
40+
"""Returns a tuple of the configured repositories."""
41+
config = load_config(self.config_file_path)
42+
return tuple(map(Repository, config))

testing/__init__.py

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
- repo: git@github.com:pre-commit/pre-commit-hooks
3+
sha: 76739902911688e8d7b13241409f9facc0e534e4
4+
hooks:
5+
- id: pyflakes
6+
files: '\.py$'
7+
- id: debug-statements
8+
files: '\.py$'
9+
- id: trailing-whitespace
10+
files: '\.(py|sh|yaml)$'
11+
- id: name-tests-test
12+
files: 'tests/.+\.py$'
13+
- id: end-of-file-fixer
14+
files: '\.(py|sh|yaml)$'
15+
16+
- repo: git@github.com:pre-commit/pre-commit
17+
sha: 47b7ca44ed1fcaa83464ed00cef72049ae22c33d
18+
hooks:
19+
- id: validate_manifest
20+
files: '^manifest.yaml$'
21+
- id: validate_config
22+
files: \.pre-commit-config.yaml

0 commit comments

Comments
 (0)