def repository_is_pending_merge(in_tmpdir):
    # Make a (non-conflicting) merge
    cmd_output('git', 'init', 'repo1')
    with cwd('repo1'):
        io.open('f1', 'w').close()
        cmd_output('git', 'add', 'f1')
        cmd_output('git', 'commit', '-m' 'commit1')

    cmd_output('git', 'clone', 'repo1', 'repo2')

    # Commit in master
    with cwd('repo1'):
        write_file('f1', 'parent\n')
        cmd_output('git', 'commit', '-am', 'master commit2')

    # Commit in clone and pull without committing
    with cwd('repo2'):
        write_file('f2', 'child\n')
        cmd_output('git', 'add', 'f2')
        cmd_output('git', 'commit', '-m', 'clone commit2')
        cmd_output('git', 'pull', '--no-commit')
        # We should end up in a pending merge
        assert io.open('f1').read().startswith('parent\n')
        assert io.open('f2').read().startswith('child\n')
        assert os.path.exists(os.path.join('.git', 'MERGE_HEAD'))
        yield
def f1_is_a_conflict_file(in_tmpdir):
    # Make a merge conflict
    cmd_output('git', 'init', 'repo1')
    with cwd('repo1'):
        io.open('f1', 'w').close()
        cmd_output('git', 'add', 'f1')
        cmd_output('git', 'commit', '-m' 'commit1')

    cmd_output('git', 'clone', 'repo1', 'repo2')

    # Commit in master
    with cwd('repo1'):
        write_file('f1', 'parent\n')
        cmd_output('git', 'commit', '-am', 'master commit2')

    # Commit in clone and pull
    with cwd('repo2'):
        write_file('f1', 'child\n')
        cmd_output('git', 'commit', '-am', 'clone commit2')
        cmd_output('git', 'pull', retcode=None)
        # We should end up in a merge conflict!
        assert io.open('f1').read().startswith(
            '<<<<<<< HEAD\n'
            'child\n'
            '=======\n'
            'parent\n'
            '>>>>>>>'
        )
        assert os.path.exists(os.path.join('.git', 'MERGE_MSG'))
        yield
Example #3
0
def test_files_running_subdir(repo_with_passing_hook, tempdir_factory):
    with cwd(repo_with_passing_hook):
        os.mkdir('subdir')
        open('subdir/foo.py', 'w').close()
        cmd_output('git', 'add', 'subdir/foo.py')

        with cwd('subdir'):
            # Use subprocess to demonstrate behaviour in main
            _, stdout, _ = cmd_output_mocked_pre_commit_home(
                sys.executable, '-m', 'pre_commit.main', 'run', '-v',
                # Files relative to where we are (#339)
                '--files', 'foo.py',
                tempdir_factory=tempdir_factory,
            )
        assert 'subdir/foo.py'.replace('/', os.sep) in stdout
Example #4
0
def test_hook_that_modifies_but_returns_zero(cap_out, store, tempdir_factory):
    git_path = make_consuming_repo(
        tempdir_factory, 'modified_file_returns_zero_repo',
    )
    with cwd(git_path):
        stage_a_file('bar.py')
        _test_run(
            cap_out,
            store,
            git_path,
            {},
            (
                # The first should fail
                b'Failed',
                # With a modified file (default message + the hook's output)
                b'Files were modified by this hook. Additional output:\n\n'
                b'Modified: foo.py',
                # The next hook should pass despite the first modifying
                b'Passed',
                # The next hook should fail
                b'Failed',
                # bar.py was modified, but provides no additional output
                b'Files were modified by this hook.\n',
            ),
            1,
            True,
        )
def test_environment_not_sourced(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        # Patch the executable to simulate rming virtualenv
        with mock.patch.object(sys, 'executable', '/does-not-exist'):
            assert install(C.CONFIG_FILE, store) == 0

        # Use a specific homedir to ignore --user installs
        homedir = tempdir_factory.get()
        ret, stdout, stderr = git_commit(
            env={
                'HOME': homedir,
                'PATH': _path_without_us(),
                # Git needs this to make a commit
                'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'],
                'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'],
                'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'],
                'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'],
            },
            retcode=None,
        )
        assert ret == 1
        assert stdout == ''
        assert stderr.replace('\r\n', '\n') == (
            '`pre-commit` not found.  '
            'Did you forget to activate your virtualenv?\n'
        )
Example #6
0
def prepare_commit_msg_repo(tempdir_factory):
    path = git_dir(tempdir_factory)
    script_name = 'add_sign_off.sh'
    config = {
        'repo': 'local',
        'hooks': [{
            'id': 'add-signoff',
            'name': 'Add "Signed off by:"',
            'entry': './{}'.format(script_name),
            'language': 'script',
            'stages': ['prepare-commit-msg'],
        }],
    }
    write_config(path, config)
    with cwd(path):
        with io.open(script_name, 'w') as script_file:
            script_file.write(
                '#!/usr/bin/env bash\n'
                'set -eu\n'
                'echo "\nSigned off by: " >> "$1"\n',
            )
            make_executable(script_name)
        cmd_output('git', 'add', '.')
        git_commit(msg=prepare_commit_msg_repo.__name__)
        yield path
Example #7
0
def test_clone_shallow_failure_fallback_to_complete(
    store, tempdir_factory,
    log_info_mock,
):
    path = git_dir(tempdir_factory)
    with cwd(path):
        git_commit()
        rev = git.head_rev(path)
        git_commit()

    # Force shallow clone failure
    def fake_shallow_clone(self, *args, **kwargs):
        raise CalledProcessError(None, None, None)
    store._shallow_clone = fake_shallow_clone

    ret = store.clone(path, rev)

    # Should have printed some stuff
    assert log_info_mock.call_args_list[0][0][0].startswith(
        'Initializing environment for ',
    )

    # Should return a directory inside of the store
    assert os.path.exists(ret)
    assert ret.startswith(store.directory)
    # Directory should start with `repo`
    _, dirname = os.path.split(ret)
    assert dirname.startswith('repo')
    # Should be checked out to the rev we specified
    assert git.head_rev(ret) == rev

    # Assert there's an entry in the sqlite db for this
    assert store.select_all_repos() == [(path, rev, ret)]
def test_adding_something(temp_git_dir):
    with cwd(temp_git_dir):
        write_file('f.py', "print('hello world')")
        cmd_output('git', 'add', 'f.py')

        # Should fail with max size of 0
        assert find_large_added_files(['f.py'], 0) == 1
def test_pre_push_legacy(tempdir_factory, store):
    upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    path = tempdir_factory.get()
    cmd_output('git', 'clone', upstream, path)
    with cwd(path):
        mkdirp(os.path.join(path, '.git/hooks'))
        with io.open(os.path.join(path, '.git/hooks/pre-push'), 'w') as f:
            f.write(
                '#!/usr/bin/env bash\n'
                'set -eu\n'
                'read lr ls rr rs\n'
                'test -n "$lr" -a -n "$ls" -a -n "$rr" -a -n "$rs"\n'
                'echo legacy\n',
            )
        make_executable(f.name)

        install(C.CONFIG_FILE, store, hook_type='pre-push')
        assert _get_commit_output(tempdir_factory)[0] == 0

        retc, output = _get_push_output(tempdir_factory)
        assert retc == 0
        first_line, _, third_line = output.splitlines()[:3]
        assert first_line == 'legacy'
        assert third_line.startswith('Bash hook')
        assert third_line.endswith('Passed')
def _test_sub_state(path, rev='rev1', status='A'):
    assert os.path.exists(path.sub_path)
    with cwd(path.sub_path):
        actual_rev = cmd_output('git', 'rev-parse', 'HEAD')[1].strip()
    assert actual_rev == getattr(path.submodule, rev)
    actual_status = get_short_git_status()['sub']
    assert actual_status == status
def test_added_file_not_in_pre_commits_list(temp_git_dir):
    with cwd(temp_git_dir):
        write_file('f.py', "print('hello world')")
        cmd_output('git', 'add', 'f.py')

        # Should pass even with a size of 0
        assert find_large_added_files(['g.py'], 0) == 0
def test_installed_from_venv(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        install(C.CONFIG_FILE, store)
        # No environment so pre-commit is not on the path when running!
        # Should still pick up the python from when we installed
        ret, output = _get_commit_output(
            tempdir_factory,
            env={
                'HOME': os.path.expanduser('~'),
                'PATH': _path_without_us(),
                'TERM': os.environ.get('TERM', ''),
                # Windows needs this to import `random`
                'SYSTEMROOT': os.environ.get('SYSTEMROOT', ''),
                # Windows needs this to resolve executables
                'PATHEXT': os.environ.get('PATHEXT', ''),
                # Git needs this to make a commit
                'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'],
                'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'],
                'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'],
                'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'],
            },
        )
        assert ret == 0
        assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_legacy_overwriting_legacy_hook(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        _write_legacy_hook(path)
        assert install(C.CONFIG_FILE, store) == 0
        _write_legacy_hook(path)
        # this previously crashed on windows.  See #1010
        assert install(C.CONFIG_FILE, store) == 0
Example #14
0
def in_conflicting_submodule(tempdir_factory):
    git_dir_1 = git_dir(tempdir_factory)
    git_dir_2 = git_dir(tempdir_factory)
    git_commit(msg=in_conflicting_submodule.__name__, cwd=git_dir_2)
    cmd_output('git', 'submodule', 'add', git_dir_2, 'sub', cwd=git_dir_1)
    with cwd(os.path.join(git_dir_1, 'sub')):
        _make_conflict()
        yield
def test_adding_something_with_conflict(temp_git_dir):
    with cwd(temp_git_dir):
        write_file('f.py', "print('hello world')")
        cmd_output('git', 'add', 'f.py')
        write_file('F.py', "print('hello world')")
        cmd_output('git', 'add', 'F.py')

        assert find_conflicting_filenames(['f.py', 'F.py']) == 1
def test_install_overwrite_no_existing_hooks(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        assert install(C.CONFIG_FILE, store, overwrite=True) == 0

        ret, output = _get_commit_output(tempdir_factory)
        assert ret == 0
        assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_failing_hooks_returns_nonzero(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'failing_hook_repo')
    with cwd(path):
        assert install(C.CONFIG_FILE, store) == 0

        ret, output = _get_commit_output(tempdir_factory)
        assert ret == 1
        assert FAILING_PRE_COMMIT_RUN.match(output)
def test_no_markdown_linebreak_ext_opt(filename, input_s, output, tmpdir):
    with cwd(tmpdir.strpath):
        with open(filename, 'w') as file_obj:
            file_obj.write(input_s)  # pragma: no branch (26 coverage bug)

        ret = fix_trailing_whitespace(['--no-markdown-linebreak-ext', filename])
        assert ret == 1
        assert open(filename).read() == output
def test_fixes_trailing_markdown_whitespace(filename, input_s, output, tmpdir):
    with cwd(tmpdir.strpath):
        with open(filename, 'w') as file_obj:
            file_obj.write(input_s)  # pragma: no branch (26 coverage bug)

        ret = fix_trailing_whitespace([filename])
        assert ret == 1
        assert open(filename).read() == output
def submodule_with_commits(tempdir_factory):
    path = git_dir(tempdir_factory)
    with cwd(path):
        git_commit()
        rev1 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip()
        git_commit()
        rev2 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip()
        yield auto_namedtuple(path=path, rev1=rev1, rev2=rev2)
Example #21
0
def test_types_hook_repository(cap_out, store, tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'types_repo')
    with cwd(git_path):
        stage_a_file('bar.py')
        stage_a_file('bar.notpy')
        ret, printed = _do_run(cap_out, store, git_path, run_opts())
        assert ret == 1
        assert b'bar.py' in printed
        assert b'bar.notpy' not in printed
Example #22
0
def aliased_repo(tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(git_path):
        with modify_config() as config:
            config['repos'][0]['hooks'].append(
                {'id': 'bash_hook', 'alias': 'foo_bash'},
            )
        stage_a_file()
        yield git_path
Example #23
0
def test_non_ascii_hook_id(repo_with_passing_hook, tempdir_factory):
    with cwd(repo_with_passing_hook):
        _, stdout, _ = cmd_output_mocked_pre_commit_home(
            sys.executable, '-m', 'pre_commit.main', 'run', '☃',
            retcode=None, tempdir_factory=tempdir_factory,
        )
        assert 'UnicodeDecodeError' not in stdout
        # Doesn't actually happen, but a reasonable assertion
        assert 'UnicodeEncodeError' not in stdout
def test_pre_push_force_push_without_fetch(tempdir_factory, store):
    upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    path1 = tempdir_factory.get()
    path2 = tempdir_factory.get()
    cmd_output('git', 'clone', upstream, path1)
    cmd_output('git', 'clone', upstream, path2)
    with cwd(path1):
        assert _get_commit_output(tempdir_factory)[0] == 0
        assert _get_push_output(tempdir_factory)[0] == 0

    with cwd(path2):
        install(C.CONFIG_FILE, store, hook_type='pre-push')
        assert _get_commit_output(tempdir_factory, msg='force!')[0] == 0

        retc, output = _get_push_output(tempdir_factory, opts=('--force',))
        assert retc == 0
        assert 'Bash hook' in output
        assert 'Passed' in output
def test_markdown_linebreak_ext_opt_all(filename, input_s, output, tmpdir):
    with cwd(tmpdir.strpath):
        with open(filename, 'w') as file_obj:
            file_obj.write(input_s)  # pragma: no branch (26 coverage bug)

        # need to make sure filename is not treated as argument to option
        ret = fix_trailing_whitespace(['--markdown-linebreak-ext=*',
                                       filename])
        assert ret == 1
        assert open(filename).read() == output
def test_allows_gitlfs(temp_git_dir):  # pragma: no cover
    with cwd(temp_git_dir):
        # Work around https://github.com/github/git-lfs/issues/913
        cmd_output('git', 'commit', '--allow-empty', '-m', 'foo')
        cmd_output('git', 'lfs', 'install')
        write_file('f.py', 'a' * 10000)
        cmd_output('git', 'lfs', 'track', 'f.py')
        cmd_output('git', 'add', '.')
        # Should succeed
        assert main(('--maxkb', '9', 'f.py')) == 0
def test_pre_push_integration_empty_push(tempdir_factory, store):
    upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    path = tempdir_factory.get()
    cmd_output('git', 'clone', upstream, path)
    with cwd(path):
        install(C.CONFIG_FILE, store, hook_type='pre-push')
        _get_push_output(tempdir_factory)
        retc, output = _get_push_output(tempdir_factory)
        assert output == 'Everything up-to-date\n'
        assert retc == 0
def test_file_conflicts_with_committed_file(temp_git_dir):
    with cwd(temp_git_dir):
        write_file('f.py', "print('hello world')")
        cmd_output('git', 'add', 'f.py')
        cmd_output('git', 'commit', '--no-verify', '-m', 'Add f.py')

        write_file('F.py', "print('hello world')")
        cmd_output('git', 'add', 'F.py')

        assert find_conflicting_filenames(['F.py']) == 1
def test_install_pre_commit_and_run_custom_path(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        cmd_output('git', 'mv', C.CONFIG_FILE, 'custom-config.yaml')
        git_commit(cwd=path)
        assert install('custom-config.yaml', store) == 0

        ret, output = _get_commit_output(tempdir_factory)
        assert ret == 0
        assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_installs_hooks_with_hooks_True(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        install(C.CONFIG_FILE, store, hooks=True)
        ret, output = _get_commit_output(
            tempdir_factory, pre_commit_home=store.directory,
        )

        assert ret == 0
        assert PRE_INSTALLED.match(output)
def test_hook_types_not_matched(capsys, tempdir_factory, mock_store_dir):
    config = {
        'repos': [
            {
                'repo': 'meta',
                'hooks': [
                    {
                        'id': 'check-useless-excludes',
                        'types': ['python'],
                    },
                ],
            },
        ],
    }

    repo = git_dir(tempdir_factory)
    add_config_to_repo(repo, config)

    with cwd(repo):
        assert check_hooks_apply.main(()) == 1

    out, _ = capsys.readouterr()
    assert 'check-useless-excludes does not apply to this repository' in out
Example #32
0
def test_hook_install_failure(mock_out_store_directory, tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'not_installable_repo')
    with cwd(git_path):
        install(Runner(git_path, C.CONFIG_FILE))

        _, stdout, _ = cmd_output_mocked_pre_commit_home(
            'git', 'commit', '-m', 'Commit!',
            # git commit puts pre-commit to stderr
            stderr=subprocess.STDOUT,
            retcode=None,
            encoding=None,
            tempdir_factory=tempdir_factory,
        )
        assert b'UnicodeDecodeError' not in stdout
        # Doesn't actually happen, but a reasonable assertion
        assert b'UnicodeEncodeError' not in stdout

        # Sanity check our output
        assert (
            b'An unexpected error has occurred: CalledProcessError: ' in
            stdout
        )
        assert '☃'.encode('UTF-8') + '²'.encode('latin1') in stdout
Example #33
0
def test_run_output_logfile(cap_out, store, tempdir_factory):
    expected_output = (
        b'This is STDOUT output\n',
        b'This is STDERR output\n',
    )

    git_path = make_consuming_repo(tempdir_factory, 'logfile_repo')
    with cwd(git_path):
        _test_run(
            cap_out,
            store,
            git_path, {},
            expected_output,
            expected_ret=1,
            stage=True,
        )
    logfile_path = os.path.join(git_path, 'test.log')
    assert os.path.exists(logfile_path)
    with open(logfile_path, 'rb') as logfile:
        logfile_content = logfile.readlines()

    for expected_output_part in expected_output:
        assert expected_output_part in logfile_content
def test_hook_excludes_everything(capsys, tempdir_factory, mock_store_dir):
    config = {
        'repos': [
            {
                'repo': 'meta',
                'hooks': [
                    {
                        'id': 'check-useless-excludes',
                        'exclude': '.pre-commit-config.yaml',
                    },
                ],
            },
        ],
    }

    repo = git_dir(tempdir_factory)
    add_config_to_repo(repo, config)

    with cwd(repo):
        assert check_hooks_apply.main(()) == 1

    out, _ = capsys.readouterr()
    assert 'check-useless-excludes does not apply to this repository' in out
Example #35
0
def test_clone(store, tempdir_factory, log_info_mock):
    path = git_dir(tempdir_factory)
    with cwd(path):
        git_commit()
        rev = git.head_rev(path)
        git_commit()

    ret = store.clone(path, rev)
    # Should have printed some stuff
    assert log_info_mock.call_args_list[0][0][0].startswith(
        'Initializing environment for ', )

    # Should return a directory inside of the store
    assert os.path.exists(ret)
    assert ret.startswith(store.directory)
    # Directory should start with `repo`
    _, dirname = os.path.split(ret)
    assert dirname.startswith('repo')
    # Should be checked out to the rev we specified
    assert git.head_rev(ret) == rev

    # Assert there's an entry in the sqlite db for this
    assert store.select_all_repos() == [(path, rev, ret)]
Example #36
0
def test_lots_of_files(store, tempdir_factory):
    # windows xargs seems to have a bug, here's a regression test for
    # our workaround
    git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(git_path):
        # Override files so we run against them
        with modify_config() as config:
            config['repos'][0]['hooks'][0]['files'] = ''

        # Write a crap ton of files
        for i in range(400):
            filename = '{}{}'.format('a' * 100, i)
            open(filename, 'w').close()

        cmd_output('git', 'add', '.')
        install(C.CONFIG_FILE, store)

        git_commit(
            fn=cmd_output_mocked_pre_commit_home,
            # git commit puts pre-commit to stderr
            stderr=subprocess.STDOUT,
            tempdir_factory=tempdir_factory,
        )
def test_replace_old_commit_script(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        runner = Runner(path, C.CONFIG_FILE)

        # Install a script that looks like our old script
        pre_commit_contents = io.open(resource_filename('hook-tmpl')).read()
        new_contents = pre_commit_contents.replace(
            CURRENT_HASH,
            PRIOR_HASHES[-1],
        )

        mkdirp(os.path.join(path, '.git/hooks'))
        with io.open(os.path.join(path, '.git/hooks/pre-commit'), 'w') as f:
            f.write(new_contents)
        make_executable(f.name)

        # Install normally
        assert install(runner, store) == 0

        ret, output = _get_commit_output(tempdir_factory)
        assert ret == 0
        assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_useless_exclude_global(capsys, tempdir_factory):
    config = {
        'exclude':
        'foo',
        'repos': [
            {
                'repo': 'meta',
                'hooks': [{
                    'id': 'check-useless-excludes'
                }],
            },
        ],
    }

    repo = git_dir(tempdir_factory)
    add_config_to_repo(repo, config)

    with cwd(repo):
        assert check_useless_excludes.main(()) == 1

    out, _ = capsys.readouterr()
    out = out.strip()
    assert "The global exclude pattern 'foo' does not match any files" == out
Example #39
0
def test_show_diff_on_failure(
    capfd,
    cap_out,
    tempdir_factory,
    mock_out_store_directory,
):
    git_path = make_consuming_repo(
        tempdir_factory,
        'modified_file_returns_zero_repo',
    )
    with cwd(git_path):
        stage_a_file('bar.py')
        _test_run(
            cap_out,
            git_path,
            {'show_diff_on_failure': True},
            # we're only testing the output after running
            (),
            1,
            True,
        )
    out, _ = capfd.readouterr()
    assert 'diff --git' in out
Example #40
0
def test_post_checkout_hook(cap_out, store, tempdir_factory):
    path = git_dir(tempdir_factory)
    config = {
        'repo': 'meta',
        'hooks': [
            {
                'id': 'identity',
                'stages': ['post-checkout']
            },
        ],
    }
    add_config_to_repo(path, config)

    with cwd(path):
        _test_run(
            cap_out,
            store,
            path,
            {'hook_stage': 'post-checkout'},
            expected_outputs=[b'identity...'],
            expected_ret=0,
            stage=False,
        )
Example #41
0
def test_pre_push_legacy(tempdir_factory, store):
    upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    path = tempdir_factory.get()
    cmd_output('git', 'clone', upstream, path)
    with cwd(path):
        os.makedirs(os.path.join(path, '.git/hooks'), exist_ok=True)
        with open(os.path.join(path, '.git/hooks/pre-push'), 'w') as f:
            f.write(
                '#!/usr/bin/env bash\n'
                'set -eu\n'
                'read lr ls rr rs\n'
                'test -n "$lr" -a -n "$ls" -a -n "$rr" -a -n "$rs"\n'
                'echo legacy\n', )
        make_executable(f.name)

        install(C.CONFIG_FILE, store, hook_types=['pre-push'])
        assert _get_commit_output(tempdir_factory)[0] == 0

        retc, output = _get_push_output(tempdir_factory)
        assert retc == 0
        first_line, _, third_line = output.splitlines()[:3]
        assert first_line == 'legacy'
        assert third_line.startswith('Bash hook')
        assert third_line.endswith('Passed')
Example #42
0
def test_environment_not_sourced(tempdir_factory, store):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        # Patch the executable to simulate rming virtualenv
        with mock.patch.object(sys, 'executable', '/does-not-exist'):
            assert not install(C.CONFIG_FILE, store, hook_types=['pre-commit'])

        # Use a specific homedir to ignore --user installs
        homedir = tempdir_factory.get()
        ret, out = git_commit(
            env={
                'HOME': homedir,
                'PATH': _path_without_us(),
                # Git needs this to make a commit
                'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'],
                'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'],
                'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'],
                'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'],
            },
            retcode=None,
        )
        assert ret == 1
        assert out == ('`pre-commit` not found.  '
                       'Did you forget to activate your virtualenv?\n')
def test_hook_types_excludes_everything(
    capsys,
    tempdir_factory,
    mock_store_dir,
):
    config = OrderedDict((
        ('repo', 'meta'),
        (
            'hooks',
            (OrderedDict((
                ('id', 'check-useless-excludes'),
                ('exclude_types', ['yaml']),
            )), ),
        ),
    ))

    repo = git_dir(tempdir_factory)
    add_config_to_repo(repo, config)

    with cwd(repo):
        assert check_hooks_apply.main(()) == 1

    out, _ = capsys.readouterr()
    assert 'check-useless-excludes does not apply to this repository' in out
Example #44
0
def test_install_existing_hooks_no_overwrite(tempdir_factory):
    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        runner = Runner(path, C.CONFIG_FILE)

        # Write out an "old" hook
        mkdirp(os.path.dirname(runner.pre_commit_path))
        with io.open(runner.pre_commit_path, 'w') as hook_file:
            hook_file.write('#!/usr/bin/env bash\necho "legacy hook"\n')
        make_executable(runner.pre_commit_path)

        # Make sure we installed the "old" hook correctly
        ret, output = _get_commit_output(tempdir_factory, touch_file='baz')
        assert ret == 0
        assert EXISTING_COMMIT_RUN.match(output)

        # Now install pre-commit (no-overwrite)
        assert install(runner) == 0

        # We should run both the legacy and pre-commit hooks
        ret, output = _get_commit_output(tempdir_factory)
        assert ret == 0
        assert output.startswith('legacy hook\n')
        assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
def test_post_commit_integration(tempdir_factory, store):
    path = git_dir(tempdir_factory)
    config = [
        {
            'repo': 'local',
            'hooks': [{
                'id': 'post-commit',
                'name': 'Post commit',
                'entry': 'touch post-commit.tmp',
                'language': 'system',
                'always_run': True,
                'verbose': True,
                'stages': ['post-commit'],
            }],
        },
    ]
    write_config(path, config)
    with cwd(path):
        _get_commit_output(tempdir_factory)
        assert not os.path.exists('post-commit.tmp')

        install(C.CONFIG_FILE, store, hook_types=['post-commit'])
        _get_commit_output(tempdir_factory)
        assert os.path.exists('post-commit.tmp')
def test_init_templatedir(tmpdir, tempdir_factory, store, cap_out):
    target = str(tmpdir.join('tmpl'))
    init_templatedir(C.CONFIG_FILE, store, target, hook_type='pre-commit')
    lines = cap_out.get().splitlines()
    assert lines[0].startswith('pre-commit installed at ')
    assert lines[1] == (
        '[WARNING] `init.templateDir` not set to the target directory'
    )
    assert lines[2].startswith(
        '[WARNING] maybe `git config --global init.templateDir',
    )

    with envcontext([('GIT_TEMPLATE_DIR', target)]):
        path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')

        with cwd(path):
            retcode, output, _ = git_commit(
                fn=cmd_output_mocked_pre_commit_home,
                tempdir_factory=tempdir_factory,
                # git commit puts pre-commit to stderr
                stderr=subprocess.STDOUT,
            )
            assert retcode == 0
            assert 'Bash hook....' in output
def test_pre_merge_commit_integration(tempdir_factory, store):
    output_pattern = re_assert.Matches(
        r'^\[INFO\] Initializing environment for .+\n'
        r'Bash hook\.+Passed\n'
        r"Merge made by the '(ort|recursive)' strategy.\n"
        r' foo \| 0\n'
        r' 1 file changed, 0 insertions\(\+\), 0 deletions\(-\)\n'
        r' create mode 100644 foo\n$',
    )

    path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(path):
        ret = install(C.CONFIG_FILE, store, hook_types=['pre-merge-commit'])
        assert ret == 0

        cmd_output('git', 'checkout', 'master', '-b', 'feature')
        _get_commit_output(tempdir_factory)
        cmd_output('git', 'checkout', 'master')
        ret, output, _ = cmd_output_mocked_pre_commit_home(
            'git', 'merge', '--no-ff', '--no-edit', 'feature',
            tempdir_factory=tempdir_factory,
        )
        assert ret == 0
        output_pattern.assert_matches(output)
def test_valid_exclude(capsys, tempdir_factory):
    config = {
        'repos': [
            {
                'repo':
                'meta',
                'hooks': [
                    {
                        'id': 'check-useless-excludes',
                        'exclude': '.pre-commit-config.yaml',
                    },
                ],
            },
        ],
    }

    repo = git_dir(tempdir_factory)
    add_config_to_repo(repo, config)

    with cwd(repo):
        assert check_useless_excludes.main(()) == 0

    out, _ = capsys.readouterr()
    assert out == ''
Example #49
0
def _do_run(cap_out, store, repo, args, environ={}, config_file=C.CONFIG_FILE):
    with cwd(repo):  # replicates `main._adjust_args_and_chdir` behaviour
        ret = run(config_file, store, args, environ=environ)
    printed = cap_out.get_bytes()
    return ret, printed
Example #50
0
def repo_with_passing_hook(tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo')
    with cwd(git_path):
        yield git_path
Example #51
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 #52
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
Example #53
0
def _do_run(cap_out, repo, args, environ={}, config_file=C.CONFIG_FILE):
    runner = Runner(repo, config_file)
    with cwd(runner.git_root):  # replicates Runner.create behaviour
        ret = run(runner, args, environ=environ)
    printed = cap_out.get_bytes()
    return ret, printed
Example #54
0
def in_tmpdir(tmpdir):
    with cwd(tmpdir.strpath):
        yield tmpdir
Example #55
0
def in_tmpdir(tempdir_factory):
    path = tempdir_factory.get()
    with cwd(path):
        yield path
Example #56
0
def test_install_refuses_core_hookspath(tempdir_factory, store):
    path = git_dir(tempdir_factory)
    with cwd(path):
        cmd_output('git', 'config', '--local', 'core.hooksPath', 'hooks')
        runner = Runner(path, C.CONFIG_FILE)
        assert install(runner, store)
Example #57
0
def repo_with_failing_hook(tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'failing_hook_repo')
    with cwd(git_path):
        yield git_path
Example #58
0
def test_is_not_in_merge_conflict(tempdir_factory):
    path = git_dir(tempdir_factory)
    with cwd(path):
        assert git.is_in_merge_conflict() is False
Example #59
0
def test_arbitrary_bytes_hook(cap_out, store, tempdir_factory):
    git_path = make_consuming_repo(tempdir_factory, 'arbitrary_bytes_repo')
    with cwd(git_path):
        _test_run(
            cap_out, store, git_path, {}, (b'\xe2\x98\x83\xb2\n',), 1, True,
        )
Example #60
0
def test_memoized_by_cwd_changes_with_different_cwd(memoized_by_cwd):
    ret = memoized_by_cwd('baz')
    with cwd('.git'):
        ret2 = memoized_by_cwd('baz')

    assert ret != ret2