use crate::Verbosity;
use anyhow::{Context, Result};
use rustc_version::Channel;
use std::{ffi::OsStr, path::Path, process::Command};
pub fn assert_channel() -> Result<()> {
let meta = rustc_version::version_meta()?;
match meta.channel {
Channel::Dev | Channel::Nightly => Ok(()),
Channel::Stable | Channel::Beta => {
anyhow::bail!(
"cargo-contract cannot build using the {:?} channel. \
Switch to nightly. \
See https://github.com/paritytech/cargo-contract#build-requires-the-nightly-toolchain",
format!("{:?}", meta.channel).to_lowercase(),
);
}
}
}
pub(crate) fn invoke_cargo<I, S, P>(
command: &str,
args: I,
working_dir: Option<P>,
verbosity: Option<Verbosity>,
) -> Result<Vec<u8>>
where
I: IntoIterator<Item = S> + std::fmt::Debug,
S: AsRef<OsStr>,
P: AsRef<Path>,
{
let cargo = std::env::var("CARGO").unwrap_or("cargo".to_string());
let mut cmd = Command::new(cargo);
if let Some(path) = working_dir {
log::debug!("Setting cargo working dir to '{}'", path.as_ref().display());
cmd.current_dir(path);
}
cmd.arg(command);
cmd.args(args);
match verbosity {
Some(Verbosity::Quiet) => cmd.arg("--quiet"),
Some(Verbosity::Verbose) => cmd.arg("--verbose"),
None => &mut cmd,
};
log::info!("invoking cargo: {:?}", cmd);
let child = cmd
.stdout(std::process::Stdio::piped())
.spawn()
.context(format!("Error executing `{:?}`", cmd))?;
let output = child.wait_with_output()?;
if output.status.success() {
Ok(output.stdout)
} else {
anyhow::bail!(
"`{:?}` failed with exit code: {:?}",
cmd,
output.status.code()
);
}
}
#[cfg(test)]
pub mod tests {
use std::path::Path;
pub fn with_tmp_dir<F>(f: F)
where
F: FnOnce(&Path) -> anyhow::Result<()>,
{
let tmp_dir = tempfile::Builder::new()
.prefix("cargo-contract.test.")
.tempdir()
.expect("temporary directory creation failed");
f(tmp_dir.path()).expect("Error executing test with tmp dir")
}
}