Skip to content

Commit

Permalink
Merge pull request #36 from dfinity-lab/hansl/canister-install
Browse files Browse the repository at this point in the history
New Feature: dfx canister install
  • Loading branch information
Hans authored Sep 18, 2019
2 parents 2927bb2 + d616773 commit 4ea44e7
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 53 deletions.
1 change: 1 addition & 0 deletions dfx/Cargo.lock

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

1 change: 1 addition & 0 deletions dfx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ wabt = "0.9.2"
[dev-dependencies]
env_logger = "0.6"
mockito = "0.20.0"
tempfile = "3.1.0"
3 changes: 3 additions & 0 deletions dfx/shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ pkgs.mkCiShell {
inputsFrom = [
dfx
];
shellHook = ''
export DFX_TIMESTAMP_DEBUG_MODE_ONLY=$(date +%s)
'';
DFX_ASSETS = dfx.DFX_ASSETS;
}
3 changes: 2 additions & 1 deletion dfx/src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ mod tests {
let env = TestEnv {};
let wat = r#"(module )"#;

let temp_path = temp_dir();
let temp_dir = tempfile::tempdir().unwrap();
let temp_path = temp_dir.into_path();
let input_path = temp_path.join("input.wat");
let output_path = temp_path.join("output.wasm");

Expand Down
10 changes: 5 additions & 5 deletions dfx/src/commands/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,21 @@ where
},
)
.and_then(|r| match r {
Response::Accepted => {
println!("Accepted");
ReadResponse::Pending => {
println!("Pending");
ok(())
}
Response::Replied {
ReadResponse::Replied {
reply: QueryResponseReply { arg: Blob(blob) },
} => {
println!("{}", String::from_utf8_lossy(&blob));
ok(())
}
Response::Rejected {
ReadResponse::Rejected {
reject_code,
reject_message,
} => err(DfxError::ClientError(reject_code, reject_message)),
Response::Unknown => err(DfxError::Unknown("Unknown response".to_owned())),
ReadResponse::Unknown => err(DfxError::Unknown("Unknown response".to_owned())),
});

let mut runtime = Runtime::new().expect("Unable to create a runtime");
Expand Down
52 changes: 52 additions & 0 deletions dfx/src/commands/canister/install.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::lib::api_client::{install_code, Blob};
use crate::lib::env::{ClientEnv, ProjectConfigEnv};
use crate::lib::error::DfxResult;
use clap::{App, Arg, ArgMatches, SubCommand};
use std::path::PathBuf;
use tokio::runtime::Runtime;

fn is_number(v: String) -> Result<(), String> {
v.parse::<u64>()
.map_err(|_| String::from("The value must be a number."))
.map(|_| ())
}

pub fn construct() -> App<'static, 'static> {
SubCommand::with_name("install")
.about("Install a canister.")
.arg(
Arg::with_name("canister")
.takes_value(true)
.help("The canister ID (a number).")
.required(true)
.validator(is_number),
)
.arg(
Arg::with_name("wasm")
.help("The wasm file to use.")
.required(true),
)
}

pub fn exec<T>(env: &T, args: &ArgMatches<'_>) -> DfxResult
where
T: ClientEnv + ProjectConfigEnv,
{
// Read the config.
let config = env.get_config().unwrap();
let project_root = config.get_path().parent().unwrap();

let canister_id = args.value_of("canister").unwrap().parse::<u64>()?;
let wasm_path = args.value_of("wasm").unwrap();
let wasm_path = PathBuf::from(project_root).join(wasm_path);

let wasm = std::fs::read(wasm_path)?;
let client = env.get_client();

let install = install_code(client, canister_id, Blob(wasm), None);

let mut runtime = Runtime::new().expect("Unable to create a runtime");
runtime.block_on(install)?;

Ok(())
}
48 changes: 48 additions & 0 deletions dfx/src/commands/canister/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::commands::CliCommand;
use crate::lib::env::{ClientEnv, ProjectConfigEnv};
use crate::lib::error::{DfxError, DfxResult};
use clap::{App, ArgMatches, SubCommand};

mod install;

fn builtins<T>() -> Vec<CliCommand<T>>
where
T: ClientEnv + ProjectConfigEnv,
{
vec![CliCommand::new(install::construct(), install::exec)]
}

pub fn construct<T>() -> App<'static, 'static>
where
T: ClientEnv + ProjectConfigEnv,
{
SubCommand::with_name("canister")
.about("Manage canisters from a network.")
.subcommands(
builtins::<T>()
.into_iter()
.map(|x| x.get_subcommand().clone()),
)
}

pub fn exec<T>(env: &T, args: &ArgMatches<'_>) -> DfxResult
where
T: ClientEnv + ProjectConfigEnv,
{
let subcommand = args.subcommand();

if let (name, Some(subcommand_args)) = subcommand {
match builtins().into_iter().find(|x| name == x.get_name()) {
Some(cmd) => cmd.execute(env, subcommand_args),
None => Err(DfxError::UnknownCommand(format!(
"Command {} not found.",
name
))),
}
} else {
construct::<T>().write_help(&mut std::io::stderr())?;
println!();
println!();
Ok(())
}
}
2 changes: 2 additions & 0 deletions dfx/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use clap::ArgMatches;

mod build;
mod call;
mod canister;
mod new;
mod start;

Expand Down Expand Up @@ -41,6 +42,7 @@ where
vec![
CliCommand::new(build::construct(), build::exec),
CliCommand::new(call::construct(), call::exec),
CliCommand::new(canister::construct::<T>(), canister::exec),
CliCommand::new(new::construct(), new::exec),
CliCommand::new(start::construct(), start::exec),
]
Expand Down
23 changes: 8 additions & 15 deletions dfx/src/config/cache.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io::{Error, ErrorKind, Result};
use std::path::PathBuf;

use crate::config::dfx_version;
use crate::util;

pub fn get_bin_cache_root() -> Result<PathBuf> {
Expand Down Expand Up @@ -31,14 +32,7 @@ pub fn get_bin_cache_root() -> Result<PathBuf> {

pub fn get_bin_cache(v: &str) -> Result<PathBuf> {
let root = get_bin_cache_root()?;

match v {
"0.2.0" => Ok(root.join("0.2.0")),
v => Err(Error::new(
ErrorKind::Other,
format!("Unknown version: {}", v),
)),
}
Ok(root.join(v))
}

pub fn is_version_installed(v: &str) -> Result<bool> {
Expand All @@ -60,15 +54,14 @@ pub fn install_version(v: &str) -> Result<PathBuf> {
return Ok(p);
}

match v {
"0.2.0" => {
util::assets::binary_cache()?.unpack(p.as_path())?;
Ok(p)
}
v => Err(Error::new(
if v == dfx_version() {
util::assets::binary_cache()?.unpack(p.as_path())?;
Ok(p)
} else {
Err(Error::new(
ErrorKind::Other,
format!("Unknown version: {}", v),
)),
))
}
}

Expand Down
29 changes: 28 additions & 1 deletion dfx/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
pub mod cache;
pub mod dfinity;

pub const DFX_VERSION: &str = env!("CARGO_PKG_VERSION");
static mut DFX_VERSION: Option<String> = None;
/// Returns the version of DFX that was built.
/// In debug, add a timestamp of the upstream compilation at the end of version to ensure all
/// debug runs are unique (and cached uniquely).
/// That timestamp is taken from the DFX_TIMESTAMP_DEBUG_MODE_ONLY env var that is set in
/// Nix.
pub fn dfx_version() -> &'static str {
unsafe {
match &DFX_VERSION {
Some(x) => x.as_str(),
None => {
let version = env!("CARGO_PKG_VERSION");

#[cfg(debug_assertions)]
{
DFX_VERSION = Some(format!(
"{}-{}",
version,
std::env::var("DFX_TIMESTAMP_DEBUG_MODE_ONLY")
.unwrap_or_else(|_| "local-debug".to_owned())
));
}

dfx_version()
}
}
}
}
Loading

0 comments on commit 4ea44e7

Please sign in to comment.