Line data Source code
1 : use crate::{env, CommandExt}; 2 : use anyhow::{anyhow, Result}; 3 : use std::{ 4 : ffi::OsStr, 5 : path::{Path, PathBuf}, 6 : process::Command, 7 : }; 8 : 9 : // smoelius: Should this be merged into `CommandExt`? 10 : pub trait SanitizeEnvironment { 11 : fn sanitize_environment(&mut self) -> &mut Self; 12 : } 13 : 14 : impl SanitizeEnvironment for Command { 15 120 : fn sanitize_environment(&mut self) -> &mut Self { 16 120 : self.env_remove(env::CARGO); 17 120 : self.env_remove(env::RUSTC); 18 120 : self.env_remove(env::RUSTUP_TOOLCHAIN); 19 120 : self 20 120 : } 21 : } 22 : 23 : // smoelius: Consider carefully whether you need to call this function! In most cases, the toolchain 24 : // you want is not the one returned by rustup. 25 30 : pub fn active_toolchain(path: &Path) -> Result<String> { 26 30 : let output = Command::new("rustup") 27 30 : .sanitize_environment() 28 30 : .current_dir(path) 29 30 : .args(["show", "active-toolchain"]) 30 30 : .logged_output(true)?; 31 30 : let stdout = std::str::from_utf8(&output.stdout)?; 32 30 : stdout 33 30 : .split_once(' ') 34 30 : .map(|(s, _)| s.to_owned()) 35 30 : .ok_or_else(|| anyhow!("Could not determine active toolchain")) 36 30 : } 37 : 38 9 : pub fn toolchain_path(path: &Path) -> Result<PathBuf> { 39 9 : let output = Command::new("rustup") 40 9 : .sanitize_environment() 41 9 : .current_dir(path) 42 9 : .args(["which", "rustc"]) 43 9 : .logged_output(true)?; 44 9 : let stdout = std::str::from_utf8(&output.stdout)?; 45 9 : let path = PathBuf::from(stdout); 46 9 : // smoelius: `path` should end with `/bin/rustc`. 47 9 : path.ancestors() 48 9 : .nth(2) 49 9 : .map(Into::into) 50 9 : .ok_or_else(|| anyhow!("Could not get ancestor")) 51 9 : } 52 : 53 7 : pub fn is_rustc<T: AsRef<OsStr> + ?Sized>(arg: &T) -> bool { 54 7 : Path::new(arg).file_stem() == Some(OsStr::new("rustc")) 55 7 : } 56 : 57 : #[test] 58 1 : fn rustc_is_rustc() { 59 1 : assert!(is_rustc("rustc")); 60 1 : }