Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a20150a

Browse files
committed
Merge pull request #94 from pre-commit/ruby_for_realz
Support ruby through a combination of rbenv, ruby-build, and GEM_HOME
2 parents 390af24 + b381bb6 commit a20150a

10 files changed

Lines changed: 124 additions & 24 deletions

File tree

pre_commit/languages/ruby.py

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,70 @@
1+
from __future__ import unicode_literals
2+
13
import contextlib
4+
import io
5+
import os
26

37
from pre_commit.languages import helpers
48
from pre_commit.util import clean_path_on_failure
59

610

7-
ENVIRONMENT_DIR = 'rvm_env'
11+
ENVIRONMENT_DIR = 'rbenv'
812

913

1014
class RubyEnv(helpers.Environment):
1115
@property
1216
def env_prefix(self):
13-
raise NotImplementedError
17+
return '. {{prefix}}{0}/bin/activate &&'.format(ENVIRONMENT_DIR)
18+
19+
def run(self, *args, **kwargs):
20+
# TODO: hardcoded version smell
21+
env = dict(os.environ, RBENV_VERSION='1.9.3-p545')
22+
return super(RubyEnv, self).run(*args, env=env, **kwargs)
1423

1524

1625
@contextlib.contextmanager
1726
def in_env(repo_cmd_runner):
1827
yield RubyEnv(repo_cmd_runner)
1928

2029

30+
def _install_rbenv(repo_cmd_runner):
31+
repo_cmd_runner.run([
32+
'git', 'clone', 'git://github.com/sstephenson/rbenv', '{prefix}rbenv',
33+
])
34+
repo_cmd_runner.run([
35+
'git', 'clone', 'git://github.com/sstephenson/ruby-build',
36+
'{prefix}rbenv/plugins/ruby-build',
37+
])
38+
39+
activate_path = repo_cmd_runner.path('rbenv', 'bin', 'activate')
40+
with io.open(activate_path, 'w') as activate_file:
41+
# This is similar to how you would install rbenv to your home directory
42+
# However we do a couple things to make the executables exposed and
43+
# configure it to work in our directory.
44+
# We also modify the PS1 variable for manual debugging sake.
45+
activate_file.write(
46+
'#!/usr/bin/env bash\n'
47+
"export RBENV_ROOT='{0}'\n"
48+
'export PATH="$RBENV_ROOT/bin:$PATH"\n'
49+
'eval "$(rbenv init -)"\n'
50+
'export PS1="(rbenv)$PS1"\n'
51+
# This lets us install gems in an isolated and repeatable
52+
# directory
53+
"export GEM_HOME='{0}/gems'\n"
54+
'export PATH="$GEM_HOME/bin:$PATH"\n'
55+
'\n'.format(repo_cmd_runner.path('rbenv'))
56+
)
57+
58+
2159
def install_environment(repo_cmd_runner):
22-
# Return immediately if we already have a virtualenv
23-
if repo_cmd_runner.exists(ENVIRONMENT_DIR):
24-
return
25-
26-
with clean_path_on_failure(repo_cmd_runner.path(ENVIRONMENT_DIR)):
27-
repo_cmd_runner.run(['__rvm-env.sh', '{{prefix}}{0}'.format(ENVIRONMENT_DIR)])
28-
with in_env(repo_cmd_runner) as env:
29-
env.run('cd {prefix} && bundle install')
60+
with clean_path_on_failure(repo_cmd_runner.path('rbenv')):
61+
_install_rbenv(repo_cmd_runner)
62+
with in_env(repo_cmd_runner) as ruby_env:
63+
# TODO: hardcoded version smell
64+
ruby_env.run('rbenv install 1.9.3-p545')
65+
ruby_env.run(
66+
'cd {prefix} && gem build *.gemspec && gem install *.gem',
67+
)
3068

3169

3270
def run_hook(repo_cmd_runner, hook, file_args):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.gem
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env ruby
2+
3+
puts 'Hello world from a ruby hook'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- id: ruby_hook
2+
name: Ruby Hook
3+
entry: ruby_hook
4+
language: ruby
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Gem::Specification.new do |s|
2+
s.name = 'ruby_hook'
3+
s.version = '0.1.0'
4+
s.authors = ['Anthony Sottile']
5+
s.summary = 'A ruby hook!'
6+
s.description = 'A ruby hook!'
7+
s.files = ['bin/ruby_hook']
8+
s.executables = ['ruby_hook']
9+
end

testing/util.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import jsonschema
22
import os
33
import os.path
4+
import pytest
45
import shutil
56
from plumbum import local
67

@@ -41,3 +42,10 @@ def is_valid_according_to_schema(obj, schema):
4142
return True
4243
except jsonschema.exceptions.ValidationError:
4344
return False
45+
46+
47+
def skipif_slowtests_false(func):
48+
return pytest.mark.skipif(
49+
os.environ.get('slowtests') == 'false',
50+
reason='slowtests=false',
51+
)(func)

tests/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA
1414
from pre_commit.clientlib.validate_config import validate_config_extra
1515
from pre_commit.jsonschema_extensions import apply_defaults
16+
from pre_commit.prefixed_command_runner import PrefixedCommandRunner
1617
from pre_commit.store import Store
1718
from testing.util import copy_tree_to_path
1819
from testing.util import get_head_sha
@@ -76,6 +77,11 @@ def node_hooks_repo(dummy_git_repo):
7677
yield _make_repo(dummy_git_repo, 'node_hooks_repo')
7778

7879

80+
@pytest.yield_fixture
81+
def ruby_hooks_repo(dummy_git_repo):
82+
yield _make_repo(dummy_git_repo, 'ruby_hooks_repo')
83+
84+
7985
@pytest.yield_fixture
8086
def consumer_repo(dummy_git_repo):
8187
yield _make_repo(dummy_git_repo, 'consumer_repo')
@@ -112,6 +118,11 @@ def config_for_node_hooks_repo(node_hooks_repo):
112118
yield _make_config(node_hooks_repo, 'foo', '\\.js$')
113119

114120

121+
@pytest.yield_fixture
122+
def config_for_ruby_hooks_repo(ruby_hooks_repo):
123+
yield _make_config(ruby_hooks_repo, 'ruby_hook', '\\.rb$')
124+
125+
115126
@pytest.yield_fixture
116127
def config_for_python_hooks_repo(python_hooks_repo):
117128
yield _make_config(python_hooks_repo, 'foo', '\\.py$')
@@ -206,3 +217,8 @@ def mock_out_store_directory(tmpdir_factory):
206217
@pytest.yield_fixture
207218
def store(tmpdir_factory):
208219
yield Store(os.path.join(tmpdir_factory.get(), '.pre-commit'))
220+
221+
222+
@pytest.yield_fixture
223+
def cmd_runner(tmpdir_factory):
224+
yield PrefixedCommandRunner(tmpdir_factory.get())

tests/languages/ruby_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import os.path
2+
3+
from pre_commit.languages.ruby import _install_rbenv
4+
5+
6+
def test_install_rbenv(cmd_runner):
7+
_install_rbenv(cmd_runner)
8+
# Should have created rbenv directory
9+
assert os.path.exists(cmd_runner.path('rbenv'))
10+
# It should be a git checkout
11+
assert os.path.exists(cmd_runner.path('rbenv', '.git'))
12+
# We should have created our `activate` script
13+
activate_path = cmd_runner.path('rbenv', 'bin', 'activate')
14+
assert os.path.exists(activate_path)
15+
16+
# Should be able to activate using our script and access the install method
17+
cmd_runner.run(
18+
[
19+
'bash',
20+
'-c',
21+
'. {prefix}/rbenv/bin/activate && rbenv install --help',
22+
],
23+
)

tests/repository_test.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pre_commit.clientlib.validate_config import validate_config_extra
77
from pre_commit.jsonschema_extensions import apply_defaults
88
from pre_commit.repository import Repository
9+
from testing.util import skipif_slowtests_false
910

1011

1112
@pytest.mark.integration
@@ -19,7 +20,6 @@ def test_install_python_repo_in_env(config_for_python_hooks_repo, store):
1920
def test_run_a_python_hook(config_for_python_hooks_repo, store):
2021
repo = Repository.create(config_for_python_hooks_repo, store)
2122
ret = repo.run_hook('foo', ['/dev/null'])
22-
2323
assert ret[0] == 0
2424
assert ret[1] == "['/dev/null']\nHello World\n"
2525

@@ -28,7 +28,6 @@ def test_run_a_python_hook(config_for_python_hooks_repo, store):
2828
def test_lots_of_files(config_for_python_hooks_repo, store):
2929
repo = Repository.create(config_for_python_hooks_repo, store)
3030
ret = repo.run_hook('foo', ['/dev/null'] * 15000)
31-
3231
assert ret[0] == 0
3332

3433

@@ -37,24 +36,29 @@ def test_cwd_of_hook(config_for_prints_cwd_repo, store):
3736
# Note: this doubles as a test for `system` hooks
3837
repo = Repository.create(config_for_prints_cwd_repo, store)
3938
ret = repo.run_hook('prints_cwd', [])
40-
4139
assert ret[0] == 0
4240
assert ret[1] == repo.repo_url + '\n'
4341

4442

45-
@pytest.mark.skipif(
46-
os.environ.get('slowtests', None) == 'false',
47-
reason="TODO: make this test not super slow",
48-
)
43+
@skipif_slowtests_false
4944
@pytest.mark.integration
5045
def test_run_a_node_hook(config_for_node_hooks_repo, store):
5146
repo = Repository.create(config_for_node_hooks_repo, store)
5247
ret = repo.run_hook('foo', [])
53-
5448
assert ret[0] == 0
5549
assert ret[1] == 'Hello World\n'
5650

5751

52+
@pytest.mark.herpderp
53+
@skipif_slowtests_false
54+
@pytest.mark.integration
55+
def test_run_a_ruby_hook(config_for_ruby_hooks_repo, store):
56+
repo = Repository.create(config_for_ruby_hooks_repo, store)
57+
ret = repo.run_hook('ruby_hook', [])
58+
assert ret[0] == 0
59+
assert ret[1] == 'Hello world from a ruby hook\n'
60+
61+
5862
@pytest.mark.integration
5963
def test_run_a_script_hook(config_for_script_hooks_repo, store):
6064
repo = Repository.create(config_for_script_hooks_repo, store)

tests/staged_files_only_test.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import shutil
99
from plumbum import local
1010

11-
from pre_commit.prefixed_command_runner import PrefixedCommandRunner
1211
from pre_commit.staged_files_only import staged_files_only
1312
from testing.auto_namedtuple import auto_namedtuple
1413
from testing.util import get_resource_path
@@ -31,11 +30,6 @@ def foo_staged(empty_git_dir):
3130
yield auto_namedtuple(path=empty_git_dir, foo_filename=foo_filename)
3231

3332

34-
@pytest.yield_fixture
35-
def cmd_runner(tmpdir_factory):
36-
yield PrefixedCommandRunner(tmpdir_factory.get())
37-
38-
3933
def _test_foo_state(path, foo_contents=FOO_CONTENTS, status='A'):
4034
assert os.path.exists(path.foo_filename)
4135
assert io.open(path.foo_filename, encoding='utf-8').read() == foo_contents

0 commit comments

Comments
 (0)