def test_local_hooks_alt_config(tempdir_factory, mock_out_store_directory): config = OrderedDict( (('repo', 'local'), ('hooks', (OrderedDict(( ('id', 'arg-per-line'), ('name', 'Args per line hook'), ('entry', 'bin/hook.sh'), ('language', 'script'), ('files', ''), ('args', ['hello', 'world']), )), OrderedDict(( ('id', 'ugly-format-json'), ('name', 'Ugly format json'), ('entry', 'ugly-format-json'), ('language', 'python'), ('files', ''), )), OrderedDict(( ('id', 'do_not_commit'), ('name', 'Block if "DO NOT COMMIT" is found'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), )))))) git_path = git_dir(tempdir_factory) alt_config_file = 'alternate_config.yaml' add_config_to_repo(git_path, config, config_file=alt_config_file) runner = Runner(git_path, alt_config_file) assert len(runner.repositories) == 1 assert len(runner.repositories[0].hooks) == 3
def test_local_hook_passes(repo_with_passing_hook, mock_out_store_directory): config = OrderedDict(( ('repo', 'local'), ('hooks', (OrderedDict(( ('id', 'flake8'), ('name', 'flake8'), ('entry', 'python -m flake8.__main__'), ('language', 'system'), ('files', r'\.py$'), )), OrderedDict(( ('id', 'do_not_commit'), ('name', 'Block if "DO NOT COMMIT" is found'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), )))) )) add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( repo_with_passing_hook, options={}, expected_outputs=[b''], expected_ret=0, stage=False )
def test_local_hook_fails( cap_out, repo_with_passing_hook, mock_out_store_directory, ): config = OrderedDict((('repo', 'local'), ('hooks', [ OrderedDict(( ('id', 'no-todo'), ('name', 'No TODO'), ('entry', 'sh -c "! grep -iI todo $@" --'), ('language', 'system'), ('files', ''), )) ]))) add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( cap_out, repo_with_passing_hook, opts={}, expected_outputs=[b''], expected_ret=1, stage=False, )
def test_local_hook_for_stages( cap_out, repo_with_passing_hook, mock_out_store_directory, stage_for_first_hook, stage_for_second_hook, hook_stage, expected_output, ): config = OrderedDict( (('repo', 'local'), ('hooks', (OrderedDict( (('id', 'flake8'), ('name', 'hook 1'), ('entry', 'python -m flake8.__main__'), ('language', 'system'), ('files', r'\.py$'), ('stages', stage_for_first_hook))), OrderedDict( (('id', 'do_not_commit'), ('name', 'hook 2'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), ('stages', stage_for_second_hook))))))) add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run(cap_out, repo_with_passing_hook, {'hook_stage': hook_stage}, expected_outputs=expected_output, expected_ret=0, stage=False)
def config_with_local_hooks(): return OrderedDict((('repo', 'local'), ('hooks', [ OrderedDict(( ('id', 'do_not_commit'), ('name', 'Block if "DO NOT COMMIT" is found'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), )) ])))
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
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', repo_path), ('sha', sha or get_head_sha(repo_path)), ( 'hooks', hooks or [OrderedDict((('id', hook['id']),)) for hook in manifest], ), )) if check: wrapped_config = apply_defaults([config], CONFIG_JSON_SCHEMA) validate_config_extra(wrapped_config) return wrapped_config[0] else: return config
def test_hook_disppearing_repo_raises(hook_disappearing_repo, runner_with_mocked_store): config = make_config_from_repo( hook_disappearing_repo.path, sha=hook_disappearing_repo.original_sha, hooks=[OrderedDict((('id', 'foo'), ))], ) with pytest.raises(RepositoryCannotBeUpdatedError): _update_repository(config, runner_with_mocked_store)
def test_local_hooks(tempdir_factory, mock_out_store_directory): config = OrderedDict( (('repo', 'local'), ('hooks', (OrderedDict(( ('id', 'arg-per-line'), ('name', 'Args per line hook'), ('entry', 'bin/hook.sh'), ('language', 'script'), ('files', ''), ('args', ['hello', 'world']), )), OrderedDict(( ('id', 'do_not_commit'), ('name', 'Block if "DO NOT COMMIT" is found'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), )))))) git_path = git_dir(tempdir_factory) add_config_to_repo(git_path, config) runner = Runner(git_path, C.CONFIG_FILE) assert len(runner.repositories) == 1 assert len(runner.repositories[0].hooks) == 2
def test_autoupdate_hook_disappearing_repo(hook_disappearing_repo, in_tmpdir, mock_out_store_directory): config = make_config_from_repo( hook_disappearing_repo.path, sha=hook_disappearing_repo.original_sha, hooks=[OrderedDict((('id', 'foo'), ))], check=False, ) write_config('.', config) before = open(C.CONFIG_FILE).read() runner = Runner('.') ret = autoupdate(runner) after = open(C.CONFIG_FILE).read() assert ret == 1 assert before == after