diff --git a/CHANGELOG.md b/CHANGELOG.md index 73db2b00e..8a3612192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased] +- `contract_build::execute` now uses a generic type to specify how command line arguments are passed to verifiable builds - [2177](https://github.com/use-ink/cargo-contract/pull/2177) + ## Version 6.0.0-beta.1 ### Fixed diff --git a/crates/build/src/docker.rs b/crates/build/src/docker.rs index b7c81f2df..8743ce463 100644 --- a/crates/build/src/docker.rs +++ b/crates/build/src/docker.rs @@ -122,8 +122,14 @@ impl From> for ImageVariant { } } +pub trait ComposeBuildArgs { + /// Takes CLI args from the host and appends them to the build command inside the + /// docker. + fn compose_build_args() -> Result>; +} + /// Launches the docker container to execute verifiable build. -pub fn docker_build(args: ExecuteArgs) -> Result { +pub fn docker_build(args: ExecuteArgs) -> Result { let ExecuteArgs { manifest_path, verbosity, @@ -139,7 +145,7 @@ pub fn docker_build(args: ExecuteArgs) -> Result { let crate_metadata = CrateMetadata::collect_with_target_dir(&manifest_path, target_dir)?; let host_folder = std::env::current_dir()?; - let args = compose_build_args()?; + let args = T::compose_build_args()?; let client = Docker::connect_with_socket_defaults().map_err(|e| { anyhow::anyhow!("{e}\nDo you have the docker engine installed in path?") @@ -511,38 +517,6 @@ async fn run_build( } } -/// Takes CLI args from the host and appends them to the build command inside the docker. -fn compose_build_args() -> Result> { - use regex::Regex; - let mut args: Vec = Vec::new(); - // match `--image` or `verify` with arg with 1 or more white spaces surrounded - let rex = Regex::new(r#"(--image|verify)[ ]*[^ ]*[ ]*"#)?; - // we join the args together, so we can remove `--image ` - // We skip the first captured argument (binary name), to allow other binaries use - // docker_build. - let args_string: String = std::env::args().skip(1).collect::>().join(" "); - let args_string = rex.replace_all(&args_string, "").to_string(); - - // and then we turn it back to the vec, filtering out commands and arguments - // that should not be passed to the docker build command - let mut os_args: Vec = 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) -} - /// Pulls the docker image from the registry. async fn pull_image(client: &Docker, image: String, verbosity: &Verbosity) -> Result<()> { let mut pull_image_stream = client.create_image( diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 157dcb733..a19276ff1 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -59,6 +59,7 @@ pub use self::{ VerbosityFlags, }, crate_metadata::CrateMetadata, + docker::ComposeBuildArgs, metadata::{ BuildInfo, InkMetadataArtifacts, @@ -575,7 +576,7 @@ fn validate_metadata_spec_for_abi( /// deploying. /// /// It does so by invoking `cargo build` and then post-processing the final binary. -pub fn execute(args: ExecuteArgs) -> Result { +pub fn execute(args: ExecuteArgs) -> Result { let ExecuteArgs { manifest_path, verbosity, @@ -592,7 +593,7 @@ pub fn execute(args: ExecuteArgs) -> Result { // if image exists, then --verifiable was called and we need to build inside docker. if build_mode == &BuildMode::Verifiable { - return docker_build(args) + return docker_build::(args) } let crate_metadata = diff --git a/crates/build/src/tests.rs b/crates/build/src/tests.rs index 5dbdca5f9..d9e11a42e 100644 --- a/crates/build/src/tests.rs +++ b/crates/build/src/tests.rs @@ -19,6 +19,7 @@ use crate::{ BuildArtifacts, BuildMode, BuildResult, + ComposeBuildArgs, CrateMetadata, ExecuteArgs, InkMetadataArtifacts, @@ -46,6 +47,13 @@ use std::{ time::SystemTime, }; +struct MockComposeBuildArgs; +impl ComposeBuildArgs for MockComposeBuildArgs { + fn compose_build_args() -> Result> { + Ok(Vec::new()) + } +} + // All functions provided here are run sequentially as part of the same `#[test]` // sharing build artifacts (but nothing else) using the [`BuildTestContext`]. // @@ -108,7 +116,7 @@ fn build_code_only(manifest_path: &ManifestPath) -> Result<()> { ..Default::default() }; - let res = super::execute(args).expect("build failed"); + let res = super::execute::(args).expect("build failed"); // our ci has set `CARGO_TARGET_DIR` to cache artifacts. // this dir does not include `/target/` as a path, hence @@ -161,7 +169,7 @@ fn check_must_not_output_contract_artifacts_in_project_dir( }; // when - super::execute(args).expect("build failed"); + super::execute::(args).expect("build failed"); // then let project_dir = project_path( @@ -195,7 +203,7 @@ fn building_template_in_debug_mode_must_work(manifest_path: &ManifestPath) -> Re }; // when - let res = super::execute(args); + let res = super::execute::(args); // then assert!(res.is_ok(), "building template in debug mode failed!"); @@ -214,7 +222,7 @@ fn building_template_in_release_mode_must_work( }; // when - let res = super::execute(args); + let res = super::execute::(args); // then assert!(res.is_ok(), "building template in release mode failed!"); @@ -244,7 +252,7 @@ fn building_contract_with_source_file_in_subfolder_must_work( }; // when - let res = super::execute(args); + let res = super::execute::(args); // then assert!(res.is_ok(), "building contract failed!"); @@ -273,7 +281,7 @@ fn building_contract_with_build_rs_must_work(manifest_path: &ManifestPath) -> Re }; // when - let res = super::execute(args); + let res = super::execute::(args); // then assert!(res.is_ok(), "building contract failed!"); @@ -291,7 +299,7 @@ fn keep_debug_symbols_in_debug_mode(manifest_path: &ManifestPath) -> Result<()> }; // todo - let _res = super::execute(args).expect("build failed"); + let _res = super::execute::(args).expect("build failed"); // we specified that debug symbols should be kept // assert!(has_debug_symbols(res.dest_binary.unwrap())); @@ -310,7 +318,7 @@ fn keep_debug_symbols_in_release_mode(manifest_path: &ManifestPath) -> Result<() }; // todo - let _res = super::execute(args).expect("build failed"); + let _res = super::execute::(args).expect("build failed"); // we specified that debug symbols should be kept // assert!(has_debug_symbols(res.dest_binary.unwrap())); @@ -328,7 +336,7 @@ fn build_with_json_output_works(manifest_path: &ManifestPath) -> Result<()> { }; // when - let res = super::execute(args).expect("build failed"); + let res = super::execute::(args).expect("build failed"); // then assert!(res.serialize_json().is_ok()); @@ -355,7 +363,9 @@ fn missing_linting_toolchain_installation_must_be_detected( extra_lints: true, ..Default::default() }; - let res = super::execute(args).map(|_| ()).unwrap_err(); + let res = super::execute::(args) + .map(|_| ()) + .unwrap_err(); // then assert!(format!("{res:?}").contains("` was not found!")); @@ -418,7 +428,7 @@ fn generates_metadata(manifest_path: &ManifestPath) -> Result<()> { }; args.manifest_path = manifest_path.clone(); - let build_result = crate::execute(args)?; + let build_result = crate::execute::(args)?; let dest_bundle = &ink_metadata_artifacts( build_result .metadata_result @@ -539,7 +549,7 @@ fn generates_solidity_metadata(manifest_path: &ManifestPath) -> Result<()> { }; args.manifest_path = manifest_path.clone(); - let build_result = crate::execute(args)?; + let build_result = crate::execute::(args)?; let metadata_result = solidity_metadata_artifacts( build_result .metadata_result @@ -684,10 +694,11 @@ fn unchanged_contract_skips_optimization_and_metadata_steps( } // when - let res1 = super::execute(args.clone()).expect("build failed"); + let res1 = + super::execute::(args.clone()).expect("build failed"); let (opt_result_modified1, metadata_modified1, contract_bundle_modified1) = get_last_modified(&res1); - let res2 = super::execute(args).expect("build failed"); + let res2 = super::execute::(args).expect("build failed"); let (opt_result_modified2, metadata_modified2, contract_bundle_modified2) = get_last_modified(&res2); @@ -711,7 +722,7 @@ fn unchanged_contract_skips_optimization_and_metadata_steps( fn unchanged_contract_no_metadata_artifacts_generates_metadata( manifest_path: &ManifestPath, ) -> Result<()> { - let res1 = super::execute(ExecuteArgs { + let res1 = super::execute::(ExecuteArgs { manifest_path: manifest_path.clone(), build_artifact: BuildArtifacts::CodeOnly, ..Default::default() @@ -724,7 +735,7 @@ fn unchanged_contract_no_metadata_artifacts_generates_metadata( let dest_binary_modified_pre = file_last_modified(&res1.dest_binary.unwrap()); - let res2 = super::execute(ExecuteArgs { + let res2 = super::execute::(ExecuteArgs { manifest_path: manifest_path.clone(), build_artifact: BuildArtifacts::All, ..Default::default() diff --git a/crates/cargo-contract/src/cmd/build.rs b/crates/cargo-contract/src/cmd/build.rs index c49cfab15..7a69b7643 100644 --- a/crates/cargo-contract/src/cmd/build.rs +++ b/crates/cargo-contract/src/cmd/build.rs @@ -19,6 +19,7 @@ use contract_build::{ BuildArtifacts, BuildMode, BuildResult, + ComposeBuildArgs, ExecuteArgs, Features, ImageVariant, @@ -36,6 +37,38 @@ use std::{ path::PathBuf, }; +pub(crate) struct CargoContractComposeBuildArgs; +impl ComposeBuildArgs for CargoContractComposeBuildArgs { + fn compose_build_args() -> Result> { + use regex::Regex; + let mut args: Vec = Vec::new(); + // match `--image` or `verify` with arg with 1 or more white spaces surrounded + let rex = Regex::new(r#"(--image|verify)[ ]*[^ ]*[ ]*"#)?; + // we join the args together, so we can remove `--image ` + let args_string: String = std::env::args().collect::>().join(" "); + let args_string = rex.replace_all(&args_string, "").to_string(); + + // and then we turn it back to the vec, filtering out commands and arguments + // that should not be passed to the docker build command + let mut os_args: Vec = 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) + } +} + /// Executes build of the smart contract which produces a PolkaVM binary that is ready for /// deploying. /// @@ -146,7 +179,7 @@ impl BuildCommand { metadata_spec: self.metadata, target_dir: None, }; - contract_build::execute(args) + contract_build::execute::(args) } } @@ -181,6 +214,6 @@ impl CheckCommand { target_dir: None, }; - contract_build::execute(args) + contract_build::execute::(args) } } diff --git a/crates/cargo-contract/src/cmd/verify.rs b/crates/cargo-contract/src/cmd/verify.rs index b174846a9..a3a63746d 100644 --- a/crates/cargo-contract/src/cmd/verify.rs +++ b/crates/cargo-contract/src/cmd/verify.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . +use crate::cmd::build::CargoContractComposeBuildArgs; use anyhow::{ Context, Result, @@ -109,7 +110,7 @@ impl VerifyCommand { ..Default::default() }; - let build_result = execute(args)?; + let build_result = execute::(args)?; // 4. Grab the code hash from the built contract and compare it with the reference // one. @@ -245,7 +246,7 @@ impl VerifyCommand { ..Default::default() }; - let build_result = execute(args)?; + let build_result = execute::(args)?; // 4. Grab the code hash from the built contract and compare it with the reference // code hash.