diff --git a/.travis.yml b/.travis.yml index 6e98e9d5..976fde03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,8 @@ python: install: pip install virtualenv script: make + + +before_install: + - git config --global user.name "Travis CI" + - git config --global user.email "user@example.com" diff --git a/Makefile b/Makefile index 161f6d0f..9aedace0 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ coverage: py_env coverage run `which py.test` tests $(TEST_TARGETS) && \ coverage report -m' -py_env: requirements.txt +py_env: requirements.txt setup.py rm -rf py_env virtualenv py_env bash -c 'source py_env/bin/activate && \ diff --git a/pre_commit/git.py b/pre_commit/git.py index 7f206125..d72008d0 100644 --- a/pre_commit/git.py +++ b/pre_commit/git.py @@ -1,16 +1,23 @@ import os import pkg_resources + +import pre_commit.constants as C from plumbum import local def get_root(): return local['git']['rev-parse', '--show-toplevel']().strip() - def get_pre_commit_path(): return os.path.join(get_root(), '.git/hooks/pre-commit') +def get_pre_commit_dir_path(): + return os.path.join(get_root(), C.PRE_COMMIT_DIR) + +def create_pre_commit_package_dir(): + local.path(get_pre_commit_dir_path()).mkdir() + def create_pre_commit(): path = get_pre_commit_path() pre_commit_file = pkg_resources.resource_filename('pre_commit', 'resources/pre-commit.sh') @@ -22,6 +29,3 @@ def remove_pre_commit(): - - - diff --git a/pre_commit/installer/__init__.py b/pre_commit/installer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pre_commit/installer/repo_installer.py b/pre_commit/installer/repo_installer.py new file mode 100644 index 00000000..c8695b1a --- /dev/null +++ b/pre_commit/installer/repo_installer.py @@ -0,0 +1,44 @@ +import contextlib + +from plumbum import local +from pre_commit import git + +class RepoInstaller(object): + + def __init__(self, git_repo_path, sha): + self.git_repo_path = git_repo_path + self.sha = sha + + @contextlib.contextmanager + def in_checkout(self): + with local.cwd(git.get_pre_commit_dir_path()): + with local.cwd(self.sha): + yield + + def create(self): + git.create_pre_commit_package_dir() + + with local.cwd(git.get_pre_commit_dir_path()): + if local.path(self.sha).exists(): + # Project already exists, no reason to re-create it + return + + local['git']['clone', self.git_repo_path, self.sha]() + with self.in_checkout(): + local['git']['checkout', self.sha]() + + def install(self): + with self.in_checkout(): + if local.path('setup.py').exists(): + local['virtualenv']['py_env']() + local['bash']['-c', 'source py_env/bin/activate && pip install .']() + + +def create_repo_in_env(git_repo_path, sha): + project = RepoInstaller(git_repo_path, sha) + project.create() + +def install_pre_commit(git_repo_path, sha): + project = RepoInstaller(git_repo_path, sha) + project.create() + project.install() \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 68613e1a..377a7bb5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ import pytest +import pre_commit.constants as C from plumbum import local @@ -7,4 +8,73 @@ from plumbum import local def empty_git_dir(tmpdir): with local.cwd(tmpdir.strpath): local['git']['init']() - yield tmpdir.strpath \ No newline at end of file + yield tmpdir.strpath + + + +def add_and_commit(): + local['git']['add', '.']() + local['git']['commit', '-m', 'random commit']() + + +@pytest.yield_fixture +def dummy_git_repo(empty_git_dir): + local['touch']['dummy']() + add_and_commit() + + yield empty_git_dir + + +@pytest.yield_fixture +def dummy_pre_commit_hooks_git_repo(dummy_git_repo): + local.path(C.MANIFEST_FILE).write(""" +hooks: + - + id: foo + name: Foo + entry: foo + language: python>2.6 + """) + + add_and_commit() + + yield dummy_git_repo + +@pytest.yield_fixture +def python_pre_commit_git_repo(dummy_pre_commit_hooks_git_repo): + local.path('setup.py').write( +""" +from setuptools import find_packages +from setuptools import setup + +setup( + name='Foo', + version='0.0.0', + packages=find_packages('.'), + entry_points={ + 'console_scripts': [ + 'entry = foo.main:func' + ], + } +) +""" + ) + + foo_module = local.path('foo') + + foo_module.mkdir() + + with local.cwd(foo_module): + local.path('__init__.py').write('') + local.path('main.py').write( +""" + +def func(): + return 0 + +""" + ) + + add_and_commit() + + yield dummy_pre_commit_hooks_git_repo diff --git a/tests/git_test.py b/tests/git_test.py index cb0331e4..9f413294 100644 --- a/tests/git_test.py +++ b/tests/git_test.py @@ -33,3 +33,5 @@ def test_remove_pre_commit(empty_git_dir): git.remove_pre_commit() assert not os.path.exists(git.get_pre_commit_path()) + + diff --git a/tests/installer/__init__.py b/tests/installer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/installer/repo_installer_test.py b/tests/installer/repo_installer_test.py new file mode 100644 index 00000000..bfa304dd --- /dev/null +++ b/tests/installer/repo_installer_test.py @@ -0,0 +1,52 @@ +import pytest +import os + +import pre_commit.constants as C +from plumbum import local +from pre_commit.installer.repo_installer import create_repo_in_env +from pre_commit.installer.repo_installer import install_pre_commit + + +def get_sha(git_repo): + with local.cwd(git_repo): + return (local['git']['log', '--format="%H"'] | local['head']['-n1'])().strip('"\n') + +@pytest.mark.integration +def test_create_repo_in_env(empty_git_dir, dummy_git_repo): + sha = get_sha(dummy_git_repo) + create_repo_in_env(dummy_git_repo, sha) + + assert os.path.exists(os.path.join(dummy_git_repo, C.PRE_COMMIT_DIR, sha)) + +@pytest.mark.integration +def test_install_python_repo_in_env(empty_git_dir, python_pre_commit_git_repo): + sha = get_sha(python_pre_commit_git_repo) + install_pre_commit(python_pre_commit_git_repo, sha) + + assert os.path.exists(os.path.join(python_pre_commit_git_repo, C.PRE_COMMIT_DIR, sha, 'py_env')) + + +@pytest.mark.integration +def test_install_config(empty_git_dir, python_pre_commit_git_repo): + + config = [ + { + 'repo': python_pre_commit_git_repo, + 'sha': get_sha(python_pre_commit_git_repo), + 'hooks': [ + { + 'id': 'foo', + 'args': [ + { + 'type': 'files', + 'opt': '*.py' + }, + ] + } + ], + }, + ] + for repo in config: + install_pre_commit(repo['repo'], repo['sha']) + + assert os.path.exists(os.path.join(python_pre_commit_git_repo, C.PRE_COMMIT_DIR, config[0]['sha'], 'py_env')) \ No newline at end of file