1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
from __future__ import annotations
import contextlib
import os.path
import shutil
from cfgv import apply_defaults
from cfgv import validate
import pre_commit.constants as C
from pre_commit import git
from pre_commit.clientlib import CONFIG_SCHEMA
from pre_commit.clientlib import load_manifest
from pre_commit.util import cmd_output
from pre_commit.util import yaml_dump
from pre_commit.util import yaml_load
from testing.util import get_resource_path
from testing.util import git_commit
def copy_tree_to_path(src_dir, dest_dir):
"""Copies all of the things inside src_dir to an already existing dest_dir.
This looks eerily similar to shutil.copytree, but copytree has no option
for not creating dest_dir.
"""
names = os.listdir(src_dir)
for name in names:
srcname = os.path.join(src_dir, name)
destname = os.path.join(dest_dir, name)
if os.path.isdir(srcname):
shutil.copytree(srcname, destname)
else:
shutil.copy(srcname, destname)
def git_dir(tempdir_factory):
path = tempdir_factory.get()
cmd_output('git', 'init', path)
return path
def make_repo(tempdir_factory, repo_source):
path = git_dir(tempdir_factory)
copy_tree_to_path(get_resource_path(repo_source), path)
cmd_output('git', 'add', '.', cwd=path)
git_commit(msg=make_repo.__name__, cwd=path)
return path
@contextlib.contextmanager
def modify_manifest(path, commit=True):
"""Modify the manifest yielded by this context to write to
.pre-commit-hooks.yaml.
"""
manifest_path = os.path.join(path, C.MANIFEST_FILE)
with open(manifest_path) as f:
manifest = yaml_load(f.read())
yield manifest
with open(manifest_path, 'w') as manifest_file:
manifest_file.write(yaml_dump(manifest))
if commit:
git_commit(msg=modify_manifest.__name__, cwd=path)
@contextlib.contextmanager
def modify_config(path='.', commit=True):
"""Modify the config yielded by this context to write to
.pre-commit-config.yaml
"""
config_path = os.path.join(path, C.CONFIG_FILE)
with open(config_path) as f:
config = yaml_load(f.read())
yield config
with open(config_path, 'w', encoding='UTF-8') as config_file:
config_file.write(yaml_dump(config))
if commit:
git_commit(msg=modify_config.__name__, cwd=path)
def sample_local_config():
return {
'repo': 'local',
'hooks': [{
'id': 'do_not_commit',
'name': 'Block if "DO NOT COMMIT" is found',
'entry': 'DO NOT COMMIT',
'language': 'pygrep',
}],
}
def sample_meta_config():
return {'repo': 'meta', 'hooks': [{'id': 'check-useless-excludes'}]}
def make_config_from_repo(repo_path, rev=None, hooks=None, check=True):
manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
config = {
'repo': f'file://{repo_path}',
'rev': rev or git.head_rev(repo_path),
'hooks': hooks or [{'id': hook['id']} for hook in manifest],
}
if check:
wrapped = validate({'repos': [config]}, CONFIG_SCHEMA)
wrapped = apply_defaults(wrapped, CONFIG_SCHEMA)
config, = wrapped['repos']
return config
else:
return config
def read_config(directory, config_file=C.CONFIG_FILE):
config_path = os.path.join(directory, config_file)
with open(config_path) as f:
config = yaml_load(f.read())
return config
def write_config(directory, config, config_file=C.CONFIG_FILE):
if type(config) is not list and 'repos' not in config:
assert isinstance(config, dict), config
config = {'repos': [config]}
with open(os.path.join(directory, config_file), 'w') as outfile:
outfile.write(yaml_dump(config))
def add_config_to_repo(git_path, config, config_file=C.CONFIG_FILE):
write_config(git_path, config, config_file=config_file)
cmd_output('git', 'add', config_file, cwd=git_path)
git_commit(msg=add_config_to_repo.__name__, cwd=git_path)
return git_path
def remove_config_from_repo(git_path, config_file=C.CONFIG_FILE):
cmd_output('git', 'rm', config_file, cwd=git_path)
git_commit(msg=remove_config_from_repo.__name__, cwd=git_path)
return git_path
def make_consuming_repo(tempdir_factory, repo_source):
path = make_repo(tempdir_factory, repo_source)
config = make_config_from_repo(path)
git_path = git_dir(tempdir_factory)
return add_config_to_repo(git_path, config)
|