示例#1
0
def test_versions_ok(tempdir_factory, store, version):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    with modify_manifest(path) as manifest:
        manifest[0]['minimum_pre_commit_version'] = version
    config = make_config_from_repo(path)
    # Should succeed
    Repository.create(config, store).require_installed()
示例#2
0
def _update_repository(repo_config, runner):
    """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 = Repository.create(repo_config, runner.store)

    with cwd(repo.repo_path_getter.repo_path):
        cmd_output('git', 'fetch')
        head_sha = cmd_output('git', 'rev-parse', 'origin/master')[1].strip()

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

    # Construct a new config with the head sha
    new_config = OrderedDict(repo_config)
    new_config['sha'] = head_sha
    new_repo = Repository.create(new_config, runner.store)

    # See if any of our hooks were deleted with the new commits
    hooks = set(hook_id for hook_id, _ in repo.hooks)
    hooks_missing = hooks - (hooks & set(new_repo.manifest.hooks.keys()))
    if hooks_missing:
        raise RepositoryCannotBeUpdatedError(
            'Cannot update because the tip of master is missing these hooks:\n'
            '{0}'.format(', '.join(sorted(hooks_missing)))
        )

    return new_config
示例#3
0
def test_config_overrides_repo_specifics(tmpdir_factory, store):
    path = make_repo(tmpdir_factory, 'script_hooks_repo')
    config = make_config_from_repo(path)

    repo = Repository.create(config, store)
    assert repo.hooks[0][1]['files'] == ''
    # Set the file regex to something else
    config['hooks'][0]['files'] = '\\.sh$'
    repo = Repository.create(config, store)
    assert repo.hooks[0][1]['files'] == '\\.sh$'
示例#4
0
def test_config_overrides_repo_specifics(tempdir_factory, store):
    path = make_repo(tempdir_factory, "script_hooks_repo")
    config = make_config_from_repo(path)

    repo = Repository.create(config, store)
    assert repo.hooks[0][1]["files"] == ""
    # Set the file regex to something else
    config["hooks"][0]["files"] = "\\.sh$"
    repo = Repository.create(config, store)
    assert repo.hooks[0][1]["files"] == "\\.sh$"
示例#5
0
def test_reinstall(tmpdir_factory, store):
    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    repo.require_installed()
    # Reinstall with same repo should not trigger another install
    # TODO: how to assert this?
    repo.require_installed()
    # Reinstall on another run should not trigger another install
    # TODO: how to assert this?
    repo = Repository.create(config, store)
    repo.require_installed()
示例#6
0
def test_tags_on_repositories(in_tmpdir, tempdir_factory, store):
    tag = "v1.1"
    git_dir_1 = _create_repo_with_tags(tempdir_factory, "prints_cwd_repo", tag)
    git_dir_2 = _create_repo_with_tags(tempdir_factory, "script_hooks_repo", tag)

    repo_1 = Repository.create(make_config_from_repo(git_dir_1, sha=tag), store)
    ret = repo_1.run_hook(repo_1.hooks[0][1], ["-L"])
    assert ret[0] == 0
    assert ret[1].strip() == _norm_pwd(in_tmpdir)

    repo_2 = Repository.create(make_config_from_repo(git_dir_2, sha=tag), store)
    ret = repo_2.run_hook(repo_2.hooks[0][1], ["bar"])
    assert ret[0] == 0
    assert ret[1] == b"bar\nHello World\n"
示例#7
0
def test_additional_dependencies_roll_forward(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    # Run the repo once without additional_dependencies
    repo = Repository.create(config, store)
    repo.require_installed()
    # Now run it with additional_dependencies
    config['hooks'][0]['additional_dependencies'] = ['mccabe']
    repo = Repository.create(config, store)
    repo.require_installed()
    # We should see our additional dependency installed
    with python.in_env(repo._cmd_runner, 'default'):
        output = cmd_output('pip', 'freeze', '-l')[1]
        assert 'mccabe' in output
示例#8
0
def test_reinstall(tmpdir_factory, store, log_info_mock):
    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    repo.require_installed()
    # We print some logging during clone (1) + install (3)
    assert log_info_mock.call_count == 4
    log_info_mock.reset_mock()
    # Reinstall with same repo should not trigger another install
    repo.require_installed()
    assert log_info_mock.call_count == 0
    # Reinstall on another run should not trigger another install
    repo = Repository.create(config, store)
    repo.require_installed()
    assert log_info_mock.call_count == 0
示例#9
0
 def repositories(self):
     """Returns a tuple of the configured repositories."""
     repos = self.config['repos']
     repos = tuple(Repository.create(x, self.store) for x in repos)
     for repo in repos:
         repo.require_installed()
     return repos
示例#10
0
 def repositories(self):
     """Returns a tuple of the configured repositories."""
     config = load_config(self.config_file_path)
     repositories = tuple(Repository.create(x, self.store) for x in config)
     for repository in repositories:
         repository.require_installed()
     return repositories
示例#11
0
 def run_on_version(version, expected_output):
     config = make_config_from_repo(path, hooks=[{"id": "python3-hook", "language_version": version}])
     repo = Repository.create(config, store)
     hook_dict, = [hook for repo_hook_id, hook in repo.hooks if repo_hook_id == "python3-hook"]
     ret = repo.run_hook(hook_dict, [])
     assert ret[0] == 0
     assert ret[1].replace(b"\r\n", b"\n") == expected_output
示例#12
0
def test_control_c_control_c_on_install(tmpdir_factory, store):
    """Regression test for #186."""
    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    hook = repo.hooks[0][1]

    class MyKeyboardInterrupt(KeyboardInterrupt):
        pass

    # To simulate a killed install, we'll make PythonEnv.run raise ^C
    # and then to simulate a second ^C during cleanup, we'll make shutil.rmtree
    # raise as well.
    with pytest.raises(MyKeyboardInterrupt):
        with mock.patch.object(
            PythonEnv, 'run', side_effect=MyKeyboardInterrupt,
        ):
            with mock.patch.object(
                shutil, 'rmtree', side_effect=MyKeyboardInterrupt,
            ):
                repo.run_hook(hook, [])

    # Should have made an environment, however this environment is broken!
    assert os.path.exists(repo.cmd_runner.path('py_env'))

    # However, it should be perfectly runnable (reinstall after botched
    # install)
    retv, stdout, stderr = repo.run_hook(hook, [])
    assert retv == 0
示例#13
0
def test_additional_dependencies(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['pep8']
    repo = Repository.create(config, store)
    venv, = repo._venvs
    assert venv == (mock.ANY, 'python', 'default', ['pep8'])
示例#14
0
def test_local_repository():
    config = config_with_local_hooks()
    local_repo = Repository.create(config, 'dummy')
    with pytest.raises(NotImplementedError):
        local_repo.sha
    with pytest.raises(NotImplementedError):
        local_repo.manifest
    assert len(local_repo.hooks) == 1
示例#15
0
def test_additional_python_dependencies_installed(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['mccabe']
    repo = Repository.create(config, store)
    repo.run_hook(repo.hooks[0][1], [])
    with python.in_env(repo.cmd_runner, 'default') as env:
        output = env.run('pip freeze -l')[1]
        assert 'mccabe' in output
示例#16
0
def test_additional_python_dependencies_installed(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['mccabe']
    repo = Repository.create(config, store)
    repo.require_installed()
    with python.in_env(repo._cmd_runner, 'default'):
        output = cmd_output('pip', 'freeze', '-l')[1]
        assert 'mccabe' in output
示例#17
0
def test_additional_dependencies_duplicated(
        tempdir_factory, store, log_warning_mock,
):
    path = make_repo(tempdir_factory, 'ruby_hooks_repo')
    config = make_config_from_repo(path)
    deps = ['thread_safe', 'tins', 'thread_safe']
    config['hooks'][0]['additional_dependencies'] = deps
    repo = Repository.create(config, store)
    venv, = repo._venvs
    assert venv == (mock.ANY, 'ruby', 'default', ['thread_safe', 'tins'])
示例#18
0
def _test_hook_repo(
    tempdir_factory, store, repo_path, hook_id, args, expected, expected_return_code=0, config_kwargs=None
):
    path = make_repo(tempdir_factory, repo_path)
    config = make_config_from_repo(path, **(config_kwargs or {}))
    repo = Repository.create(config, store)
    hook_dict = [hook for repo_hook_id, hook in repo.hooks if repo_hook_id == hook_id][0]
    ret = repo.run_hook(hook_dict, args)
    assert ret[0] == expected_return_code
    assert ret[1].replace(b"\r\n", b"\n") == expected
示例#19
0
def test_additional_ruby_dependencies_installed(
        tempdir_factory, store,
):  # pragma: no cover (non-windows)
    path = make_repo(tempdir_factory, 'ruby_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['thread_safe']
    repo = Repository.create(config, store)
    repo.run_hook(repo.hooks[0][1], [])
    with ruby.in_env(repo.cmd_runner, 'default') as env:
        output = env.run('gem list --local')[1]
        assert 'thread_safe' in output
示例#20
0
def test_tags_on_repositories(in_tmpdir, tmpdir_factory, store):
    tag = 'v1.1'
    git_dir_1 = _create_repo_with_tags(tmpdir_factory, 'prints_cwd_repo', tag)
    git_dir_2 = _create_repo_with_tags(
        tmpdir_factory, 'script_hooks_repo', tag,
    )

    repo_1 = Repository.create(
        make_config_from_repo(git_dir_1, sha=tag), store,
    )
    ret = repo_1.run_hook(repo_1.hooks[0][1], ['-L'])
    assert ret[0] == 0
    assert ret[1].strip() == _norm_pwd(in_tmpdir)

    repo_2 = Repository.create(
        make_config_from_repo(git_dir_2, sha=tag), store,
    )
    ret = repo_2.run_hook(repo_2.hooks[0][1], ['bar'])
    assert ret[0] == 0
    assert ret[1] == 'bar\nHello World\n'
示例#21
0
def test_really_long_file_paths(tempdir_factory, store):
    base_path = tempdir_factory.get()
    really_long_path = os.path.join(base_path, "really_long" * 10)
    cmd_output("git", "init", really_long_path)

    path = make_repo(tempdir_factory, "python_hooks_repo")
    config = make_config_from_repo(path)

    with cwd(really_long_path):
        repo = Repository.create(config, store)
        repo.require_installed()
示例#22
0
def test_really_long_file_paths(tmpdir_factory, store):
    base_path = tmpdir_factory.get()
    really_long_path = os.path.join(base_path, 'really_long' * 10)
    cmd_output('git', 'init', really_long_path)

    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)

    with cwd(really_long_path):
        repo = Repository.create(config, store)
        repo.require_installed()
示例#23
0
def _update_repo(repo_config, runner, 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 = Repository.create(repo_config, runner.store)

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

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

    # Construct a new config with the head sha
    new_config = OrderedDict(repo_config)
    new_config['sha'] = rev
    new_repo = Repository.create(new_config, runner.store)

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

    return new_config
示例#24
0
def test_invalidated_virtualenv(tempdir_factory, store):
    # A cached virtualenv may become invalidated if the system python upgrades
    # This should not cause every hook in that virtualenv to fail.
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)

    # Simulate breaking of the virtualenv
    repo.require_installed()
    version = python.get_default_version()
    libdir = repo._cmd_runner.path('py_env-{}'.format(version), 'lib', version)
    paths = [
        os.path.join(libdir, p) for p in ('site.py', 'site.pyc', '__pycache__')
    ]
    cmd_output('rm', '-rf', *paths)

    # pre-commit should rebuild the virtualenv and it should be runnable
    repo = Repository.create(config, store)
    hook = repo.hooks[0][1]
    retv, stdout, stderr = repo.run_hook(hook, [])
    assert retv == 0
示例#25
0
def test_hook_id_not_present(tempdir_factory, store, fake_log_handler):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['id'] = 'i-dont-exist'
    repo = Repository.create(config, store)
    with pytest.raises(SystemExit):
        repo.require_installed()
    assert fake_log_handler.handle.call_args[0][0].msg == (
        '`i-dont-exist` is not present in repository {}.  '
        'Typo? Perhaps it is introduced in a newer version?  '
        'Often `pre-commit autoupdate` fixes this.'.format(path)
    )
示例#26
0
def test_additional_ruby_dependencies_installed(
        tempdir_factory, store,
):  # pragma: no cover (non-windows)
    path = make_repo(tempdir_factory, 'ruby_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['thread_safe', 'tins']
    repo = Repository.create(config, store)
    repo.require_installed()
    with ruby.in_env(repo._cmd_runner, 'default'):
        output = cmd_output('gem', 'list', '--local')[1]
        assert 'thread_safe' in output
        assert 'tins' in output
示例#27
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"
示例#28
0
def test_additional_node_dependencies_installed(
        tempdir_factory, store,
):  # pragma: no cover (non-windows)
    path = make_repo(tempdir_factory, 'node_hooks_repo')
    config = make_config_from_repo(path)
    # Careful to choose a small package that's not depped by npm
    config['hooks'][0]['additional_dependencies'] = ['lodash']
    repo = Repository.create(config, store)
    repo.require_installed()
    with node.in_env(repo._cmd_runner, 'default'):
        cmd_output('npm', 'config', 'set', 'global', 'true')
        output = cmd_output('npm', 'ls')[1]
        assert 'lodash' in output
示例#29
0
def test_additional_node_dependencies_installed(
        tempdir_factory, store,
):  # pragma: no cover (non-windows)
    path = make_repo(tempdir_factory, 'node_hooks_repo')
    config = make_config_from_repo(path)
    # Careful to choose a small package that's not depped by npm
    config['hooks'][0]['additional_dependencies'] = ['lodash']
    repo = Repository.create(config, store)
    repo.run_hook(repo.hooks[0][1], [])
    with node.in_env(repo.cmd_runner, 'default') as env:
        env.run('npm config set global true')
        output = env.run(('npm ls'))[1]
        assert 'lodash' in output
示例#30
0
 def run_on_version(version, expected_output):
     config = make_config_from_repo(
         path, hooks=[{'id': 'python3-hook', 'language_version': version}],
     )
     repo = Repository.create(config, store)
     hook_dict, = [
         hook
         for repo_hook_id, hook in repo.hooks
         if repo_hook_id == 'python3-hook'
     ]
     ret = repo.run_hook(hook_dict, [])
     assert ret[0] == 0
     assert ret[1].replace(b'\r\n', b'\n') == expected_output
示例#31
0
def test_local_repository():
    config = config_with_local_hooks()
    local_repo = Repository.create(config, 'dummy')
    with pytest.raises(NotImplementedError):
        local_repo.manifest
    assert len(local_repo.hooks) == 1
示例#32
0
def test_repo_url(mock_repo_config):
    repo = Repository(mock_repo_config, None)
    assert repo.repo_url == '[email protected]:pre-commit/pre-commit-hooks'
示例#33
0
def test_sha(mock_repo_config):
    repo = Repository(mock_repo_config, None)
    assert repo.sha == '5e713f8878b7d100c0e059f8cc34be4fc2e8f897'
示例#34
0
def test_venvs(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    venv, = repo._venvs
    assert venv == (mock.ANY, 'python', python.get_default_version(), [])
示例#35
0
def test_additional_dependencies(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    config['hooks'][0]['additional_dependencies'] = ['pep8']
    repo = Repository.create(config, store)
    assert repo.additional_dependencies['python']['default'] == set(('pep8',))
示例#36
0
def test_languages(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    assert repo.languages == set([('python', 'default')])