Skip to content

Commit 9df1663

Browse files
bors[bot]matklad
andauthored
Merge #2755
2755: Cleanup r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2 parents 6c14014 + 5e7995e commit 9df1663

File tree

6 files changed

+344
-371
lines changed

6 files changed

+344
-371
lines changed

xtask/src/cmd.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use std::process::{Command, Output, Stdio};
2+
3+
use anyhow::{Context, Result};
4+
5+
use crate::project_root;
6+
7+
pub struct Cmd<'a> {
8+
pub unix: &'a str,
9+
pub windows: &'a str,
10+
pub work_dir: &'a str,
11+
}
12+
13+
impl Cmd<'_> {
14+
pub fn run(self) -> Result<()> {
15+
if cfg!(windows) {
16+
run(self.windows, self.work_dir)
17+
} else {
18+
run(self.unix, self.work_dir)
19+
}
20+
}
21+
pub fn run_with_output(self) -> Result<Output> {
22+
if cfg!(windows) {
23+
run_with_output(self.windows, self.work_dir)
24+
} else {
25+
run_with_output(self.unix, self.work_dir)
26+
}
27+
}
28+
}
29+
30+
pub fn run(cmdline: &str, dir: &str) -> Result<()> {
31+
do_run(cmdline, dir, &mut |c| {
32+
c.stdout(Stdio::inherit());
33+
})
34+
.map(|_| ())
35+
}
36+
37+
pub fn run_with_output(cmdline: &str, dir: &str) -> Result<Output> {
38+
do_run(cmdline, dir, &mut |_| {})
39+
}
40+
41+
fn do_run(cmdline: &str, dir: &str, f: &mut dyn FnMut(&mut Command)) -> Result<Output> {
42+
eprintln!("\nwill run: {}", cmdline);
43+
let proj_dir = project_root().join(dir);
44+
let mut args = cmdline.split_whitespace();
45+
let exec = args.next().unwrap();
46+
let mut cmd = Command::new(exec);
47+
f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit()));
48+
let output = cmd.output().with_context(|| format!("running `{}`", cmdline))?;
49+
if !output.status.success() {
50+
anyhow::bail!("`{}` exited with {}", cmdline, output.status);
51+
}
52+
Ok(output)
53+
}

xtask/src/help.rs

Lines changed: 0 additions & 46 deletions
This file was deleted.

xtask/src/install.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//! Installs rust-analyzer language server and/or editor plugin.
2+
3+
use std::{env, path::PathBuf, str};
4+
5+
use anyhow::{Context, Result};
6+
7+
use crate::cmd::{run, run_with_output, Cmd};
8+
9+
// Latest stable, feel free to send a PR if this lags behind.
10+
const REQUIRED_RUST_VERSION: u32 = 40;
11+
12+
pub struct InstallCmd {
13+
pub client: Option<ClientOpt>,
14+
pub server: Option<ServerOpt>,
15+
}
16+
17+
pub enum ClientOpt {
18+
VsCode,
19+
}
20+
21+
pub struct ServerOpt {
22+
pub jemalloc: bool,
23+
}
24+
25+
impl InstallCmd {
26+
pub fn run(self) -> Result<()> {
27+
if cfg!(target_os = "macos") {
28+
fix_path_for_mac().context("Fix path for mac")?
29+
}
30+
if let Some(server) = self.server {
31+
install_server(server).context("install server")?;
32+
}
33+
if let Some(client) = self.client {
34+
install_client(client).context("install client")?;
35+
}
36+
Ok(())
37+
}
38+
}
39+
40+
fn fix_path_for_mac() -> Result<()> {
41+
let mut vscode_path: Vec<PathBuf> = {
42+
const COMMON_APP_PATH: &str =
43+
r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin";
44+
const ROOT_DIR: &str = "";
45+
let home_dir = match env::var("HOME") {
46+
Ok(home) => home,
47+
Err(e) => anyhow::bail!("Failed getting HOME from environment with error: {}.", e),
48+
};
49+
50+
[ROOT_DIR, &home_dir]
51+
.iter()
52+
.map(|dir| String::from(*dir) + COMMON_APP_PATH)
53+
.map(PathBuf::from)
54+
.filter(|path| path.exists())
55+
.collect()
56+
};
57+
58+
if !vscode_path.is_empty() {
59+
let vars = match env::var_os("PATH") {
60+
Some(path) => path,
61+
None => anyhow::bail!("Could not get PATH variable from env."),
62+
};
63+
64+
let mut paths = env::split_paths(&vars).collect::<Vec<_>>();
65+
paths.append(&mut vscode_path);
66+
let new_paths = env::join_paths(paths).context("build env PATH")?;
67+
env::set_var("PATH", &new_paths);
68+
}
69+
70+
Ok(())
71+
}
72+
73+
fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
74+
let npm_version = Cmd {
75+
unix: r"npm --version",
76+
windows: r"cmd.exe /c npm --version",
77+
work_dir: "./editors/code",
78+
}
79+
.run();
80+
81+
if npm_version.is_err() {
82+
eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin")
83+
}
84+
85+
Cmd { unix: r"npm install", windows: r"cmd.exe /c npm install", work_dir: "./editors/code" }
86+
.run()?;
87+
Cmd {
88+
unix: r"npm run package --scripts-prepend-node-path",
89+
windows: r"cmd.exe /c npm run package",
90+
work_dir: "./editors/code",
91+
}
92+
.run()?;
93+
94+
let code_binary = ["code", "code-insiders", "codium"].iter().find(|bin| {
95+
Cmd {
96+
unix: &format!("{} --version", bin),
97+
windows: &format!("cmd.exe /c {}.cmd --version", bin),
98+
work_dir: "./editors/code",
99+
}
100+
.run()
101+
.is_ok()
102+
});
103+
104+
let code_binary = match code_binary {
105+
Some(it) => it,
106+
None => anyhow::bail!("Can't execute `code --version`. Perhaps it is not in $PATH?"),
107+
};
108+
109+
Cmd {
110+
unix: &format!(r"{} --install-extension ./ra-lsp-0.0.1.vsix --force", code_binary),
111+
windows: &format!(
112+
r"cmd.exe /c {}.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
113+
code_binary
114+
),
115+
work_dir: "./editors/code",
116+
}
117+
.run()?;
118+
119+
let output = Cmd {
120+
unix: &format!(r"{} --list-extensions", code_binary),
121+
windows: &format!(r"cmd.exe /c {}.cmd --list-extensions", code_binary),
122+
work_dir: ".",
123+
}
124+
.run_with_output()?;
125+
126+
if !str::from_utf8(&output.stdout)?.contains("ra-lsp") {
127+
anyhow::bail!(
128+
"Could not install the Visual Studio Code extension. \
129+
Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again."
130+
);
131+
}
132+
133+
Ok(())
134+
}
135+
136+
fn install_server(opts: ServerOpt) -> Result<()> {
137+
let mut old_rust = false;
138+
if let Ok(output) = run_with_output("cargo --version", ".") {
139+
if let Ok(stdout) = String::from_utf8(output.stdout) {
140+
println!("{}", stdout);
141+
if !check_version(&stdout, REQUIRED_RUST_VERSION) {
142+
old_rust = true;
143+
}
144+
}
145+
}
146+
147+
if old_rust {
148+
eprintln!(
149+
"\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n",
150+
REQUIRED_RUST_VERSION,
151+
)
152+
}
153+
154+
let res = if opts.jemalloc {
155+
run("cargo install --path crates/ra_lsp_server --locked --force --features jemalloc", ".")
156+
} else {
157+
run("cargo install --path crates/ra_lsp_server --locked --force", ".")
158+
};
159+
160+
if res.is_err() && old_rust {
161+
eprintln!(
162+
"\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n",
163+
REQUIRED_RUST_VERSION,
164+
)
165+
}
166+
167+
res
168+
}
169+
170+
fn check_version(version_output: &str, min_minor_version: u32) -> bool {
171+
// Parse second the number out of
172+
// cargo 1.39.0-beta (1c6ec66d5 2019-09-30)
173+
let minor: Option<u32> = version_output.split('.').nth(1).and_then(|it| it.parse().ok());
174+
match minor {
175+
None => true,
176+
Some(minor) => minor >= min_minor_version,
177+
}
178+
}

0 commit comments

Comments
 (0)