From 91f9bc2b866fc87dbaadb29a8c72eba10ae57c5c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Jan 2020 14:42:56 +0100 Subject: Refactor xtasks --- xtask/src/main.rs | 283 ++++++++++++++---------------------------------------- 1 file changed, 72 insertions(+), 211 deletions(-) (limited to 'xtask/src/main.rs') diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b42946a4c..9309b2fbd 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -7,244 +7,105 @@ //! //! This binary is integrated into the `cargo` command line by using an alias in //! `.cargo/config`. -mod help; -use std::{env, fmt::Write, path::PathBuf, str}; +use std::env; -use anyhow::Context; use pico_args::Arguments; use xtask::{ codegen::{self, Mode}, - install_pre_commit_hook, reformat_staged_files, run, run_clippy, run_fuzzer, run_rustfmt, - run_with_output, Cmd, Result, + install::{ClientOpt, InstallCmd, ServerOpt}, + pre_commit, run_clippy, run_fuzzer, run_rustfmt, Result, }; -// Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 40; - -struct InstallOpt { - client: Option, - server: Option, -} - -enum ClientOpt { - VsCode, -} - -struct ServerOpt { - jemalloc: bool, -} - fn main() -> Result<()> { if env::args().next().map(|it| it.contains("pre-commit")) == Some(true) { - return reformat_staged_files(); + return pre_commit::run_hook(); } - let subcommand = match std::env::args_os().nth(1) { - None => { - eprintln!("{}", help::GLOBAL_HELP); - return Ok(()); - } - Some(s) => s, - }; - let mut matches = Arguments::from_vec(std::env::args_os().skip(2).collect()); - let subcommand = &*subcommand.to_string_lossy(); - match subcommand { + let subcommand = std::env::args().nth(1).unwrap_or_default(); + let mut args = Arguments::from_vec(std::env::args_os().skip(2).collect()); + + match subcommand.as_str() { "install" => { - if matches.contains(["-h", "--help"]) { - eprintln!("{}", help::INSTALL_HELP); + if args.contains(["-h", "--help"]) { + eprintln!( + "\ +cargo xtask install +Install rust-analyzer server or editor plugin. + +USAGE: + cargo xtask install [FLAGS] + +FLAGS: + --client-code Install only VS Code plugin + --server Install only the language server + --jemalloc Use jemalloc for server + -h, --help Prints help information + " + ); return Ok(()); } - let server = matches.contains("--server"); - let client_code = matches.contains("--client-code"); + let server = args.contains("--server"); + let client_code = args.contains("--client-code"); if server && client_code { - eprintln!("{}", help::INSTALL_RA_CONFLICT); + eprintln!( + "error: The argument `--server` cannot be used with `--client-code`\n\n\ + For more information try --help" + ); return Ok(()); } - let jemalloc = matches.contains("--jemalloc"); - matches.finish().or_else(handle_extra_flags)?; - let opts = InstallOpt { + + let jemalloc = args.contains("--jemalloc"); + + args.finish()?; + + InstallCmd { client: if server { None } else { Some(ClientOpt::VsCode) }, server: if client_code { None } else { Some(ServerOpt { jemalloc }) }, - }; - install(opts)? + } + .run() } "codegen" => { + args.finish()?; codegen::generate_syntax(Mode::Overwrite)?; codegen::generate_parser_tests(Mode::Overwrite)?; codegen::generate_assists_docs(Mode::Overwrite)?; + Ok(()) } - "format" => run_rustfmt(Mode::Overwrite)?, - "install-pre-commit-hook" => install_pre_commit_hook()?, - "lint" => run_clippy()?, - "fuzz-tests" => run_fuzzer()?, - _ => eprintln!("{}", help::GLOBAL_HELP), - } - Ok(()) -} - -fn handle_extra_flags(e: pico_args::Error) -> Result<()> { - if let pico_args::Error::UnusedArgsLeft(flags) = e { - let mut invalid_flags = String::new(); - for flag in flags { - write!(&mut invalid_flags, "{}, ", flag)?; + "format" => { + args.finish()?; + run_rustfmt(Mode::Overwrite) } - let (invalid_flags, _) = invalid_flags.split_at(invalid_flags.len() - 2); - anyhow::bail!("Invalid flags: {}", invalid_flags) - } else { - anyhow::bail!(e.to_string()) - } -} - -fn install(opts: InstallOpt) -> Result<()> { - if cfg!(target_os = "macos") { - fix_path_for_mac().context("Fix path for mac")? - } - if let Some(server) = opts.server { - install_server(server).context("install server")?; - } - if let Some(client) = opts.client { - install_client(client).context("install client")?; - } - Ok(()) -} - -fn fix_path_for_mac() -> Result<()> { - let mut vscode_path: Vec = { - const COMMON_APP_PATH: &str = - r"/Applications/Visual Studio Code.app/Contents/Resources/app/bin"; - const ROOT_DIR: &str = ""; - let home_dir = match env::var("HOME") { - Ok(home) => home, - Err(e) => anyhow::bail!("Failed getting HOME from environment with error: {}.", e), - }; - - [ROOT_DIR, &home_dir] - .iter() - .map(|dir| String::from(*dir) + COMMON_APP_PATH) - .map(PathBuf::from) - .filter(|path| path.exists()) - .collect() - }; - - if !vscode_path.is_empty() { - let vars = match env::var_os("PATH") { - Some(path) => path, - None => anyhow::bail!("Could not get PATH variable from env."), - }; - - let mut paths = env::split_paths(&vars).collect::>(); - paths.append(&mut vscode_path); - let new_paths = env::join_paths(paths).context("build env PATH")?; - env::set_var("PATH", &new_paths); - } - - Ok(()) -} - -fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { - let npm_version = Cmd { - unix: r"npm --version", - windows: r"cmd.exe /c npm --version", - work_dir: "./editors/code", - } - .run(); - - if npm_version.is_err() { - eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") - } - - Cmd { unix: r"npm install", windows: r"cmd.exe /c npm install", work_dir: "./editors/code" } - .run()?; - Cmd { - unix: r"npm run package --scripts-prepend-node-path", - windows: r"cmd.exe /c npm run package", - work_dir: "./editors/code", - } - .run()?; - - let code_binary = ["code", "code-insiders", "codium"].iter().find(|bin| { - Cmd { - unix: &format!("{} --version", bin), - windows: &format!("cmd.exe /c {}.cmd --version", bin), - work_dir: "./editors/code", + "install-pre-commit-hook" => { + args.finish()?; + pre_commit::install_hook() } - .run() - .is_ok() - }); - - let code_binary = match code_binary { - Some(it) => it, - None => anyhow::bail!("Can't execute `code --version`. Perhaps it is not in $PATH?"), - }; - - Cmd { - unix: &format!(r"{} --install-extension ./ra-lsp-0.0.1.vsix --force", code_binary), - windows: &format!( - r"cmd.exe /c {}.cmd --install-extension ./ra-lsp-0.0.1.vsix --force", - code_binary - ), - work_dir: "./editors/code", - } - .run()?; - - let output = Cmd { - unix: &format!(r"{} --list-extensions", code_binary), - windows: &format!(r"cmd.exe /c {}.cmd --list-extensions", code_binary), - work_dir: ".", - } - .run_with_output()?; - - if !str::from_utf8(&output.stdout)?.contains("ra-lsp") { - anyhow::bail!( - "Could not install the Visual Studio Code extension. \ - Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again." - ); - } - - Ok(()) -} - -fn install_server(opts: ServerOpt) -> Result<()> { - let mut old_rust = false; - if let Ok(output) = run_with_output("cargo --version", ".") { - if let Ok(stdout) = String::from_utf8(output.stdout) { - println!("{}", stdout); - if !check_version(&stdout, REQUIRED_RUST_VERSION) { - old_rust = true; - } + "lint" => { + args.finish()?; + run_clippy() + } + "fuzz-tests" => { + args.finish()?; + run_fuzzer() + } + _ => { + eprintln!( + "\ +cargo xtask +Run custom build command. + +USAGE: + cargo xtask + +SUBCOMMANDS: + format + install-pre-commit-hook + fuzz-tests + codegen + install + lint" + ); + Ok(()) } - } - - if old_rust { - eprintln!( - "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION, - ) - } - - let res = if opts.jemalloc { - run("cargo install --path crates/ra_lsp_server --locked --force --features jemalloc", ".") - } else { - run("cargo install --path crates/ra_lsp_server --locked --force", ".") - }; - - if res.is_err() && old_rust { - eprintln!( - "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", - REQUIRED_RUST_VERSION, - ) - } - - res -} - -fn check_version(version_output: &str, min_minor_version: u32) -> bool { - // Parse second the number out of - // cargo 1.39.0-beta (1c6ec66d5 2019-09-30) - let minor: Option = version_output.split('.').nth(1).and_then(|it| it.parse().ok()); - match minor { - None => true, - Some(minor) => minor >= min_minor_version, } } -- cgit v1.2.3