diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/Cargo.toml | 2 | ||||
-rw-r--r-- | xtask/src/codegen.rs | 21 | ||||
-rw-r--r-- | xtask/src/codegen/gen_assists_docs.rs | 2 | ||||
-rw-r--r-- | xtask/src/codegen/gen_features.rs | 12 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 15 | ||||
-rw-r--r-- | xtask/src/dist.rs | 33 | ||||
-rw-r--r-- | xtask/src/install.rs | 46 | ||||
-rw-r--r-- | xtask/src/lib.rs | 52 | ||||
-rw-r--r-- | xtask/src/main.rs | 4 | ||||
-rw-r--r-- | xtask/src/metrics.rs | 39 | ||||
-rw-r--r-- | xtask/src/not_bash.rs | 169 | ||||
-rw-r--r-- | xtask/src/pre_cache.rs | 5 | ||||
-rw-r--r-- | xtask/src/pre_commit.rs | 8 | ||||
-rw-r--r-- | xtask/src/release.rs | 60 | ||||
-rw-r--r-- | xtask/tests/tidy.rs | 36 |
15 files changed, 177 insertions, 327 deletions
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 01a838825..2ef956485 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -18,5 +18,5 @@ quote = "1.0.2" | |||
18 | ungrammar = "1.1.3" | 18 | ungrammar = "1.1.3" |
19 | walkdir = "2.3.1" | 19 | walkdir = "2.3.1" |
20 | write-json = "0.1.0" | 20 | write-json = "0.1.0" |
21 | fs-err = "2.3" | 21 | xshell = "0.1" |
22 | # Avoid adding more dependencies to this crate | 22 | # Avoid adding more dependencies to this crate |
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 45b17bb48..3ee4c1adf 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs | |||
@@ -15,12 +15,9 @@ use std::{ | |||
15 | fmt, mem, | 15 | fmt, mem, |
16 | path::{Path, PathBuf}, | 16 | path::{Path, PathBuf}, |
17 | }; | 17 | }; |
18 | use xshell::{cmd, pushenv, read_file, write_file}; | ||
18 | 19 | ||
19 | use crate::{ | 20 | use crate::{ensure_rustfmt, project_root, Result}; |
20 | ensure_rustfmt, | ||
21 | not_bash::{fs2, pushenv, run}, | ||
22 | project_root, Result, | ||
23 | }; | ||
24 | 21 | ||
25 | pub use self::{ | 22 | pub use self::{ |
26 | gen_assists_docs::{generate_assists_docs, generate_assists_tests}, | 23 | gen_assists_docs::{generate_assists_docs, generate_assists_tests}, |
@@ -57,7 +54,7 @@ impl CodegenCmd { | |||
57 | /// A helper to update file on disk if it has changed. | 54 | /// A helper to update file on disk if it has changed. |
58 | /// With verify = false, | 55 | /// With verify = false, |
59 | fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { | 56 | fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { |
60 | match fs2::read_to_string(path) { | 57 | match read_file(path) { |
61 | Ok(old_contents) if normalize(&old_contents) == normalize(contents) => { | 58 | Ok(old_contents) if normalize(&old_contents) == normalize(contents) => { |
62 | return Ok(()); | 59 | return Ok(()); |
63 | } | 60 | } |
@@ -67,7 +64,7 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { | |||
67 | anyhow::bail!("`{}` is not up-to-date", path.display()); | 64 | anyhow::bail!("`{}` is not up-to-date", path.display()); |
68 | } | 65 | } |
69 | eprintln!("updating {}", path.display()); | 66 | eprintln!("updating {}", path.display()); |
70 | fs2::write(path, contents)?; | 67 | write_file(path, contents)?; |
71 | return Ok(()); | 68 | return Ok(()); |
72 | 69 | ||
73 | fn normalize(s: &str) -> String { | 70 | fn normalize(s: &str) -> String { |
@@ -77,13 +74,13 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> { | |||
77 | 74 | ||
78 | const PREAMBLE: &str = "Generated file, do not edit by hand, see `xtask/src/codegen`"; | 75 | const PREAMBLE: &str = "Generated file, do not edit by hand, see `xtask/src/codegen`"; |
79 | 76 | ||
80 | fn reformat(text: impl std::fmt::Display) -> Result<String> { | 77 | fn reformat(text: &str) -> Result<String> { |
81 | let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); | 78 | let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); |
82 | ensure_rustfmt()?; | 79 | ensure_rustfmt()?; |
83 | let stdout = run!( | 80 | let rustfmt_toml = project_root().join("rustfmt.toml"); |
84 | "rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display(); | 81 | let stdout = cmd!("rustfmt --config-path {rustfmt_toml} --config fn_single_line=true") |
85 | <text.to_string().as_bytes() | 82 | .stdin(text) |
86 | )?; | 83 | .read()?; |
87 | Ok(format!("//! {}\n\n{}\n", PREAMBLE, stdout)) | 84 | Ok(format!("//! {}\n\n{}\n", PREAMBLE, stdout)) |
88 | } | 85 | } |
89 | 86 | ||
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index f0ded8b87..ff307e2aa 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -134,7 +134,7 @@ r#####" | |||
134 | 134 | ||
135 | buf.push_str(&test) | 135 | buf.push_str(&test) |
136 | } | 136 | } |
137 | let buf = reformat(buf)?; | 137 | let buf = reformat(&buf.to_string())?; |
138 | codegen::update(&project_root().join("crates/assists/src/tests/generated.rs"), &buf, mode) | 138 | codegen::update(&project_root().join("crates/assists/src/tests/generated.rs"), &buf, mode) |
139 | } | 139 | } |
140 | 140 | ||
diff --git a/xtask/src/codegen/gen_features.rs b/xtask/src/codegen/gen_features.rs index 78268308b..3cf15ce02 100644 --- a/xtask/src/codegen/gen_features.rs +++ b/xtask/src/codegen/gen_features.rs | |||
@@ -3,15 +3,13 @@ use std::path::{Path, PathBuf}; | |||
3 | 3 | ||
4 | use quote::quote; | 4 | use quote::quote; |
5 | use walkdir::WalkDir; | 5 | use walkdir::WalkDir; |
6 | use xshell::{cmd, read_file}; | ||
6 | 7 | ||
7 | use crate::{ | 8 | use crate::codegen::{project_root, reformat, update, Mode, Result}; |
8 | codegen::{project_root, reformat, update, Mode, Result}, | ||
9 | not_bash::{fs2, run}, | ||
10 | }; | ||
11 | 9 | ||
12 | pub fn generate_features(mode: Mode) -> Result<()> { | 10 | pub fn generate_features(mode: Mode) -> Result<()> { |
13 | if !Path::new("./target/rust").exists() { | 11 | if !Path::new("./target/rust").exists() { |
14 | run!("git clone https://github.com/rust-lang/rust ./target/rust")?; | 12 | cmd!("git clone https://github.com/rust-lang/rust ./target/rust").run()?; |
15 | } | 13 | } |
16 | 14 | ||
17 | let contents = generate_descriptor("./target/rust/src/doc/unstable-book/src".into())?; | 15 | let contents = generate_descriptor("./target/rust/src/doc/unstable-book/src".into())?; |
@@ -34,7 +32,7 @@ fn generate_descriptor(src_dir: PathBuf) -> Result<String> { | |||
34 | .map(|entry| { | 32 | .map(|entry| { |
35 | let path = entry.path(); | 33 | let path = entry.path(); |
36 | let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_"); | 34 | let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_"); |
37 | let doc = fs2::read_to_string(path).unwrap(); | 35 | let doc = read_file(path).unwrap(); |
38 | 36 | ||
39 | quote! { LintCompletion { label: #feature_ident, description: #doc } } | 37 | quote! { LintCompletion { label: #feature_ident, description: #doc } } |
40 | }); | 38 | }); |
@@ -46,5 +44,5 @@ fn generate_descriptor(src_dir: PathBuf) -> Result<String> { | |||
46 | #(#definitions),* | 44 | #(#definitions),* |
47 | ]; | 45 | ]; |
48 | }; | 46 | }; |
49 | reformat(ts) | 47 | reformat(&ts.to_string()) |
50 | } | 48 | } |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 733493fef..02f4095ce 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -61,10 +61,13 @@ fn generate_tokens(grammar: &AstSrc) -> Result<String> { | |||
61 | } | 61 | } |
62 | }); | 62 | }); |
63 | 63 | ||
64 | let pretty = reformat(quote! { | 64 | let pretty = reformat( |
65 | use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; | 65 | "e! { |
66 | #(#tokens)* | 66 | use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken}; |
67 | })? | 67 | #(#tokens)* |
68 | } | ||
69 | .to_string(), | ||
70 | )? | ||
68 | .replace("#[derive", "\n#[derive"); | 71 | .replace("#[derive", "\n#[derive"); |
69 | Ok(pretty) | 72 | Ok(pretty) |
70 | } | 73 | } |
@@ -261,7 +264,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
261 | } | 264 | } |
262 | } | 265 | } |
263 | 266 | ||
264 | let pretty = reformat(res)?; | 267 | let pretty = reformat(&res)?; |
265 | Ok(pretty) | 268 | Ok(pretty) |
266 | } | 269 | } |
267 | 270 | ||
@@ -383,7 +386,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
383 | } | 386 | } |
384 | }; | 387 | }; |
385 | 388 | ||
386 | reformat(ast) | 389 | reformat(&ast.to_string()) |
387 | } | 390 | } |
388 | 391 | ||
389 | fn to_upper_snake_case(s: &str) -> String { | 392 | fn to_upper_snake_case(s: &str) -> String { |
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs index aa7d94967..9e15a5a4c 100644 --- a/xtask/src/dist.rs +++ b/xtask/src/dist.rs | |||
@@ -1,4 +1,3 @@ | |||
1 | use flate2::{write::GzEncoder, Compression}; | ||
2 | use std::{ | 1 | use std::{ |
3 | env, | 2 | env, |
4 | fs::File, | 3 | fs::File, |
@@ -7,11 +6,10 @@ use std::{ | |||
7 | }; | 6 | }; |
8 | 7 | ||
9 | use anyhow::Result; | 8 | use anyhow::Result; |
9 | use flate2::{write::GzEncoder, Compression}; | ||
10 | use xshell::{cmd, cp, mkdir_p, pushd, read_file, rm_rf, write_file}; | ||
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{date_iso, project_root}; |
12 | not_bash::{date_iso, fs2, pushd, rm_rf, run}, | ||
13 | project_root, | ||
14 | }; | ||
15 | 13 | ||
16 | pub struct DistCmd { | 14 | pub struct DistCmd { |
17 | pub nightly: bool, | 15 | pub nightly: bool, |
@@ -22,7 +20,7 @@ impl DistCmd { | |||
22 | pub fn run(self) -> Result<()> { | 20 | pub fn run(self) -> Result<()> { |
23 | let dist = project_root().join("dist"); | 21 | let dist = project_root().join("dist"); |
24 | rm_rf(&dist)?; | 22 | rm_rf(&dist)?; |
25 | fs2::create_dir_all(&dist)?; | 23 | mkdir_p(&dist)?; |
26 | 24 | ||
27 | if let Some(version) = self.client_version { | 25 | if let Some(version) = self.client_version { |
28 | let release_tag = if self.nightly { "nightly".to_string() } else { date_iso()? }; | 26 | let release_tag = if self.nightly { "nightly".to_string() } else { date_iso()? }; |
@@ -34,7 +32,7 @@ impl DistCmd { | |||
34 | } | 32 | } |
35 | 33 | ||
36 | fn dist_client(version: &str, release_tag: &str) -> Result<()> { | 34 | fn dist_client(version: &str, release_tag: &str) -> Result<()> { |
37 | let _d = pushd("./editors/code"); | 35 | let _d = pushd("./editors/code")?; |
38 | let nightly = release_tag == "nightly"; | 36 | let nightly = release_tag == "nightly"; |
39 | 37 | ||
40 | let mut patch = Patch::new("./package.json")?; | 38 | let mut patch = Patch::new("./package.json")?; |
@@ -54,20 +52,16 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> { | |||
54 | } | 52 | } |
55 | patch.commit()?; | 53 | patch.commit()?; |
56 | 54 | ||
57 | run!("npm ci")?; | 55 | cmd!("npm ci").run()?; |
58 | run!("npx vsce package -o ../../dist/rust-analyzer.vsix")?; | 56 | cmd!("npx vsce package -o ../../dist/rust-analyzer.vsix").run()?; |
59 | Ok(()) | 57 | Ok(()) |
60 | } | 58 | } |
61 | 59 | ||
62 | fn dist_server() -> Result<()> { | 60 | fn dist_server() -> Result<()> { |
63 | if cfg!(target_os = "linux") { | 61 | if cfg!(target_os = "linux") { |
64 | env::set_var("CC", "clang"); | 62 | env::set_var("CC", "clang"); |
65 | run!( | ||
66 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" | ||
67 | )?; | ||
68 | } else { | ||
69 | run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; | ||
70 | } | 63 | } |
64 | cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release").run()?; | ||
71 | 65 | ||
72 | let (src, dst) = if cfg!(target_os = "linux") { | 66 | let (src, dst) = if cfg!(target_os = "linux") { |
73 | ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux") | 67 | ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux") |
@@ -82,7 +76,7 @@ fn dist_server() -> Result<()> { | |||
82 | let src = Path::new(src); | 76 | let src = Path::new(src); |
83 | let dst = Path::new(dst); | 77 | let dst = Path::new(dst); |
84 | 78 | ||
85 | fs2::copy(&src, &dst)?; | 79 | cp(&src, &dst)?; |
86 | gzip(&src, &dst.with_extension("gz"))?; | 80 | gzip(&src, &dst.with_extension("gz"))?; |
87 | 81 | ||
88 | Ok(()) | 82 | Ok(()) |
@@ -105,7 +99,7 @@ struct Patch { | |||
105 | impl Patch { | 99 | impl Patch { |
106 | fn new(path: impl Into<PathBuf>) -> Result<Patch> { | 100 | fn new(path: impl Into<PathBuf>) -> Result<Patch> { |
107 | let path = path.into(); | 101 | let path = path.into(); |
108 | let contents = fs2::read_to_string(&path)?; | 102 | let contents = read_file(&path)?; |
109 | Ok(Patch { path, original_contents: contents.clone(), contents }) | 103 | Ok(Patch { path, original_contents: contents.clone(), contents }) |
110 | } | 104 | } |
111 | 105 | ||
@@ -115,13 +109,14 @@ impl Patch { | |||
115 | self | 109 | self |
116 | } | 110 | } |
117 | 111 | ||
118 | fn commit(&self) -> io::Result<()> { | 112 | fn commit(&self) -> Result<()> { |
119 | fs2::write(&self.path, &self.contents) | 113 | write_file(&self.path, &self.contents)?; |
114 | Ok(()) | ||
120 | } | 115 | } |
121 | } | 116 | } |
122 | 117 | ||
123 | impl Drop for Patch { | 118 | impl Drop for Patch { |
124 | fn drop(&mut self) { | 119 | fn drop(&mut self) { |
125 | fs2::write(&self.path, &self.original_contents).unwrap(); | 120 | write_file(&self.path, &self.original_contents).unwrap(); |
126 | } | 121 | } |
127 | } | 122 | } |
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index fcc4f05e4..789e9f27b 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -3,8 +3,7 @@ | |||
3 | use std::{env, path::PathBuf, str}; | 3 | use std::{env, path::PathBuf, str}; |
4 | 4 | ||
5 | use anyhow::{bail, format_err, Context, Result}; | 5 | use anyhow::{bail, format_err, Context, Result}; |
6 | 6 | use xshell::{cmd, pushd}; | |
7 | use crate::not_bash::{pushd, run}; | ||
8 | 7 | ||
9 | // Latest stable, feel free to send a PR if this lags behind. | 8 | // Latest stable, feel free to send a PR if this lags behind. |
10 | const REQUIRED_RUST_VERSION: u32 = 47; | 9 | const REQUIRED_RUST_VERSION: u32 = 47; |
@@ -76,7 +75,7 @@ fn fix_path_for_mac() -> Result<()> { | |||
76 | } | 75 | } |
77 | 76 | ||
78 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | 77 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { |
79 | let _dir = pushd("./editors/code"); | 78 | let _dir = pushd("./editors/code")?; |
80 | 79 | ||
81 | let find_code = |f: fn(&str) -> bool| -> Result<&'static str> { | 80 | let find_code = |f: fn(&str) -> bool| -> Result<&'static str> { |
82 | ["code", "code-insiders", "codium", "code-oss"] | 81 | ["code", "code-insiders", "codium", "code-oss"] |
@@ -89,24 +88,25 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | |||
89 | }; | 88 | }; |
90 | 89 | ||
91 | let installed_extensions = if cfg!(unix) { | 90 | let installed_extensions = if cfg!(unix) { |
92 | run!("npm --version").context("`npm` is required to build the VS Code plugin")?; | 91 | cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?; |
93 | run!("npm install")?; | 92 | cmd!("npm install").run()?; |
94 | 93 | ||
95 | run!("npm run package --scripts-prepend-node-path")?; | 94 | cmd!("npm run package --scripts-prepend-node-path").run()?; |
96 | 95 | ||
97 | let code = find_code(|bin| run!("{} --version", bin).is_ok())?; | 96 | let code = find_code(|bin| cmd!("{bin} --version").read().is_ok())?; |
98 | run!("{} --install-extension rust-analyzer.vsix --force", code)?; | 97 | cmd!("{code} --install-extension rust-analyzer.vsix --force").run()?; |
99 | run!("{} --list-extensions", code; echo = false)? | 98 | cmd!("{code} --list-extensions").read()? |
100 | } else { | 99 | } else { |
101 | run!("cmd.exe /c npm --version") | 100 | cmd!("cmd.exe /c npm --version") |
101 | .run() | ||
102 | .context("`npm` is required to build the VS Code plugin")?; | 102 | .context("`npm` is required to build the VS Code plugin")?; |
103 | run!("cmd.exe /c npm install")?; | 103 | cmd!("cmd.exe /c npm install").run()?; |
104 | 104 | ||
105 | run!("cmd.exe /c npm run package")?; | 105 | cmd!("cmd.exe /c npm run package").run()?; |
106 | 106 | ||
107 | let code = find_code(|bin| run!("cmd.exe /c {}.cmd --version", bin).is_ok())?; | 107 | let code = find_code(|bin| cmd!("cmd.exe /c {bin}.cmd --version").read().is_ok())?; |
108 | run!(r"cmd.exe /c {}.cmd --install-extension rust-analyzer.vsix --force", code)?; | 108 | cmd!("cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?; |
109 | run!("cmd.exe /c {}.cmd --list-extensions", code; echo = false)? | 109 | cmd!("cmd.exe /c {code}.cmd --list-extensions").read()? |
110 | }; | 110 | }; |
111 | 111 | ||
112 | if !installed_extensions.contains("rust-analyzer") { | 112 | if !installed_extensions.contains("rust-analyzer") { |
@@ -122,7 +122,7 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | |||
122 | 122 | ||
123 | fn install_server(opts: ServerOpt) -> Result<()> { | 123 | fn install_server(opts: ServerOpt) -> Result<()> { |
124 | let mut old_rust = false; | 124 | let mut old_rust = false; |
125 | if let Ok(stdout) = run!("cargo --version") { | 125 | if let Ok(stdout) = cmd!("cargo --version").read() { |
126 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { | 126 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { |
127 | old_rust = true; | 127 | old_rust = true; |
128 | } | 128 | } |
@@ -134,12 +134,13 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
134 | REQUIRED_RUST_VERSION, | 134 | REQUIRED_RUST_VERSION, |
135 | ) | 135 | ) |
136 | } | 136 | } |
137 | 137 | let features = match opts.malloc { | |
138 | let malloc_feature = match opts.malloc { | 138 | Malloc::System => &[][..], |
139 | Malloc::System => "", | 139 | Malloc::Mimalloc => &["--features", "mimalloc"], |
140 | Malloc::Mimalloc => "--features mimalloc", | ||
141 | }; | 140 | }; |
142 | let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", malloc_feature); | 141 | |
142 | let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force {features...}"); | ||
143 | let res = cmd.run(); | ||
143 | 144 | ||
144 | if res.is_err() && old_rust { | 145 | if res.is_err() && old_rust { |
145 | eprintln!( | 146 | eprintln!( |
@@ -148,7 +149,8 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
148 | ); | 149 | ); |
149 | } | 150 | } |
150 | 151 | ||
151 | res.map(drop) | 152 | res?; |
153 | Ok(()) | ||
152 | } | 154 | } |
153 | 155 | ||
154 | fn check_version(version_output: &str, min_minor_version: u32) -> bool { | 156 | fn check_version(version_output: &str, min_minor_version: u32) -> bool { |
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index e790d995f..babec2dbd 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs | |||
@@ -2,7 +2,6 @@ | |||
2 | //! | 2 | //! |
3 | //! See https://github.com/matklad/cargo-xtask/ | 3 | //! See https://github.com/matklad/cargo-xtask/ |
4 | 4 | ||
5 | pub mod not_bash; | ||
6 | pub mod codegen; | 5 | pub mod codegen; |
7 | mod ast_src; | 6 | mod ast_src; |
8 | 7 | ||
@@ -19,11 +18,9 @@ use std::{ | |||
19 | }; | 18 | }; |
20 | 19 | ||
21 | use walkdir::{DirEntry, WalkDir}; | 20 | use walkdir::{DirEntry, WalkDir}; |
21 | use xshell::{cmd, pushd, pushenv}; | ||
22 | 22 | ||
23 | use crate::{ | 23 | use crate::codegen::Mode; |
24 | codegen::Mode, | ||
25 | not_bash::{pushd, pushenv}, | ||
26 | }; | ||
27 | 24 | ||
28 | pub use anyhow::{bail, Context as _, Result}; | 25 | pub use anyhow::{bail, Context as _, Result}; |
29 | 26 | ||
@@ -53,18 +50,19 @@ pub fn rust_files(path: &Path) -> impl Iterator<Item = PathBuf> { | |||
53 | } | 50 | } |
54 | 51 | ||
55 | pub fn run_rustfmt(mode: Mode) -> Result<()> { | 52 | pub fn run_rustfmt(mode: Mode) -> Result<()> { |
56 | let _dir = pushd(project_root()); | 53 | let _dir = pushd(project_root())?; |
57 | let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); | 54 | let _e = pushenv("RUSTUP_TOOLCHAIN", "stable"); |
58 | ensure_rustfmt()?; | 55 | ensure_rustfmt()?; |
59 | match mode { | 56 | let check = match mode { |
60 | Mode::Overwrite => run!("cargo fmt"), | 57 | Mode::Overwrite => &[][..], |
61 | Mode::Verify => run!("cargo fmt -- --check"), | 58 | Mode::Verify => &["--", "--check"], |
62 | }?; | 59 | }; |
60 | cmd!("cargo fmt {check...}").run()?; | ||
63 | Ok(()) | 61 | Ok(()) |
64 | } | 62 | } |
65 | 63 | ||
66 | fn ensure_rustfmt() -> Result<()> { | 64 | fn ensure_rustfmt() -> Result<()> { |
67 | let out = run!("rustfmt --version")?; | 65 | let out = cmd!("rustfmt --version").read()?; |
68 | if !out.contains("stable") { | 66 | if !out.contains("stable") { |
69 | bail!( | 67 | bail!( |
70 | "Failed to run rustfmt from toolchain 'stable'. \ | 68 | "Failed to run rustfmt from toolchain 'stable'. \ |
@@ -75,40 +73,46 @@ fn ensure_rustfmt() -> Result<()> { | |||
75 | } | 73 | } |
76 | 74 | ||
77 | pub fn run_clippy() -> Result<()> { | 75 | pub fn run_clippy() -> Result<()> { |
78 | if run!("cargo clippy --version").is_err() { | 76 | if cmd!("cargo clippy --version").read().is_err() { |
79 | bail!( | 77 | bail!( |
80 | "Failed run cargo clippy. \ | 78 | "Failed run cargo clippy. \ |
81 | Please run `rustup component add clippy` to install it.", | 79 | Please run `rustup component add clippy` to install it.", |
82 | ) | 80 | ) |
83 | } | 81 | } |
84 | 82 | ||
85 | let allowed_lints = [ | 83 | let allowed_lints = " |
86 | "clippy::collapsible_if", | 84 | -A clippy::collapsible_if |
87 | "clippy::needless_pass_by_value", | 85 | -A clippy::needless_pass_by_value |
88 | "clippy::nonminimal_bool", | 86 | -A clippy::nonminimal_bool |
89 | "clippy::redundant_pattern_matching", | 87 | -A clippy::redundant_pattern_matching |
90 | ]; | 88 | " |
91 | run!("cargo clippy --all-features --all-targets -- -A {}", allowed_lints.join(" -A "))?; | 89 | .split_ascii_whitespace(); |
90 | cmd!("cargo clippy --all-features --all-targets -- {allowed_lints...}").run()?; | ||
92 | Ok(()) | 91 | Ok(()) |
93 | } | 92 | } |
94 | 93 | ||
95 | pub fn run_fuzzer() -> Result<()> { | 94 | pub fn run_fuzzer() -> Result<()> { |
96 | let _d = pushd("./crates/syntax"); | 95 | let _d = pushd("./crates/syntax")?; |
97 | let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly"); | 96 | let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly"); |
98 | if run!("cargo fuzz --help").is_err() { | 97 | if cmd!("cargo fuzz --help").read().is_err() { |
99 | run!("cargo install cargo-fuzz")?; | 98 | cmd!("cargo install cargo-fuzz").run()?; |
100 | }; | 99 | }; |
101 | 100 | ||
102 | // Expecting nightly rustc | 101 | // Expecting nightly rustc |
103 | let out = run!("rustc --version")?; | 102 | let out = cmd!("rustc --version").read()?; |
104 | if !out.contains("nightly") { | 103 | if !out.contains("nightly") { |
105 | bail!("fuzz tests require nightly rustc") | 104 | bail!("fuzz tests require nightly rustc") |
106 | } | 105 | } |
107 | 106 | ||
108 | run!("cargo fuzz run parser")?; | 107 | cmd!("cargo fuzz run parser").run()?; |
109 | Ok(()) | 108 | Ok(()) |
110 | } | 109 | } |
111 | 110 | ||
111 | fn date_iso() -> Result<String> { | ||
112 | let res = cmd!("date --iso --utc").read()?; | ||
113 | Ok(res) | ||
114 | } | ||
115 | |||
112 | fn is_release_tag(tag: &str) -> bool { | 116 | fn is_release_tag(tag: &str) -> bool { |
113 | tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit()) | 117 | tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit()) |
114 | } | 118 | } |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 3f4aa5497..97e5dcd4e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -12,12 +12,12 @@ use std::env; | |||
12 | 12 | ||
13 | use codegen::CodegenCmd; | 13 | use codegen::CodegenCmd; |
14 | use pico_args::Arguments; | 14 | use pico_args::Arguments; |
15 | use xshell::pushd; | ||
15 | use xtask::{ | 16 | use xtask::{ |
16 | codegen::{self, Mode}, | 17 | codegen::{self, Mode}, |
17 | dist::DistCmd, | 18 | dist::DistCmd, |
18 | install::{ClientOpt, InstallCmd, Malloc, ServerOpt}, | 19 | install::{ClientOpt, InstallCmd, Malloc, ServerOpt}, |
19 | metrics::MetricsCmd, | 20 | metrics::MetricsCmd, |
20 | not_bash::pushd, | ||
21 | pre_cache::PreCacheCmd, | 21 | pre_cache::PreCacheCmd, |
22 | pre_commit, project_root, | 22 | pre_commit, project_root, |
23 | release::{PromoteCmd, ReleaseCmd}, | 23 | release::{PromoteCmd, ReleaseCmd}, |
@@ -29,7 +29,7 @@ fn main() -> Result<()> { | |||
29 | return pre_commit::run_hook(); | 29 | return pre_commit::run_hook(); |
30 | } | 30 | } |
31 | 31 | ||
32 | let _d = pushd(project_root()); | 32 | let _d = pushd(project_root())?; |
33 | 33 | ||
34 | let mut args = Arguments::from_env(); | 34 | let mut args = Arguments::from_env(); |
35 | let subcommand = args.subcommand()?.unwrap_or_default(); | 35 | let subcommand = args.subcommand()?.unwrap_or_default(); |
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 4bade2c7e..e0d1aaf97 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs | |||
@@ -7,8 +7,7 @@ use std::{ | |||
7 | }; | 7 | }; |
8 | 8 | ||
9 | use anyhow::{bail, format_err, Result}; | 9 | use anyhow::{bail, format_err, Result}; |
10 | 10 | use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf}; | |
11 | use crate::not_bash::{fs2, pushd, pushenv, rm_rf, run}; | ||
12 | 11 | ||
13 | type Unit = String; | 12 | type Unit = String; |
14 | 13 | ||
@@ -23,12 +22,13 @@ impl MetricsCmd { | |||
23 | rm_rf("./target/release")?; | 22 | rm_rf("./target/release")?; |
24 | } | 23 | } |
25 | if !Path::new("./target/rustc-perf").exists() { | 24 | if !Path::new("./target/rustc-perf").exists() { |
26 | fs2::create_dir_all("./target/rustc-perf")?; | 25 | mkdir_p("./target/rustc-perf")?; |
27 | run!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")?; | 26 | cmd!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf") |
27 | .run()?; | ||
28 | } | 28 | } |
29 | { | 29 | { |
30 | let _d = pushd("./target/rustc-perf"); | 30 | let _d = pushd("./target/rustc-perf")?; |
31 | run!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033")?; | 31 | cmd!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033").run()?; |
32 | } | 32 | } |
33 | 33 | ||
34 | let _env = pushenv("RA_METRICS", "1"); | 34 | let _env = pushenv("RA_METRICS", "1"); |
@@ -39,17 +39,20 @@ impl MetricsCmd { | |||
39 | metrics.measure_analysis_stats("webrender")?; | 39 | metrics.measure_analysis_stats("webrender")?; |
40 | 40 | ||
41 | if !self.dry_run { | 41 | if !self.dry_run { |
42 | let _d = pushd("target"); | 42 | let _d = pushd("target")?; |
43 | let metrics_token = env::var("METRICS_TOKEN").unwrap(); | 43 | let metrics_token = env::var("METRICS_TOKEN").unwrap(); |
44 | let repo = format!("https://{}@github.com/rust-analyzer/metrics.git", metrics_token); | 44 | cmd!( |
45 | run!("git clone --depth 1 {}", repo)?; | 45 | "git clone --depth 1 https://{metrics_token}@github.com/rust-analyzer/metrics.git" |
46 | let _d = pushd("metrics"); | 46 | ) |
47 | .run()?; | ||
48 | let _d = pushd("metrics")?; | ||
47 | 49 | ||
48 | let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?; | 50 | let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?; |
49 | writeln!(file, "{}", metrics.json())?; | 51 | writeln!(file, "{}", metrics.json())?; |
50 | run!("git add .")?; | 52 | cmd!("git add .").run()?; |
51 | run!("git -c user.name=Bot -c [email protected] commit --message 📈")?; | 53 | cmd!("git -c user.name=Bot -c [email protected] commit --message 📈") |
52 | run!("git push origin master")?; | 54 | .run()?; |
55 | cmd!("git push origin master").run()?; | ||
53 | } | 56 | } |
54 | eprintln!("{:#?}", metrics); | 57 | eprintln!("{:#?}", metrics); |
55 | Ok(()) | 58 | Ok(()) |
@@ -59,10 +62,10 @@ impl MetricsCmd { | |||
59 | impl Metrics { | 62 | impl Metrics { |
60 | fn measure_build(&mut self) -> Result<()> { | 63 | fn measure_build(&mut self) -> Result<()> { |
61 | eprintln!("\nMeasuring build"); | 64 | eprintln!("\nMeasuring build"); |
62 | run!("cargo fetch")?; | 65 | cmd!("cargo fetch").run()?; |
63 | 66 | ||
64 | let time = Instant::now(); | 67 | let time = Instant::now(); |
65 | run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?; | 68 | cmd!("cargo build --release --package rust-analyzer --bin rust-analyzer").run()?; |
66 | let time = time.elapsed(); | 69 | let time = time.elapsed(); |
67 | self.report("build", time.as_millis() as u64, "ms".into()); | 70 | self.report("build", time.as_millis() as u64, "ms".into()); |
68 | Ok(()) | 71 | Ok(()) |
@@ -78,7 +81,7 @@ impl Metrics { | |||
78 | } | 81 | } |
79 | fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> { | 82 | fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> { |
80 | eprintln!("\nMeasuring analysis-stats/{}", name); | 83 | eprintln!("\nMeasuring analysis-stats/{}", name); |
81 | let output = run!("./target/release/rust-analyzer analysis-stats --quiet {}", path)?; | 84 | let output = cmd!("./target/release/rust-analyzer analysis-stats --quiet {path}").read()?; |
82 | for (metric, value, unit) in parse_metrics(&output) { | 85 | for (metric, value, unit) in parse_metrics(&output) { |
83 | self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into()); | 86 | self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into()); |
84 | } | 87 | } |
@@ -118,7 +121,7 @@ impl Metrics { | |||
118 | fn new() -> Result<Metrics> { | 121 | fn new() -> Result<Metrics> { |
119 | let host = Host::new()?; | 122 | let host = Host::new()?; |
120 | let timestamp = SystemTime::now(); | 123 | let timestamp = SystemTime::now(); |
121 | let revision = run!("git rev-parse HEAD")?; | 124 | let revision = cmd!("git rev-parse HEAD").read()?; |
122 | Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() }) | 125 | Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() }) |
123 | } | 126 | } |
124 | 127 | ||
@@ -160,7 +163,7 @@ impl Host { | |||
160 | return Ok(Host { os, cpu, mem }); | 163 | return Ok(Host { os, cpu, mem }); |
161 | 164 | ||
162 | fn read_field<'a>(path: &str, field: &str) -> Result<String> { | 165 | fn read_field<'a>(path: &str, field: &str) -> Result<String> { |
163 | let text = fs2::read_to_string(path)?; | 166 | let text = read_file(path)?; |
164 | 167 | ||
165 | let line = text | 168 | let line = text |
166 | .lines() | 169 | .lines() |
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs deleted file mode 100644 index 038898993..000000000 --- a/xtask/src/not_bash.rs +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | //! A bad shell -- small cross platform module for writing glue code | ||
2 | |||
3 | use std::{ | ||
4 | cell::RefCell, | ||
5 | env, | ||
6 | ffi::OsString, | ||
7 | io::{self, Write}, | ||
8 | path::{Path, PathBuf}, | ||
9 | process::{Command, Stdio}, | ||
10 | }; | ||
11 | |||
12 | use anyhow::{bail, Context, Result}; | ||
13 | |||
14 | pub use fs_err as fs2; | ||
15 | |||
16 | #[macro_export] | ||
17 | macro_rules! run { | ||
18 | ($($expr:expr),*) => { | ||
19 | run!($($expr),*; echo = true) | ||
20 | }; | ||
21 | ($($expr:expr),* ; echo = $echo:expr) => { | ||
22 | $crate::not_bash::run_process(format!($($expr),*), $echo, None) | ||
23 | }; | ||
24 | ($($expr:expr),* ; <$stdin:expr) => { | ||
25 | $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) | ||
26 | }; | ||
27 | } | ||
28 | pub use crate::run; | ||
29 | |||
30 | pub struct Pushd { | ||
31 | _p: (), | ||
32 | } | ||
33 | |||
34 | pub fn pushd(path: impl Into<PathBuf>) -> Pushd { | ||
35 | Env::with(|env| env.pushd(path.into())); | ||
36 | Pushd { _p: () } | ||
37 | } | ||
38 | |||
39 | impl Drop for Pushd { | ||
40 | fn drop(&mut self) { | ||
41 | Env::with(|env| env.popd()) | ||
42 | } | ||
43 | } | ||
44 | |||
45 | pub struct Pushenv { | ||
46 | _p: (), | ||
47 | } | ||
48 | |||
49 | pub fn pushenv(var: &str, value: &str) -> Pushenv { | ||
50 | Env::with(|env| env.pushenv(var.into(), value.into())); | ||
51 | Pushenv { _p: () } | ||
52 | } | ||
53 | |||
54 | impl Drop for Pushenv { | ||
55 | fn drop(&mut self) { | ||
56 | Env::with(|env| env.popenv()) | ||
57 | } | ||
58 | } | ||
59 | |||
60 | pub fn rm_rf(path: impl AsRef<Path>) -> io::Result<()> { | ||
61 | let path = path.as_ref(); | ||
62 | if !path.exists() { | ||
63 | return Ok(()); | ||
64 | } | ||
65 | if path.is_file() { | ||
66 | fs2::remove_file(path) | ||
67 | } else { | ||
68 | fs2::remove_dir_all(path) | ||
69 | } | ||
70 | } | ||
71 | |||
72 | #[doc(hidden)] | ||
73 | pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> { | ||
74 | run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd)) | ||
75 | } | ||
76 | |||
77 | pub fn date_iso() -> Result<String> { | ||
78 | run!("date --iso --utc") | ||
79 | } | ||
80 | |||
81 | fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> { | ||
82 | let mut args = shelx(cmd); | ||
83 | let binary = args.remove(0); | ||
84 | let current_dir = Env::with(|it| it.cwd().to_path_buf()); | ||
85 | |||
86 | if echo { | ||
87 | println!("> {}", cmd) | ||
88 | } | ||
89 | |||
90 | let mut command = Command::new(binary); | ||
91 | command.args(args).current_dir(current_dir).stderr(Stdio::inherit()); | ||
92 | let output = match stdin { | ||
93 | None => command.stdin(Stdio::null()).output(), | ||
94 | Some(stdin) => { | ||
95 | command.stdin(Stdio::piped()).stdout(Stdio::piped()); | ||
96 | let mut process = command.spawn()?; | ||
97 | process.stdin.take().unwrap().write_all(stdin)?; | ||
98 | process.wait_with_output() | ||
99 | } | ||
100 | }?; | ||
101 | let stdout = String::from_utf8(output.stdout)?; | ||
102 | |||
103 | if echo { | ||
104 | print!("{}", stdout) | ||
105 | } | ||
106 | |||
107 | if !output.status.success() { | ||
108 | bail!("{}", output.status) | ||
109 | } | ||
110 | |||
111 | Ok(stdout.trim().to_string()) | ||
112 | } | ||
113 | |||
114 | // FIXME: some real shell lexing here | ||
115 | fn shelx(cmd: &str) -> Vec<String> { | ||
116 | let mut res = Vec::new(); | ||
117 | for (string_piece, in_quotes) in cmd.split('\'').zip([false, true].iter().copied().cycle()) { | ||
118 | if in_quotes { | ||
119 | res.push(string_piece.to_string()) | ||
120 | } else { | ||
121 | if !string_piece.is_empty() { | ||
122 | res.extend(string_piece.split_ascii_whitespace().map(|it| it.to_string())) | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | res | ||
127 | } | ||
128 | |||
129 | struct Env { | ||
130 | pushd_stack: Vec<PathBuf>, | ||
131 | pushenv_stack: Vec<(OsString, Option<OsString>)>, | ||
132 | } | ||
133 | |||
134 | impl Env { | ||
135 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { | ||
136 | thread_local! { | ||
137 | static ENV: RefCell<Env> = RefCell::new(Env { | ||
138 | pushd_stack: vec![env::current_dir().unwrap()], | ||
139 | pushenv_stack: vec![], | ||
140 | }); | ||
141 | } | ||
142 | ENV.with(|it| f(&mut *it.borrow_mut())) | ||
143 | } | ||
144 | |||
145 | fn pushd(&mut self, dir: PathBuf) { | ||
146 | let dir = self.cwd().join(dir); | ||
147 | self.pushd_stack.push(dir); | ||
148 | env::set_current_dir(self.cwd()) | ||
149 | .unwrap_or_else(|err| panic!("Failed to set cwd to {}: {}", self.cwd().display(), err)); | ||
150 | } | ||
151 | fn popd(&mut self) { | ||
152 | self.pushd_stack.pop().unwrap(); | ||
153 | env::set_current_dir(self.cwd()).unwrap(); | ||
154 | } | ||
155 | fn pushenv(&mut self, var: OsString, value: OsString) { | ||
156 | self.pushenv_stack.push((var.clone(), env::var_os(&var))); | ||
157 | env::set_var(var, value) | ||
158 | } | ||
159 | fn popenv(&mut self) { | ||
160 | let (var, value) = self.pushenv_stack.pop().unwrap(); | ||
161 | match value { | ||
162 | None => env::remove_var(var), | ||
163 | Some(value) => env::set_var(var, value), | ||
164 | } | ||
165 | } | ||
166 | fn cwd(&self) -> &Path { | ||
167 | self.pushd_stack.last().unwrap() | ||
168 | } | ||
169 | } | ||
diff --git a/xtask/src/pre_cache.rs b/xtask/src/pre_cache.rs index 47ba6ba24..569f88f68 100644 --- a/xtask/src/pre_cache.rs +++ b/xtask/src/pre_cache.rs | |||
@@ -4,8 +4,7 @@ use std::{ | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | use anyhow::Result; | 6 | use anyhow::Result; |
7 | 7 | use xshell::rm_rf; | |
8 | use crate::not_bash::{fs2, rm_rf}; | ||
9 | 8 | ||
10 | pub struct PreCacheCmd; | 9 | pub struct PreCacheCmd; |
11 | 10 | ||
@@ -26,7 +25,7 @@ impl PreCacheCmd { | |||
26 | } | 25 | } |
27 | } | 26 | } |
28 | 27 | ||
29 | fs2::remove_file("./target/.rustc_info.json")?; | 28 | rm_rf("./target/.rustc_info.json")?; |
30 | 29 | ||
31 | let to_delete = read_dir("./crates", FileType::is_dir)? | 30 | let to_delete = read_dir("./crates", FileType::is_dir)? |
32 | .into_iter() | 31 | .into_iter() |
diff --git a/xtask/src/pre_commit.rs b/xtask/src/pre_commit.rs index 056f34acf..8f2dbea19 100644 --- a/xtask/src/pre_commit.rs +++ b/xtask/src/pre_commit.rs | |||
@@ -3,19 +3,21 @@ | |||
3 | use std::{fs, path::PathBuf}; | 3 | use std::{fs, path::PathBuf}; |
4 | 4 | ||
5 | use anyhow::{bail, Result}; | 5 | use anyhow::{bail, Result}; |
6 | use xshell::cmd; | ||
6 | 7 | ||
7 | use crate::{not_bash::run, project_root, run_rustfmt, Mode}; | 8 | use crate::{project_root, run_rustfmt, Mode}; |
8 | 9 | ||
9 | // FIXME: if there are changed `.ts` files, also reformat TypeScript (by | 10 | // FIXME: if there are changed `.ts` files, also reformat TypeScript (by |
10 | // shelling out to `npm fmt`). | 11 | // shelling out to `npm fmt`). |
11 | pub fn run_hook() -> Result<()> { | 12 | pub fn run_hook() -> Result<()> { |
12 | run_rustfmt(Mode::Overwrite)?; | 13 | run_rustfmt(Mode::Overwrite)?; |
13 | 14 | ||
14 | let diff = run!("git diff --diff-filter=MAR --name-only --cached")?; | 15 | let diff = cmd!("git diff --diff-filter=MAR --name-only --cached").read()?; |
15 | 16 | ||
16 | let root = project_root(); | 17 | let root = project_root(); |
17 | for line in diff.lines() { | 18 | for line in diff.lines() { |
18 | run!("git update-index --add {}", root.join(line).display())?; | 19 | let file = root.join(line); |
20 | cmd!("git update-index --add {file}").run()?; | ||
19 | } | 21 | } |
20 | 22 | ||
21 | Ok(()) | 23 | Ok(()) |
diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 3aab29801..14fc1f0dd 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs | |||
@@ -1,8 +1,6 @@ | |||
1 | use crate::{ | 1 | use xshell::{cmd, cp, pushd, read_dir, write_file}; |
2 | codegen, is_release_tag, | 2 | |
3 | not_bash::{date_iso, fs2, pushd, run}, | 3 | use crate::{codegen, date_iso, is_release_tag, project_root, Mode, Result}; |
4 | project_root, Mode, Result, | ||
5 | }; | ||
6 | 4 | ||
7 | pub struct ReleaseCmd { | 5 | pub struct ReleaseCmd { |
8 | pub dry_run: bool, | 6 | pub dry_run: bool, |
@@ -11,10 +9,10 @@ pub struct ReleaseCmd { | |||
11 | impl ReleaseCmd { | 9 | impl ReleaseCmd { |
12 | pub fn run(self) -> Result<()> { | 10 | pub fn run(self) -> Result<()> { |
13 | if !self.dry_run { | 11 | if !self.dry_run { |
14 | run!("git switch release")?; | 12 | cmd!("git switch release").run()?; |
15 | run!("git fetch upstream --tags --force")?; | 13 | cmd!("git fetch upstream --tags --force").run()?; |
16 | run!("git reset --hard tags/nightly")?; | 14 | cmd!("git reset --hard tags/nightly").run()?; |
17 | run!("git push")?; | 15 | cmd!("git push").run()?; |
18 | } | 16 | } |
19 | codegen::generate_assists_docs(Mode::Overwrite)?; | 17 | codegen::generate_assists_docs(Mode::Overwrite)?; |
20 | codegen::generate_feature_docs(Mode::Overwrite)?; | 18 | codegen::generate_feature_docs(Mode::Overwrite)?; |
@@ -23,8 +21,8 @@ impl ReleaseCmd { | |||
23 | let changelog_dir = website_root.join("./thisweek/_posts"); | 21 | let changelog_dir = website_root.join("./thisweek/_posts"); |
24 | 22 | ||
25 | let today = date_iso()?; | 23 | let today = date_iso()?; |
26 | let commit = run!("git rev-parse HEAD")?; | 24 | let commit = cmd!("git rev-parse HEAD").read()?; |
27 | let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count(); | 25 | let changelog_n = read_dir(changelog_dir.as_path())?.len(); |
28 | 26 | ||
29 | let contents = format!( | 27 | let contents = format!( |
30 | "\ | 28 | "\ |
@@ -52,20 +50,20 @@ https://github.com/sponsors/rust-analyzer[GitHub Sponsors]. | |||
52 | ); | 50 | ); |
53 | 51 | ||
54 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | 52 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); |
55 | fs2::write(&path, &contents)?; | 53 | write_file(&path, &contents)?; |
56 | 54 | ||
57 | for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { | 55 | for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { |
58 | let src = project_root().join("./docs/user/").join(adoc); | 56 | let src = project_root().join("./docs/user/").join(adoc); |
59 | let dst = website_root.join(adoc); | 57 | let dst = website_root.join(adoc); |
60 | fs2::copy(src, dst)?; | 58 | cp(src, dst)?; |
61 | } | 59 | } |
62 | 60 | ||
63 | let tags = run!("git tag --list"; echo = false)?; | 61 | let tags = cmd!("git tag --list").read()?; |
64 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); | 62 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); |
65 | 63 | ||
66 | let git_log = run!("git log {}..HEAD --merges --reverse", prev_tag; echo = false)?; | 64 | let git_log = cmd!("git log {prev_tag}..HEAD --merges --reverse").read()?; |
67 | let git_log_dst = website_root.join("git.log"); | 65 | let git_log_dst = website_root.join("git.log"); |
68 | fs2::write(git_log_dst, &git_log)?; | 66 | write_file(git_log_dst, &git_log)?; |
69 | 67 | ||
70 | Ok(()) | 68 | Ok(()) |
71 | } | 69 | } |
@@ -77,27 +75,25 @@ pub struct PromoteCmd { | |||
77 | 75 | ||
78 | impl PromoteCmd { | 76 | impl PromoteCmd { |
79 | pub fn run(self) -> Result<()> { | 77 | pub fn run(self) -> Result<()> { |
80 | let _dir = pushd("../rust-rust-analyzer"); | 78 | let _dir = pushd("../rust-rust-analyzer")?; |
81 | run!("git switch master")?; | 79 | cmd!("git switch master").run()?; |
82 | run!("git fetch upstream")?; | 80 | cmd!("git fetch upstream").run()?; |
83 | run!("git reset --hard upstream/master")?; | 81 | cmd!("git reset --hard upstream/master").run()?; |
84 | run!("git submodule update --recursive")?; | 82 | cmd!("git submodule update --recursive").run()?; |
85 | 83 | ||
86 | let branch = format!("rust-analyzer-{}", date_iso()?); | 84 | let branch = format!("rust-analyzer-{}", date_iso()?); |
87 | run!("git switch -c {}", branch)?; | 85 | cmd!("git switch -c {branch}").run()?; |
88 | { | 86 | { |
89 | let _dir = pushd("src/tools/rust-analyzer"); | 87 | let _dir = pushd("src/tools/rust-analyzer")?; |
90 | run!("git fetch origin")?; | 88 | cmd!("git fetch origin").run()?; |
91 | run!("git reset --hard origin/release")?; | 89 | cmd!("git reset --hard origin/release").run()?; |
92 | } | 90 | } |
93 | run!("git add src/tools/rust-analyzer")?; | 91 | cmd!("git add src/tools/rust-analyzer").run()?; |
94 | run!("git commit -m':arrow_up: rust-analyzer'")?; | 92 | cmd!("git commit -m':arrow_up: rust-analyzer'").run()?; |
95 | if !self.dry_run { | 93 | if !self.dry_run { |
96 | run!("git push")?; | 94 | cmd!("git push").run()?; |
97 | run!( | 95 | cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost") |
98 | "xdg-open https://github.com/matklad/rust/pull/new/{}?body=r%3F%20%40ghost", | 96 | .run()?; |
99 | branch | ||
100 | )?; | ||
101 | } | 97 | } |
102 | Ok(()) | 98 | Ok(()) |
103 | } | 99 | } |
diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index b3bb9d543..d335adb72 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs | |||
@@ -3,9 +3,9 @@ use std::{ | |||
3 | path::{Path, PathBuf}, | 3 | path::{Path, PathBuf}, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use xshell::{cmd, read_file}; | ||
6 | use xtask::{ | 7 | use xtask::{ |
7 | codegen::{self, Mode}, | 8 | codegen::{self, Mode}, |
8 | not_bash::{fs2, run}, | ||
9 | project_root, run_rustfmt, rust_files, | 9 | project_root, run_rustfmt, rust_files, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -48,14 +48,13 @@ fn smoke_test_docs_generation() { | |||
48 | fn check_lsp_extensions_docs() { | 48 | fn check_lsp_extensions_docs() { |
49 | let expected_hash = { | 49 | let expected_hash = { |
50 | let lsp_ext_rs = | 50 | let lsp_ext_rs = |
51 | fs2::read_to_string(project_root().join("crates/rust-analyzer/src/lsp_ext.rs")) | 51 | read_file(project_root().join("crates/rust-analyzer/src/lsp_ext.rs")).unwrap(); |
52 | .unwrap(); | ||
53 | stable_hash(lsp_ext_rs.as_str()) | 52 | stable_hash(lsp_ext_rs.as_str()) |
54 | }; | 53 | }; |
55 | 54 | ||
56 | let actual_hash = { | 55 | let actual_hash = { |
57 | let lsp_extensions_md = | 56 | let lsp_extensions_md = |
58 | fs2::read_to_string(project_root().join("docs/dev/lsp-extensions.md")).unwrap(); | 57 | read_file(project_root().join("docs/dev/lsp-extensions.md")).unwrap(); |
59 | let text = lsp_extensions_md | 58 | let text = lsp_extensions_md |
60 | .lines() | 59 | .lines() |
61 | .find_map(|line| line.strip_prefix("lsp_ext.rs hash:")) | 60 | .find_map(|line| line.strip_prefix("lsp_ext.rs hash:")) |
@@ -83,7 +82,7 @@ Please adjust docs/dev/lsp-extensions.md. | |||
83 | fn rust_files_are_tidy() { | 82 | fn rust_files_are_tidy() { |
84 | let mut tidy_docs = TidyDocs::default(); | 83 | let mut tidy_docs = TidyDocs::default(); |
85 | for path in rust_files(&project_root().join("crates")) { | 84 | for path in rust_files(&project_root().join("crates")) { |
86 | let text = fs2::read_to_string(&path).unwrap(); | 85 | let text = read_file(&path).unwrap(); |
87 | check_todo(&path, &text); | 86 | check_todo(&path, &text); |
88 | check_trailing_ws(&path, &text); | 87 | check_trailing_ws(&path, &text); |
89 | deny_clippy(&path, &text); | 88 | deny_clippy(&path, &text); |
@@ -94,8 +93,10 @@ fn rust_files_are_tidy() { | |||
94 | 93 | ||
95 | #[test] | 94 | #[test] |
96 | fn check_merge_commits() { | 95 | fn check_merge_commits() { |
97 | let stdout = run!("git rev-list --merges --invert-grep --author 'bors\\[bot\\]' HEAD~19.."; echo = false) | 96 | let stdout = |
98 | .unwrap(); | 97 | dbg!(cmd!("git rev-list --merges --invert-grep --author 'bors\\[bot\\]' HEAD~19..")) |
98 | .read() | ||
99 | .unwrap(); | ||
99 | if !stdout.is_empty() { | 100 | if !stdout.is_empty() { |
100 | panic!( | 101 | panic!( |
101 | " | 102 | " |
@@ -168,7 +169,7 @@ Zlib OR Apache-2.0 OR MIT | |||
168 | .filter(|it| !it.is_empty()) | 169 | .filter(|it| !it.is_empty()) |
169 | .collect::<Vec<_>>(); | 170 | .collect::<Vec<_>>(); |
170 | 171 | ||
171 | let meta = run!("cargo metadata --format-version 1"; echo = false).unwrap(); | 172 | let meta = cmd!("cargo metadata --format-version 1").read().unwrap(); |
172 | let mut licenses = meta | 173 | let mut licenses = meta |
173 | .split(|c| c == ',' || c == '{' || c == '}') | 174 | .split(|c| c == ',' || c == '{' || c == '}') |
174 | .filter(|it| it.contains(r#""license""#)) | 175 | .filter(|it| it.contains(r#""license""#)) |
@@ -177,6 +178,25 @@ Zlib OR Apache-2.0 OR MIT | |||
177 | .collect::<Vec<_>>(); | 178 | .collect::<Vec<_>>(); |
178 | licenses.sort(); | 179 | licenses.sort(); |
179 | licenses.dedup(); | 180 | licenses.dedup(); |
181 | if licenses != expected { | ||
182 | let mut diff = String::new(); | ||
183 | |||
184 | diff += &format!("New Licenses:\n"); | ||
185 | for &l in licenses.iter() { | ||
186 | if !expected.contains(&l) { | ||
187 | diff += &format!(" {}\n", l) | ||
188 | } | ||
189 | } | ||
190 | |||
191 | diff += &format!("\nMissing Licenses:\n"); | ||
192 | for &l in expected.iter() { | ||
193 | if !licenses.contains(&l) { | ||
194 | diff += &format!(" {}\n", l) | ||
195 | } | ||
196 | } | ||
197 | |||
198 | panic!("different set of licenses!\n{}", diff); | ||
199 | } | ||
180 | assert_eq!(licenses, expected); | 200 | assert_eq!(licenses, expected); |
181 | } | 201 | } |
182 | 202 | ||