diff --git a/CHANGELOG.md b/CHANGELOG.md index c21bf728b9..0374e5cec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ The minor version will be incremented upon a breaking change and the patch versi - lang: Eliminate temporary Vec allocations when serializing data with discriminant and set the default capacity to 256 bytes ([#2691](https://github.com/coral-xyz/anchor/pull/2691)). - lang: Allow custom lifetime in Accounts structure ([#2741](https://github.com/coral-xyz/anchor/pull/2741)). - lang: Remove `try_to_vec` usage while setting the return data in order to reduce heap memory usage ([#2744](https://github.com/coral-xyz/anchor/pull/2744)) +- cli: Show installation progress if Solana tools are not installed when using toolchain overrides ([#2757](https://github.com/coral-xyz/anchor/pull/2757)). ### Breaking diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 6a706fdd08..050af212af 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -495,21 +495,28 @@ fn override_toolchain(cfg_override: &ConfigOverride) -> Result Result { - let output = std::process::Command::new(cmd_name) - .arg("--version") - .output()?; - let output_version = std::str::from_utf8(&output.stdout)?; - let version = Regex::new(r"(\d+\.\d+\.\S+)") + fn parse_version(text: &str) -> String { + Regex::new(r"(\d+\.\d+\.\S+)") .unwrap() - .captures_iter(output_version) + .captures_iter(text) .next() .unwrap() .get(0) .unwrap() .as_str() - .to_string(); + .to_string() + } + fn get_current_version(cmd_name: &str) -> Result { + let output = std::process::Command::new(cmd_name) + .arg("--version") + .output()?; + if !output.status.success() { + return Err(anyhow!("Failed to run `{cmd_name} --version`")); + } + + let output_version = std::str::from_utf8(&output.stdout)?; + let version = parse_version(output_version); Ok(version) } @@ -519,15 +526,33 @@ fn override_toolchain(cfg_override: &ConfigOverride) -> Result std::io::Result { + fn override_solana_version(version: String) -> Result { + let output = std::process::Command::new("solana-install") + .arg("list") + .output()?; + if !output.status.success() { + return Err(anyhow!("Failed to list installed `solana` versions")); + } + + // Hide the installation progress if the version is already installed + let is_installed = std::str::from_utf8(&output.stdout)? + .lines() + .any(|line| parse_version(line) == version); + let (stderr, stdout) = if is_installed { + (Stdio::null(), Stdio::null()) + } else { + (Stdio::inherit(), Stdio::inherit()) + }; + std::process::Command::new("solana-install") .arg("init") .arg(&version) - .stderr(Stdio::null()) - .stdout(Stdio::null()) + .stderr(stderr) + .stdout(stdout) .spawn()? .wait() .map(|status| status.success()) + .map_err(|err| anyhow!("Failed to run `solana-install` command: {err}")) } match override_solana_version(solana_version.to_owned())? { @@ -537,12 +562,10 @@ fn override_toolchain(cfg_override: &ConfigOverride) -> Result Err(anyhow!("Failed to restore `solana` version")), } })), - false => { - eprintln!( - "Failed to override `solana` version to {solana_version}, \ + false => eprintln!( + "Failed to override `solana` version to {solana_version}, \ using {current_version} instead" - ); - } + ), } } }