use anyhow::Result;
use contract_build::{
BuildArtifacts,
BuildMode,
BuildResult,
ComposeBuildArgs,
ExecuteArgs,
Features,
ImageVariant,
ManifestPath,
MetadataSpec,
Network,
OutputType,
UnstableFlags,
UnstableOptions,
Verbosity,
VerbosityFlags,
};
use std::{
convert::TryFrom,
path::PathBuf,
};
pub(crate) struct CargoContractComposeBuildArgs;
impl ComposeBuildArgs for CargoContractComposeBuildArgs {
fn compose_build_args() -> Result<Vec<String>> {
use regex::Regex;
let mut args: Vec<String> = Vec::new();
let rex = Regex::new(r#"(--image|verify)[ ]*[^ ]*[ ]*"#)?;
let args_string: String = std::env::args().collect::<Vec<String>>().join(" ");
let args_string = rex.replace_all(&args_string, "").to_string();
let mut os_args: Vec<String> = args_string
.split_ascii_whitespace()
.filter(|a| {
a != &"--verifiable"
&& !a.contains("cargo-contract")
&& a != &"cargo"
&& a != &"contract"
&& a != &"build"
&& a != &"--output-json"
})
.map(|s| s.to_string())
.collect();
args.append(&mut os_args);
Ok(args)
}
}
#[derive(Debug, clap::Args)]
#[clap(name = "build")]
pub struct BuildCommand {
#[clap(long, value_parser)]
manifest_path: Option<PathBuf>,
#[clap(long = "release")]
build_release: bool,
#[clap(long = "offline")]
build_offline: bool,
#[clap(long = "generate", value_enum, default_value = "all")]
build_artifact: BuildArtifacts,
#[clap(flatten)]
features: Features,
#[clap(flatten)]
verbosity: VerbosityFlags,
#[clap(flatten)]
unstable_options: UnstableOptions,
#[clap(long)]
keep_debug_symbols: bool,
#[clap(long, conflicts_with = "verbose")]
output_json: bool,
#[clap(long, default_value_t = false)]
verifiable: bool,
#[clap(long, default_value = None)]
image: Option<String>,
#[clap(long)]
metadata: Option<MetadataSpec>,
}
impl BuildCommand {
pub fn exec(&self) -> Result<BuildResult> {
let manifest_path = ManifestPath::try_from(self.manifest_path.as_ref())?;
let unstable_flags: UnstableFlags =
TryFrom::<&UnstableOptions>::try_from(&self.unstable_options)?;
let verbosity = TryFrom::<&VerbosityFlags>::try_from(&self.verbosity)?;
let build_mode = if self.verifiable {
BuildMode::Verifiable
} else {
match self.build_release {
true => BuildMode::Release,
false => BuildMode::Debug,
}
};
let network = match self.build_offline {
true => Network::Offline,
false => Network::Online,
};
let output_type = match self.output_json {
true => OutputType::Json,
false => OutputType::HumanReadable,
};
if self.image.is_some() && build_mode != BuildMode::Verifiable {
anyhow::bail!("--image flag can only be used with verifiable builds!");
}
let image = match &self.image {
Some(i) => ImageVariant::Custom(i.clone()),
None => ImageVariant::Default,
};
let args = ExecuteArgs {
manifest_path,
verbosity,
build_mode,
features: self.features.clone(),
network,
build_artifact: self.build_artifact,
unstable_flags,
keep_debug_symbols: self.keep_debug_symbols,
extra_lints: false,
output_type,
image,
metadata_spec: self.metadata,
target_dir: None,
};
contract_build::execute::<CargoContractComposeBuildArgs>(args)
}
}
#[derive(Debug, clap::Args)]
#[clap(name = "check")]
pub struct CheckCommand {
#[clap(long, value_parser)]
manifest_path: Option<PathBuf>,
#[clap(flatten)]
verbosity: VerbosityFlags,
}
impl CheckCommand {
pub fn exec(&self) -> Result<BuildResult> {
let manifest_path = ManifestPath::try_from(self.manifest_path.as_ref())?;
let verbosity: Verbosity = TryFrom::<&VerbosityFlags>::try_from(&self.verbosity)?;
let args = ExecuteArgs {
manifest_path,
verbosity,
build_mode: BuildMode::Debug,
features: Default::default(),
network: Network::default(),
build_artifact: BuildArtifacts::CheckOnly,
unstable_flags: Default::default(),
keep_debug_symbols: false,
extra_lints: false,
output_type: OutputType::default(),
image: ImageVariant::Default,
metadata_spec: Default::default(),
target_dir: None,
};
contract_build::execute::<CargoContractComposeBuildArgs>(args)
}
}