mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-13 12:30:08 -06:00
Add first pass at migration mode.
This commit is contained in:
@@ -1,24 +1,44 @@
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import io
|
||||
import os
|
||||
import os.path
|
||||
import pkg_resources
|
||||
import stat
|
||||
|
||||
# This is used to identify the hook file we install
|
||||
IDENTIFYING_HASH = 'd8ee923c46731b42cd95cc869add4062'
|
||||
|
||||
|
||||
def is_our_pre_commit(filename):
|
||||
return IDENTIFYING_HASH in io.open(filename).read()
|
||||
|
||||
|
||||
def make_executable(filename):
|
||||
original_mode = os.stat(filename).st_mode
|
||||
os.chmod(
|
||||
filename,
|
||||
original_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH,
|
||||
)
|
||||
|
||||
|
||||
def install(runner):
|
||||
"""Install the pre-commit hooks."""
|
||||
pre_commit_file = pkg_resources.resource_filename(
|
||||
'pre_commit', 'resources/pre-commit-hook',
|
||||
)
|
||||
|
||||
# If we have an existing hook, move it to pre-commit.legacy
|
||||
if (
|
||||
os.path.exists(runner.pre_commit_path) and
|
||||
not is_our_pre_commit(runner.pre_commit_path)
|
||||
):
|
||||
os.rename(runner.pre_commit_path, runner.pre_commit_path + '.legacy')
|
||||
|
||||
with open(runner.pre_commit_path, 'w') as pre_commit_file_obj:
|
||||
pre_commit_file_obj.write(open(pre_commit_file).read())
|
||||
|
||||
original_mode = os.stat(runner.pre_commit_path).st_mode
|
||||
os.chmod(
|
||||
runner.pre_commit_path,
|
||||
original_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH,
|
||||
)
|
||||
make_executable(runner.pre_commit_path)
|
||||
|
||||
print('pre-commit installed at {0}'.format(runner.pre_commit_path))
|
||||
return 0
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# This is a randomish md5 to identify this script
|
||||
# d8ee923c46731b42cd95cc869add4062
|
||||
|
||||
HERE=$(dirname $(readlink -f "$0"))
|
||||
|
||||
retv=0
|
||||
|
||||
which pre-commit > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -6,4 +12,20 @@ if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Run the legacy pre-commit if it exists
|
||||
if [ -x "$HERE"/pre-commit.legacy ]; then
|
||||
"$HERE"/pre-commit.legacy
|
||||
if [ $? -ne 0 ]; then
|
||||
retv=1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Run pre-commit
|
||||
pre-commit
|
||||
if [ $? -ne 0 ]; then
|
||||
retv=1
|
||||
fi
|
||||
|
||||
exit $retv
|
||||
|
||||
@@ -11,14 +11,44 @@ import stat
|
||||
from plumbum import local
|
||||
|
||||
from pre_commit.commands.install import install
|
||||
from pre_commit.commands.install import is_our_pre_commit
|
||||
from pre_commit.commands.install import make_executable
|
||||
from pre_commit.runner import Runner
|
||||
from testing.fixtures import git_dir
|
||||
from testing.fixtures import make_consuming_repo
|
||||
|
||||
|
||||
def _get_commit_output(tmpdir_factory):
|
||||
local['touch']('foo')
|
||||
local['git']('add', 'foo')
|
||||
def test_is_not_our_pre_commit():
|
||||
assert is_our_pre_commit('setup.py') is False
|
||||
|
||||
|
||||
def test_is_our_pre_commit():
|
||||
assert is_our_pre_commit(
|
||||
pkg_resources.resource_filename(
|
||||
'pre_commit', 'resources/pre-commit-hook',
|
||||
)
|
||||
) is True
|
||||
|
||||
|
||||
def test_install_pre_commit(tmpdir_factory):
|
||||
path = git_dir(tmpdir_factory)
|
||||
runner = Runner(path)
|
||||
ret = install(runner)
|
||||
assert ret == 0
|
||||
assert os.path.exists(runner.pre_commit_path)
|
||||
pre_commit_contents = io.open(runner.pre_commit_path).read()
|
||||
pre_commit_script = pkg_resources.resource_filename(
|
||||
'pre_commit', 'resources/pre-commit-hook',
|
||||
)
|
||||
expected_contents = io.open(pre_commit_script).read()
|
||||
assert pre_commit_contents == expected_contents
|
||||
stat_result = os.stat(runner.pre_commit_path)
|
||||
assert stat_result.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
|
||||
|
||||
def _get_commit_output(tmpdir_factory, touch_file='foo'):
|
||||
local['touch'](touch_file)
|
||||
local['git']('add', touch_file)
|
||||
# Don't want to write to home directory
|
||||
env = dict(os.environ, **{'PRE_COMMIT_HOME': tmpdir_factory.get()})
|
||||
return local['git'].run(
|
||||
@@ -41,34 +71,6 @@ NORMAL_PRE_COMMIT_RUN = re.compile(
|
||||
)
|
||||
|
||||
|
||||
FAILING_PRE_COMMIT_RUN = re.compile(
|
||||
r'^\[INFO\] Installing environment for .+\.\n'
|
||||
r'\[INFO\] Once installed this environment will be reused\.\n'
|
||||
r'\[INFO\] This may take a few minutes\.\.\.\n'
|
||||
r'Failing hook\.+Failed\n'
|
||||
r'\n'
|
||||
r'Fail\n'
|
||||
r'foo\n'
|
||||
r'\n$'
|
||||
)
|
||||
|
||||
|
||||
def test_install_pre_commit(tmpdir_factory):
|
||||
path = git_dir(tmpdir_factory)
|
||||
runner = Runner(path)
|
||||
ret = install(runner)
|
||||
assert ret == 0
|
||||
assert os.path.exists(runner.pre_commit_path)
|
||||
pre_commit_contents = io.open(runner.pre_commit_path).read()
|
||||
pre_commit_sh = pkg_resources.resource_filename(
|
||||
'pre_commit', 'resources/pre-commit-hook',
|
||||
)
|
||||
expected_contents = io.open(pre_commit_sh).read()
|
||||
assert pre_commit_contents == expected_contents
|
||||
stat_result = os.stat(runner.pre_commit_path)
|
||||
assert stat_result.st_mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
|
||||
|
||||
def test_install_pre_commit_and_run(tmpdir_factory):
|
||||
path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo')
|
||||
with local.cwd(path):
|
||||
@@ -108,6 +110,18 @@ def test_environment_not_sourced(tmpdir_factory):
|
||||
)
|
||||
|
||||
|
||||
FAILING_PRE_COMMIT_RUN = re.compile(
|
||||
r'^\[INFO\] Installing environment for .+\.\n'
|
||||
r'\[INFO\] Once installed this environment will be reused\.\n'
|
||||
r'\[INFO\] This may take a few minutes\.\.\.\n'
|
||||
r'Failing hook\.+Failed\n'
|
||||
r'\n'
|
||||
r'Fail\n'
|
||||
r'foo\n'
|
||||
r'\n$'
|
||||
)
|
||||
|
||||
|
||||
def test_failing_hooks_returns_nonzero(tmpdir_factory):
|
||||
path = make_consuming_repo(tmpdir_factory, 'failing_hook_repo')
|
||||
with local.cwd(path):
|
||||
@@ -116,3 +130,63 @@ def test_failing_hooks_returns_nonzero(tmpdir_factory):
|
||||
ret, output = _get_commit_output(tmpdir_factory)
|
||||
assert ret == 1
|
||||
assert FAILING_PRE_COMMIT_RUN.match(output)
|
||||
|
||||
|
||||
EXISTING_COMMIT_RUN = re.compile(
|
||||
r'^legacy hook\n'
|
||||
r'\[master [a-f0-9]{7}\] Commit!\n'
|
||||
r' 0 files changed\n'
|
||||
r' create mode 100644 baz\n$'
|
||||
)
|
||||
|
||||
|
||||
def test_install_existing_hooks_no_overwrite(tmpdir_factory):
|
||||
path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo')
|
||||
with local.cwd(path):
|
||||
runner = Runner(path)
|
||||
|
||||
# Write out an "old" hook
|
||||
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(tmpdir_factory, touch_file='baz')
|
||||
assert ret == 0
|
||||
assert EXISTING_COMMIT_RUN.match(output)
|
||||
|
||||
# Now install pre-commit (no-overwrite)
|
||||
assert install(Runner(path)) == 0
|
||||
|
||||
# We should run both the legacy and pre-commit hooks
|
||||
ret, output = _get_commit_output(tmpdir_factory)
|
||||
assert ret == 0
|
||||
assert output.startswith('legacy hook\n')
|
||||
assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
|
||||
|
||||
|
||||
FAIL_OLD_HOOK = re.compile(
|
||||
r'fail!\n'
|
||||
r'\[INFO\] Installing environment for .+\.\n'
|
||||
r'\[INFO\] Once installed this environment will be reused\.\n'
|
||||
r'\[INFO\] This may take a few minutes\.\.\.\n'
|
||||
r'Bash hook\.+Passed\n'
|
||||
)
|
||||
|
||||
|
||||
def test_failing_existing_hook_returns_1(tmpdir_factory):
|
||||
path = make_consuming_repo(tmpdir_factory, 'script_hooks_repo')
|
||||
with local.cwd(path):
|
||||
runner = Runner(path)
|
||||
|
||||
# Write out a failing "old" hook
|
||||
with io.open(runner.pre_commit_path, 'w') as hook_file:
|
||||
hook_file.write('#!/usr/bin/env bash\necho "fail!"\nexit 1\n')
|
||||
make_executable(runner.pre_commit_path)
|
||||
|
||||
assert install(Runner(path)) == 0
|
||||
|
||||
# We should get a failure from the legacy hook
|
||||
ret, output = _get_commit_output(tmpdir_factory)
|
||||
assert ret == 1
|
||||
assert FAIL_OLD_HOOK.match(output)
|
||||
|
||||
Reference in New Issue
Block a user