use clap::Parser;
use pchain_compile::{config::Config, DockerConfig, DockerOption, BuildOptions};
use std::path::{Path, PathBuf};
#[derive(Debug, Parser)]
#[clap(
name = "pchain-compile",
version = env!("CARGO_PKG_VERSION"),
about = "ParallelChain Smart Contract Compile CLI\n\n\
A command line tool for reproducibly building Rust code into compact, gas-efficient WebAssembly ParallelChain Smart Contract.",
author = "<ParallelChain Lab>",
long_about = None
)]
enum PchainCompile {
#[clap(arg_required_else_help = true, display_order = 1, verbatim_doc_comment)]
Build {
#[clap(long = "source", display_order = 1, verbatim_doc_comment)]
source_path: Vec<PathBuf>,
#[clap(long = "destination", display_order = 2, verbatim_doc_comment)]
destination_path: Option<PathBuf>,
#[clap(long = "locked", display_order = 3, verbatim_doc_comment)]
locked: bool,
#[clap(
long = "dockerless",
display_order = 4,
verbatim_doc_comment,
group = "docker-option"
)]
dockerless: bool,
#[clap(
long = "use-docker-tag",
display_order = 5,
verbatim_doc_comment,
group = "docker-option"
)]
docker_image_tag: Option<String>,
},
}
#[tokio::main]
async fn main() {
let args = PchainCompile::parse();
match args {
PchainCompile::Build {
source_path,
destination_path,
locked,
dockerless,
docker_image_tag,
} => {
if source_path.is_empty() {
println!("Please provide at least one source!");
std::process::exit(-1);
}
println!("Build process started. This could take several minutes for large contracts.");
let build_options = BuildOptions {
locked
};
let docker_option = if dockerless {
DockerOption::Dockerless
} else {
DockerOption::Docker(DockerConfig {
tag: docker_image_tag,
})
};
let mut join_handles = vec![];
source_path.into_iter().for_each(|source_path| {
let config = Config {
source_path,
destination_path: destination_path.clone(),
build_options: build_options.clone(),
docker_option: docker_option.clone(),
};
join_handles.push(tokio::spawn(config.run()));
});
let mut results = vec![];
for handle in join_handles {
results.push(handle.await.unwrap());
}
let (success, fails): (Vec<_>, Vec<_>) = results.into_iter().partition(Result::is_ok);
if !success.is_empty() {
let dst_path = destination_path
.clone()
.unwrap_or(Path::new(".").to_path_buf());
let contracts: Vec<String> = success.into_iter().map(|r| r.ok().unwrap()).collect();
println!("Finished compiling. ParallelChain Mainnet smart contract(s) {:?} are saved at ({})", contracts, dunce::canonicalize(dst_path).unwrap().to_str().unwrap());
}
if !fails.is_empty() {
println!("Compiling fails.");
fails.into_iter().for_each(|e| {
let error = e.err().unwrap();
println!("{}\n{}\n", error, error.detail());
});
}
}
};
}