Idempotent location and installation of rust src

This commit is contained in:
Kirill Bulatov 2020-02-18 00:03:57 +02:00
parent 50cf1e3d67
commit addb61df36

View File

@ -47,19 +47,16 @@ pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIte
} }
pub fn discover(cargo_toml: &Path) -> Result<Sysroot> { pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
let mut src = try_find_src_path(cargo_toml)?; let src = get_or_install_rust_src(cargo_toml)?;
if !src.exists() { if !src.exists() {
src = try_install_rust_src(cargo_toml)?; Err(anyhow!(
if !src.exists() { "can't load standard library from sysroot\n\
Err(anyhow!( {}\n\
"can't load standard library from sysroot\n\ (discovered via `rustc --print sysroot`)\n\
{}\n\ try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
(discovered via `rustc --print sysroot`)\n\ src.display(),
try running `rustup component add rust-src` or set `RUST_SRC_PATH`", ))?;
src.display(),
))?;
}
} }
let mut sysroot = Sysroot { crates: Arena::default() }; let mut sysroot = Sysroot { crates: Arena::default() };
@ -93,47 +90,59 @@ fn by_name(&self, name: &str) -> Option<SysrootCrate> {
} }
} }
fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
if let Ok(path) = env::var("RUST_SRC_PATH") { fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
return Ok(path.into()); if let Ok(path) = env::var("RUST_SRC_PATH") {
return Ok(path.into());
}
let rustc_output = Command::new("rustc")
.current_dir(cargo_toml.parent().unwrap())
.args(&["--print", "sysroot"])
.output()
.context("rustc --print sysroot failed")?;
if !rustc_output.status.success() {
match rustc_output.status.code() {
Some(code) => bail!(
"failed to locate sysroot: rustc --print sysroot exited with code {}",
code
),
None => {
bail!("failed to locate sysroot: rustc --print sysroot terminated by signal")
}
};
}
let stdout = String::from_utf8(rustc_output.stdout)?;
let sysroot_path = Path::new(stdout.trim());
Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
} }
let rustc_output = Command::new("rustc") fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
.current_dir(cargo_toml.parent().unwrap()) let rustup_output = Command::new("rustup")
.args(&["--print", "sysroot"]) .current_dir(cargo_toml.parent().unwrap())
.output() .args(&["component", "add", "rust-src"])
.context("rustc --print sysroot failed")?; .output()
if !rustc_output.status.success() { .context("rustup component add rust-src failed")?;
match rustc_output.status.code() { if !rustup_output.status.success() {
Some(code) => { match rustup_output.status.code() {
bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code) Some(code) => bail!(
} "failed to install rust-src: rustup component add rust-src exited with code {}",
None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"), code
}; ),
None => bail!(
"failed to install rust-src: rustup component add rust-src terminated by signal"
),
};
}
try_find_src_path(cargo_toml)
} }
let stdout = String::from_utf8(rustc_output.stdout)?;
let sysroot_path = Path::new(stdout.trim());
Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
}
fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { let src = try_find_src_path(cargo_toml)?;
let rustup_output = Command::new("rustup") if !src.exists() {
.current_dir(cargo_toml.parent().unwrap()) try_install_rust_src(cargo_toml)
.args(&["component", "add", "rust-src"]) } else {
.output() Ok(src)
.context("rustup component add rust-src failed")?;
if !rustup_output.status.success() {
match rustup_output.status.code() {
Some(code) => bail!(
"failed to install rust-src: rustup component add rust-src exited with code {}",
code
),
None => bail!(
"failed to install rust-src: rustup component add rust-src terminated by signal"
),
};
} }
try_find_src_path(cargo_toml)
} }
impl SysrootCrate { impl SysrootCrate {