diff options
Diffstat (limited to 'testing/fixtures.py')
-rw-r--r-- | testing/fixtures.py | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/testing/fixtures.py b/testing/fixtures.py new file mode 100644 index 0000000..79a1160 --- /dev/null +++ b/testing/fixtures.py @@ -0,0 +1,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.yaml import yaml_dump +from pre_commit.yaml 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', '-c', 'init.defaultBranch=master', '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) |