mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-26 02:49:09 -06:00
Add pre-commit try-repo
`try-repo` is useful for: - Trying out a remote hook repository without needing to configure it. - Testing a hook repository while developing it.
This commit is contained in:
44
pre_commit/commands/try_repo.py
Normal file
44
pre_commit/commands/try_repo.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import collections
|
||||
import os.path
|
||||
|
||||
from aspy.yaml import ordered_dump
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import git
|
||||
from pre_commit import output
|
||||
from pre_commit.commands.run import run
|
||||
from pre_commit.manifest import Manifest
|
||||
from pre_commit.runner import Runner
|
||||
from pre_commit.store import Store
|
||||
from pre_commit.util import tmpdir
|
||||
|
||||
|
||||
def try_repo(args):
|
||||
ref = args.ref or git.head_sha(args.repo)
|
||||
|
||||
with tmpdir() as tempdir:
|
||||
if args.hook:
|
||||
hooks = [{'id': args.hook}]
|
||||
else:
|
||||
manifest = Manifest(Store(tempdir).clone(args.repo, ref))
|
||||
hooks = [{'id': hook_id} for hook_id in sorted(manifest.hooks)]
|
||||
|
||||
items = (('repo', args.repo), ('sha', ref), ('hooks', hooks))
|
||||
config = {'repos': [collections.OrderedDict(items)]}
|
||||
config_s = ordered_dump(config, **C.YAML_DUMP_KWARGS)
|
||||
|
||||
config_filename = os.path.join(tempdir, C.CONFIG_FILE)
|
||||
with open(config_filename, 'w') as cfg:
|
||||
cfg.write(config_s)
|
||||
|
||||
output.write_line('=' * 79)
|
||||
output.write_line('Using config:')
|
||||
output.write_line('=' * 79)
|
||||
output.write(config_s)
|
||||
output.write_line('=' * 79)
|
||||
|
||||
runner = Runner('.', config_filename, store_dir=tempdir)
|
||||
return run(runner, args)
|
||||
@@ -97,6 +97,11 @@ def get_changed_files(new, old):
|
||||
)[1])
|
||||
|
||||
|
||||
def head_sha(remote):
|
||||
_, out, _ = cmd_output('git', 'ls-remote', '--exit-code', remote, 'HEAD')
|
||||
return out.split()[0]
|
||||
|
||||
|
||||
def check_for_cygwin_mismatch():
|
||||
"""See https://github.com/pre-commit/pre-commit/issues/354"""
|
||||
if sys.platform in ('cygwin', 'win32'): # pragma: no cover (windows)
|
||||
|
||||
@@ -17,6 +17,7 @@ from pre_commit.commands.install_uninstall import uninstall
|
||||
from pre_commit.commands.migrate_config import migrate_config
|
||||
from pre_commit.commands.run import run
|
||||
from pre_commit.commands.sample_config import sample_config
|
||||
from pre_commit.commands.try_repo import try_repo
|
||||
from pre_commit.error_handler import error_handler
|
||||
from pre_commit.logging_handler import add_logging_handler
|
||||
from pre_commit.runner import Runner
|
||||
@@ -53,6 +54,41 @@ def _add_hook_type_option(parser):
|
||||
)
|
||||
|
||||
|
||||
def _add_run_options(parser):
|
||||
parser.add_argument('hook', nargs='?', help='A single hook-id to run')
|
||||
parser.add_argument('--verbose', '-v', action='store_true', default=False)
|
||||
parser.add_argument(
|
||||
'--origin', '-o',
|
||||
help="The origin branch's commit_id when using `git push`.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--source', '-s',
|
||||
help="The remote branch's commit_id when using `git push`.",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--commit-msg-filename',
|
||||
help='Filename to check when running during `commit-msg`',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--hook-stage', choices=('commit', 'push', 'commit-msg'),
|
||||
default='commit',
|
||||
help='The stage during which the hook is fired e.g. commit or push.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--show-diff-on-failure', action='store_true',
|
||||
help='When hooks fail, run `git diff` directly afterward.',
|
||||
)
|
||||
mutex_group = parser.add_mutually_exclusive_group(required=False)
|
||||
mutex_group.add_argument(
|
||||
'--all-files', '-a', action='store_true', default=False,
|
||||
help='Run on all the files in the repo.',
|
||||
)
|
||||
mutex_group.add_argument(
|
||||
'--files', nargs='*', default=[],
|
||||
help='Specific filenames to run hooks on.',
|
||||
)
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
argv = argv if argv is not None else sys.argv[1:]
|
||||
argv = [five.to_text(arg) for arg in argv]
|
||||
@@ -142,40 +178,7 @@ def main(argv=None):
|
||||
run_parser = subparsers.add_parser('run', help='Run hooks.')
|
||||
_add_color_option(run_parser)
|
||||
_add_config_option(run_parser)
|
||||
run_parser.add_argument('hook', nargs='?', help='A single hook-id to run')
|
||||
run_parser.add_argument(
|
||||
'--verbose', '-v', action='store_true', default=False,
|
||||
)
|
||||
run_parser.add_argument(
|
||||
'--origin', '-o',
|
||||
help="The origin branch's commit_id when using `git push`.",
|
||||
)
|
||||
run_parser.add_argument(
|
||||
'--source', '-s',
|
||||
help="The remote branch's commit_id when using `git push`.",
|
||||
)
|
||||
run_parser.add_argument(
|
||||
'--commit-msg-filename',
|
||||
help='Filename to check when running during `commit-msg`',
|
||||
)
|
||||
run_parser.add_argument(
|
||||
'--hook-stage', choices=('commit', 'push', 'commit-msg'),
|
||||
default='commit',
|
||||
help='The stage during which the hook is fired e.g. commit or push.',
|
||||
)
|
||||
run_parser.add_argument(
|
||||
'--show-diff-on-failure', action='store_true',
|
||||
help='When hooks fail, run `git diff` directly afterward.',
|
||||
)
|
||||
run_mutex_group = run_parser.add_mutually_exclusive_group(required=False)
|
||||
run_mutex_group.add_argument(
|
||||
'--all-files', '-a', action='store_true', default=False,
|
||||
help='Run on all the files in the repo.',
|
||||
)
|
||||
run_mutex_group.add_argument(
|
||||
'--files', nargs='*', default=[],
|
||||
help='Specific filenames to run hooks on.',
|
||||
)
|
||||
_add_run_options(run_parser)
|
||||
|
||||
sample_config_parser = subparsers.add_parser(
|
||||
'sample-config', help='Produce a sample {} file'.format(C.CONFIG_FILE),
|
||||
@@ -183,6 +186,24 @@ def main(argv=None):
|
||||
_add_color_option(sample_config_parser)
|
||||
_add_config_option(sample_config_parser)
|
||||
|
||||
try_repo_parser = subparsers.add_parser(
|
||||
'try-repo',
|
||||
help='Try the hooks in a repository, useful for developing new hooks.',
|
||||
)
|
||||
_add_color_option(try_repo_parser)
|
||||
_add_config_option(try_repo_parser)
|
||||
try_repo_parser.add_argument(
|
||||
'repo', help='Repository to source hooks from.',
|
||||
)
|
||||
try_repo_parser.add_argument(
|
||||
'--ref',
|
||||
help=(
|
||||
'Manually select a ref to run against, otherwise the `HEAD` '
|
||||
'revision will be used.'
|
||||
),
|
||||
)
|
||||
_add_run_options(try_repo_parser)
|
||||
|
||||
help = subparsers.add_parser(
|
||||
'help', help='Show help for a specific command.',
|
||||
)
|
||||
@@ -231,6 +252,8 @@ def main(argv=None):
|
||||
return run(runner, args)
|
||||
elif args.command == 'sample-config':
|
||||
return sample_config()
|
||||
elif args.command == 'try-repo':
|
||||
return try_repo(args)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
'Command {} not implemented.'.format(args.command),
|
||||
|
||||
@@ -14,9 +14,8 @@ logger = logging.getLogger('pre_commit')
|
||||
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, repo_path, repo_url):
|
||||
def __init__(self, repo_path):
|
||||
self.repo_path = repo_path
|
||||
self.repo_url = repo_url
|
||||
|
||||
@cached_property
|
||||
def manifest_contents(self):
|
||||
|
||||
@@ -146,7 +146,7 @@ class Repository(object):
|
||||
|
||||
@cached_property
|
||||
def manifest(self):
|
||||
return Manifest(self._repo_path, self.repo_config['repo'])
|
||||
return Manifest(self._repo_path)
|
||||
|
||||
@cached_property
|
||||
def hooks(self):
|
||||
|
||||
@@ -15,13 +15,14 @@ class Runner(object):
|
||||
repository under test.
|
||||
"""
|
||||
|
||||
def __init__(self, git_root, config_file):
|
||||
def __init__(self, git_root, config_file, store_dir=None):
|
||||
self.git_root = git_root
|
||||
self.config_file = config_file
|
||||
self._store_dir = store_dir
|
||||
|
||||
@classmethod
|
||||
def create(cls, config_file):
|
||||
"""Creates a PreCommitRunner by doing the following:
|
||||
"""Creates a Runner by doing the following:
|
||||
- Finds the root of the current git repository
|
||||
- chdir to that directory
|
||||
"""
|
||||
@@ -63,4 +64,4 @@ class Runner(object):
|
||||
|
||||
@cached_property
|
||||
def store(self):
|
||||
return Store()
|
||||
return Store(self._store_dir)
|
||||
|
||||
Reference in New Issue
Block a user