diff options
-rw-r--r-- | editors/code/package-lock.json | 2 | ||||
-rw-r--r-- | editors/code/package.json | 3 | ||||
-rw-r--r-- | xtask/src/cmd.rs | 56 | ||||
-rw-r--r-- | xtask/src/install.rs | 116 | ||||
-rw-r--r-- | xtask/src/lib.rs | 58 | ||||
-rw-r--r-- | xtask/src/not_bash.rs | 123 | ||||
-rw-r--r-- | xtask/src/pre_commit.rs | 6 |
7 files changed, 202 insertions, 162 deletions
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 5c056463e..a7a1829dd 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json | |||
@@ -1,6 +1,6 @@ | |||
1 | { | 1 | { |
2 | "name": "rust-analyzer", | 2 | "name": "rust-analyzer", |
3 | "version": "0.1.0", | 3 | "version": "0.2.0-dev", |
4 | "lockfileVersion": 1, | 4 | "lockfileVersion": 1, |
5 | "requires": true, | 5 | "requires": true, |
6 | "dependencies": { | 6 | "dependencies": { |
diff --git a/editors/code/package.json b/editors/code/package.json index f687eb8d4..2b8e5aec5 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -5,7 +5,8 @@ | |||
5 | "preview": true, | 5 | "preview": true, |
6 | "private": true, | 6 | "private": true, |
7 | "icon": "icon.png", | 7 | "icon": "icon.png", |
8 | "version": "0.1.0", | 8 | "//": "The real version is in release.yaml, this one just needs to be bigger", |
9 | "version": "0.2.0-dev", | ||
9 | "publisher": "matklad", | 10 | "publisher": "matklad", |
10 | "repository": { | 11 | "repository": { |
11 | "url": "https://github.com/rust-analyzer/rust-analyzer.git", | 12 | "url": "https://github.com/rust-analyzer/rust-analyzer.git", |
diff --git a/xtask/src/cmd.rs b/xtask/src/cmd.rs deleted file mode 100644 index 37497fb74..000000000 --- a/xtask/src/cmd.rs +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
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<String> { | ||
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<String> { | ||
38 | let output = do_run(cmdline, dir, &mut |_| {})?; | ||
39 | let stdout = String::from_utf8(output.stdout)?; | ||
40 | let stdout = stdout.trim().to_string(); | ||
41 | Ok(stdout) | ||
42 | } | ||
43 | |||
44 | fn do_run(cmdline: &str, dir: &str, f: &mut dyn FnMut(&mut Command)) -> Result<Output> { | ||
45 | eprintln!("\nwill run: {}", cmdline); | ||
46 | let proj_dir = project_root().join(dir); | ||
47 | let mut args = cmdline.split_whitespace(); | ||
48 | let exec = args.next().unwrap(); | ||
49 | let mut cmd = Command::new(exec); | ||
50 | f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit())); | ||
51 | let output = cmd.output().with_context(|| format!("running `{}`", cmdline))?; | ||
52 | if !output.status.success() { | ||
53 | anyhow::bail!("`{}` exited with {}", cmdline, output.status); | ||
54 | } | ||
55 | Ok(output) | ||
56 | } | ||
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 99e1eddb1..540a66130 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | use std::{env, path::PathBuf, str}; | 3 | use std::{env, path::PathBuf, str}; |
4 | 4 | ||
5 | use anyhow::{Context, Result}; | 5 | use anyhow::{bail, format_err, Context, Result}; |
6 | 6 | ||
7 | use crate::cmd::{run, run_with_output, Cmd}; | 7 | use crate::not_bash::{ls, pushd, rm, run}; |
8 | 8 | ||
9 | // Latest stable, feel free to send a PR if this lags behind. | 9 | // Latest stable, feel free to send a PR if this lags behind. |
10 | const REQUIRED_RUST_VERSION: u32 = 41; | 10 | const REQUIRED_RUST_VERSION: u32 = 41; |
@@ -55,7 +55,7 @@ fn fix_path_for_mac() -> Result<()> { | |||
55 | const ROOT_DIR: &str = ""; | 55 | const ROOT_DIR: &str = ""; |
56 | let home_dir = match env::var("HOME") { | 56 | let home_dir = match env::var("HOME") { |
57 | Ok(home) => home, | 57 | Ok(home) => home, |
58 | Err(e) => anyhow::bail!("Failed getting HOME from environment with error: {}.", e), | 58 | Err(e) => bail!("Failed getting HOME from environment with error: {}.", e), |
59 | }; | 59 | }; |
60 | 60 | ||
61 | [ROOT_DIR, &home_dir] | 61 | [ROOT_DIR, &home_dir] |
@@ -69,7 +69,7 @@ fn fix_path_for_mac() -> Result<()> { | |||
69 | if !vscode_path.is_empty() { | 69 | if !vscode_path.is_empty() { |
70 | let vars = match env::var_os("PATH") { | 70 | let vars = match env::var_os("PATH") { |
71 | Some(path) => path, | 71 | Some(path) => path, |
72 | None => anyhow::bail!("Could not get PATH variable from env."), | 72 | None => bail!("Could not get PATH variable from env."), |
73 | }; | 73 | }; |
74 | 74 | ||
75 | let mut paths = env::split_paths(&vars).collect::<Vec<_>>(); | 75 | let mut paths = env::split_paths(&vars).collect::<Vec<_>>(); |
@@ -82,84 +82,61 @@ fn fix_path_for_mac() -> Result<()> { | |||
82 | } | 82 | } |
83 | 83 | ||
84 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | 84 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { |
85 | let npm_version = Cmd { | 85 | let _dir = pushd("./editors/code"); |
86 | unix: r"npm --version", | ||
87 | windows: r"cmd.exe /c npm --version", | ||
88 | work_dir: "./editors/code", | ||
89 | } | ||
90 | .run(); | ||
91 | |||
92 | if npm_version.is_err() { | ||
93 | eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") | ||
94 | } | ||
95 | 86 | ||
96 | Cmd { unix: r"npm install", windows: r"cmd.exe /c npm install", work_dir: "./editors/code" } | 87 | let find_code = |f: fn(&str) -> bool| -> Result<&'static str> { |
97 | .run()?; | 88 | ["code", "code-insiders", "codium", "code-oss"] |
98 | Cmd { | 89 | .iter() |
99 | unix: r"npm run package --scripts-prepend-node-path", | 90 | .copied() |
100 | windows: r"cmd.exe /c npm run package", | 91 | .find(|bin| f(bin)) |
101 | work_dir: "./editors/code", | 92 | .ok_or_else(|| { |
102 | } | 93 | format_err!("Can't execute `code --version`. Perhaps it is not in $PATH?") |
103 | .run()?; | 94 | }) |
95 | }; | ||
104 | 96 | ||
105 | let code_binary = ["code", "code-insiders", "codium", "code-oss"].iter().find(|bin| { | 97 | let installed_extensions; |
106 | Cmd { | 98 | if cfg!(unix) { |
107 | unix: &format!("{} --version", bin), | 99 | run!("npm --version").context("`npm` is required to build the VS Code plugin")?; |
108 | windows: &format!("cmd.exe /c {}.cmd --version", bin), | 100 | run!("npm install")?; |
109 | work_dir: "./editors/code", | ||
110 | } | ||
111 | .run() | ||
112 | .is_ok() | ||
113 | }); | ||
114 | 101 | ||
115 | let code_binary = match code_binary { | 102 | let vsix_pkg = { |
116 | Some(it) => it, | 103 | rm("*.vsix")?; |
117 | None => anyhow::bail!("Can't execute `code --version`. Perhaps it is not in $PATH?"), | 104 | run!("npm run package --scripts-prepend-node-path")?; |
118 | }; | 105 | ls("*.vsix")?.pop().unwrap() |
106 | }; | ||
119 | 107 | ||
120 | Cmd { | 108 | let code = find_code(|bin| run!("{} --version", bin).is_ok())?; |
121 | unix: &format!(r"{} --install-extension ./rust-analyzer-0.1.0.vsix --force", code_binary), | 109 | run!("{} --install-extension {} --force", code, vsix_pkg.display())?; |
122 | windows: &format!( | 110 | installed_extensions = run!("{} --list-extensions", code; echo = false)?; |
123 | r"cmd.exe /c {}.cmd --install-extension ./rust-analyzer-0.1.0.vsix --force", | 111 | } else { |
124 | code_binary | 112 | run!("cmd.exe /c npm --version") |
125 | ), | 113 | .context("`npm` is required to build the VS Code plugin")?; |
126 | work_dir: "./editors/code", | 114 | run!("cmd.exe /c npm install")?; |
127 | } | 115 | |
128 | .run()?; | 116 | let vsix_pkg = { |
117 | rm("*.vsix")?; | ||
118 | run!("cmd.exe /c npm run package")?; | ||
119 | ls("*.vsix")?.pop().unwrap() | ||
120 | }; | ||
129 | 121 | ||
130 | let installed_extensions = Cmd { | 122 | let code = find_code(|bin| run!("cmd.exe /c {}.cmd --version", bin).is_ok())?; |
131 | unix: &format!(r"{} --list-extensions", code_binary), | 123 | run!(r"cmd.exe /c {}.cmd --install-extension {} --force", code, vsix_pkg.display())?; |
132 | windows: &format!(r"cmd.exe /c {}.cmd --list-extensions", code_binary), | 124 | installed_extensions = run!("cmd.exe /c {}.cmd --list-extensions", code; echo = false)?; |
133 | work_dir: ".", | ||
134 | } | 125 | } |
135 | .run_with_output()?; | ||
136 | 126 | ||
137 | if !installed_extensions.contains("rust-analyzer") { | 127 | if !installed_extensions.contains("rust-analyzer") { |
138 | anyhow::bail!( | 128 | bail!( |
139 | "Could not install the Visual Studio Code extension. \ | 129 | "Could not install the Visual Studio Code extension. \ |
140 | Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again." | 130 | Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again." |
141 | ); | 131 | ); |
142 | } | 132 | } |
143 | 133 | ||
144 | if installed_extensions.contains("ra-lsp") { | ||
145 | Cmd { | ||
146 | unix: &format!(r"{} --uninstall-extension matklad.ra-lsp", code_binary), | ||
147 | windows: &format!( | ||
148 | r"cmd.exe /c {}.cmd --uninstall-extension matklad.ra-lsp", | ||
149 | code_binary | ||
150 | ), | ||
151 | work_dir: "./editors/code", | ||
152 | } | ||
153 | .run()?; | ||
154 | } | ||
155 | |||
156 | Ok(()) | 134 | Ok(()) |
157 | } | 135 | } |
158 | 136 | ||
159 | fn install_server(opts: ServerOpt) -> Result<()> { | 137 | fn install_server(opts: ServerOpt) -> Result<()> { |
160 | let mut old_rust = false; | 138 | let mut old_rust = false; |
161 | if let Ok(stdout) = run_with_output("cargo --version", ".") { | 139 | if let Ok(stdout) = run!("cargo --version") { |
162 | println!("{}", stdout); | ||
163 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { | 140 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { |
164 | old_rust = true; | 141 | old_rust = true; |
165 | } | 142 | } |
@@ -172,20 +149,17 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
172 | ) | 149 | ) |
173 | } | 150 | } |
174 | 151 | ||
175 | let res = if opts.jemalloc { | 152 | let jemalloc = if opts.jemalloc { "--features jemalloc" } else { "" }; |
176 | run("cargo install --path crates/ra_lsp_server --locked --force --features jemalloc", ".") | 153 | let res = run!("cargo install --path crates/ra_lsp_server --locked --force {}", jemalloc); |
177 | } else { | ||
178 | run("cargo install --path crates/ra_lsp_server --locked --force", ".") | ||
179 | }; | ||
180 | 154 | ||
181 | if res.is_err() && old_rust { | 155 | if res.is_err() && old_rust { |
182 | eprintln!( | 156 | eprintln!( |
183 | "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", | 157 | "\nWARNING: at least rust 1.{}.0 is required to compile rust-analyzer\n", |
184 | REQUIRED_RUST_VERSION, | 158 | REQUIRED_RUST_VERSION, |
185 | ) | 159 | ); |
186 | } | 160 | } |
187 | 161 | ||
188 | res | 162 | res.map(drop) |
189 | } | 163 | } |
190 | 164 | ||
191 | fn check_version(version_output: &str, min_minor_version: u32) -> bool { | 165 | fn check_version(version_output: &str, min_minor_version: u32) -> bool { |
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 1bb1882b0..d2ef2e95b 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | mod cmd; | 3 | pub mod not_bash; |
4 | pub mod install; | 4 | pub mod install; |
5 | pub mod pre_commit; | 5 | pub mod pre_commit; |
6 | 6 | ||
@@ -16,8 +16,8 @@ use std::{ | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | cmd::{run, run_with_output}, | ||
20 | codegen::Mode, | 19 | codegen::Mode, |
20 | not_bash::{pushd, run}, | ||
21 | }; | 21 | }; |
22 | 22 | ||
23 | pub use anyhow::Result; | 23 | pub use anyhow::Result; |
@@ -38,9 +38,9 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> { | |||
38 | ensure_rustfmt()?; | 38 | ensure_rustfmt()?; |
39 | 39 | ||
40 | if mode == Mode::Verify { | 40 | if mode == Mode::Verify { |
41 | run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?; | 41 | run!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN)?; |
42 | } else { | 42 | } else { |
43 | run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?; | 43 | run!("rustup run {} -- cargo fmt", TOOLCHAIN)?; |
44 | } | 44 | } |
45 | Ok(()) | 45 | Ok(()) |
46 | } | 46 | } |
@@ -70,8 +70,9 @@ fn ensure_rustfmt() -> Result<()> { | |||
70 | Ok(status) if status.success() => return Ok(()), | 70 | Ok(status) if status.success() => return Ok(()), |
71 | _ => (), | 71 | _ => (), |
72 | }; | 72 | }; |
73 | run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; | 73 | run!("rustup toolchain install {}", TOOLCHAIN)?; |
74 | run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".") | 74 | run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?; |
75 | Ok(()) | ||
75 | } | 76 | } |
76 | 77 | ||
77 | pub fn run_clippy() -> Result<()> { | 78 | pub fn run_clippy() -> Result<()> { |
@@ -92,34 +93,31 @@ pub fn run_clippy() -> Result<()> { | |||
92 | "clippy::nonminimal_bool", | 93 | "clippy::nonminimal_bool", |
93 | "clippy::redundant_pattern_matching", | 94 | "clippy::redundant_pattern_matching", |
94 | ]; | 95 | ]; |
95 | run( | 96 | run!( |
96 | &format!( | 97 | "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}", |
97 | "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}", | 98 | TOOLCHAIN, |
98 | TOOLCHAIN, | 99 | allowed_lints.join(" -A ") |
99 | allowed_lints.join(" -A ") | ||
100 | ), | ||
101 | ".", | ||
102 | )?; | 100 | )?; |
103 | Ok(()) | 101 | Ok(()) |
104 | } | 102 | } |
105 | 103 | ||
106 | fn install_clippy() -> Result<()> { | 104 | fn install_clippy() -> Result<()> { |
107 | run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; | 105 | run!("rustup toolchain install {}", TOOLCHAIN)?; |
108 | run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".") | 106 | run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?; |
107 | Ok(()) | ||
109 | } | 108 | } |
110 | 109 | ||
111 | pub fn run_fuzzer() -> Result<()> { | 110 | pub fn run_fuzzer() -> Result<()> { |
112 | match Command::new("cargo") | 111 | let _d = pushd("./crates/ra_syntax"); |
113 | .args(&["fuzz", "--help"]) | 112 | match run!("cargo fuzz --help") { |
114 | .stderr(Stdio::null()) | 113 | Ok(_) => (), |
115 | .stdout(Stdio::null()) | 114 | _ => { |
116 | .status() | 115 | run!("cargo install cargo-fuzz")?; |
117 | { | 116 | } |
118 | Ok(status) if status.success() => (), | ||
119 | _ => run("cargo install cargo-fuzz", ".")?, | ||
120 | }; | 117 | }; |
121 | 118 | ||
122 | run("rustup run nightly -- cargo fuzz run parser", "./crates/ra_syntax") | 119 | run!("rustup run nightly -- cargo fuzz run parser")?; |
120 | Ok(()) | ||
123 | } | 121 | } |
124 | 122 | ||
125 | /// Cleans the `./target` dir after the build such that only | 123 | /// Cleans the `./target` dir after the build such that only |
@@ -161,15 +159,15 @@ fn rm_rf(path: &Path) -> Result<()> { | |||
161 | } | 159 | } |
162 | 160 | ||
163 | pub fn run_release() -> Result<()> { | 161 | pub fn run_release() -> Result<()> { |
164 | run("git switch release", ".")?; | 162 | run!("git switch release")?; |
165 | run("git fetch upstream", ".")?; | 163 | run!("git fetch upstream")?; |
166 | run("git reset --hard upstream/master", ".")?; | 164 | run!("git reset --hard upstream/master")?; |
167 | run("git push", ".")?; | 165 | run!("git push")?; |
168 | 166 | ||
169 | let changelog_dir = project_root().join("../rust-analyzer.github.io/thisweek/_posts"); | 167 | let changelog_dir = project_root().join("../rust-analyzer.github.io/thisweek/_posts"); |
170 | 168 | ||
171 | let today = run_with_output("date --iso", ".")?; | 169 | let today = run!("date --iso")?; |
172 | let commit = run_with_output("git rev-parse HEAD", ".")?; | 170 | let commit = run!("git rev-parse HEAD")?; |
173 | let changelog_n = fs::read_dir(changelog_dir.as_path())?.count(); | 171 | let changelog_n = fs::read_dir(changelog_dir.as_path())?.count(); |
174 | 172 | ||
175 | let contents = format!( | 173 | let contents = format!( |
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs new file mode 100644 index 000000000..56d6c6c2d --- /dev/null +++ b/xtask/src/not_bash.rs | |||
@@ -0,0 +1,123 @@ | |||
1 | //! A bad shell -- small cross platform module for writing glue code | ||
2 | use std::{ | ||
3 | cell::RefCell, | ||
4 | env, | ||
5 | ffi::OsStr, | ||
6 | fs, | ||
7 | path::PathBuf, | ||
8 | process::{Command, Stdio}, | ||
9 | }; | ||
10 | |||
11 | use anyhow::{bail, Context, Result}; | ||
12 | |||
13 | macro_rules! _run { | ||
14 | ($($expr:expr),*) => { | ||
15 | run!($($expr),*; echo = true) | ||
16 | }; | ||
17 | ($($expr:expr),* ; echo = $echo:expr) => { | ||
18 | $crate::not_bash::run_process(format!($($expr),*), $echo) | ||
19 | }; | ||
20 | } | ||
21 | pub(crate) use _run as run; | ||
22 | |||
23 | pub struct Pushd { | ||
24 | _p: (), | ||
25 | } | ||
26 | |||
27 | pub fn pushd(path: impl Into<PathBuf>) -> Pushd { | ||
28 | Env::with(|env| env.pushd(path.into())); | ||
29 | Pushd { _p: () } | ||
30 | } | ||
31 | |||
32 | impl Drop for Pushd { | ||
33 | fn drop(&mut self) { | ||
34 | Env::with(|env| env.popd()) | ||
35 | } | ||
36 | } | ||
37 | |||
38 | pub fn rm(glob: &str) -> Result<()> { | ||
39 | let cwd = Env::with(|env| env.cwd()); | ||
40 | ls(glob)?.into_iter().try_for_each(|it| fs::remove_file(cwd.join(it)))?; | ||
41 | Ok(()) | ||
42 | } | ||
43 | |||
44 | pub fn ls(glob: &str) -> Result<Vec<PathBuf>> { | ||
45 | let cwd = Env::with(|env| env.cwd()); | ||
46 | let mut res = Vec::new(); | ||
47 | for entry in fs::read_dir(&cwd)? { | ||
48 | let entry = entry?; | ||
49 | if matches(&entry.file_name(), glob) { | ||
50 | let path = entry.path(); | ||
51 | let path = path.strip_prefix(&cwd).unwrap(); | ||
52 | res.push(path.to_path_buf()) | ||
53 | } | ||
54 | } | ||
55 | return Ok(res); | ||
56 | |||
57 | fn matches(file_name: &OsStr, glob: &str) -> bool { | ||
58 | assert!(glob.starts_with('*')); | ||
59 | file_name.to_string_lossy().ends_with(&glob[1..]) | ||
60 | } | ||
61 | } | ||
62 | |||
63 | #[doc(hidden)] | ||
64 | pub fn run_process(cmd: String, echo: bool) -> Result<String> { | ||
65 | run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) | ||
66 | } | ||
67 | |||
68 | fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { | ||
69 | let cwd = Env::with(|env| env.cwd()); | ||
70 | let mut args = shelx(cmd); | ||
71 | let binary = args.remove(0); | ||
72 | |||
73 | if echo { | ||
74 | println!("> {}", cmd) | ||
75 | } | ||
76 | |||
77 | let output = Command::new(binary) | ||
78 | .args(args) | ||
79 | .current_dir(cwd) | ||
80 | .stdin(Stdio::null()) | ||
81 | .stderr(Stdio::inherit()) | ||
82 | .output()?; | ||
83 | let stdout = String::from_utf8(output.stdout)?; | ||
84 | |||
85 | if echo { | ||
86 | print!("{}", stdout) | ||
87 | } | ||
88 | |||
89 | if !output.status.success() { | ||
90 | bail!("{}", output.status) | ||
91 | } | ||
92 | |||
93 | Ok(stdout) | ||
94 | } | ||
95 | |||
96 | // FIXME: some real shell lexing here | ||
97 | fn shelx(cmd: &str) -> Vec<String> { | ||
98 | cmd.split_whitespace().map(|it| it.to_string()).collect() | ||
99 | } | ||
100 | |||
101 | #[derive(Default)] | ||
102 | struct Env { | ||
103 | pushd_stack: Vec<PathBuf>, | ||
104 | } | ||
105 | |||
106 | impl Env { | ||
107 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { | ||
108 | thread_local! { | ||
109 | static ENV: RefCell<Env> = Default::default(); | ||
110 | } | ||
111 | ENV.with(|it| f(&mut *it.borrow_mut())) | ||
112 | } | ||
113 | |||
114 | fn pushd(&mut self, dir: PathBuf) { | ||
115 | self.pushd_stack.push(dir) | ||
116 | } | ||
117 | fn popd(&mut self) { | ||
118 | self.pushd_stack.pop().unwrap(); | ||
119 | } | ||
120 | fn cwd(&self) -> PathBuf { | ||
121 | self.pushd_stack.last().cloned().unwrap_or_else(|| env::current_dir().unwrap()) | ||
122 | } | ||
123 | } | ||
diff --git a/xtask/src/pre_commit.rs b/xtask/src/pre_commit.rs index 1533f64dc..056f34acf 100644 --- a/xtask/src/pre_commit.rs +++ b/xtask/src/pre_commit.rs | |||
@@ -4,18 +4,18 @@ use std::{fs, path::PathBuf}; | |||
4 | 4 | ||
5 | use anyhow::{bail, Result}; | 5 | use anyhow::{bail, Result}; |
6 | 6 | ||
7 | use crate::{cmd::run_with_output, project_root, run, run_rustfmt, Mode}; | 7 | use crate::{not_bash::run, project_root, run_rustfmt, Mode}; |
8 | 8 | ||
9 | // FIXME: if there are changed `.ts` files, also reformat TypeScript (by | 9 | // FIXME: if there are changed `.ts` files, also reformat TypeScript (by |
10 | // shelling out to `npm fmt`). | 10 | // shelling out to `npm fmt`). |
11 | pub fn run_hook() -> Result<()> { | 11 | pub fn run_hook() -> Result<()> { |
12 | run_rustfmt(Mode::Overwrite)?; | 12 | run_rustfmt(Mode::Overwrite)?; |
13 | 13 | ||
14 | let diff = run_with_output("git diff --diff-filter=MAR --name-only --cached", ".")?; | 14 | let diff = run!("git diff --diff-filter=MAR --name-only --cached")?; |
15 | 15 | ||
16 | let root = project_root(); | 16 | let root = project_root(); |
17 | for line in diff.lines() { | 17 | for line in diff.lines() { |
18 | run(&format!("git update-index --add {}", root.join(line).to_string_lossy()), ".")?; | 18 | run!("git update-index --add {}", root.join(line).display())?; |
19 | } | 19 | } |
20 | 20 | ||
21 | Ok(()) | 21 | Ok(()) |