-
Notifications
You must be signed in to change notification settings - Fork 441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new plugin: rust #579
Add new plugin: rust #579
Changes from 9 commits
8b9e9cf
99388bd
05fb2a4
19e28be
a4beaba
53d7d06
737e9c2
cd19dd9
2f23a30
1350055
f992900
9046a9c
9497f7b
005308d
c99170b
f9ad891
681faa6
c7c0bf5
36f31fe
d483d1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,3 +14,5 @@ dist | |
htmlcov | ||
__pycache__ | ||
docs/**.html | ||
Cargo.lock | ||
target |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = "simple-rust" | ||
version = "0.1.0" | ||
authors = ["Marius Gripsgard <mariogrip@ubuntu.com>"] | ||
|
||
[dependencies] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
name: test-package | ||
version: 0.1 | ||
summary: A simple rust project. | ||
description: A simple rust project. | ||
confinement: strict | ||
|
||
parts: | ||
simple-rust: | ||
plugin: rust | ||
source: . |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fn main() { | ||
println!("There is rust on snaps!"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright (C) 2016 Marius Gripsgard (mariogrip@ubuntu.com) | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 3 as | ||
# published by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
import os, integration_tests | ||
|
||
class RustPluginTestCase(integration_tests.TestCase): | ||
|
||
def test_stage_rust_plugin(self): | ||
project_dir = 'simple-rust' | ||
self.run_snapcraft('stage', project_dir) | ||
|
||
binary_output = self.get_output_ignoring_non_zero_exit( | ||
os.path.join('stage', 'bin', 'simple-rust'), cwd=project_dir) | ||
self.assertEqual("There is rust on snaps!\n", binary_output) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# Copyright (C) 2016 Marius Gripsgard (mariogrip@ubuntu.com) | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 3 as | ||
# published by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
"""This rust plugin is useful for building rust based parts. | ||
|
||
Rust uses cargo to drive the build. | ||
|
||
This plugin uses the common plugin keywords as well as those for "sources". | ||
For more information check the 'plugins' topic for the former and the | ||
'sources' topic for the latter. | ||
|
||
Additionally, this plugin uses the following plugin-specific keywords: | ||
|
||
- rust-channel | ||
(string) | ||
select rust channel (stable, beta, nightly) | ||
- rust-revision | ||
(string) | ||
select rust version | ||
""" | ||
|
||
import os | ||
import snapcraft | ||
import shutil | ||
|
||
|
||
class RustPlugin(snapcraft.BasePlugin): | ||
|
||
@classmethod | ||
def schema(cls): | ||
schema = super().schema() | ||
schema['properties']['rust-channel'] = { | ||
'type': 'string', | ||
} | ||
schema['properties']['rust-revision'] = { | ||
'type': 'string', | ||
} | ||
return schema | ||
|
||
def __init__(self, name, options, project): | ||
super().__init__(name, options, project) | ||
self._rustpath = os.path.join(self.partdir, "rust") | ||
self._rustc = os.path.join(self._rustpath, "bin", "rustc") | ||
self._rustdoc = os.path.join(self._rustpath, "bin", "rustdoc") | ||
self._cargo = os.path.join(self._rustpath, "bin", "cargo") | ||
self._rustlib = os.path.join(self._rustpath, "lib") | ||
|
||
def build(self): | ||
super().build() | ||
self.run([self._cargo, "install", | ||
"-j{}".format(self.project.parallel_build_count), | ||
"--root", self.installdir], env=self._build_env()) | ||
|
||
def _build_env(self): | ||
env = os.environ.copy() | ||
env.update({"RUSTC": self._rustc, | ||
"RUSTDOC": self._rustdoc, | ||
"RUST_PATH": self._rustlib}) | ||
return env | ||
|
||
def pull(self): | ||
super().pull() | ||
self._fetch_rust() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is missing a |
||
|
||
def clean_pull(self): | ||
super().clean_pull() | ||
|
||
# Remove the rust path (if any) | ||
if os.path.exists(self._rustpath): | ||
shutil.rmtree(self._rustpath) | ||
|
||
def _fetch_rust(self): | ||
options = [] | ||
|
||
if self.options.rust_revision: | ||
options.append("--revision=%s" % self.options.rust_revision) | ||
|
||
if self.options.rust_channel: | ||
if self.options.rust_channel in ["stable", "beta", "nightly"]: | ||
options.append("--channel=%s" % self.options.rust_channel) | ||
else: | ||
raise EnvironmentError("%s is not a valid rust channel" | ||
% self.options.rust_channel) | ||
|
||
rustup = "rustup.sh" | ||
self.run(["wget", "-N", "https://static.rust-lang.org/rustup.sh", | ||
"-O", rustup]) | ||
self.run(["chmod", "+x", rustup]) | ||
self.run(["./%s" % rustup, | ||
"--prefix=%s" % self._rustpath, | ||
"--disable-sudo", "--save"]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- | ||
# | ||
# Copyright (C) 2016 Canonical Ltd | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 3 as | ||
# published by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
import os | ||
|
||
from unittest import mock | ||
|
||
import snapcraft | ||
from snapcraft import tests | ||
from snapcraft.plugins import rust | ||
|
||
|
||
class MakePluginTestCase(tests.TestCase): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe update the test case class name? |
||
|
||
def setUp(self): | ||
super().setUp() | ||
|
||
class Options: | ||
makefile = None | ||
make_parameters = [] | ||
|
||
self.options = Options() | ||
self.project_options = snapcraft.ProjectOptions() | ||
|
||
def test_schema(self): | ||
schema = rust.RustPlugin.schema() | ||
|
||
properties = schema['properties'] | ||
self.assertTrue('rust-channel' in properties, | ||
'Expected "rust-channel" to be included in properties') | ||
self.assertTrue('rust-revision' in properties, | ||
'Expected "rust-revision to be included in properties') | ||
|
||
rust_channel = properties['rust-channel'] | ||
self.assertTrue('type' in rust_channel, | ||
'Expected "type" to be included in "rust-channel"') | ||
|
||
rust_channel_type = rust_channel['type'] | ||
self.assertEqual(rust_channel_type, 'string', | ||
'Expected "rust-channel" "type" to be "string", ' | ||
'but it was "{}"'.format(rust_channel_type)) | ||
|
||
rust_revision = properties['rust-revision'] | ||
self.assertTrue('type' in rust_revision, | ||
'Expected "type" to be included in "rust-revision"') | ||
|
||
rust_revision_type = rust_revision['type'] | ||
self.assertEqual(rust_revision_type, 'string', | ||
'Expected "rust-revision" "type" to be "string", ' | ||
'but it was "{}"'.format(rust_revision_type)) | ||
|
||
@mock.patch.object(rust.RustPlugin, 'run') | ||
def test_build(self, run_mock): | ||
plugin = rust.RustPlugin('test-part', self.options, | ||
self.project_options) | ||
os.makedirs(plugin.sourcedir) | ||
|
||
plugin.build() | ||
|
||
self.assertEqual(1, run_mock.call_count) | ||
run_mock.assert_has_calls([ | ||
mock.call([plugin._cargo, 'install', | ||
'-j{}'.format(plugin.project.parallel_build_count), | ||
'--root', plugin.installdir], env=plugin._build_env()) | ||
]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice work so far! Coveralls points out that you are missing some tests here. In line 84 of that Coveralls page for example, shows that there is no test for an invalid Rust channel. I don't have commit access and Coveralls could be totally wrong, but I thought I should point it out just in case Coveralls is right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But oxide is still missing!