From a7133d6742b6d3dae8b76ff6b24bc157f25c5e43 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 23 Jun 2014 12:57:55 -0700 Subject: [PATCH 1/5] Add make archives scripts. --- pre_commit/make_archives.py | 65 +++++++++++++++++++++++++++++++++++++ pre_commit/util.py | 24 ++++++++++++++ tests/make_archives_test.py | 62 +++++++++++++++++++++++++++++++++++ tests/util_test.py | 7 ++++ 4 files changed, 158 insertions(+) create mode 100644 pre_commit/make_archives.py create mode 100644 tests/make_archives_test.py diff --git a/pre_commit/make_archives.py b/pre_commit/make_archives.py new file mode 100644 index 00000000..e989750b --- /dev/null +++ b/pre_commit/make_archives.py @@ -0,0 +1,65 @@ +from __future__ import absolute_import +from __future__ import print_function +from __future__ import unicode_literals + +import os.path +import shutil +from plumbum import local + +from pre_commit.util import tarfile_open +from pre_commit.util import tmpdir + + +# This is a script for generating the tarred resources for git repo +# dependencies. Currently it's just for "vendoring" ruby support packages. + + +REPOS = ( + ('rbenv', 'git://github.com/sstephenson/rbenv', '13a474c'), + ('ruby-build', 'git://github.com/sstephenson/ruby-build', 'd3d5fe0'), + ( + 'ruby-download', + 'git://github.com/garnieretienne/rvm-download', + 'f2e9f1e', + ), +) + + +RESOURCES_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), 'resources') +) + + +def make_archive(name, repo, ref, destdir): + """Makes an archive of a repository in the given destdir. + + :param text name: Name to give the archive. For instance foo. The file + that is created will be called foo.tar.gz. + :param text repo: Repository to clone. + :param text ref: Tag/SHA/branch to check out. + :param text destdir: Directory to place archives in. + """ + output_path = os.path.join(destdir, name + '.tar.gz') + with tmpdir() as tempdir: + # Clone the repository to the temporary directory + local['git']('clone', repo, tempdir) + with local.cwd(tempdir): + local['git']('checkout', ref) + + # We don't want the '.git' directory + shutil.rmtree(os.path.join(tempdir, '.git')) + + with tarfile_open(output_path, 'w|gz') as tf: + tf.add(tempdir, name) + + return output_path + + +def main(): + for archive_name, repo, ref in REPOS: + print('Making {0}.tar.gz for {1}@{2}'.format(archive_name, repo, ref)) + make_archive(archive_name, repo, ref, RESOURCES_DIR) + + +if __name__ == '__main__': + exit(main()) diff --git a/pre_commit/util.py b/pre_commit/util.py index 4b625c27..03bd4a28 100644 --- a/pre_commit/util.py +++ b/pre_commit/util.py @@ -7,6 +7,8 @@ import os import os.path import shutil import sys +import tarfile +import tempfile def memoize_by_cwd(func): @@ -65,3 +67,25 @@ def hex_md5(s): :param text s: """ return hashlib.md5(s.encode('utf-8')).hexdigest() + + +@contextlib.contextmanager +def tarfile_open(*args, **kwargs): + """Compatibility layer because python2.6""" + tf = tarfile.open(*args, **kwargs) + try: + yield tf + finally: + tf.close() + + +@contextlib.contextmanager +def tmpdir(): + """Contextmanager to create a temporary directory. It will be cleaned up + afterwards. + """ + tempdir = tempfile.mkdtemp() + try: + yield tempdir + finally: + shutil.rmtree(tempdir) diff --git a/tests/make_archives_test.py b/tests/make_archives_test.py new file mode 100644 index 00000000..290a0caf --- /dev/null +++ b/tests/make_archives_test.py @@ -0,0 +1,62 @@ +from __future__ import absolute_import +from __future__ import unicode_literals + +import mock +import os.path +import pytest +from plumbum import local + +from pre_commit import make_archives +from pre_commit.util import tarfile_open +from testing.fixtures import git_dir +from testing.util import get_head_sha +from testing.util import skipif_slowtests_false + + +def test_make_archive(tmpdir_factory): + output_dir = tmpdir_factory.get() + git_path = git_dir(tmpdir_factory) + # Add a files to the git directory + with local.cwd(git_path): + local['touch']('foo') + local['git']('add', '.') + local['git']('commit', '-m', 'foo') + # We'll use this sha + head_sha = get_head_sha('.') + # And check that this file doesn't exist + local['touch']('bar') + local['git']('add', '.') + local['git']('commit', '-m', 'bar') + + # Do the thing + archive_path = make_archives.make_archive( + 'foo', git_path, head_sha, output_dir, + ) + + assert archive_path == os.path.join(output_dir, 'foo.tar.gz') + assert os.path.exists(archive_path) + + extract_dir = tmpdir_factory.get() + + # Extract the tar + with tarfile_open(archive_path) as tf: + tf.extractall(extract_dir) + + # Verify the contents of the tar + assert os.path.exists(os.path.join(extract_dir, 'foo')) + assert os.path.exists(os.path.join(extract_dir, 'foo', 'foo')) + assert not os.path.exists(os.path.join(extract_dir, 'foo', '.git')) + assert not os.path.exists(os.path.join(extract_dir, 'foo', 'bar')) + + +@skipif_slowtests_false +@pytest.mark.integration +def test_main(tmpdir_factory): + path = tmpdir_factory.get() + + # Don't actually want to make these in the current repo + with mock.patch.object(make_archives, 'RESOURCES_DIR', path): + make_archives.main() + + for archive, _, _ in make_archives.REPOS: + assert os.path.exists(os.path.join(path, archive + '.tar.gz')) diff --git a/tests/util_test.py b/tests/util_test.py index e406d604..b34b47ab 100644 --- a/tests/util_test.py +++ b/tests/util_test.py @@ -12,6 +12,7 @@ from pre_commit.util import clean_path_on_failure from pre_commit.util import entry from pre_commit.util import memoize_by_cwd from pre_commit.util import shell_escape +from pre_commit.util import tmpdir @pytest.fixture @@ -112,3 +113,9 @@ def test_clean_path_on_failure_cleans_for_system_exit(in_tmpdir): ) def test_shell_escape(input_str, expected): assert shell_escape(input_str) == expected + + +def test_tmpdir(): + with tmpdir() as tempdir: + assert os.path.exists(tempdir) + assert not os.path.exists(tempdir) From c7b605fee212bc6f0b66a23784cb8102522c3d7d Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 23 Jun 2014 13:06:14 -0700 Subject: [PATCH 2/5] Add the archive resources. --- pre_commit/resources/rbenv.tar.gz | Bin 0 -> 24345 bytes pre_commit/resources/ruby-build.tar.gz | Bin 0 -> 33136 bytes pre_commit/resources/ruby-download.tar.gz | Bin 0 -> 3999 bytes setup.py | 5 ++++- 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 pre_commit/resources/rbenv.tar.gz create mode 100644 pre_commit/resources/ruby-build.tar.gz create mode 100644 pre_commit/resources/ruby-download.tar.gz diff --git a/pre_commit/resources/rbenv.tar.gz b/pre_commit/resources/rbenv.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bd517311ca99e45ce626345b9861f27562b1b784 GIT binary patch literal 24345 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 Y&+@bUEI-T7@8|RX1D?^W^8hdc09Yn{HUIzs literal 0 HcmV?d00001 diff --git a/pre_commit/resources/ruby-build.tar.gz b/pre_commit/resources/ruby-build.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..10368199892ce1ae4b871669e6cc89ccad525757 GIT binary patch literal 33136 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 literal 0 HcmV?d00001 diff --git a/pre_commit/resources/ruby-download.tar.gz b/pre_commit/resources/ruby-download.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..24bc6479cad00035d97d7a7710a5497e538b8ece GIT binary patch literal 3999 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 F007=z|Lgz& literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 25afb566..f7550cf6 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,10 @@ setup( packages=find_packages('.', exclude=('tests*', 'testing*')), package_data={ 'pre_commit': [ - 'resources/pre-commit-hook' + 'resources/pre-commit-hook', + 'resources/rbenv.tar.gz', + 'resources/ruby-build.tar.gz', + 'resources/ruby-download.tar.gz', ] }, install_requires=[ From 8fee06b53ed523988f56930b48100381366b3284 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 23 Jun 2014 13:18:40 -0700 Subject: [PATCH 3/5] resource_filename instead of trying to remember the right invocation to pkg_resources. --- pre_commit/commands/install_uninstall.py | 7 +++---- pre_commit/util.py | 8 ++++++++ tests/commands/install_uninstall_test.py | 22 +++++----------------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py index 249c87d0..ab91eacf 100644 --- a/pre_commit/commands/install_uninstall.py +++ b/pre_commit/commands/install_uninstall.py @@ -4,9 +4,10 @@ from __future__ import unicode_literals import io import os import os.path -import pkg_resources import stat +from pre_commit.util import resource_filename + # This is used to identify the hook file we install PREVIOUS_IDENTIFYING_HASHES = [ @@ -36,9 +37,7 @@ def make_executable(filename): def install(runner, overwrite=False): """Install the pre-commit hooks.""" - pre_commit_file = pkg_resources.resource_filename( - 'pre_commit', 'resources/pre-commit-hook', - ) + pre_commit_file = resource_filename('pre-commit-hook') # If we have an existing hook, move it to pre-commit.legacy if ( diff --git a/pre_commit/util.py b/pre_commit/util.py index 03bd4a28..a46de364 100644 --- a/pre_commit/util.py +++ b/pre_commit/util.py @@ -5,6 +5,7 @@ import functools import hashlib import os import os.path +import pkg_resources import shutil import sys import tarfile @@ -89,3 +90,10 @@ def tmpdir(): yield tempdir finally: shutil.rmtree(tempdir) + + +def resource_filename(filename): + return pkg_resources.resource_filename( + 'pre_commit', + os.path.join('resources', filename), + ) diff --git a/tests/commands/install_uninstall_test.py b/tests/commands/install_uninstall_test.py index bb511384..ae9dddfb 100644 --- a/tests/commands/install_uninstall_test.py +++ b/tests/commands/install_uninstall_test.py @@ -5,7 +5,6 @@ import io import os import os.path import re -import pkg_resources import subprocess import stat from plumbum import local @@ -18,6 +17,7 @@ from pre_commit.commands.install_uninstall import is_previous_pre_commit from pre_commit.commands.install_uninstall import make_executable from pre_commit.commands.install_uninstall import uninstall from pre_commit.runner import Runner +from pre_commit.util import resource_filename from testing.fixtures import git_dir from testing.fixtures import make_consuming_repo @@ -27,11 +27,7 @@ def test_is_not_our_pre_commit(): def test_is_our_pre_commit(): - assert is_our_pre_commit( - pkg_resources.resource_filename( - 'pre_commit', 'resources/pre-commit-hook', - ) - ) is True + assert is_our_pre_commit(resource_filename('pre-commit-hook')) def test_is_not_previous_pre_commit(): @@ -39,11 +35,7 @@ def test_is_not_previous_pre_commit(): def test_is_also_not_previous_pre_commit(): - assert is_previous_pre_commit( - pkg_resources.resource_filename( - 'pre_commit', 'resources/pre-commit-hook', - ) - ) is False + assert not is_previous_pre_commit(resource_filename('pre-commit-hook')) def test_is_previous_pre_commit(in_tmpdir): @@ -60,9 +52,7 @@ def test_install_pre_commit(tmpdir_factory): 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', - ) + pre_commit_script = resource_filename('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) @@ -317,9 +307,7 @@ def test_replace_old_commit_script(tmpdir_factory): # Install a script that looks like our old script pre_commit_contents = io.open( - pkg_resources.resource_filename( - 'pre_commit', 'resources/pre-commit-hook', - ) + resource_filename('pre-commit-hook'), ).read() new_contents = pre_commit_contents.replace( IDENTIFYING_HASH, PREVIOUS_IDENTIFYING_HASHES[-1], From bee56cd5bc619540a93f05aa60033a1d2009f8ed Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 23 Jun 2014 13:50:40 -0700 Subject: [PATCH 4/5] Use our archives instead of pulling from gits. --- pre_commit/languages/ruby.py | 20 +++++++++----------- tests/languages/ruby_test.py | 5 ----- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/pre_commit/languages/ruby.py b/pre_commit/languages/ruby.py index b4a3be06..2f4b9931 100644 --- a/pre_commit/languages/ruby.py +++ b/pre_commit/languages/ruby.py @@ -6,6 +6,8 @@ import io from pre_commit.languages import helpers from pre_commit.prefixed_command_runner import CalledProcessError from pre_commit.util import clean_path_on_failure +from pre_commit.util import resource_filename +from pre_commit.util import tarfile_open ENVIRONMENT_DIR = 'rbenv' @@ -23,22 +25,18 @@ def in_env(repo_cmd_runner): def _install_rbenv(repo_cmd_runner, version='default'): - repo_cmd_runner.run([ - 'git', 'clone', 'git://github.com/sstephenson/rbenv', '{prefix}rbenv', - ]) + with tarfile_open(resource_filename('rbenv.tar.gz')) as tf: + tf.extractall(repo_cmd_runner.path('.')) # Only install ruby-build if the version is specified if version != 'default': # ruby-download - repo_cmd_runner.run([ - 'git', 'clone', 'git://github.com/garnieretienne/rvm-download', - '{prefix}rbenv/plugins/ruby-download', - ]) + with tarfile_open(resource_filename('ruby-download.tar.gz')) as tf: + tf.extractall(repo_cmd_runner.path('rbenv', 'plugins')) + # ruby-build - repo_cmd_runner.run([ - 'git', 'clone', 'git://github.com/sstephenson/ruby-build', - '{prefix}rbenv/plugins/ruby-build', - ]) + with tarfile_open(resource_filename('ruby-build.tar.gz')) as tf: + tf.extractall(repo_cmd_runner.path('rbenv', 'plugins')) activate_path = repo_cmd_runner.path('rbenv', 'bin', 'activate') with io.open(activate_path, 'w') as activate_file: diff --git a/tests/languages/ruby_test.py b/tests/languages/ruby_test.py index d55b36b0..3ffb4019 100644 --- a/tests/languages/ruby_test.py +++ b/tests/languages/ruby_test.py @@ -3,16 +3,12 @@ from __future__ import unicode_literals import os.path from pre_commit.languages.ruby import _install_rbenv -from testing.util import skipif_slowtests_false -@skipif_slowtests_false def test_install_rbenv(cmd_runner): _install_rbenv(cmd_runner) # Should have created rbenv directory assert os.path.exists(cmd_runner.path('rbenv')) - # It should be a git checkout - assert os.path.exists(cmd_runner.path('rbenv', '.git')) # We should have created our `activate` script activate_path = cmd_runner.path('rbenv', 'bin', 'activate') assert os.path.exists(activate_path) @@ -27,7 +23,6 @@ def test_install_rbenv(cmd_runner): ) -@skipif_slowtests_false def test_install_rbenv_with_version(cmd_runner): _install_rbenv(cmd_runner, version='1.9.3p547') From df526679507c205b7718750054f088ba1f251c4e Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 23 Jun 2014 14:09:42 -0700 Subject: [PATCH 5/5] Fix writing tarfile with unicode filename in python 2.6 --- pre_commit/make_archives.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pre_commit/make_archives.py b/pre_commit/make_archives.py index e989750b..4bae338c 100644 --- a/pre_commit/make_archives.py +++ b/pre_commit/make_archives.py @@ -49,7 +49,9 @@ def make_archive(name, repo, ref, destdir): # We don't want the '.git' directory shutil.rmtree(os.path.join(tempdir, '.git')) - with tarfile_open(output_path, 'w|gz') as tf: + # XXX: py2.6 derps if filename is unicode while writing + # XXX: str() is used to preserve behavior in py3 + with tarfile_open(str(output_path), 'w|gz') as tf: tf.add(tempdir, name) return output_path