Example #1
0
def test_autoupdate_old_revision_broken(tempdir_factory, in_tmpdir, store):
    """In $FUTURE_VERSION, hooks.yaml will no longer be supported.  This
    asserts that when that day comes, pre-commit will be able to autoupdate
    despite not being able to read hooks.yaml in that repository.
    """
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path, check=False)

    cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml', cwd=path)
    git_commit(cwd=path)
    # Assume this is the revision the user's old repository was at
    rev = git.head_rev(path)
    cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE, cwd=path)
    git_commit(cwd=path)
    update_rev = git.head_rev(path)

    config['rev'] = rev
    write_config('.', config)
    with open(C.CONFIG_FILE) as f:
        before = f.read()
    ret = autoupdate(C.CONFIG_FILE, store, tags_only=False)
    with open(C.CONFIG_FILE) as f:
        after = f.read()
    assert ret == 0
    assert before != after
    assert update_rev in after
Example #2
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'])
Example #3
0
def test_autoupdate_old_revision_broken(
    tempdir_factory, in_tmpdir, mock_out_store_directory,
):
    """In $FUTURE_VERSION, hooks.yaml will no longer be supported.  This
    asserts that when that day comes, pre-commit will be able to autoupdate
    despite not being able to read hooks.yaml in that repository.
    """
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path, check=False)

    with cwd(path):
        cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml')
        cmd_output('git', 'commit', '-m', 'simulate old repo')
        # Assume this is the revision the user's old repository was at
        rev = get_head_sha(path)
        cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE)
        cmd_output('git', 'commit', '-m', 'move hooks file')
        update_rev = get_head_sha(path)

    config['sha'] = rev
    write_config('.', config)
    before = open(C.CONFIG_FILE).read()
    ret = autoupdate(Runner('.', C.CONFIG_FILE), tags_only=False)
    after = open(C.CONFIG_FILE).read()
    assert ret == 0
    assert before != after
    assert update_rev in after
Example #4
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()
Example #5
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
Example #6
0
def test_default_python_language_version(store, tempdir_factory):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    repo_path = store.clone(path, get_head_sha(path))
    manifest = Manifest(repo_path, path)

    # This assertion is difficult as it is version dependent, just assert
    # that it is *something*
    assert manifest.hooks['foo']['language_version'] != 'default'
Example #7
0
def hook_disappearing_repo(tempdir_factory):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    original_rev = git.head_rev(path)

    with modify_manifest(path) as manifest:
        manifest[0]['id'] = 'bar'

    yield auto_namedtuple(path=path, original_rev=original_rev)
Example #8
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
Example #9
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
Example #10
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$'
Example #11
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
Example #12
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$"
Example #13
0
def out_of_date_repo(tempdir_factory):
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    original_rev = git.head_rev(path)

    git_commit(cwd=path)
    head_rev = git.head_rev(path)

    yield auto_namedtuple(
        path=path, original_rev=original_rev, head_rev=head_rev,
    )
Example #14
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'])
Example #15
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()
Example #16
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()
Example #17
0
def test_gc_repo_not_cloned(tempdir_factory, store, in_git_dir, cap_out):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    write_config('.', make_config_from_repo(path))
    store.mark_config_used(C.CONFIG_FILE)

    assert _config_count(store) == 1
    assert _repo_count(store) == 0
    assert not gc(store)
    assert _config_count(store) == 1
    assert _repo_count(store) == 0
    assert cap_out.get().splitlines()[-1] == '0 repo(s) removed.'
Example #18
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
Example #19
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()
Example #20
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)
    )
Example #21
0
def out_of_date_repo(tmpdir_factory):
    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    original_sha = get_head_sha(path)

    # Make a commit
    with local.cwd(path):
        local['git']['commit', '--allow-empty', '-m', 'foo']()
    head_sha = get_head_sha(path)

    yield auto_namedtuple(
        path=path, original_sha=original_sha, head_sha=head_sha,
    )
Example #22
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
Example #23
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
Example #24
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
Example #25
0
def hook_disappearing_repo(tmpdir_factory):
    path = make_repo(tmpdir_factory, 'python_hooks_repo')
    original_sha = get_head_sha(path)

    with local.cwd(path):
        shutil.copy(
            get_resource_path('manifest_without_foo.yaml'),
            C.MANIFEST_FILE,
        )
        local['git']('add', '.')
        local['git']('commit', '-m', 'Remove foo')

    yield auto_namedtuple(path=path, original_sha=original_sha)
Example #26
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
Example #27
0
def test_switch_language_versions_doesnt_clobber(tempdir_factory, store):
    # We're using the python3 repo because it prints the python version
    path = make_repo(tempdir_factory, "python3_hooks_repo")

    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

    run_on_version("python3.4", b"3.4\n[]\nHello World\n")
    run_on_version("python3.3", b"3.3\n[]\nHello World\n")
Example #28
0
def test_too_new_version(tempdir_factory, store, fake_log_handler):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    with modify_manifest(path) as manifest:
        manifest[0]['minimum_pre_commit_version'] = '999.0.0'
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    with pytest.raises(SystemExit):
        repo.require_installed()
    msg = fake_log_handler.handle.call_args[0][0].msg
    assert re.match(
        r'^The hook `bash_hook` requires pre-commit version 999\.0\.0 but '
        r'version \d+\.\d+\.\d+ is installed.  '
        r'Perhaps run `pip install --upgrade pre-commit`\.$',
        msg,
    )
Example #29
0
def test_legacy_manifest_warn(store, tempdir_factory, log_warning_mock):
    path = make_repo(tempdir_factory, 'legacy_hooks_yaml_repo')
    head_sha = get_head_sha(path)
    repo_path = store.clone(path, head_sha)
    Manifest(repo_path, path).manifest_contents

    # Should have printed a warning
    assert log_warning_mock.call_args_list[0][0][0] == (
        '{} uses legacy hooks.yaml to provide hooks.\n'
        'In newer versions, this file is called .pre-commit-hooks.yaml\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(path)
    )
Example #30
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
Example #31
0
def test_reinstall(tempdir_factory, store, log_info_mock):
    path = make_repo(tempdir_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
Example #32
0
def test_too_new_version(tempdir_factory, store, fake_log_handler):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    with modify_manifest(path) as manifest:
        manifest[0]['minimum_pre_commit_version'] = '999.0.0'
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)
    with pytest.raises(SystemExit):
        repo.require_installed()
    msg = fake_log_handler.handle.call_args[0][0].msg
    assert re.match(
        r'^The hook `bash_hook` requires pre-commit version 999\.0\.0 but '
        r'version \d+\.\d+\.\d+ is installed.  '
        r'Perhaps run `pip install --upgrade pre-commit`\.$',
        msg,
    )
Example #33
0
def test_additional_golang_dependencies_installed(
        tempdir_factory, store,
):
    path = make_repo(tempdir_factory, 'golang_hooks_repo')
    config = make_config_from_repo(path)
    # A small go package
    deps = ['github.com/golang/example/hello']
    config['hooks'][0]['additional_dependencies'] = deps
    repo = Repository.create(config, store)
    repo.require_installed()
    binaries = os.listdir(repo._cmd_runner.path(
        helpers.environment_dir(golang.ENVIRONMENT_DIR, 'default'), 'bin',
    ))
    # normalize for windows
    binaries = [os.path.splitext(binary)[0] for binary in binaries]
    assert 'hello' in binaries
Example #34
0
def test_additional_rust_cli_dependencies_installed(
        tempdir_factory, store, dep,
):
    path = make_repo(tempdir_factory, 'rust_hooks_repo')
    config = make_config_from_repo(path)
    # A small rust package with no dependencies.
    config['hooks'][0]['additional_dependencies'] = [dep]
    repo = Repository.create(config, store)
    repo.require_installed()
    (prefix, _, _, _), = repo._venvs()
    binaries = os.listdir(prefix.path(
        helpers.environment_dir(rust.ENVIRONMENT_DIR, 'default'), 'bin',
    ))
    # normalize for windows
    binaries = [os.path.splitext(binary)[0] for binary in binaries]
    assert 'shellharden' in binaries
def _test_hook_repo(
    tempdir_factory,
    store,
    repo_path,
    hook_id,
    args,
    expected,
    expected_return_code=0,
    config_kwargs=None,
    color=False,
):
    path = make_repo(tempdir_factory, repo_path)
    config = make_config_from_repo(path, **(config_kwargs or {}))
    ret, out = _get_hook(config, store, hook_id).run(args, color=color)
    assert ret == expected_return_code
    assert _norm_out(out) == expected
Example #36
0
def test_additional_rust_cli_dependencies_installed(
        tempdir_factory, store, dep,
):
    path = make_repo(tempdir_factory, 'rust_hooks_repo')
    config = make_config_from_repo(path)
    # A small rust package with no dependencies.
    config['hooks'][0]['additional_dependencies'] = [dep]
    hook = _get_hook(config, store, 'rust-hook')
    binaries = os.listdir(
        hook.prefix.path(
            helpers.environment_dir(rust.ENVIRONMENT_DIR, C.DEFAULT), 'bin',
        ),
    )
    # normalize for windows
    binaries = [os.path.splitext(binary)[0] for binary in binaries]
    assert 'shellharden' in binaries
Example #37
0
def _test_hook_repo(tmpdir_factory,
                    store,
                    repo_path,
                    hook_id,
                    args,
                    expected,
                    expected_return_code=0,
                    config_kwargs=None):
    path = make_repo(tmpdir_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('\r\n', '\n') == expected
Example #38
0
def test_additional_golang_dependencies_installed(
        tempdir_factory, store,
):
    path = make_repo(tempdir_factory, 'golang_hooks_repo')
    config = make_config_from_repo(path)
    # A small go package
    deps = ['github.com/golang/example/hello']
    config['hooks'][0]['additional_dependencies'] = deps
    hook = _get_hook(config, store, 'golang-hook')
    binaries = os.listdir(
        hook.prefix.path(
            helpers.environment_dir(golang.ENVIRONMENT_DIR, C.DEFAULT), 'bin',
        ),
    )
    # normalize for windows
    binaries = [os.path.splitext(binary)[0] for binary in binaries]
    assert 'hello' in binaries
Example #39
0
def test_additional_dependencies_roll_forward(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')

    config1 = make_config_from_repo(path)
    hook1 = _get_hook(config1, store, 'foo')
    with python.in_env(hook1.prefix, hook1.language_version):
        assert 'mccabe' not in cmd_output('pip', 'freeze', '-l')[1]

    # Make another repo with additional dependencies
    config2 = make_config_from_repo(path)
    config2['hooks'][0]['additional_dependencies'] = ['mccabe']
    hook2 = _get_hook(config2, store, 'foo')
    with python.in_env(hook2.prefix, hook2.language_version):
        assert 'mccabe' in cmd_output('pip', 'freeze', '-l')[1]

    # should not have affected original
    with python.in_env(hook1.prefix, hook1.language_version):
        assert 'mccabe' not in cmd_output('pip', 'freeze', '-l')[1]
Example #40
0
def test_invalid_manifest_gcd(tempdir_factory, store, in_git_dir, cap_out):
    # clean up repos from old pre-commit versions
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    write_config('.', make_config_from_repo(path))
    store.mark_config_used(C.CONFIG_FILE)

    # trigger a clone
    assert not autoupdate(C.CONFIG_FILE, store, tags_only=False)

    # we'll "break" the manifest to simulate an old version clone
    (_, _, path), = store.select_all_repos()
    os.remove(os.path.join(path, C.MANIFEST_FILE))

    assert _config_count(store) == 1
    assert _repo_count(store) == 1
    assert not gc(store)
    assert _config_count(store) == 1
    assert _repo_count(store) == 0
    assert cap_out.get().splitlines()[-1] == '1 repo(s) removed.'
Example #41
0
def test_gc(tempdir_factory, store, in_git_dir, cap_out):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    old_rev = git.head_rev(path)
    git_commit(cwd=path)

    write_config('.', make_config_from_repo(path, rev=old_rev))
    store.mark_config_used(C.CONFIG_FILE)

    # update will clone both the old and new repo, making the old one gc-able
    assert not autoupdate(C.CONFIG_FILE, store, tags_only=False)

    assert _config_count(store) == 1
    assert _repo_count(store) == 2
    assert not gc(store)
    assert _config_count(store) == 1
    assert _repo_count(store) == 1
    assert cap_out.get().splitlines()[-1] == '1 repo(s) removed.'

    _remove_config_assert_cleared(store, cap_out)
Example #42
0
def test_manifest_hooks(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    config = make_config_from_repo(path)
    hook = _get_hook(config, store, 'bash_hook')

    assert hook == Hook(
        src=f'file://{path}',
        prefix=Prefix(mock.ANY),
        additional_dependencies=[],
        alias='',
        always_run=False,
        args=[],
        description='',
        entry='bin/hook.sh',
        exclude='^$',
        exclude_types=[],
        files='',
        id='bash_hook',
        language='script',
        language_version='default',
        log_file='',
        minimum_pre_commit_version='0',
        name='Bash hook',
        pass_filenames=True,
        require_serial=False,
        stages=(
            'commit',
            'merge-commit',
            'prepare-commit-msg',
            'commit-msg',
            'post-commit',
            'manual',
            'post-checkout',
            'push',
            'post-merge',
            'post-rewrite',
        ),
        types=['file'],
        types_or=[],
        verbose=False,
        fail_fast=False,
    )
Example #43
0
def test_switch_language_versions_doesnt_clobber(tempdir_factory, store):
    # We're using the python3 repo because it prints the python version
    path = make_repo(tempdir_factory, 'python3_hooks_repo')

    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 _norm_out(ret[1]) == expected_output

    run_on_version('python3.4', b'3.4\n[]\nHello World\n')
    run_on_version('python3.5', b'3.5\n[]\nHello World\n')
Example #44
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)
    hook = _get_hook(config, store, 'foo')

    # Simulate breaking of the virtualenv
    libdir = hook.prefix.path(
        helpers.environment_dir(python.ENVIRONMENT_DIR, hook.language_version),
        'lib', hook.language_version,
    )
    paths = [
        os.path.join(libdir, p) for p in ('site.py', 'site.pyc', '__pycache__')
    ]
    cmd_output_b('rm', '-rf', *paths)

    # pre-commit should rebuild the virtualenv and it should be runnable
    retv, stdout, stderr = _get_hook(config, store, 'foo').run(())
    assert retv == 0
Example #45
0
def test_gc_config_with_missing_hook(
        tempdir_factory, store, in_git_dir, cap_out,
):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    write_config('.', make_config_from_repo(path))
    store.mark_config_used(C.CONFIG_FILE)
    # to trigger a clone
    all_hooks(load_config(C.CONFIG_FILE), store)

    with modify_config() as config:
        # add a hook which does not exist, make sure we don't crash
        config['repos'][0]['hooks'].append({'id': 'does-not-exist'})

    assert _config_count(store) == 1
    assert _repo_count(store) == 1
    assert not gc(store)
    assert _config_count(store) == 1
    assert _repo_count(store) == 1
    assert cap_out.get().splitlines()[-1] == '0 repo(s) removed.'

    _remove_config_assert_cleared(store, cap_out)
Example #46
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
Example #47
0
def test_try_repo_uncommitted_changes(cap_out, tempdir_factory):
    repo = make_repo(tempdir_factory, 'script_hooks_repo')
    # make an uncommitted change
    with modify_manifest(repo, commit=False) as manifest:
        manifest[0]['name'] = 'modified name!'

    with cwd(git_dir(tempdir_factory)):
        open('test-fie', 'a').close()
        cmd_output('git', 'add', '.')
        assert not try_repo(try_repo_opts(repo))

    start, config, rest = _get_out(cap_out)
    assert start == '[WARNING] Creating temporary repo with uncommitted changes...\n'  # noqa: E501
    config_pattern = re_assert.Matches(
        '^repos:\n'
        '-   repo: .+shadow-repo\n'
        '    rev: .+\n'
        '    hooks:\n'
        '    -   id: bash_hook\n$', )
    config_pattern.assert_matches(config)
    assert rest == 'modified name!...........................................................Passed\n'  # noqa: E501
Example #48
0
def test_additional_dependencies_roll_forward(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'python_hooks_repo')

    config1 = make_config_from_repo(path)
    repo1 = Repository.create(config1, store)
    repo1.require_installed()
    (prefix1, _, version1, _), = repo1._venvs()
    with python.in_env(prefix1, version1):
        assert 'mccabe' not in cmd_output('pip', 'freeze', '-l')[1]

    # Make another repo with additional dependencies
    config2 = make_config_from_repo(path)
    config2['hooks'][0]['additional_dependencies'] = ['mccabe']
    repo2 = Repository.create(config2, store)
    repo2.require_installed()
    (prefix2, _, version2, _), = repo2._venvs()
    with python.in_env(prefix2, version2):
        assert 'mccabe' in cmd_output('pip', 'freeze', '-l')[1]

    # should not have affected original
    with python.in_env(prefix1, version1):
        assert 'mccabe' not in cmd_output('pip', 'freeze', '-l')[1]
Example #49
0
def test_control_c_control_c_on_install(tempdir_factory, store):
    """Regression test for #186."""
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path)
    hooks = [_get_hook_no_install(config, store, 'foo')]

    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(
                helpers,
                'run_setup_cmd',
                side_effect=MyKeyboardInterrupt,
        ):
            with mock.patch.object(
                    shutil,
                    'rmtree',
                    side_effect=MyKeyboardInterrupt,
            ):
                install_hook_envs(hooks, store)

    # Should have made an environment, however this environment is broken!
    hook, = hooks
    assert hook.prefix.exists(
        helpers.environment_dir(python.ENVIRONMENT_DIR,
                                hook.language_version), )

    # However, it should be perfectly runnable (reinstall after botched
    # install)
    install_hook_envs(hooks, store)
    ret, out = _hook_run(hook, (), color=False)
    assert ret == 0
Example #50
0
def test_autoupdate_old_revision_broken(tempdir_factory, in_tmpdir, store):
    """In $FUTURE_VERSION, hooks.yaml will no longer be supported.  This
    asserts that when that day comes, pre-commit will be able to autoupdate
    despite not being able to read hooks.yaml in that repository.
    """
    path = make_repo(tempdir_factory, 'python_hooks_repo')
    config = make_config_from_repo(path, check=False)

    cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml', cwd=path)
    cmd_output('git', 'commit', '-m', 'simulate old repo', cwd=path)
    # Assume this is the revision the user's old repository was at
    rev = git.head_rev(path)
    cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE, cwd=path)
    cmd_output('git', 'commit', '-m', 'move hooks file', cwd=path)
    update_rev = git.head_rev(path)

    config['rev'] = rev
    write_config('.', config)
    before = open(C.CONFIG_FILE).read()
    ret = autoupdate(Runner('.', C.CONFIG_FILE), store, tags_only=False)
    after = open(C.CONFIG_FILE).read()
    assert ret == 0
    assert before != after
    assert update_rev in after
Example #51
0
def test_manifest_hooks(tempdir_factory, store):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    config = make_config_from_repo(path)
    repo = Repository.create(config, store)

    assert repo.manifest_hooks['bash_hook'] == {
        'always_run': False,
        'additional_dependencies': [],
        'args': [],
        'description': '',
        'entry': 'bin/hook.sh',
        'exclude': '^$',
        'files': '',
        'id': 'bash_hook',
        'language': 'script',
        'language_version': 'default',
        'log_file': '',
        'minimum_pre_commit_version': '0',
        'name': 'Bash hook',
        'pass_filenames': True,
        'stages': [],
        'types': ['file'],
        'exclude_types': [],
    }
Example #52
0
def up_to_date(tempdir_factory):
    yield make_repo(tempdir_factory, 'python_hooks_repo')
Example #53
0
def _create_repo_with_tags(tempdir_factory, src, tag):
    path = make_repo(tempdir_factory, src)
    with cwd(path):
        cmd_output('git', 'tag', tag)
    return path
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')])
Example #55
0
def manifest(store, tempdir_factory):
    path = make_repo(tempdir_factory, 'script_hooks_repo')
    head_sha = get_head_sha(path)
    repo_path = store.clone(path, head_sha)
    yield Manifest(repo_path, path)
Example #56
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(), [])
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',))
Example #58
0
def _run_try_repo(tempdir_factory, **kwargs):
    repo = make_repo(tempdir_factory, 'modified_file_returns_zero_repo')
    with cwd(git_dir(tempdir_factory)):
        _add_test_file()
        assert not try_repo(try_repo_opts(repo, **kwargs))
Example #59
0
def _run_try_repo(tempdir_factory, **kwargs):
    repo = make_repo(tempdir_factory, 'modified_file_returns_zero_repo')
    with cwd(git_dir(tempdir_factory)):
        open('test-file', 'a').close()
        cmd_output('git', 'add', '.')
        assert not try_repo(try_repo_opts(repo, **kwargs))
Example #60
0
def _create_repo_with_tags(tempdir_factory, src, tag):
    path = make_repo(tempdir_factory, src)
    cmd_output_b('git', 'tag', tag, cwd=path)
    return path