From 0c99407af0b2078222dcca272fff048c281e2e90 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 15 May 2023 12:21:51 +0100 Subject: [PATCH 01/16] Use duct to build/invoke cargo command --- Cargo.lock | 33 +++++++++++++++ crates/build/Cargo.toml | 1 + crates/build/src/lib.rs | 25 ++++++++++-- crates/build/src/metadata.rs | 7 ++-- crates/build/src/util/mod.rs | 79 ++++++++++++++---------------------- 5 files changed, 90 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adc964ddc..65477f8a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -814,6 +814,7 @@ dependencies = [ "clap", "colored", "contract-metadata", + "duct", "heck", "hex", "impl-serde", @@ -1171,6 +1172,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "duct" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ae3fc31835f74c2a7ceda3aeede378b0ae2e74c8f1c36559fcc9ae2a4e7d3e" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -2681,6 +2694,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "os_pipe" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "output_vt100" version = "0.1.3" @@ -3719,6 +3742,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "signature" version = "1.6.4" diff --git a/crates/build/Cargo.toml b/crates/build/Cargo.toml index ad119f5e5..a2d571e7f 100644 --- a/crates/build/Cargo.toml +++ b/crates/build/Cargo.toml @@ -19,6 +19,7 @@ blake2 = "0.10.6" cargo_metadata = "0.15.4" colored = "2.0.0" clap = { version = "4.2.7", features = ["derive", "env"] } +duct = "0.13.6" heck = "0.4.0" hex = "0.4.3" impl-serde = "0.4.0" diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 237eeb325..bfa5059b9 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -291,7 +291,15 @@ fn exec_cargo_for_onchain_target( None }; - util::invoke_cargo(command, &args, manifest_path.directory(), verbosity, env)?; + let cargo = util::cargo_cmd( + command, + &args, + manifest_path.directory(), + verbosity, + env, + ); + + cargo.run()?; // todo capture stderr Ok(()) }; @@ -357,8 +365,15 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re Ok(()) })? .using_temp(|manifest_path| { - util::invoke_cargo("dylint", &args, manifest_path.directory(), verbosity, env) - .map(|_| ()) + let cargo = util::cargo_cmd( + "dylint", + &args, + manifest_path.directory(), + verbosity, + env, + ); + cargo.run()?; + Ok(()) })?; Ok(()) @@ -548,7 +563,9 @@ fn assert_compatible_ink_dependencies( ) -> Result<()> { for dependency in ["parity-scale-codec", "scale-info"].iter() { let args = ["-i", dependency, "--duplicates"]; - let _ = util::invoke_cargo("tree", args, manifest_path.directory(), verbosity, vec![]) + let cargo = util::cargo_cmd("tree", args, manifest_path.directory(), verbosity, vec![]); + cargo + .run() .with_context(|| { format!( "Mismatching versions of `{dependency}` were found!\n\ diff --git a/crates/build/src/metadata.rs b/crates/build/src/metadata.rs index f929b75d3..d6cad3fa2 100644 --- a/crates/build/src/metadata.rs +++ b/crates/build/src/metadata.rs @@ -149,16 +149,17 @@ pub(crate) fn execute( network.append_to_args(&mut args); features.append_to_args(&mut args); - let stdout = util::invoke_cargo( + let cmd = util::cargo_cmd( "run", args, crate_metadata.manifest_path.directory(), verbosity, vec![], - )?; + ); + let output = cmd.stdout_capture().run()?; let ink_meta: serde_json::Map = - serde_json::from_slice(&stdout)?; + serde_json::from_slice(&output.stdout)?; let metadata = ContractMetadata::new(source, contract, user, ink_meta); { let mut metadata = metadata.clone(); diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index c4273f3bb..2c00f707c 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -18,14 +18,11 @@ pub mod tests; use crate::Verbosity; -use anyhow::{ - Context, - Result, -}; +use anyhow::Result; +use duct::Expression; use std::{ - ffi::OsStr, + ffi::OsString, path::Path, - process::Command, }; // Returns the current Rust toolchain formatted by `-`. @@ -36,7 +33,7 @@ pub(crate) fn rust_toolchain() -> Result { Ok(toolchain) } -/// Invokes `cargo` with the subcommand `command` and the supplied `args`. +/// Builds an [`Expression`] for invoking `cargo`. /// /// In case `working_dir` is set, the command will be invoked with that folder /// as the working directory. @@ -44,67 +41,53 @@ pub(crate) fn rust_toolchain() -> Result { /// In case `env` is given environment variables can be either set or unset: /// * To _set_ push an item a la `("VAR_NAME", Some("VAR_VALUE"))` to the `env` vector. /// * To _unset_ push an item a la `("VAR_NAME", None)` to the `env` vector. -/// -/// If successful, returns the stdout bytes. -pub fn invoke_cargo( +pub fn cargo_cmd( command: &str, args: I, working_dir: Option

, verbosity: Verbosity, env: Vec<(&str, Option)>, -) -> Result> +) -> Expression where I: IntoIterator + std::fmt::Debug, - S: AsRef, + S: Into, P: AsRef, { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); - let mut cmd = Command::new(cargo); + let mut cmd_args = Vec::new(); - env.iter().for_each(|(env_key, maybe_env_val)| { - match maybe_env_val { - Some(env_val) => cmd.env(env_key, env_val), - None => cmd.env_remove(env_key), - }; - }); + cmd_args.push("--color=always"); - if let Some(path) = working_dir { - tracing::debug!("Setting cargo working dir to '{}'", path.as_ref().display()); - cmd.current_dir(path); - } - - cmd.arg(command); - cmd.args(args); match verbosity { - Verbosity::Quiet => cmd.arg("--quiet"), + Verbosity::Quiet => cmd_args.push("--quiet"), Verbosity::Verbose => { if command != "dylint" { - cmd.arg("--verbose") - } else { - &mut cmd + cmd_args.push("--verbose") } } - Verbosity::Default => &mut cmd, + Verbosity::Default => (), }; - tracing::debug!("Invoking cargo: {:?}", cmd); - - let child = cmd - // capture the stdout to return from this function as bytes - .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() - ); + let mut cmd_args: Vec = cmd_args.iter().map(Into::into).collect(); + for arg in args { + cmd_args.push(arg.into()); } + + let mut cmd = duct::cmd(cargo, &cmd_args); + + env.iter().for_each(|(env_key, maybe_env_val)| { + match maybe_env_val { + Some(env_val) => cmd = cmd.env(env_key, env_val), + None => cmd = cmd.env_remove(env_key), + }; + }); + + if let Some(path) = working_dir { + tracing::debug!("Setting cargo working dir to '{}'", path.as_ref().display()); + cmd = cmd.dir(path.as_ref()); + } + + cmd } /// Returns the base name of the path. From d7e488f1991dc9067de746a4993875873037adb9 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 15 May 2023 12:32:07 +0100 Subject: [PATCH 02/16] Push command to args --- crates/build/src/util/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 2c00f707c..46a3174c6 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -56,6 +56,7 @@ where let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); let mut cmd_args = Vec::new(); + cmd_args.push(command); cmd_args.push("--color=always"); match verbosity { From f1aa1abde8500683756854a23e0182aeadf35fe0 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 15 May 2023 12:33:25 +0100 Subject: [PATCH 03/16] Ignore cargo tree stdout --- crates/build/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index bfa5059b9..46fbc87d9 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -565,6 +565,7 @@ fn assert_compatible_ink_dependencies( let args = ["-i", dependency, "--duplicates"]; let cargo = util::cargo_cmd("tree", args, manifest_path.directory(), verbosity, vec![]); cargo + .stdout_null() .run() .with_context(|| { format!( From 4e58d0939ca753e4a7479f99166f81badf16a7d1 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 15 May 2023 14:49:55 +0100 Subject: [PATCH 04/16] Suggest adding `no_main` --- crates/build/src/lib.rs | 45 ++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 46fbc87d9..3d514de99 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -84,6 +84,10 @@ use parity_wasm::elements::{ use semver::Version; use std::{ fs, + io::{ + BufRead, + BufReader, + }, path::{ Path, PathBuf, @@ -291,15 +295,35 @@ fn exec_cargo_for_onchain_target( None }; - let cargo = util::cargo_cmd( - command, - &args, - manifest_path.directory(), - verbosity, - env, - ); - - cargo.run()?; // todo capture stderr + let cargo = + util::cargo_cmd(command, &args, manifest_path.directory(), verbosity, env); + + let reader = cargo.stderr_to_stdout().reader()?; + + let buf_reader = BufReader::new(reader); + for line in buf_reader.lines() { + match line { + Ok(line) => { + if line.contains("error[E0601]") { + println!( + "\n{}", + "Ensure the contract is annotated with `no_main` e.g.:" + .bright_yellow() + .bold() + ); + println!( + "{}\n", + "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]" + .bold() + ); + } + println!("{}", line); + } + Err(err) => { + anyhow::bail!(err); + } + } + } Ok(()) }; @@ -563,7 +587,8 @@ fn assert_compatible_ink_dependencies( ) -> Result<()> { for dependency in ["parity-scale-codec", "scale-info"].iter() { let args = ["-i", dependency, "--duplicates"]; - let cargo = util::cargo_cmd("tree", args, manifest_path.directory(), verbosity, vec![]); + let cargo = + util::cargo_cmd("tree", args, manifest_path.directory(), verbosity, vec![]); cargo .stdout_null() .run() From 3a595ad491afbbb441dd7f1069e2d060d4df532f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 16 May 2023 17:29:50 +0100 Subject: [PATCH 05/16] Read one byte at a time to get the progress bar --- crates/build/src/lib.rs | 61 ++++++++++++++++++++---------------- crates/build/src/util/mod.rs | 7 +++++ 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 3d514de99..54c34e60c 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -84,10 +84,7 @@ use parity_wasm::elements::{ use semver::Version; use std::{ fs, - io::{ - BufRead, - BufReader, - }, + io, path::{ Path, PathBuf, @@ -297,32 +294,42 @@ fn exec_cargo_for_onchain_target( let cargo = util::cargo_cmd(command, &args, manifest_path.directory(), verbosity, env); + let cargo = util::cargo_tty_output(cargo); - let reader = cargo.stderr_to_stdout().reader()?; - - let buf_reader = BufReader::new(reader); - for line in buf_reader.lines() { - match line { - Ok(line) => { - if line.contains("error[E0601]") { - println!( - "\n{}", - "Ensure the contract is annotated with `no_main` e.g.:" - .bright_yellow() - .bold() - ); - println!( - "{}\n", - "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]" - .bold() - ); - } - println!("{}", line); - } - Err(err) => { - anyhow::bail!(err); + let missing_main_err = "error[E0601]".as_bytes(); + let mut err_buf = + std::collections::VecDeque::with_capacity(missing_main_err.len()); + + let mut reader = cargo.stderr_to_stdout().reader()?; + let mut buffer = [0u8; 1]; + + loop { + let bytes_read = io::Read::read(&mut reader, &mut buffer)?; + io::Write::write(&mut io::stderr(), &buffer[0..bytes_read])?; + + for byte in buffer[0..bytes_read].iter() { + err_buf.push_back(*byte); + if err_buf.len() > missing_main_err.len() { + err_buf.pop_front(); } } + if missing_main_err == err_buf.make_contiguous() { + eprintln!( + "\n\n{}", + "Ensure the contract is annotated with `no_main` e.g.:" + .bright_yellow() + .bold() + ); + eprintln!( + "{}\n", + "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]".bold() + ); + } + + if bytes_read == 0 { + break + } + buffer = [0u8; 1]; } Ok(()) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 46a3174c6..7337bdee0 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -91,6 +91,13 @@ where cmd } +/// Configures the cargo command to output colour and the progress bar. +pub fn cargo_tty_output(cmd: Expression) -> Expression { + cmd.env("CARGO_TERM_COLOR", "always") + .env("CARGO_TERM_PROGRESS_WIDTH", "100") + .env("CARGO_TERM_PROGRESS_WHEN", "always") +} + /// Returns the base name of the path. pub(crate) fn base_name(path: &Path) -> &str { path.file_name() From c7ab39772000fca6530cd905085877a1bcc21143 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 16 May 2023 17:49:33 +0100 Subject: [PATCH 06/16] Refactor to separate method --- crates/build/src/lib.rs | 80 +++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 54c34e60c..8f13585d4 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -83,6 +83,7 @@ use parity_wasm::elements::{ }; use semver::Version; use std::{ + collections::VecDeque, fs, io, path::{ @@ -294,45 +295,8 @@ fn exec_cargo_for_onchain_target( let cargo = util::cargo_cmd(command, &args, manifest_path.directory(), verbosity, env); - let cargo = util::cargo_tty_output(cargo); - let missing_main_err = "error[E0601]".as_bytes(); - let mut err_buf = - std::collections::VecDeque::with_capacity(missing_main_err.len()); - - let mut reader = cargo.stderr_to_stdout().reader()?; - let mut buffer = [0u8; 1]; - - loop { - let bytes_read = io::Read::read(&mut reader, &mut buffer)?; - io::Write::write(&mut io::stderr(), &buffer[0..bytes_read])?; - - for byte in buffer[0..bytes_read].iter() { - err_buf.push_back(*byte); - if err_buf.len() > missing_main_err.len() { - err_buf.pop_front(); - } - } - if missing_main_err == err_buf.make_contiguous() { - eprintln!( - "\n\n{}", - "Ensure the contract is annotated with `no_main` e.g.:" - .bright_yellow() - .bold() - ); - eprintln!( - "{}\n", - "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]".bold() - ); - } - - if bytes_read == 0 { - break - } - buffer = [0u8; 1]; - } - - Ok(()) + invoke_cargo_and_scan_for_error(cargo) }; if unstable_flags.original_manifest { @@ -359,6 +323,46 @@ fn exec_cargo_for_onchain_target( Ok(()) } +/// Executes the supplied cargo command, reading the output and scanning for known errors. +/// Writes the captured stderr back to stderr and maintains the cargo tty progress bar. +fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { + let cargo = util::cargo_tty_output(cargo); + + let missing_main_err = "error[E0601]".as_bytes(); + let mut err_buf = VecDeque::with_capacity(missing_main_err.len()); + + let mut reader = cargo.stderr_to_stdout().reader()?; + let mut buffer = [0u8; 1]; + + loop { + let bytes_read = io::Read::read(&mut reader, &mut buffer)?; + io::Write::write(&mut io::stderr(), &buffer[0..bytes_read])?; + for byte in buffer[0..bytes_read].iter() { + err_buf.push_back(*byte); + if err_buf.len() > missing_main_err.len() { + err_buf.pop_front(); + } + } + if missing_main_err == err_buf.make_contiguous() { + eprintln!( + "\n\n{}", + "Ensure the contract is annotated with `no_main` e.g.:" + .bright_yellow() + .bold() + ); + eprintln!( + "{}\n", + "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]".bold() + ); + } + if bytes_read == 0 { + break + } + buffer = [0u8; 1]; + } + Ok(()) +} + /// Executes `cargo dylint` with the ink! linting driver that is built during /// the `build.rs`. /// From b5febf057977f478f02471811ed72651d0581dc8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 16 May 2023 18:01:41 +0100 Subject: [PATCH 07/16] Update crates/build/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Müller --- crates/build/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 8f13585d4..95fd859ee 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -346,7 +346,7 @@ fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { if missing_main_err == err_buf.make_contiguous() { eprintln!( "\n\n{}", - "Ensure the contract is annotated with `no_main` e.g.:" + "Ensure the contract is annotated with `no_main`, e.g.:" .bright_yellow() .bold() ); From 9f7a0a47105cf51d517b12fb0152199bb81b9889 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 10:30:11 +0100 Subject: [PATCH 08/16] Detect term size --- Cargo.lock | 11 +++++++++++ crates/build/Cargo.toml | 1 + crates/build/src/util/mod.rs | 8 ++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 65477f8a9..d96dae217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -827,6 +827,7 @@ dependencies = [ "serde_json", "strum", "tempfile", + "term_size", "toml 0.7.3", "tracing", "url", @@ -4385,6 +4386,16 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "term_size" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "termcolor" version = "1.2.0" diff --git a/crates/build/Cargo.toml b/crates/build/Cargo.toml index a2d571e7f..07fcee95b 100644 --- a/crates/build/Cargo.toml +++ b/crates/build/Cargo.toml @@ -32,6 +32,7 @@ semver = { version = "1.0.17", features = ["serde"] } serde = { version = "1", default-features = false, features = ["derive"] } serde_json = "1.0.96" tempfile = "3.5.0" +term_size = "0.3.2" url = { version = "2.3.1", features = ["serde"] } wasm-opt = "0.112.0" which = "4.4.0" diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 7337bdee0..8ab29a942 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -93,8 +93,12 @@ where /// Configures the cargo command to output colour and the progress bar. pub fn cargo_tty_output(cmd: Expression) -> Expression { - cmd.env("CARGO_TERM_COLOR", "always") - .env("CARGO_TERM_PROGRESS_WIDTH", "100") + let term_size = term_size::dimensions_stderr() + .map(|(width, _)| width.to_string()) + .unwrap_or_else(|| "100".to_string()); + cmd + .env("CARGO_TERM_COLOR", "always") + .env("CARGO_TERM_PROGRESS_WIDTH", term_size) .env("CARGO_TERM_PROGRESS_WHEN", "always") } From a2505c39096c14bf403cca3d33549391ebabc01b Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 10:48:29 +0100 Subject: [PATCH 09/16] Update suggestion and exit on error --- crates/build/src/lib.rs | 22 +++++++++++++--------- crates/build/src/util/mod.rs | 3 +-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 95fd859ee..9387b5ebf 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -326,6 +326,13 @@ fn exec_cargo_for_onchain_target( /// Executes the supplied cargo command, reading the output and scanning for known errors. /// Writes the captured stderr back to stderr and maintains the cargo tty progress bar. fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { + macro_rules! eprintln_red { + ($value:expr) => {{ + use colored::Colorize as _; + ::std::eprintln!("{}", $value.bright_red().bold()); + }}; + } + let cargo = util::cargo_tty_output(cargo); let missing_main_err = "error[E0601]".as_bytes(); @@ -344,16 +351,13 @@ fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { } } if missing_main_err == err_buf.make_contiguous() { - eprintln!( - "\n\n{}", - "Ensure the contract is annotated with `no_main`, e.g.:" - .bright_yellow() - .bold() - ); - eprintln!( - "{}\n", - "#![cfg_attr(not(feature = \"std\"), no_std, no_main)]".bold() + eprintln_red!( + ": Your contract must be annotated with the `no_main` attribute." ); + eprintln_red!("Examples how to do this:"); + eprintln_red!(" - `#![cfg_attr(not(feature = \"std\"), no_std, no_main)]`"); + eprintln_red!(" - `#[no_main]`\n"); + return Err(anyhow::anyhow!("missing `no_main` attribute")) } if bytes_read == 0 { break diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 8ab29a942..6bac221a8 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -96,8 +96,7 @@ pub fn cargo_tty_output(cmd: Expression) -> Expression { let term_size = term_size::dimensions_stderr() .map(|(width, _)| width.to_string()) .unwrap_or_else(|| "100".to_string()); - cmd - .env("CARGO_TERM_COLOR", "always") + cmd.env("CARGO_TERM_COLOR", "always") .env("CARGO_TERM_PROGRESS_WIDTH", term_size) .env("CARGO_TERM_PROGRESS_WHEN", "always") } From bb5ac97ab250e4e800fdfda00d9d14041b7df2c7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 10:57:40 +0100 Subject: [PATCH 10/16] Update message --- crates/build/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 9387b5ebf..f01b267b8 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -343,16 +343,17 @@ fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { loop { let bytes_read = io::Read::read(&mut reader, &mut buffer)?; - io::Write::write(&mut io::stderr(), &buffer[0..bytes_read])?; for byte in buffer[0..bytes_read].iter() { err_buf.push_back(*byte); if err_buf.len() > missing_main_err.len() { - err_buf.pop_front(); + let byte = err_buf.pop_front().expect("buffer is not empty"); + io::Write::write(&mut io::stderr(), &[byte])?; } } if missing_main_err == err_buf.make_contiguous() { + eprintln!("\nExited with error: [E0601]"); eprintln_red!( - ": Your contract must be annotated with the `no_main` attribute." + "Your contract must be annotated with the `no_main` attribute.\n" ); eprintln_red!("Examples how to do this:"); eprintln_red!(" - `#![cfg_attr(not(feature = \"std\"), no_std, no_main)]`"); From a746e57e3f0cd9f4444fb6c59cee984118894ed3 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 10:58:29 +0100 Subject: [PATCH 11/16] Hardcode term size --- crates/build/src/util/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 6bac221a8..b0dd76b0f 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -93,9 +93,10 @@ where /// Configures the cargo command to output colour and the progress bar. pub fn cargo_tty_output(cmd: Expression) -> Expression { - let term_size = term_size::dimensions_stderr() - .map(|(width, _)| width.to_string()) - .unwrap_or_else(|| "100".to_string()); + // let term_size = term_size::dimensions_stderr() + // .map(|(width, _)| width.to_string()) + // .unwrap_or_else(|| "100".to_string()); + let term_size = "100"; cmd.env("CARGO_TERM_COLOR", "always") .env("CARGO_TERM_PROGRESS_WIDTH", term_size) .env("CARGO_TERM_PROGRESS_WHEN", "always") From e041261f7d2eef0768957aa227092f9e7fc4d567 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 11:00:25 +0100 Subject: [PATCH 12/16] Hardcode term size --- crates/build/src/util/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index b0dd76b0f..c99a55a10 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -96,6 +96,7 @@ pub fn cargo_tty_output(cmd: Expression) -> Expression { // let term_size = term_size::dimensions_stderr() // .map(|(width, _)| width.to_string()) // .unwrap_or_else(|| "100".to_string()); + use term_size::dimensions_stderr; let term_size = "100"; cmd.env("CARGO_TERM_COLOR", "always") .env("CARGO_TERM_PROGRESS_WIDTH", term_size) From b90369df05b91540a9aed7be159474f31bc3d2af Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 11:41:13 +0100 Subject: [PATCH 13/16] Only detect term size on non windows OS --- crates/build/src/util/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index c99a55a10..ec322d3ff 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -93,11 +93,14 @@ where /// Configures the cargo command to output colour and the progress bar. pub fn cargo_tty_output(cmd: Expression) -> Expression { - // let term_size = term_size::dimensions_stderr() - // .map(|(width, _)| width.to_string()) - // .unwrap_or_else(|| "100".to_string()); - use term_size::dimensions_stderr; + #[cfg(windows)] let term_size = "100"; + + #[cfg(not(windows))] + let term_size = term_size::dimensions_stderr() + .map(|(width, _)| width.to_string()) + .unwrap_or_else(|| "100".to_string()); + cmd.env("CARGO_TERM_COLOR", "always") .env("CARGO_TERM_PROGRESS_WIDTH", term_size) .env("CARGO_TERM_PROGRESS_WHEN", "always") From b1f47a8e7aaeac4421b5cf37a043ccab5d4edd52 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 11:42:37 +0100 Subject: [PATCH 14/16] Red --- crates/build/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index f01b267b8..010e11483 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -351,7 +351,7 @@ fn invoke_cargo_and_scan_for_error(cargo: duct::Expression) -> Result<()> { } } if missing_main_err == err_buf.make_contiguous() { - eprintln!("\nExited with error: [E0601]"); + eprintln_red!("\nExited with error: [E0601]"); eprintln_red!( "Your contract must be annotated with the `no_main` attribute.\n" ); From 483a2b66684617223d7002c6f216a22878281438 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 11:50:06 +0100 Subject: [PATCH 15/16] Use term_size for windows --- crates/build/src/util/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index ec322d3ff..9f17bcd56 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -94,6 +94,7 @@ where /// Configures the cargo command to output colour and the progress bar. pub fn cargo_tty_output(cmd: Expression) -> Expression { #[cfg(windows)] + use term_size as _; let term_size = "100"; #[cfg(not(windows))] From 87d7f06a2bffb4df555b5cbc21abab2bad3c61ce Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 17 May 2023 11:50:34 +0100 Subject: [PATCH 16/16] use term_size as _; --- crates/build/src/util/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/build/src/util/mod.rs b/crates/build/src/util/mod.rs index 9f17bcd56..0cc5a6a88 100644 --- a/crates/build/src/util/mod.rs +++ b/crates/build/src/util/mod.rs @@ -24,6 +24,7 @@ use std::{ ffi::OsString, path::Path, }; +use term_size as _; // Returns the current Rust toolchain formatted by `-`. pub(crate) fn rust_toolchain() -> Result { @@ -94,7 +95,6 @@ where /// Configures the cargo command to output colour and the progress bar. pub fn cargo_tty_output(cmd: Expression) -> Expression { #[cfg(windows)] - use term_size as _; let term_size = "100"; #[cfg(not(windows))]