aboutsummaryrefslogtreecommitdiff
path: root/crates/tools/src/main.rs
blob: 6583b700c371d8b5c4d9b115ff3b0c96799f1314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use clap::{App, SubCommand};
use core::str;
use failure::bail;
use tools::{
    generate, gen_tests, install_format_hook, run, run_with_output, run_rustfmt,
    Overwrite, Result, run_fuzzer,
};

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(SubCommand::with_name("install-code"))
        .subcommand(SubCommand::with_name("format"))
        .subcommand(SubCommand::with_name("format-hook"))
        .subcommand(SubCommand::with_name("fuzz-tests"))
        .get_matches();
    match matches.subcommand_name().expect("Subcommand must be specified") {
        "install-code" => {
            setup_environment()?;
            install_code_extension()?;
        }
        "gen-tests" => gen_tests(Overwrite)?,
        "gen-syntax" => generate(Overwrite)?,
        "format" => run_rustfmt(Overwrite)?,
        "format-hook" => install_format_hook()?,
        "fuzz-tests" => run_fuzzer()?,
        _ => unreachable!(),
    }
    Ok(())
}

fn setup_environment() -> Result<()> {
    if cfg!(target_os = "macos") {
        vscode_path_helpers::append_vscode_path()?;
    }

    Ok(())
}

fn install_code_extension() -> Result<()> {
    run("cargo install --path crates/ra_lsp_server --force", ".")?;
    if cfg!(windows) {
        run(r"cmd.exe /c npm.cmd ci", "./editors/code")?;
        run(r"cmd.exe /c npm.cmd run package", "./editors/code")?;
    } else {
        run(r"npm ci", "./editors/code")?;
        run(r"npm run package", "./editors/code")?;
    }
    if cfg!(windows) {
        run(
            r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
            "./editors/code",
        )?;
    } else {
        run(r"code --install-extension ./ra-lsp-0.0.1.vsix --force", "./editors/code")?;
    }
    verify_installed_extensions()?;
    Ok(())
}

fn verify_installed_extensions() -> Result<()> {
    let exts = if cfg!(windows) {
        run_with_output(r"cmd.exe /c code.cmd --list-extensions", ".")?
    } else {
        run_with_output(r"code --list-extensions", ".")?
    };
    if !str::from_utf8(&exts.stdout)?.contains("ra-lsp") {
        bail!(
            "Could not install the Visual Studio Code extension. Please make sure you \
             have at least NodeJS 10.x installed and try again."
        );
    }
    Ok(())
}

#[cfg(target_os = "macos")]
mod vscode_path_helpers {
    use super::Result;
    use std::{path::{PathBuf}, env};
    use failure::bail;

    pub(crate) fn append_vscode_path() -> Result<()> {
        let vars = match env::var_os("PATH") {
            Some(path) => path,
            None => bail!("Could not get PATH variable from env."),
        };

        let vscode_path = get_vscode_path()?;
        let mut paths = env::split_paths(&vars).collect::<Vec<_>>();
        paths.push(vscode_path);
        let new_paths = env::join_paths(paths)?;
        env::set_var("PATH", &new_paths);

        Ok(())
    }

    fn get_vscode_path() -> Result<PathBuf> {
        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) => bail!("Failed getting HOME from environment with error: {}.", e),
        };

        for dir in [ROOT_DIR, &home_dir].iter() {
            let path = String::from(dir.clone()) + COMMON_APP_PATH;
            let path = PathBuf::from(path);
            if path.exists() {
                return Ok(path);
            }
        }

        bail!(
            "Could not find Visual Studio Code application. Please make sure you \
             have Visual Studio Code installed and try again or install extension \
             manually."
        )
    }
}

#[cfg(not(target_os = "macos"))]
mod vscode_path_helpers {
    use super::Result;
    pub(crate) fn append_vscode_path() -> Result<()> {
        Ok(())
    }
}