예제 #1
0
def validate_manifest(filenames: list[str]) -> int:
    ret = 0

    for filename in filenames:
        try:
            clientlib.load_manifest(filename)
        except clientlib.InvalidManifestError as e:
            print(e)
            ret = 1

    return ret
예제 #2
0
파일: gc.py 프로젝트: pre-commit/pre-commit
def _mark_used_repos(store, all_repos, unused_repos, repo):
    if repo['repo'] == META:
        return
    elif repo['repo'] == LOCAL:
        for hook in repo['hooks']:
            deps = hook.get('additional_dependencies')
            unused_repos.discard((
                store.db_repo_name(repo['repo'], deps), C.LOCAL_REPO_VERSION,
            ))
    else:
        key = (repo['repo'], repo['rev'])
        path = all_repos.get(key)
        # can't inspect manifest if it isn't cloned
        if path is None:
            return

        try:
            manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
        except InvalidManifestError:
            return
        else:
            unused_repos.discard(key)
            by_id = {hook['id']: hook for hook in manifest}

        for hook in repo['hooks']:
            if hook['id'] not in by_id:
                continue

            deps = hook.get(
                'additional_dependencies',
                by_id[hook['id']]['additional_dependencies'],
            )
            unused_repos.discard((
                store.db_repo_name(repo['repo'], deps), repo['rev'],
            ))
예제 #3
0
def try_repo(args):
    with tmpdir() as tempdir:
        repo, ref = _repo_ref(tempdir, args.repo, args.ref)

        store = Store(tempdir)
        if args.hook:
            hooks = [{'id': args.hook}]
        else:
            repo_path = store.clone(repo, ref)
            manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
            manifest = sorted(manifest, key=lambda hook: hook['id'])
            hooks = [{'id': hook['id']} for hook in manifest]

        items = (('repo', repo), ('rev', 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)

        return run(config_filename, store, args)
예제 #4
0
def make_config_from_repo(
    repo_path,
    sha=None,
    hooks=None,
    check=True,
    legacy=False,
):
    filename = C.MANIFEST_FILE_LEGACY if legacy else C.MANIFEST_FILE
    manifest = load_manifest(os.path.join(repo_path, filename))
    config = OrderedDict((
        ('repo', repo_path),
        ('sha', sha or get_head_sha(repo_path)),
        (
            'hooks',
            hooks
            or [OrderedDict((('id', hook['id']), )) for hook in manifest],
        ),
    ))

    if check:
        wrapped = validate([config], CONFIG_SCHEMA)
        config, = apply_defaults(wrapped, CONFIG_SCHEMA)
        return config
    else:
        return config
예제 #5
0
def try_repo(args: argparse.Namespace) -> int:
    with tmpdir() as tempdir:
        repo, ref = _repo_ref(tempdir, args.repo, args.ref)

        store = Store(tempdir)
        if args.hook:
            hooks = [{"id": args.hook}]
        else:
            repo_path = store.clone(repo, ref)
            manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
            manifest = sorted(manifest, key=lambda hook: hook["id"])
            hooks = [{"id": hook["id"]} for hook in manifest]

        config = {"repos": [{"repo": repo, "rev": ref, "hooks": hooks}]}
        config_s = yaml_dump(config)

        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)

        return run(config_filename, store, args)
예제 #6
0
def _cloned_repository_hooks(
    repo_config: Dict[str, Any],
    store: Store,
    root_config: Dict[str, Any],
) -> Tuple[Hook, ...]:
    repo, rev = repo_config['repo'], repo_config['rev']
    manifest_path = os.path.join(store.clone(repo, rev), C.MANIFEST_FILE)
    by_id = {hook['id']: hook for hook in load_manifest(manifest_path)}

    for hook in repo_config['hooks']:
        if hook['id'] not in by_id:
            logger.error(
                f'`{hook["id"]}` is not present in repository {repo}.  '
                f'Typo? Perhaps it is introduced in a newer version?  '
                f'Often `pre-commit autoupdate` fixes this.', )
            exit(1)

    hook_dcts = [
        _hook(by_id[hook['id']], hook, root_config=root_config)
        for hook in repo_config['hooks']
    ]
    return tuple(
        Hook.create(
            repo_config['repo'],
            Prefix(store.clone(repo, rev, hook['additional_dependencies'])),
            hook,
        ) for hook in hook_dcts)
예제 #7
0
def try_repo(args):
    ref = args.ref or git.head_rev(args.repo)

    with tmpdir() as tempdir:
        if args.hook:
            hooks = [{'id': args.hook}]
        else:
            repo_path = Store(tempdir).clone(args.repo, ref)
            manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
            manifest = sorted(manifest, key=lambda hook: hook['id'])
            hooks = [{'id': hook['id']} for hook in manifest]

        items = (('repo', args.repo), ('rev', 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)
예제 #8
0
def try_repo(args: argparse.Namespace) -> int:
    with tmpdir() as tempdir:
        repo, ref = _repo_ref(tempdir, args.repo, args.ref)

        store = Store(tempdir)
        if args.hook:
            hooks = [{'id': args.hook}]
        else:
            repo_path = store.clone(repo, ref)
            manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
            manifest = sorted(manifest, key=lambda hook: hook['id'])
            hooks = [{'id': hook['id']} for hook in manifest]

        config = {'repos': [{'repo': repo, 'rev': ref, 'hooks': hooks}]}
        config_s = yaml_dump(config)

        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)

        return run(config_filename, store, args)
예제 #9
0
def _cloned_repository_hooks(repo_config, store, root_config):
    repo, rev = repo_config['repo'], repo_config['rev']
    manifest_path = os.path.join(store.clone(repo, rev), C.MANIFEST_FILE)
    by_id = {hook['id']: hook for hook in load_manifest(manifest_path)}

    for hook in repo_config['hooks']:
        if hook['id'] not in by_id:
            logger.error(
                '`{}` is not present in repository {}.  '
                'Typo? Perhaps it is introduced in a newer version?  '
                'Often `pre-commit autoupdate` fixes this.'
                .format(hook['id'], repo),
            )
            exit(1)

    hook_dcts = [
        _hook(by_id[hook['id']], hook, root_config=root_config)
        for hook in repo_config['hooks']
    ]
    return tuple(
        Hook.create(
            repo_config['repo'],
            Prefix(store.clone(repo, rev, hook['additional_dependencies'])),
            hook,
        )
        for hook in hook_dcts
    )
예제 #10
0
def local_python_config():
    # Make a "local" hooks repo that just installs our other hooks repo
    repo_path = get_resource_path('python_hooks_repo')
    manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
    hooks = [
        dict(hook, additional_dependencies=[repo_path]) for hook in manifest
    ]
    return {'repo': 'local', 'hooks': hooks}
예제 #11
0
 def manifest_contents(self):
     default_path = os.path.join(self.repo_path, C.MANIFEST_FILE)
     legacy_path = os.path.join(self.repo_path, C.MANIFEST_FILE_LEGACY)
     if os.path.exists(legacy_path) and not os.path.exists(default_path):
         logger.warning(
             '{} uses legacy {} to provide hooks.\n'
             'In newer versions, this file is called {}\n'
             'This will work in this version of pre-commit but will be '
             'removed at a later time.\n'
             'If `pre-commit autoupdate` does not silence this warning '
             'consider making an issue / pull request.'.format(
                 self.repo_url, C.MANIFEST_FILE_LEGACY, C.MANIFEST_FILE,
             ),
         )
         return load_manifest(legacy_path)
     else:
         return load_manifest(default_path)
예제 #12
0
 def manifest_contents(self):
     default_path = os.path.join(self.repo_path, C.MANIFEST_FILE)
     legacy_path = os.path.join(self.repo_path, C.MANIFEST_FILE_LEGACY)
     if os.path.exists(legacy_path) and not os.path.exists(default_path):
         logger.warning(
             '{} uses legacy {} to provide hooks.\n'
             'In newer versions, this file is called {}\n'
             'This will work in this version of pre-commit but will be '
             'removed at a later time.\n'
             'If `pre-commit autoupdate` does not silence this warning '
             'consider making an issue / pull request.'.format(
                 self.repo_url, C.MANIFEST_FILE_LEGACY, C.MANIFEST_FILE,
             )
         )
         return load_manifest(legacy_path)
     else:
         return load_manifest(default_path)
예제 #13
0
def test_local_python_repo(store):
    # Make a "local" hooks repo that just installs our other hooks repo
    repo_path = get_resource_path('python_hooks_repo')
    manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
    hooks = [
        dict(hook, additional_dependencies=[repo_path]) for hook in manifest
    ]
    config = {'repo': 'local', 'hooks': hooks}
    repo = Repository.create(config, store)
    (_, hook), = repo.hooks
    ret = repo.run_hook(hook, ('filename',))
    assert ret[0] == 0
    assert ret[1].replace(b'\r\n', b'\n') == b"['filename']\nHello World\n"
예제 #14
0
def test_local_python_repo(store):
    # Make a "local" hooks repo that just installs our other hooks repo
    repo_path = get_resource_path('python_hooks_repo')
    manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
    hooks = [
        dict(hook, additional_dependencies=[repo_path]) for hook in manifest
    ]
    config = {'repo': 'local', 'hooks': hooks}
    repo = Repository.create(config, store)
    (_, hook), = repo.hooks
    ret = repo.run_hook(hook, ('filename', ))
    assert ret[0] == 0
    assert _norm_out(ret[1]) == b"['filename']\nHello World\n"
예제 #15
0
def _check_hooks_still_exist_at_rev(repo_config, info, store):
    try:
        path = store.clone(repo_config['repo'], info.rev)
        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
    except InvalidManifestError as e:
        raise RepositoryCannotBeUpdatedError(six.text_type(e))

    # See if any of our hooks were deleted with the new commits
    hooks = {hook['id'] for hook in repo_config['hooks']}
    hooks_missing = hooks - {hook['id'] for hook in manifest}
    if hooks_missing:
        raise RepositoryCannotBeUpdatedError(
            'Cannot update because the tip of master is missing these hooks:\n'
            '{}'.format(', '.join(sorted(hooks_missing))), )
예제 #16
0
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': 'file://{}'.format(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
예제 #17
0
def get_manifest(repo_path: str) -> Tuple[bool, str, List[Dict[str, Any]]]:
    print(f'*** {repo_path}')
    with tempfile.TemporaryDirectory() as directory:
        repo_dir = os.path.join(directory, 'repo')
        cmd = ('git', 'clone', '--depth', '1', '-q', repo_path, repo_dir)
        subprocess.check_call(cmd)
        manifest_path = os.path.join(repo_dir, '.pre-commit-hooks.yaml')
        # Validate the manifest just to make sure it's ok.
        manifest = load_manifest(manifest_path)
        # hooks should not set debugging `verbose: true` flag
        for hook in manifest:
            if hook['verbose']:
                print(f'{repo_path} ({hook["id"]}) sets `verbose: true`')
                return False, repo_path, []

        with open(manifest_path) as f:
            return True, repo_path, fast_load(f)
예제 #18
0
def _update_repo(repo_config, store, tags_only):
    """Updates a repository to the tip of `master`.  If the repository cannot
    be updated because a hook that is configured does not exist in `master`,
    this raises a RepositoryCannotBeUpdatedError

    Args:
        repo_config - A config for a repository
    """
    with tmpdir() as repo_path:
        git.init_repo(repo_path, repo_config['repo'])
        cmd_output('git', 'fetch', 'origin', 'HEAD', '--tags', cwd=repo_path)

        tag_cmd = ('git', 'describe', 'FETCH_HEAD', '--tags')
        if tags_only:
            tag_cmd += ('--abbrev=0',)
        else:
            tag_cmd += ('--exact',)
        try:
            rev = cmd_output(*tag_cmd, cwd=repo_path)[1].strip()
        except CalledProcessError:
            tag_cmd = ('git', 'rev-parse', 'FETCH_HEAD')
            rev = cmd_output(*tag_cmd, cwd=repo_path)[1].strip()

    # Don't bother trying to update if our rev is the same
    if rev == repo_config['rev']:
        return repo_config

    try:
        path = store.clone(repo_config['repo'], rev)
        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
    except InvalidManifestError as e:
        raise RepositoryCannotBeUpdatedError(six.text_type(e))

    # See if any of our hooks were deleted with the new commits
    hooks = {hook['id'] for hook in repo_config['hooks']}
    hooks_missing = hooks - {hook['id'] for hook in manifest}
    if hooks_missing:
        raise RepositoryCannotBeUpdatedError(
            'Cannot update because the tip of master is missing these hooks:\n'
            '{}'.format(', '.join(sorted(hooks_missing))),
        )

    # Construct a new config with the head rev
    new_config = repo_config.copy()
    new_config['rev'] = rev
    return new_config
예제 #19
0
def _update_repo(repo_config, store, tags_only):
    """Updates a repository to the tip of `master`.  If the repository cannot
    be updated because a hook that is configured does not exist in `master`,
    this raises a RepositoryCannotBeUpdatedError

    Args:
        repo_config - A config for a repository
    """
    repo_path = store.clone(repo_config['repo'], repo_config['rev'])

    cmd_output('git', 'fetch', cwd=repo_path)
    tag_cmd = ('git', 'describe', 'origin/master', '--tags')
    if tags_only:
        tag_cmd += ('--abbrev=0',)
    else:
        tag_cmd += ('--exact',)
    try:
        rev = cmd_output(*tag_cmd, cwd=repo_path)[1].strip()
    except CalledProcessError:
        tag_cmd = ('git', 'rev-parse', 'origin/master')
        rev = cmd_output(*tag_cmd, cwd=repo_path)[1].strip()

    # Don't bother trying to update if our rev is the same
    if rev == repo_config['rev']:
        return repo_config

    try:
        path = store.clone(repo_config['repo'], rev)
        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
    except InvalidManifestError as e:
        raise RepositoryCannotBeUpdatedError(six.text_type(e))

    # See if any of our hooks were deleted with the new commits
    hooks = {hook['id'] for hook in repo_config['hooks']}
    hooks_missing = hooks - {hook['id'] for hook in manifest}
    if hooks_missing:
        raise RepositoryCannotBeUpdatedError(
            'Cannot update because the tip of master is missing these hooks:\n'
            '{}'.format(', '.join(sorted(hooks_missing))),
        )

    # Construct a new config with the head rev
    new_config = repo_config.copy()
    new_config['rev'] = rev
    return new_config
예제 #20
0
def _check_hooks_still_exist_at_rev(
    repo_config: Dict[str, Any],
    info: RevInfo,
    store: Store,
) -> None:
    try:
        path = store.clone(repo_config['repo'], info.rev)
        manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
    except InvalidManifestError as e:
        raise RepositoryCannotBeUpdatedError(str(e))

    # See if any of our hooks were deleted with the new commits
    hooks = {hook['id'] for hook in repo_config['hooks']}
    hooks_missing = hooks - {hook['id'] for hook in manifest}
    if hooks_missing:
        raise RepositoryCannotBeUpdatedError(
            f'Cannot update because the tip of HEAD is missing these hooks:\n'
            f'{", ".join(sorted(hooks_missing))}', )
예제 #21
0
def make_config_from_repo(repo_path, sha=None, hooks=None, check=True):
    manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
    config = OrderedDict((
        ('repo', 'file://{}'.format(repo_path)),
        ('sha', sha or get_head_sha(repo_path)),
        (
            'hooks',
            hooks or [OrderedDict((('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
예제 #22
0
def make_config_from_repo(repo_path, sha=None, hooks=None, check=True):
    manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE))
    config = OrderedDict((
        ('repo', 'file://{}'.format(repo_path)),
        ('sha', sha or git.head_sha(repo_path)),
        (
            'hooks',
            hooks or [OrderedDict((('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
예제 #23
0
def _mark_used_repos(
    store: Store,
    all_repos: dict[tuple[str, str], str],
    unused_repos: set[tuple[str, str]],
    repo: dict[str, Any],
) -> None:
    if repo['repo'] == META:
        return
    elif repo['repo'] == LOCAL:
        for hook in repo['hooks']:
            deps = hook.get('additional_dependencies')
            unused_repos.discard((
                store.db_repo_name(repo['repo'], deps),
                C.LOCAL_REPO_VERSION,
            ))
    else:
        key = (repo['repo'], repo['rev'])
        path = all_repos.get(key)
        # can't inspect manifest if it isn't cloned
        if path is None:
            return

        try:
            manifest = load_manifest(os.path.join(path, C.MANIFEST_FILE))
        except InvalidManifestError:
            return
        else:
            unused_repos.discard(key)
            by_id = {hook['id']: hook for hook in manifest}

        for hook in repo['hooks']:
            if hook['id'] not in by_id:
                continue

            deps = hook.get(
                'additional_dependencies',
                by_id[hook['id']]['additional_dependencies'],
            )
            unused_repos.discard((
                store.db_repo_name(repo['repo'], deps),
                repo['rev'],
            ))
예제 #24
0
def make_config_from_repo(
        repo_path, sha=None, hooks=None, check=True, legacy=False,
):
    filename = C.MANIFEST_FILE_LEGACY if legacy else C.MANIFEST_FILE
    manifest = load_manifest(os.path.join(repo_path, filename))
    config = OrderedDict((
        ('repo', repo_path),
        ('sha', sha or get_head_sha(repo_path)),
        (
            'hooks',
            hooks or [OrderedDict((('id', hook['id']),)) for hook in manifest],
        ),
    ))

    if check:
        wrapped = validate([config], CONFIG_SCHEMA)
        config, = apply_defaults(wrapped, CONFIG_SCHEMA)
        return config
    else:
        return config
예제 #25
0
import re

import pytest
from pre_commit.clientlib import load_manifest
from pre_commit.constants import MANIFEST_FILE

HOOKS = {h['id']: re.compile(h['entry']) for h in load_manifest(MANIFEST_FILE)}


@pytest.mark.parametrize(
    's',
    (
        'x = 1 # type: ignore_me',
        'x = 1  # type: int',
        'x = 1  # type int',
        'x = 1  # type: int  # noqa',
    ),
)
def test_python_use_type_annotations_positive(s):
    assert HOOKS['python-use-type-annotations'].search(s)


@pytest.mark.parametrize(
    's',
    (
        'x = 1',
        'x = 1  # type:ignore',
        'x = 1  # type: ignore',
        'x = 1  # type:  ignore',
        'x = 1  # type: ignore # noqa',
        'x = 1  # type: ignore  # noqa',
예제 #26
0
 def manifest_hooks(self):
     repo, rev = self.repo_config['repo'], self.repo_config['rev']
     repo_path = self.store.clone(repo, rev)
     manifest_path = os.path.join(repo_path, C.MANIFEST_FILE)
     return {hook['id']: hook for hook in load_manifest(manifest_path)}
예제 #27
0
 def manifest_contents(self):
     return load_manifest(os.path.join(self.repo_path, C.MANIFEST_FILE))
예제 #28
0
 def manifest_hooks(self):
     manifest_path = os.path.join(self._repo_path, C.MANIFEST_FILE)
     return {hook['id']: hook for hook in load_manifest(manifest_path)}
예제 #29
0
def pre_commit_manifest():
    return load_manifest(MANIFEST_FILE)
예제 #30
0
 def manifest_contents(self):
     return load_manifest(os.path.join(self.repo_path, C.MANIFEST_FILE))