X Tutup
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ before_install:
fi
- git --version
- './get-swift.sh && export PATH="/tmp/swift/usr/bin:$PATH"'
- 'curl -sSf https://sh.rustup.rs | bash -s -- -y'
- export PATH="$HOME/.cargo/bin:$PATH"
after_success: coveralls
cache:
directories:
Expand Down
2 changes: 2 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ install:
- pip install tox virtualenv --upgrade
- "mkdir -p C:\\Temp"
- "SET TMPDIR=C:\\Temp"
- "curl -sSf https://sh.rustup.rs | bash -s -- -y"
- "SET PATH=%USERPROFILE%\\.cargo\\bin;%PATH%"

# Not a C# project
build: false
Expand Down
2 changes: 2 additions & 0 deletions pre_commit/languages/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pre_commit.languages import python
from pre_commit.languages import python_venv
from pre_commit.languages import ruby
from pre_commit.languages import rust
from pre_commit.languages import script
from pre_commit.languages import swift
from pre_commit.languages import system
Expand Down Expand Up @@ -60,6 +61,7 @@
'python': python,
'python_venv': python_venv,
'ruby': ruby,
'rust': rust,
'script': script,
'swift': swift,
'system': system,
Expand Down
94 changes: 94 additions & 0 deletions pre_commit/languages/rust.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from __future__ import unicode_literals

import contextlib
import os.path

import toml

from pre_commit.envcontext import envcontext
from pre_commit.envcontext import Var
from pre_commit.languages import helpers
from pre_commit.util import clean_path_on_failure
from pre_commit.util import cmd_output
from pre_commit.xargs import xargs


ENVIRONMENT_DIR = 'rustenv'
get_default_version = helpers.basic_get_default_version
healthy = helpers.basic_healthy


def get_env_patch(target_dir):
return (
(
'PATH',
(os.path.join(target_dir, 'bin'), os.pathsep, Var('PATH')),
),
)


@contextlib.contextmanager
def in_env(prefix):
target_dir = prefix.path(
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
)
with envcontext(get_env_patch(target_dir)):
yield


def _add_dependencies(cargo_toml_path, additional_dependencies):
with open(cargo_toml_path, 'r+') as f:
cargo_toml = toml.load(f)
cargo_toml.setdefault('dependencies', {})
for dep in additional_dependencies:
name, _, spec = dep.partition(':')
cargo_toml['dependencies'][name] = spec or '*'
f.seek(0)
toml.dump(cargo_toml, f)
f.truncate()


def install_environment(prefix, version, additional_dependencies):
helpers.assert_version_default('rust', version)
directory = prefix.path(
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
)

# There are two cases where we might want to specify more dependencies:
# as dependencies for the library being built, and as binary packages
# to be `cargo install`'d.
#
# Unlike e.g. Python, if we just `cargo install` a library, it won't be
# used for compilation. And if we add a crate providing a binary to the
# `Cargo.toml`, the binary won't be built.
#
# Because of this, we allow specifying "cli" dependencies by prefixing
# with 'cli:'.
cli_deps = {
dep for dep in additional_dependencies if dep.startswith('cli:')
}
lib_deps = set(additional_dependencies) - cli_deps

if len(lib_deps) > 0:
_add_dependencies(prefix.path('Cargo.toml'), lib_deps)

with clean_path_on_failure(directory):
packages_to_install = {()}
for cli_dep in cli_deps:
cli_dep = cli_dep[len('cli:'):]
package, _, version = cli_dep.partition(':')
if version != '':
packages_to_install.add((package, '--version', version))
else:
packages_to_install.add((package,))

for package in packages_to_install:
cmd_output(
'cargo', 'install', '--bins', '--root', directory, *package,
cwd=prefix.prefix_dir
)


def run_hook(prefix, hook, file_args):
with in_env(prefix):
return xargs(helpers.to_cmd(hook), file_args)
7 changes: 7 additions & 0 deletions pre_commit/resources/empty_template/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "__fake_crate"
version = "0.0.0"

[[bin]]
name = "__fake_cmd"
path = "main.rs"
1 change: 1 addition & 0 deletions pre_commit/resources/empty_template/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
'nodeenv>=0.11.1',
'pyyaml',
'six',
'toml',
'virtualenv',
],
entry_points={
Expand Down
5 changes: 5 additions & 0 deletions testing/resources/rust_hooks_repo/.pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- id: rust-hook
name: rust example hook
entry: rust-hello-world
language: rust
files: ''
3 changes: 3 additions & 0 deletions testing/resources/rust_hooks_repo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions testing/resources/rust_hooks_repo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "rust-hello-world"
version = "0.1.0"
3 changes: 3 additions & 0 deletions testing/resources/rust_hooks_repo/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("hello world");
}
68 changes: 68 additions & 0 deletions tests/repository_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pre_commit.languages import pcre
from pre_commit.languages import python
from pre_commit.languages import ruby
from pre_commit.languages import rust
from pre_commit.repository import Repository
from pre_commit.util import cmd_output
from testing.fixtures import config_with_local_hooks
Expand Down Expand Up @@ -282,6 +283,55 @@ def test_golang_hook(tempdir_factory, store):
)


@pytest.mark.integration
def test_rust_hook(tempdir_factory, store):
_test_hook_repo(
tempdir_factory, store, 'rust_hooks_repo',
'rust-hook', [], b'hello world\n',
)


@pytest.mark.integration
@pytest.mark.parametrize('dep', ('cli:shellharden:3.1.0', 'cli:shellharden'))
def test_additional_rust_cli_dependencies_installed(
tempdir_factory, store, dep,
):
path = make_repo(tempdir_factory, 'rust_hooks_repo')
config = make_config_from_repo(path)
# A small rust package with no dependencies.
config['hooks'][0]['additional_dependencies'] = [dep]
repo = Repository.create(config, store)
repo.require_installed()
(prefix, _, _, _), = repo._venvs()
binaries = os.listdir(prefix.path(
helpers.environment_dir(rust.ENVIRONMENT_DIR, 'default'), 'bin',
))
# normalize for windows
binaries = [os.path.splitext(binary)[0] for binary in binaries]
assert 'shellharden' in binaries


@pytest.mark.integration
def test_additional_rust_lib_dependencies_installed(
tempdir_factory, store,
):
path = make_repo(tempdir_factory, 'rust_hooks_repo')
config = make_config_from_repo(path)
# A small rust package with no dependencies.
deps = ['shellharden:3.1.0']
config['hooks'][0]['additional_dependencies'] = deps
repo = Repository.create(config, store)
repo.require_installed()
(prefix, _, _, _), = repo._venvs()
binaries = os.listdir(prefix.path(
helpers.environment_dir(rust.ENVIRONMENT_DIR, 'default'), 'bin',
))
# normalize for windows
binaries = [os.path.splitext(binary)[0] for binary in binaries]
assert 'rust-hello-world' in binaries
assert 'shellharden' not in binaries


@pytest.mark.integration
def test_missing_executable(tempdir_factory, store):
_test_hook_repo(
Expand Down Expand Up @@ -554,6 +604,24 @@ def test_local_golang_additional_dependencies(store):
assert _norm_out(ret[1]) == b"Hello, Go examples!\n"


def test_local_rust_additional_dependencies(store):
config = {
'repo': 'local',
'hooks': [{
'id': 'hello',
'name': 'hello',
'entry': 'hello',
'language': 'rust',
'additional_dependencies': ['cli:hello-cli:0.2.2'],
}],
}
repo = Repository.create(config, store)
(_, hook), = repo.hooks
ret = repo.run_hook(hook, ())
assert ret[0] == 0
assert _norm_out(ret[1]) == b"Hello World!\n"


def test_reinstall(tempdir_factory, store, log_info_mock):
path = make_repo(tempdir_factory, 'python_hooks_repo')
config = make_config_from_repo(path)
Expand Down
X Tutup