This commit is contained in:
Thierry Deo 2017-02-15 21:27:49 +00:00 committed by GitHub
commit 908d45a144
17 changed files with 133 additions and 81 deletions

View file

@ -30,7 +30,7 @@ def _update_repo(repo_config, runner, tags_only):
Args: Args:
repo_config - A config for a repository repo_config - A config for a repository
""" """
repo = Repository.create(repo_config, runner.store) repo = Repository.create(repo_config, runner.store, runner.git_root)
with cwd(repo.repo_path_getter.repo_path): with cwd(repo.repo_path_getter.repo_path):
cmd_output('git', 'fetch') cmd_output('git', 'fetch')
@ -51,7 +51,7 @@ def _update_repo(repo_config, runner, tags_only):
# Construct a new config with the head sha # Construct a new config with the head sha
new_config = OrderedDict(repo_config) new_config = OrderedDict(repo_config)
new_config['sha'] = rev new_config['sha'] = rev
new_repo = Repository.create(new_config, runner.store) new_repo = Repository.create(new_config, runner.store, runner.git_root)
# See if any of our hooks were deleted with the new commits # See if any of our hooks were deleted with the new commits
hooks = {hook['id'] for hook in repo.repo_config['hooks']} hooks = {hook['id'] for hook in repo.repo_config['hooks']}

View file

@ -58,6 +58,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): # pragma: windows no cover ): # pragma: windows no cover
assert repo_cmd_runner.exists('Dockerfile'), ( assert repo_cmd_runner.exists('Dockerfile'), (
'No Dockerfile was found in the hook repository' 'No Dockerfile was found in the hook repository'

View file

@ -48,6 +48,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): ):
helpers.assert_version_default('golang', version) helpers.assert_version_default('golang', version)
directory = repo_cmd_runner.path( directory = repo_cmd_runner.path(

View file

@ -37,6 +37,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): # pragma: windows no cover ): # pragma: windows no cover
additional_dependencies = tuple(additional_dependencies) additional_dependencies = tuple(additional_dependencies)
assert repo_cmd_runner.exists('package.json') assert repo_cmd_runner.exists('package.json')

View file

@ -13,6 +13,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): ):
"""Installation for pcre type is a noop.""" """Installation for pcre type is a noop."""
raise AssertionError('Cannot install pcre repo.') raise AssertionError('Cannot install pcre repo.')

View file

@ -58,6 +58,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): ):
additional_dependencies = tuple(additional_dependencies) additional_dependencies = tuple(additional_dependencies)
directory = helpers.environment_dir(ENVIRONMENT_DIR, version) directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
@ -73,10 +74,12 @@ def install_environment(
else: else:
venv_cmd.extend(['-p', os.path.realpath(sys.executable)]) venv_cmd.extend(['-p', os.path.realpath(sys.executable)])
repo_cmd_runner.run(venv_cmd, cwd='/') repo_cmd_runner.run(venv_cmd, cwd='/')
to_install = () if is_local_hook else ('.',)
to_install += additional_dependencies
with in_env(repo_cmd_runner, version): with in_env(repo_cmd_runner, version):
helpers.run_setup_cmd( helpers.run_setup_cmd(
repo_cmd_runner, repo_cmd_runner,
('pip', 'install', '.') + additional_dependencies, ('pip', 'install') + to_install,
) )

View file

@ -100,6 +100,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): # pragma: windows no cover ): # pragma: windows no cover
additional_dependencies = tuple(additional_dependencies) additional_dependencies = tuple(additional_dependencies)
directory = helpers.environment_dir(ENVIRONMENT_DIR, version) directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
@ -115,15 +116,18 @@ def install_environment(
_install_ruby(repo_cmd_runner, version) _install_ruby(repo_cmd_runner, version)
# Need to call this after installing to set up the shims # Need to call this after installing to set up the shims
helpers.run_setup_cmd(repo_cmd_runner, ('rbenv', 'rehash')) helpers.run_setup_cmd(repo_cmd_runner, ('rbenv', 'rehash'))
if not is_local_hook:
helpers.run_setup_cmd( helpers.run_setup_cmd(
repo_cmd_runner, repo_cmd_runner,
('gem', 'build') + repo_cmd_runner.star('.gemspec'), ('gem', 'build') + repo_cmd_runner.star('.gemspec'),
) )
to_install = () if is_local_hook else repo_cmd_runner.star('.gem')
to_install += additional_dependencies
helpers.run_setup_cmd( helpers.run_setup_cmd(
repo_cmd_runner, repo_cmd_runner,
( (
('gem', 'install', '--no-ri', '--no-rdoc') + ('gem', 'install', '--no-ri', '--no-rdoc') +
repo_cmd_runner.star('.gem') + additional_dependencies to_install
), ),
) )

View file

@ -11,6 +11,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): ):
"""Installation for script type is a noop.""" """Installation for script type is a noop."""
raise AssertionError('Cannot install script repo.') raise AssertionError('Cannot install script repo.')

View file

@ -32,6 +32,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): # pragma: windows no cover ): # pragma: windows no cover
helpers.assert_version_default('swift', version) helpers.assert_version_default('swift', version)
helpers.assert_no_additional_deps('swift', additional_dependencies) helpers.assert_no_additional_deps('swift', additional_dependencies)

View file

@ -11,6 +11,7 @@ def install_environment(
repo_cmd_runner, repo_cmd_runner,
version='default', version='default',
additional_dependencies=(), additional_dependencies=(),
is_local_hook=False,
): ):
"""Installation for system type is a noop.""" """Installation for system type is a noop."""
raise AssertionError('Cannot install system repo.') raise AssertionError('Cannot install system repo.')

View file

@ -38,13 +38,14 @@ class Repository(object):
self.__installed = False self.__installed = False
@classmethod @classmethod
def create(cls, config, store): def create(cls, config, store, owner):
if is_local_hooks(config):
return LocalRepository(config)
else:
repo_path_getter = store.get_repo_path_getter( repo_path_getter = store.get_repo_path_getter(
config['repo'], config['sha'] config['repo'],
owner if is_local_hooks(config) else config['sha'],
) )
if is_local_hooks(config):
return LocalRepository(config, repo_path_getter)
else:
return cls(config, repo_path_getter) return cls(config, repo_path_getter)
@cached_property @cached_property
@ -104,6 +105,16 @@ class Repository(object):
def cmd_runner(self): def cmd_runner(self):
return PrefixedCommandRunner(self.repo_path_getter.repo_path) return PrefixedCommandRunner(self.repo_path_getter.repo_path)
@cached_property
def local_cmd_runner(self):
return self.cmd_runner
def language_cmd_runner(self, language):
if language in ['script', 'system']:
return self.local_cmd_runner
else:
return self.cmd_runner
def require_installed(self): def require_installed(self):
if self.__installed: if self.__installed:
return return
@ -179,6 +190,7 @@ class Repository(object):
language.install_environment( language.install_environment(
self.cmd_runner, language_version, self.cmd_runner, language_version,
self.additional_dependencies[language_name][language_version], self.additional_dependencies[language_name][language_version],
is_local_hooks(self.repo_config),
) )
# Write our state to indicate we're installed # Write our state to indicate we're installed
write_state(venv, language_name, language_version) write_state(venv, language_name, language_version)
@ -192,14 +204,11 @@ class Repository(object):
""" """
self.require_installed() self.require_installed()
return languages[hook['language']].run_hook( return languages[hook['language']].run_hook(
self.cmd_runner, hook, file_args, self.language_cmd_runner(hook['language']), hook, file_args,
) )
class LocalRepository(Repository): class LocalRepository(Repository):
def __init__(self, repo_config):
super(LocalRepository, self).__init__(repo_config, None)
@cached_property @cached_property
def hooks(self): def hooks(self):
return tuple( return tuple(
@ -208,13 +217,9 @@ class LocalRepository(Repository):
) )
@cached_property @cached_property
def cmd_runner(self): def local_cmd_runner(self):
return PrefixedCommandRunner(git.get_root()) return PrefixedCommandRunner(git.get_root())
@cached_property
def manifest(self):
raise NotImplementedError
class _UniqueList(list): class _UniqueList(list):
def __init__(self): def __init__(self):

View file

@ -41,7 +41,9 @@ class Runner(object):
def repositories(self): def repositories(self):
"""Returns a tuple of the configured repositories.""" """Returns a tuple of the configured repositories."""
config = load_config(self.config_file_path) config = load_config(self.config_file_path)
repositories = tuple(Repository.create(x, self.store) for x in config) repositories = tuple(
Repository.create(x, self.store, self.git_root) for x in config
)
for repository in repositories: for repository in repositories:
repository.require_installed() repository.require_installed()
return repositories return repositories

View file

@ -9,6 +9,7 @@ import tempfile
from cached_property import cached_property from cached_property import cached_property
from pre_commit.clientlib.validate_config import _LOCAL_HOOKS_MAGIC_REPO_STRING
from pre_commit.prefixed_command_runner import PrefixedCommandRunner from pre_commit.prefixed_command_runner import PrefixedCommandRunner
from pre_commit.util import clean_path_on_failure from pre_commit.util import clean_path_on_failure
from pre_commit.util import cmd_output from pre_commit.util import cmd_output
@ -43,7 +44,7 @@ class Store(object):
@cached_property @cached_property
def repo_path(self): def repo_path(self):
return self._store.clone(self._repo, self._ref) return self._store.initialize_repo(self._repo, self._ref)
def __init__(self, directory=None): def __init__(self, directory=None):
if directory is None: if directory is None:
@ -97,39 +98,44 @@ class Store(object):
self._create() self._create()
self.__created = True self.__created = True
def clone(self, url, ref): def initialize_repo(self, repo, sha):
"""Clone the given url and checkout the specific ref.""" """Initializes the repository by cloning a remote or preparing an
empty local folder for local hooks. If the repo if 'local',
the sha used is the path to git_root of this repo so that several
local hooks for different projects are separated."""
self.require_created() self.require_created()
# Check if we already exist # Check if we already exist
with sqlite3.connect(self.db_path) as db: with sqlite3.connect(self.db_path) as db:
result = db.execute( result = db.execute(
'SELECT path FROM repos WHERE repo = ? AND ref = ?', 'SELECT path FROM repos WHERE repo = ? AND ref = ?',
[url, ref], [repo, sha],
).fetchone() ).fetchone()
if result: if result:
return result[0] return result[0]
logger.info('Initializing environment for {}.'.format(url)) logger.info('Initializing environment for {}.'.format(repo))
dir = tempfile.mkdtemp(prefix='repo', dir=self.directory) dir = tempfile.mkdtemp(prefix='repo', dir=self.directory)
if repo != _LOCAL_HOOKS_MAGIC_REPO_STRING:
with clean_path_on_failure(dir): with clean_path_on_failure(dir):
cmd_output( cmd_output(
'git', 'clone', '--no-checkout', url, dir, env=no_git_env(), 'git', 'clone', '--no-checkout', repo, dir,
env=no_git_env(),
) )
with cwd(dir): with cwd(dir):
cmd_output('git', 'reset', ref, '--hard', env=no_git_env()) cmd_output('git', 'reset', sha, '--hard', env=no_git_env())
# Update our db with the created repo # Update our db with the created repo
with sqlite3.connect(self.db_path) as db: with sqlite3.connect(self.db_path) as db:
db.execute( db.execute(
'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)', 'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)',
[url, ref, dir], [repo, sha, dir],
) )
return dir return dir
def get_repo_path_getter(self, repo, ref): def get_repo_path_getter(self, repo, sha):
return self.RepoPathGetter(repo, ref, self) return self.RepoPathGetter(repo, sha, self)
@cached_property @cached_property
def cmd_runner(self): def cmd_runner(self):

View file

@ -66,14 +66,14 @@ def modify_config(path='.', commit=True):
cmd_output('git', 'commit', '-am', 'update config', cwd=path) cmd_output('git', 'commit', '-am', 'update config', cwd=path)
def config_with_local_hooks(): def config_with_local_hooks(language='pcre'):
return OrderedDict(( return OrderedDict((
('repo', 'local'), ('repo', 'local'),
('hooks', [OrderedDict(( ('hooks', [OrderedDict((
('id', 'do_not_commit'), ('id', language),
('name', 'Block if "DO NOT COMMIT" is found'), ('name', language),
('entry', 'DO NOT COMMIT'), ('entry', language),
('language', 'pcre'), ('language', language),
('files', '^(.*)$'), ('files', '^(.*)$'),
))]) ))])
)) ))

View file

@ -11,10 +11,15 @@ from pre_commit.languages.all import languages
@pytest.mark.parametrize('language', all_languages) @pytest.mark.parametrize('language', all_languages)
def test_install_environment_argspec(language): def test_install_environment_argspec(language):
expected_argspec = inspect.ArgSpec( expected_argspec = inspect.ArgSpec(
args=['repo_cmd_runner', 'version', 'additional_dependencies'], args=[
'repo_cmd_runner',
'version',
'additional_dependencies',
'is_local_hook',
],
varargs=None, varargs=None,
keywords=None, keywords=None,
defaults=('default', ()), defaults=('default', (), False),
) )
argspec = inspect.getargspec(languages[language].install_environment) argspec = inspect.getargspec(languages[language].install_environment)
assert argspec == expected_argspec assert argspec == expected_argspec

View file

@ -50,7 +50,7 @@ def _test_hook_repo(
): ):
path = make_repo(tempdir_factory, repo_path) path = make_repo(tempdir_factory, repo_path)
config = make_config_from_repo(path, **(config_kwargs or {})) config = make_config_from_repo(path, **(config_kwargs or {}))
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
hook_dict = [ hook_dict = [
hook for repo_hook_id, hook in repo.hooks if repo_hook_id == hook_id hook for repo_hook_id, hook in repo.hooks if repo_hook_id == hook_id
][0] ][0]
@ -108,7 +108,7 @@ def test_switch_language_versions_doesnt_clobber(tempdir_factory, store):
config = make_config_from_repo( config = make_config_from_repo(
path, hooks=[{'id': 'python3-hook', 'language_version': version}], path, hooks=[{'id': 'python3-hook', 'language_version': version}],
) )
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
hook_dict, = [ hook_dict, = [
hook hook
for repo_hook_id, hook in repo.hooks for repo_hook_id, hook in repo.hooks
@ -462,7 +462,7 @@ def test_repo_url(mock_repo_config):
def test_languages(tempdir_factory, store): def test_languages(tempdir_factory, store):
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
assert repo.languages == {('python', 'default')} assert repo.languages == {('python', 'default')}
@ -471,7 +471,7 @@ def test_additional_dependencies(tempdir_factory, store):
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
config['hooks'][0]['additional_dependencies'] = ['pep8'] config['hooks'][0]['additional_dependencies'] = ['pep8']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
assert repo.additional_dependencies['python']['default'] == ['pep8'] assert repo.additional_dependencies['python']['default'] == ['pep8']
@ -483,7 +483,7 @@ def test_additional_dependencies_duplicated(
config = make_config_from_repo(path) config = make_config_from_repo(path)
config['hooks'][0]['additional_dependencies'] = [ config['hooks'][0]['additional_dependencies'] = [
'thread_safe', 'tins', 'thread_safe'] 'thread_safe', 'tins', 'thread_safe']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
assert repo.additional_dependencies['ruby']['default'] == [ assert repo.additional_dependencies['ruby']['default'] == [
'thread_safe', 'tins'] 'thread_safe', 'tins']
@ -493,7 +493,7 @@ def test_additional_python_dependencies_installed(tempdir_factory, store):
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
config['hooks'][0]['additional_dependencies'] = ['mccabe'] config['hooks'][0]['additional_dependencies'] = ['mccabe']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
with python.in_env(repo.cmd_runner, 'default'): with python.in_env(repo.cmd_runner, 'default'):
output = cmd_output('pip', 'freeze', '-l')[1] output = cmd_output('pip', 'freeze', '-l')[1]
@ -505,11 +505,11 @@ def test_additional_dependencies_roll_forward(tempdir_factory, store):
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
# Run the repo once without additional_dependencies # Run the repo once without additional_dependencies
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
# Now run it with additional_dependencies # Now run it with additional_dependencies
config['hooks'][0]['additional_dependencies'] = ['mccabe'] config['hooks'][0]['additional_dependencies'] = ['mccabe']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
# We should see our additional dependency installed # We should see our additional dependency installed
with python.in_env(repo.cmd_runner, 'default'): with python.in_env(repo.cmd_runner, 'default'):
@ -526,7 +526,7 @@ def test_additional_ruby_dependencies_installed(
path = make_repo(tempdir_factory, 'ruby_hooks_repo') path = make_repo(tempdir_factory, 'ruby_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
config['hooks'][0]['additional_dependencies'] = ['thread_safe', 'tins'] config['hooks'][0]['additional_dependencies'] = ['thread_safe', 'tins']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
with ruby.in_env(repo.cmd_runner, 'default'): with ruby.in_env(repo.cmd_runner, 'default'):
output = cmd_output('gem', 'list', '--local')[1] output = cmd_output('gem', 'list', '--local')[1]
@ -544,7 +544,7 @@ def test_additional_node_dependencies_installed(
config = make_config_from_repo(path) config = make_config_from_repo(path)
# Careful to choose a small package that's not depped by npm # Careful to choose a small package that's not depped by npm
config['hooks'][0]['additional_dependencies'] = ['lodash'] config['hooks'][0]['additional_dependencies'] = ['lodash']
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
with node.in_env(repo.cmd_runner, 'default'): with node.in_env(repo.cmd_runner, 'default'):
cmd_output('npm', 'config', 'set', 'global', 'true') cmd_output('npm', 'config', 'set', 'global', 'true')
@ -561,7 +561,7 @@ def test_additional_golang_dependencies_installed(
# A small go package # A small go package
deps = ['github.com/golang/example/hello'] deps = ['github.com/golang/example/hello']
config['hooks'][0]['additional_dependencies'] = deps config['hooks'][0]['additional_dependencies'] = deps
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
binaries = os.listdir(repo.cmd_runner.path( binaries = os.listdir(repo.cmd_runner.path(
helpers.environment_dir(golang.ENVIRONMENT_DIR, 'default'), 'bin', helpers.environment_dir(golang.ENVIRONMENT_DIR, 'default'), 'bin',
@ -571,10 +571,38 @@ def test_additional_golang_dependencies_installed(
assert 'hello' in binaries assert 'hello' in binaries
@skipif_slowtests_false
@xfailif_windows_no_ruby
@pytest.mark.integration
def test_install_local_ruby_hook(
tempdir_factory, store,
): # pragma: no cover (non-windows)
config = config_with_local_hooks('ruby')
config['hooks'][0]['additional_dependencies'] = ['thread_safe']
repo = Repository.create(config, store, '/path/to/repo/')
repo.require_installed()
with ruby.in_env(repo.cmd_runner, 'default'):
output = cmd_output('gem', 'list', '--local')[1]
assert 'thread_safe' in output
@pytest.mark.integration
def test_install_local_python_hook(
tempdir_factory, store,
): # pragma: no cover (non-windows)
config = config_with_local_hooks('python')
config['hooks'][0]['additional_dependencies'] = ['mccabe']
repo = Repository.create(config, store, '/path/to/repo/')
repo.require_installed()
with python.in_env(repo.cmd_runner, 'default'):
output = cmd_output('pip', 'freeze', '-l')[1]
assert 'mccabe' in output
def test_reinstall(tempdir_factory, store, log_info_mock): def test_reinstall(tempdir_factory, store, log_info_mock):
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
# We print some logging during clone (1) + install (3) # We print some logging during clone (1) + install (3)
assert log_info_mock.call_count == 4 assert log_info_mock.call_count == 4
@ -583,7 +611,7 @@ def test_reinstall(tempdir_factory, store, log_info_mock):
repo.require_installed() repo.require_installed()
assert log_info_mock.call_count == 0 assert log_info_mock.call_count == 0
# Reinstall on another run should not trigger another install # Reinstall on another run should not trigger another install
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
assert log_info_mock.call_count == 0 assert log_info_mock.call_count == 0
@ -592,7 +620,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
"""Regression test for #186.""" """Regression test for #186."""
path = make_repo(tempdir_factory, 'python_hooks_repo') path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
hook = repo.hooks[0][1] hook = repo.hooks[0][1]
class MyKeyboardInterrupt(KeyboardInterrupt): class MyKeyboardInterrupt(KeyboardInterrupt):
@ -629,7 +657,7 @@ def test_really_long_file_paths(tempdir_factory, store):
config = make_config_from_repo(path) config = make_config_from_repo(path)
with cwd(really_long_path): with cwd(really_long_path):
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
repo.require_installed() repo.require_installed()
@ -638,11 +666,11 @@ def test_config_overrides_repo_specifics(tempdir_factory, store):
path = make_repo(tempdir_factory, 'script_hooks_repo') path = make_repo(tempdir_factory, 'script_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
assert repo.hooks[0][1]['files'] == '' assert repo.hooks[0][1]['files'] == ''
# Set the file regex to something else # Set the file regex to something else
config['hooks'][0]['files'] = '\\.sh$' config['hooks'][0]['files'] = '\\.sh$'
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
assert repo.hooks[0][1]['files'] == '\\.sh$' assert repo.hooks[0][1]['files'] == '\\.sh$'
@ -662,28 +690,20 @@ def test_tags_on_repositories(in_tmpdir, tempdir_factory, store):
) )
repo_1 = Repository.create( repo_1 = Repository.create(
make_config_from_repo(git_dir_1, sha=tag), store, make_config_from_repo(git_dir_1, sha=tag), store, git_dir_1
) )
ret = repo_1.run_hook(repo_1.hooks[0][1], ['-L']) ret = repo_1.run_hook(repo_1.hooks[0][1], ['-L'])
assert ret[0] == 0 assert ret[0] == 0
assert ret[1].strip() == _norm_pwd(in_tmpdir) assert ret[1].strip() == _norm_pwd(in_tmpdir)
repo_2 = Repository.create( repo_2 = Repository.create(
make_config_from_repo(git_dir_2, sha=tag), store, make_config_from_repo(git_dir_2, sha=tag), store, git_dir_2
) )
ret = repo_2.run_hook(repo_2.hooks[0][1], ['bar']) ret = repo_2.run_hook(repo_2.hooks[0][1], ['bar'])
assert ret[0] == 0 assert ret[0] == 0
assert ret[1] == b'bar\nHello World\n' assert ret[1] == b'bar\nHello World\n'
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
@pytest.yield_fixture @pytest.yield_fixture
def fake_log_handler(): def fake_log_handler():
handler = mock.Mock(level=logging.INFO) handler = mock.Mock(level=logging.INFO)
@ -697,7 +717,7 @@ def test_hook_id_not_present(tempdir_factory, store, fake_log_handler):
path = make_repo(tempdir_factory, 'script_hooks_repo') path = make_repo(tempdir_factory, 'script_hooks_repo')
config = make_config_from_repo(path) config = make_config_from_repo(path)
config['hooks'][0]['id'] = 'i-dont-exist' config['hooks'][0]['id'] = 'i-dont-exist'
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
repo.install() repo.install()
assert fake_log_handler.handle.call_args[0][0].msg == ( assert fake_log_handler.handle.call_args[0][0].msg == (
@ -712,7 +732,7 @@ def test_too_new_version(tempdir_factory, store, fake_log_handler):
with modify_manifest(path) as manifest: with modify_manifest(path) as manifest:
manifest[0]['minimum_pre_commit_version'] = '999.0.0' manifest[0]['minimum_pre_commit_version'] = '999.0.0'
config = make_config_from_repo(path) config = make_config_from_repo(path)
repo = Repository.create(config, store) repo = Repository.create(config, store, path)
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
repo.install() repo.install()
msg = fake_log_handler.handle.call_args[0][0].msg msg = fake_log_handler.handle.call_args[0][0].msg
@ -734,4 +754,4 @@ def test_versions_ok(tempdir_factory, store, version):
manifest[0]['minimum_pre_commit_version'] = version manifest[0]['minimum_pre_commit_version'] = version
config = make_config_from_repo(path) config = make_config_from_repo(path)
# Should succeed # Should succeed
Repository.create(config, store).install() Repository.create(config, store, path).install()

View file

@ -79,14 +79,14 @@ def test_does_not_recreate_if_directory_already_exists(store):
assert not os.path.exists(os.path.join(store.directory, 'README')) assert not os.path.exists(os.path.join(store.directory, 'README'))
def test_clone(store, tempdir_factory, log_info_mock): def test_initialize_repo(store, tempdir_factory, log_info_mock):
path = git_dir(tempdir_factory) path = git_dir(tempdir_factory)
with cwd(path): with cwd(path):
cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') cmd_output('git', 'commit', '--allow-empty', '-m', 'foo')
sha = get_head_sha(path) sha = get_head_sha(path)
cmd_output('git', 'commit', '--allow-empty', '-m', 'bar') cmd_output('git', 'commit', '--allow-empty', '-m', 'bar')
ret = store.clone(path, sha) ret = store.initialize_repo(path, sha)
# Should have printed some stuff # Should have printed some stuff
assert log_info_mock.call_args_list[0][0][0].startswith( assert log_info_mock.call_args_list[0][0][0].startswith(
'Initializing environment for ' 'Initializing environment for '
@ -98,7 +98,7 @@ def test_clone(store, tempdir_factory, log_info_mock):
# Directory should start with `repo` # Directory should start with `repo`
_, dirname = os.path.split(ret) _, dirname = os.path.split(ret)
assert dirname.startswith('repo') assert dirname.startswith('repo')
# Should be checked out to the sha we specified # Should be checked out to the sha we specifieds
assert get_head_sha(ret) == sha assert get_head_sha(ret) == sha
# Assert there's an entry in the sqlite db for this # Assert there's an entry in the sqlite db for this
@ -110,11 +110,11 @@ def test_clone(store, tempdir_factory, log_info_mock):
assert path == ret assert path == ret
def test_clone_cleans_up_on_checkout_failure(store): def test_initialize_repo_cleans_up_on_checkout_failure(store):
try: try:
# This raises an exception because you can't clone something that # This raises an exception because you can't clone something that
# doesn't exist! # doesn't exist!
store.clone('/i_dont_exist_lol', 'fake_sha') store.initialize_repo('/i_dont_exist_lol', 'fake_sha')
except Exception as e: except Exception as e:
assert '/i_dont_exist_lol' in five.text(e) assert '/i_dont_exist_lol' in five.text(e)
@ -130,7 +130,7 @@ def test_has_cmd_runner_at_directory(store):
assert ret.prefix_dir == store.directory + os.sep assert ret.prefix_dir == store.directory + os.sep
def test_clone_when_repo_already_exists(store): def test_initialize_repo_when_repo_already_exists(store):
# Create an entry in the sqlite db that makes it look like the repo has # Create an entry in the sqlite db that makes it look like the repo has
# been cloned. # been cloned.
store.require_created() store.require_created()
@ -141,7 +141,7 @@ def test_clone_when_repo_already_exists(store):
'VALUES ("fake_repo", "fake_ref", "fake_path")' 'VALUES ("fake_repo", "fake_ref", "fake_path")'
) )
assert store.clone('fake_repo', 'fake_ref') == 'fake_path' assert store.initialize_repo('fake_repo', 'fake_ref') == 'fake_path'
def test_require_created_when_directory_exists_but_not_db(store): def test_require_created_when_directory_exists_but_not_db(store):