aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/install.rs
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src/install.rs')
-rw-r--r--xtask/src/install.rs120
1 files changed, 48 insertions, 72 deletions
diff --git a/xtask/src/install.rs b/xtask/src/install.rs
index ea2194248..177028b08 100644
--- a/xtask/src/install.rs
+++ b/xtask/src/install.rs
@@ -5,60 +5,32 @@ use std::{env, path::PathBuf, str};
5use anyhow::{bail, format_err, Context, Result}; 5use anyhow::{bail, format_err, Context, Result};
6use xshell::{cmd, pushd}; 6use xshell::{cmd, pushd};
7 7
8use crate::flags;
9
8// Latest stable, feel free to send a PR if this lags behind. 10// Latest stable, feel free to send a PR if this lags behind.
9const REQUIRED_RUST_VERSION: u32 = 50; 11const REQUIRED_RUST_VERSION: u32 = 50;
10 12
11pub(crate) struct InstallCmd { 13impl flags::Install {
12 pub(crate) client: Option<ClientOpt>, 14 pub(crate) fn run(self) -> Result<()> {
13 pub(crate) server: Option<ServerOpt>, 15 if cfg!(target_os = "macos") {
14} 16 fix_path_for_mac().context("Fix path for mac")?
15 17 }
16#[derive(Clone, Copy)] 18 if let Some(server) = self.server() {
17pub(crate) enum ClientOpt { 19 install_server(server).context("install server")?;
18 VsCode, 20 }
19 VsCodeExploration, 21 if let Some(client) = self.client() {
20 VsCodeInsiders, 22 install_client(client).context("install client")?;
21 VsCodium,
22 VsCodeOss,
23 Any,
24}
25
26impl ClientOpt {
27 pub(crate) const fn as_cmds(&self) -> &'static [&'static str] {
28 match self {
29 ClientOpt::VsCode => &["code"],
30 ClientOpt::VsCodeExploration => &["code-exploration"],
31 ClientOpt::VsCodeInsiders => &["code-insiders"],
32 ClientOpt::VsCodium => &["codium"],
33 ClientOpt::VsCodeOss => &["code-oss"],
34 ClientOpt::Any => &["code", "code-exploration", "code-insiders", "codium", "code-oss"],
35 } 23 }
24 Ok(())
36 } 25 }
37} 26}
38 27
39impl Default for ClientOpt { 28#[derive(Clone)]
40 fn default() -> Self { 29pub(crate) struct ClientOpt {
41 ClientOpt::Any 30 pub(crate) code_bin: Option<String>,
42 }
43} 31}
44 32
45impl std::str::FromStr for ClientOpt { 33const VS_CODES: &[&str] = &["code", "code-exploration", "code-insiders", "codium", "code-oss"];
46 type Err = anyhow::Error;
47
48 fn from_str(s: &str) -> Result<Self, Self::Err> {
49 [
50 ClientOpt::VsCode,
51 ClientOpt::VsCodeExploration,
52 ClientOpt::VsCodeInsiders,
53 ClientOpt::VsCodium,
54 ClientOpt::VsCodeOss,
55 ]
56 .iter()
57 .copied()
58 .find(|c| [s] == c.as_cmds())
59 .ok_or_else(|| anyhow::format_err!("no such client"))
60 }
61}
62 34
63pub(crate) struct ServerOpt { 35pub(crate) struct ServerOpt {
64 pub(crate) malloc: Malloc, 36 pub(crate) malloc: Malloc,
@@ -70,21 +42,6 @@ pub(crate) enum Malloc {
70 Jemalloc, 42 Jemalloc,
71} 43}
72 44
73impl InstallCmd {
74 pub(crate) fn run(self) -> Result<()> {
75 if cfg!(target_os = "macos") {
76 fix_path_for_mac().context("Fix path for mac")?
77 }
78 if let Some(server) = self.server {
79 install_server(server).context("install server")?;
80 }
81 if let Some(client) = self.client {
82 install_client(client).context("install client")?;
83 }
84 Ok(())
85 }
86}
87
88fn fix_path_for_mac() -> Result<()> { 45fn fix_path_for_mac() -> Result<()> {
89 let mut vscode_path: Vec<PathBuf> = { 46 let mut vscode_path: Vec<PathBuf> = {
90 const COMMON_APP_PATH: &str = 47 const COMMON_APP_PATH: &str =
@@ -121,21 +78,12 @@ fn fix_path_for_mac() -> Result<()> {
121fn install_client(client_opt: ClientOpt) -> Result<()> { 78fn install_client(client_opt: ClientOpt) -> Result<()> {
122 let _dir = pushd("./editors/code"); 79 let _dir = pushd("./editors/code");
123 80
124 let find_code = |f: fn(&str) -> bool| -> Result<&'static str> { 81 // Package extension.
125 client_opt.as_cmds().iter().copied().find(|bin| f(bin)).ok_or_else(|| { 82 if cfg!(unix) {
126 format_err!("Can't execute `code --version`. Perhaps it is not in $PATH?")
127 })
128 };
129
130 let installed_extensions = if cfg!(unix) {
131 cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?; 83 cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?;
132 cmd!("npm ci").run()?; 84 cmd!("npm ci").run()?;
133 85
134 cmd!("npm run package --scripts-prepend-node-path").run()?; 86 cmd!("npm run package --scripts-prepend-node-path").run()?;
135
136 let code = find_code(|bin| cmd!("{bin} --version").read().is_ok())?;
137 cmd!("{code} --install-extension rust-analyzer.vsix --force").run()?;
138 cmd!("{code} --list-extensions").read()?
139 } else { 87 } else {
140 cmd!("cmd.exe /c npm --version") 88 cmd!("cmd.exe /c npm --version")
141 .run() 89 .run()
@@ -143,8 +91,36 @@ fn install_client(client_opt: ClientOpt) -> Result<()> {
143 cmd!("cmd.exe /c npm ci").run()?; 91 cmd!("cmd.exe /c npm ci").run()?;
144 92
145 cmd!("cmd.exe /c npm run package").run()?; 93 cmd!("cmd.exe /c npm run package").run()?;
94 };
95
96 // Find the appropriate VS Code binary.
97 let lifetime_extender;
98 let candidates: &[&str] = match client_opt.code_bin.as_deref() {
99 Some(it) => {
100 lifetime_extender = [it];
101 &lifetime_extender[..]
102 }
103 None => VS_CODES,
104 };
105 let code = candidates
106 .iter()
107 .copied()
108 .find(|&bin| {
109 if cfg!(unix) {
110 cmd!("{bin} --version").read().is_ok()
111 } else {
112 cmd!("cmd.exe /c {bin}.cmd --version").read().is_ok()
113 }
114 })
115 .ok_or_else(|| {
116 format_err!("Can't execute `{} --version`. Perhaps it is not in $PATH?", candidates[0])
117 })?;
146 118
147 let code = find_code(|bin| cmd!("cmd.exe /c {bin}.cmd --version").read().is_ok())?; 119 // Install & verify.
120 let installed_extensions = if cfg!(unix) {
121 cmd!("{code} --install-extension rust-analyzer.vsix --force").run()?;
122 cmd!("{code} --list-extensions").read()?
123 } else {
148 cmd!("cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?; 124 cmd!("cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?;
149 cmd!("cmd.exe /c {code}.cmd --list-extensions").read()? 125 cmd!("cmd.exe /c {code}.cmd --list-extensions").read()?
150 }; 126 };