aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-02-17 22:03:57 +0000
committerKirill Bulatov <[email protected]>2020-02-17 22:07:15 +0000
commitaddb61df36bff1e54e89c103922774e6f9dd4f21 (patch)
treecb0958fabd0ea2b94b14d6c86e002b202da65305 /crates
parent50cf1e3d67f4f716d06f0f86a0bf7e85782e3d61 (diff)
Idempotent location and installation of rust src
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_project_model/src/sysroot.rs103
1 files changed, 56 insertions, 47 deletions
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 28756c7ca..43b062023 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -47,19 +47,16 @@ impl Sysroot {
47 } 47 }
48 48
49 pub fn discover(cargo_toml: &Path) -> Result<Sysroot> { 49 pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
50 let mut src = try_find_src_path(cargo_toml)?; 50 let src = get_or_install_rust_src(cargo_toml)?;
51 51
52 if !src.exists() { 52 if !src.exists() {
53 src = try_install_rust_src(cargo_toml)?; 53 Err(anyhow!(
54 if !src.exists() { 54 "can't load standard library from sysroot\n\
55 Err(anyhow!( 55 {}\n\
56 "can't load standard library from sysroot\n\ 56 (discovered via `rustc --print sysroot`)\n\
57 {}\n\ 57 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
58 (discovered via `rustc --print sysroot`)\n\ 58 src.display(),
59 try running `rustup component add rust-src` or set `RUST_SRC_PATH`", 59 ))?;
60 src.display(),
61 ))?;
62 }
63 } 60 }
64 61
65 let mut sysroot = Sysroot { crates: Arena::default() }; 62 let mut sysroot = Sysroot { crates: Arena::default() };
@@ -93,47 +90,59 @@ impl Sysroot {
93 } 90 }
94} 91}
95 92
96fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { 93fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
97 if let Ok(path) = env::var("RUST_SRC_PATH") { 94 fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
98 return Ok(path.into()); 95 if let Ok(path) = env::var("RUST_SRC_PATH") {
96 return Ok(path.into());
97 }
98
99 let rustc_output = Command::new("rustc")
100 .current_dir(cargo_toml.parent().unwrap())
101 .args(&["--print", "sysroot"])
102 .output()
103 .context("rustc --print sysroot failed")?;
104 if !rustc_output.status.success() {
105 match rustc_output.status.code() {
106 Some(code) => bail!(
107 "failed to locate sysroot: rustc --print sysroot exited with code {}",
108 code
109 ),
110 None => {
111 bail!("failed to locate sysroot: rustc --print sysroot terminated by signal")
112 }
113 };
114 }
115 let stdout = String::from_utf8(rustc_output.stdout)?;
116 let sysroot_path = Path::new(stdout.trim());
117 Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
99 } 118 }
100 119
101 let rustc_output = Command::new("rustc") 120 fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
102 .current_dir(cargo_toml.parent().unwrap()) 121 let rustup_output = Command::new("rustup")
103 .args(&["--print", "sysroot"]) 122 .current_dir(cargo_toml.parent().unwrap())
104 .output() 123 .args(&["component", "add", "rust-src"])
105 .context("rustc --print sysroot failed")?; 124 .output()
106 if !rustc_output.status.success() { 125 .context("rustup component add rust-src failed")?;
107 match rustc_output.status.code() { 126 if !rustup_output.status.success() {
108 Some(code) => { 127 match rustup_output.status.code() {
109 bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code) 128 Some(code) => bail!(
110 } 129 "failed to install rust-src: rustup component add rust-src exited with code {}",
111 None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"), 130 code
112 }; 131 ),
132 None => bail!(
133 "failed to install rust-src: rustup component add rust-src terminated by signal"
134 ),
135 };
136 }
137 try_find_src_path(cargo_toml)
113 } 138 }
114 let stdout = String::from_utf8(rustc_output.stdout)?;
115 let sysroot_path = Path::new(stdout.trim());
116 Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
117}
118 139
119fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { 140 let src = try_find_src_path(cargo_toml)?;
120 let rustup_output = Command::new("rustup") 141 if !src.exists() {
121 .current_dir(cargo_toml.parent().unwrap()) 142 try_install_rust_src(cargo_toml)
122 .args(&["component", "add", "rust-src"]) 143 } else {
123 .output() 144 Ok(src)
124 .context("rustup component add rust-src failed")?;
125 if !rustup_output.status.success() {
126 match rustup_output.status.code() {
127 Some(code) => bail!(
128 "failed to install rust-src: rustup component add rust-src exited with code {}",
129 code
130 ),
131 None => bail!(
132 "failed to install rust-src: rustup component add rust-src terminated by signal"
133 ),
134 };
135 } 145 }
136 try_find_src_path(cargo_toml)
137} 146}
138 147
139impl SysrootCrate { 148impl SysrootCrate {