aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src/main.rs')
-rw-r--r--xtask/src/main.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
new file mode 100644
index 000000000..623058436
--- /dev/null
+++ b/xtask/src/main.rs
@@ -0,0 +1,218 @@
1//! FIXME: write short doc here
2
3mod help;
4
5use core::fmt::Write;
6use core::str;
7use pico_args::Arguments;
8use std::{env, path::PathBuf};
9use xtask::{
10 gen_tests, generate_boilerplate, install_format_hook, run, run_clippy, run_fuzzer, run_rustfmt,
11 Cmd, Overwrite, Result,
12};
13
14struct InstallOpt {
15 client: Option<ClientOpt>,
16 server: Option<ServerOpt>,
17}
18
19enum ClientOpt {
20 VsCode,
21}
22
23struct ServerOpt {
24 jemalloc: bool,
25}
26
27fn main() -> Result<()> {
28 let subcommand = match std::env::args_os().nth(1) {
29 None => {
30 eprintln!("{}", help::GLOBAL_HELP);
31 return Ok(());
32 }
33 Some(s) => s,
34 };
35 let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect());
36 let subcommand = &*subcommand.to_string_lossy();
37 match subcommand {
38 "install" => {
39 if matches.contains(["-h", "--help"]) {
40 eprintln!("{}", help::INSTALL_HELP);
41 return Ok(());
42 }
43 let server = matches.contains("--server");
44 let client_code = matches.contains("--client-code");
45 if server && client_code {
46 eprintln!("{}", help::INSTALL_RA_CONFLICT);
47 return Ok(());
48 }
49 let jemalloc = matches.contains("--jemalloc");
50 matches.finish().or_else(handle_extra_flags)?;
51 let opts = InstallOpt {
52 client: if server { None } else { Some(ClientOpt::VsCode) },
53 server: if client_code { None } else { Some(ServerOpt { jemalloc: jemalloc }) },
54 };
55 install(opts)?
56 }
57 "gen-tests" => {
58 if matches.contains(["-h", "--help"]) {
59 help::print_no_param_subcommand_help(&subcommand);
60 return Ok(());
61 }
62 gen_tests(Overwrite)?
63 }
64 "codegen" => {
65 if matches.contains(["-h", "--help"]) {
66 help::print_no_param_subcommand_help(&subcommand);
67 return Ok(());
68 }
69 generate_boilerplate(Overwrite)?
70 }
71 "format" => {
72 if matches.contains(["-h", "--help"]) {
73 help::print_no_param_subcommand_help(&subcommand);
74 return Ok(());
75 }
76 run_rustfmt(Overwrite)?
77 }
78 "format-hook" => {
79 if matches.contains(["-h", "--help"]) {
80 help::print_no_param_subcommand_help(&subcommand);
81 return Ok(());
82 }
83 install_format_hook()?
84 }
85 "lint" => {
86 if matches.contains(["-h", "--help"]) {
87 help::print_no_param_subcommand_help(&subcommand);
88 return Ok(());
89 }
90 run_clippy()?
91 }
92 "fuzz-tests" => {
93 if matches.contains(["-h", "--help"]) {
94 help::print_no_param_subcommand_help(&subcommand);
95 return Ok(());
96 }
97 run_fuzzer()?
98 }
99 _ => eprintln!("{}", help::GLOBAL_HELP),
100 }
101 Ok(())
102}
103
104fn handle_extra_flags(e: pico_args::Error) -> Result<()> {
105 if let pico_args::Error::UnusedArgsLeft(flags) = e {
106 let mut invalid_flags = String::new();
107 for flag in flags {
108 write!(&mut invalid_flags, "{}, ", flag)?;
109 }
110 let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2);
111 Err(format!("Invalid flags: {}", invalid_flags).into())
112 } else {
113 Err(e.to_string().into())
114 }
115}
116
117fn install(opts: InstallOpt) -> Result<()> {
118 if cfg!(target_os = "macos") {
119 fix_path_for_mac()?
120 }
121 if let Some(server) = opts.server {
122 install_server(server)?;
123 }
124 if let Some(client) = opts.client {
125 install_client(client)?;
126 }
127 Ok(())
128}
129
130fn fix_path_for_mac() -> Result<()> {
131 let mut vscode_path: Vec<PathBuf> = {
132 const COMMON_APP_PATH: &str =
133 r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin";
134 const ROOT_DIR: &str = "";
135 let home_dir = match env::var("HOME") {
136 Ok(home) => home,
137 Err(e) => Err(format!("Failed getting HOME from environment with error: {}.", e))?,
138 };
139
140 [ROOT_DIR, &home_dir]
141 .iter()
142 .map(|dir| String::from(*dir) + COMMON_APP_PATH)
143 .map(PathBuf::from)
144 .filter(|path| path.exists())
145 .collect()
146 };
147
148 if !vscode_path.is_empty() {
149 let vars = match env::var_os("PATH") {
150 Some(path) => path,
151 None => Err("Could not get PATH variable from env.")?,
152 };
153
154 let mut paths = env::split_paths(&vars).collect::<Vec<_>>();
155 paths.append(&mut vscode_path);
156 let new_paths = env::join_paths(paths)?;
157 env::set_var("PATH", &new_paths);
158 }
159
160 Ok(())
161}
162
163fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
164 Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?;
165 Cmd {
166 unix: r"npm run package",
167 windows: r"cmd.exe /c npm.cmd run package",
168 work_dir: "./editors/code",
169 }
170 .run()?;
171
172 let code_binary = ["code", "code-insiders", "codium"].iter().find(|bin| {
173 Cmd {
174 unix: &format!("{} --version", bin),
175 windows: &format!("cmd.exe /c {}.cmd --version", bin),
176 work_dir: "./editors/code",
177 }
178 .run()
179 .is_ok()
180 });
181
182 let code_binary = match code_binary {
183 Some(it) => it,
184 None => Err("Can't execute `code --version`. Perhaps it is not in $PATH?")?,
185 };
186
187 Cmd {
188 unix: &format!(r"{} --install-extension ./ra-lsp-0.0.1.vsix --force", code_binary),
189 windows: &format!(
190 r"cmd.exe /c {}.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
191 code_binary
192 ),
193 work_dir: "./editors/code",
194 }
195 .run()?;
196
197 let output = Cmd {
198 unix: &format!(r"{} --list-extensions", code_binary),
199 windows: &format!(r"cmd.exe /c {}.cmd --list-extensions", code_binary),
200 work_dir: ".",
201 }
202 .run_with_output()?;
203
204 if !str::from_utf8(&output.stdout)?.contains("ra-lsp") {
205 Err("Could not install the Visual Studio Code extension. \
206 Please make sure you have at least NodeJS 10.x installed and try again.")?;
207 }
208
209 Ok(())
210}
211
212fn install_server(opts: ServerOpt) -> Result<()> {
213 if opts.jemalloc {
214 run("cargo install --path crates/ra_lsp_server --locked --force --features jemalloc", ".")
215 } else {
216 run("cargo install --path crates/ra_lsp_server --locked --force", ".")
217 }
218}