mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-20 01:24:42 +04:00
Merge pull request #60 from pre-commit/control_c_58
Clean up directories on failure. Closes #58.
This commit is contained in:
commit
36ecf23c2e
8 changed files with 103 additions and 38 deletions
|
|
@ -3,6 +3,7 @@ import contextlib
|
||||||
from pre_commit.languages import helpers
|
from pre_commit.languages import helpers
|
||||||
from pre_commit.languages import python
|
from pre_commit.languages import python
|
||||||
from pre_commit.prefixed_command_runner import CalledProcessError
|
from pre_commit.prefixed_command_runner import CalledProcessError
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
|
|
||||||
|
|
||||||
NODE_ENV = 'node_env'
|
NODE_ENV = 'node_env'
|
||||||
|
|
@ -30,19 +31,27 @@ def install_environment(repo_cmd_runner):
|
||||||
if repo_cmd_runner.exists(NODE_ENV):
|
if repo_cmd_runner.exists(NODE_ENV):
|
||||||
return
|
return
|
||||||
|
|
||||||
repo_cmd_runner.run(['virtualenv', '{{prefix}}{0}'.format(python.PY_ENV)])
|
with clean_path_on_failure(repo_cmd_runner.path(python.PY_ENV)):
|
||||||
|
repo_cmd_runner.run(
|
||||||
|
['virtualenv', '{{prefix}}{0}'.format(python.PY_ENV)],
|
||||||
|
)
|
||||||
|
|
||||||
with python.in_env(repo_cmd_runner) as python_env:
|
with python.in_env(repo_cmd_runner) as python_env:
|
||||||
python_env.run('pip install nodeenv')
|
python_env.run('pip install nodeenv')
|
||||||
|
|
||||||
|
with clean_path_on_failure(repo_cmd_runner.path(NODE_ENV)):
|
||||||
# Try and use the system level node executable first
|
# Try and use the system level node executable first
|
||||||
try:
|
try:
|
||||||
python_env.run('nodeenv -n system {{prefix}}{0}'.format(NODE_ENV))
|
python_env.run(
|
||||||
|
'nodeenv -n system {{prefix}}{0}'.format(NODE_ENV),
|
||||||
|
)
|
||||||
except CalledProcessError:
|
except CalledProcessError:
|
||||||
# TODO: log failure here
|
# TODO: log failure here
|
||||||
# cleanup
|
# cleanup
|
||||||
# TODO: local.path(NODE_ENV).delete()
|
# TODO: local.path(NODE_ENV).delete()
|
||||||
python_env.run('nodeenv --jobs 4 {{prefix}}{0}'.format(NODE_ENV))
|
python_env.run(
|
||||||
|
'nodeenv --jobs 4 {{prefix}}{0}'.format(NODE_ENV),
|
||||||
|
)
|
||||||
|
|
||||||
with in_env(repo_cmd_runner) as node_env:
|
with in_env(repo_cmd_runner) as node_env:
|
||||||
node_env.run('cd {prefix} && npm install -g')
|
node_env.run('cd {prefix} && npm install -g')
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
from pre_commit.languages import helpers
|
from pre_commit.languages import helpers
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
|
|
||||||
|
|
||||||
PY_ENV = 'py_env'
|
PY_ENV = 'py_env'
|
||||||
|
|
@ -25,6 +26,7 @@ def install_environment(repo_cmd_runner):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Install a virtualenv
|
# Install a virtualenv
|
||||||
|
with clean_path_on_failure(repo_cmd_runner.path(PY_ENV)):
|
||||||
repo_cmd_runner.run(['virtualenv', '{{prefix}}{0}'.format(PY_ENV)])
|
repo_cmd_runner.run(['virtualenv', '{{prefix}}{0}'.format(PY_ENV)])
|
||||||
with in_env(repo_cmd_runner) as env:
|
with in_env(repo_cmd_runner) as env:
|
||||||
env.run('cd {prefix} && pip install .')
|
env.run('cd {prefix} && pip install .')
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
from pre_commit.languages import helpers
|
from pre_commit.languages import helpers
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
|
|
||||||
|
|
||||||
RVM_ENV = 'rvm_env'
|
RVM_ENV = 'rvm_env'
|
||||||
|
|
@ -23,6 +24,7 @@ def install_environment(repo_cmd_runner):
|
||||||
if repo_cmd_runner.exists(RVM_ENV):
|
if repo_cmd_runner.exists(RVM_ENV):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
with clean_path_on_failure(repo_cmd_runner.path(RVM_ENV)):
|
||||||
repo_cmd_runner.run(['__rvm-env.sh', '{{prefix}}{0}'.format(RVM_ENV)])
|
repo_cmd_runner.run(['__rvm-env.sh', '{{prefix}}{0}'.format(RVM_ENV)])
|
||||||
with in_env(repo_cmd_runner) as env:
|
with in_env(repo_cmd_runner) as env:
|
||||||
env.run('cd {prefix} && bundle install')
|
env.run('cd {prefix} && bundle install')
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from pre_commit.languages.all import languages
|
||||||
from pre_commit.ordereddict import OrderedDict
|
from pre_commit.ordereddict import OrderedDict
|
||||||
from pre_commit.prefixed_command_runner import PrefixedCommandRunner
|
from pre_commit.prefixed_command_runner import PrefixedCommandRunner
|
||||||
from pre_commit.util import cached_property
|
from pre_commit.util import cached_property
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
|
|
||||||
|
|
||||||
class Repository(object):
|
class Repository(object):
|
||||||
|
|
@ -62,6 +63,7 @@ class Repository(object):
|
||||||
# Project already exists, no reason to re-create it
|
# Project already exists, no reason to re-create it
|
||||||
return
|
return
|
||||||
|
|
||||||
|
with clean_path_on_failure(unicode(local.path(self.sha))):
|
||||||
local['git']['clone', '--no-checkout', self.repo_url, self.sha]()
|
local['git']['clone', '--no-checkout', self.repo_url, self.sha]()
|
||||||
with self.in_checkout():
|
with self.in_checkout():
|
||||||
local['git']['checkout', self.sha]()
|
local['git']['checkout', self.sha]()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
|
|
||||||
|
import contextlib
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -49,3 +52,14 @@ def entry(func):
|
||||||
argv = sys.argv[1:]
|
argv = sys.argv[1:]
|
||||||
return func(argv)
|
return func(argv)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def clean_path_on_failure(path):
|
||||||
|
"""Cleans up the directory on an exceptional failure."""
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except BaseException:
|
||||||
|
if os.path.exists(path):
|
||||||
|
shutil.rmtree(path)
|
||||||
|
raise
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,17 @@ from testing.util import get_resource_path
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.yield_fixture
|
||||||
def empty_git_dir(tmpdir):
|
def in_tmpdir(tmpdir):
|
||||||
with local.cwd(tmpdir.strpath):
|
with local.cwd(tmpdir.strpath):
|
||||||
local['git']['init']()
|
|
||||||
yield tmpdir.strpath
|
yield tmpdir.strpath
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.yield_fixture
|
||||||
|
def empty_git_dir(in_tmpdir):
|
||||||
|
local['git']['init']()
|
||||||
|
yield in_tmpdir
|
||||||
|
|
||||||
|
|
||||||
def add_and_commit():
|
def add_and_commit():
|
||||||
local['git']['add', '.']()
|
local['git']['add', '.']()
|
||||||
local['git']['commit', '-m', 'random commit {0}'.format(time.time())]()
|
local['git']['commit', '-m', 'random commit {0}'.format(time.time())]()
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import os
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
import subprocess
|
import subprocess
|
||||||
from plumbum import local
|
|
||||||
|
|
||||||
from pre_commit.prefixed_command_runner import _replace_cmd
|
from pre_commit.prefixed_command_runner import _replace_cmd
|
||||||
from pre_commit.prefixed_command_runner import CalledProcessError
|
from pre_commit.prefixed_command_runner import CalledProcessError
|
||||||
|
|
@ -110,21 +109,18 @@ def test_from_command_runner_preserves_popen(popen_mock, makedirs_mock):
|
||||||
makedirs_mock.assert_called_once_with('foo/bar/')
|
makedirs_mock.assert_called_once_with('foo/bar/')
|
||||||
|
|
||||||
|
|
||||||
def test_create_path_if_not_exists(tmpdir):
|
def test_create_path_if_not_exists(in_tmpdir):
|
||||||
with local.cwd(tmpdir.strpath):
|
|
||||||
instance = PrefixedCommandRunner('foo')
|
instance = PrefixedCommandRunner('foo')
|
||||||
assert not os.path.exists('foo')
|
assert not os.path.exists('foo')
|
||||||
instance._create_path_if_not_exists()
|
instance._create_path_if_not_exists()
|
||||||
assert os.path.exists('foo')
|
assert os.path.exists('foo')
|
||||||
|
|
||||||
|
|
||||||
def test_exists_does_not_exist(tmpdir):
|
def test_exists_does_not_exist(in_tmpdir):
|
||||||
with local.cwd(tmpdir.strpath):
|
|
||||||
assert not PrefixedCommandRunner('.').exists('foo')
|
assert not PrefixedCommandRunner('.').exists('foo')
|
||||||
|
|
||||||
|
|
||||||
def test_exists_does_exist(tmpdir):
|
def test_exists_does_exist(in_tmpdir):
|
||||||
with local.cwd(tmpdir.strpath):
|
|
||||||
os.mkdir('foo')
|
os.mkdir('foo')
|
||||||
assert PrefixedCommandRunner('.').exists('foo')
|
assert PrefixedCommandRunner('.').exists('foo')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
from plumbum import local
|
from plumbum import local
|
||||||
|
|
||||||
from pre_commit.util import cached_property
|
from pre_commit.util import cached_property
|
||||||
|
from pre_commit.util import clean_path_on_failure
|
||||||
from pre_commit.util import entry
|
from pre_commit.util import entry
|
||||||
from pre_commit.util import memoize_by_cwd
|
from pre_commit.util import memoize_by_cwd
|
||||||
|
|
||||||
|
|
@ -84,3 +87,35 @@ def test_no_arguments_passed_uses_argv(entry_func):
|
||||||
with mock.patch.object(sys, 'argv', argv):
|
with mock.patch.object(sys, 'argv', argv):
|
||||||
ret = entry_func()
|
ret = entry_func()
|
||||||
assert ret == argv[1:]
|
assert ret == argv[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def test_clean_on_failure_noop(in_tmpdir):
|
||||||
|
with clean_path_on_failure('foo'): pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_clean_path_on_failure_does_nothing_when_not_raising(in_tmpdir):
|
||||||
|
with clean_path_on_failure('foo'):
|
||||||
|
os.mkdir('foo')
|
||||||
|
assert os.path.exists('foo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_clean_path_on_failure_cleans_for_normal_exception(in_tmpdir):
|
||||||
|
class MyException(Exception): pass
|
||||||
|
|
||||||
|
with pytest.raises(MyException):
|
||||||
|
with clean_path_on_failure('foo'):
|
||||||
|
os.mkdir('foo')
|
||||||
|
raise MyException
|
||||||
|
|
||||||
|
assert not os.path.exists('foo')
|
||||||
|
|
||||||
|
|
||||||
|
def test_clean_path_on_failure_cleans_for_system_exit(in_tmpdir):
|
||||||
|
class MySystemExit(SystemExit): pass
|
||||||
|
|
||||||
|
with pytest.raises(MySystemExit):
|
||||||
|
with clean_path_on_failure('foo'):
|
||||||
|
os.mkdir('foo')
|
||||||
|
raise MySystemExit
|
||||||
|
|
||||||
|
assert not os.path.exists('foo')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue