diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/ast_src.rs | 16 | ||||
-rw-r--r-- | xtask/src/cmd.rs | 53 | ||||
-rw-r--r-- | xtask/src/install.rs | 138 | ||||
-rw-r--r-- | xtask/src/lib.rs | 94 | ||||
-rw-r--r-- | xtask/src/main.rs | 7 | ||||
-rw-r--r-- | xtask/src/not_bash.rs | 165 | ||||
-rw-r--r-- | xtask/src/pre_commit.rs | 8 |
7 files changed, 310 insertions, 171 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 67d1f41bc..2d9ae904b 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -120,6 +120,8 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
120 | "FOR_TYPE", | 120 | "FOR_TYPE", |
121 | "IMPL_TRAIT_TYPE", | 121 | "IMPL_TRAIT_TYPE", |
122 | "DYN_TRAIT_TYPE", | 122 | "DYN_TRAIT_TYPE", |
123 | "OR_PAT", | ||
124 | "PAREN_PAT", | ||
123 | "REF_PAT", | 125 | "REF_PAT", |
124 | "BOX_PAT", | 126 | "BOX_PAT", |
125 | "BIND_PAT", | 127 | "BIND_PAT", |
@@ -412,26 +414,28 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
412 | struct MatchExpr { Expr, MatchArmList } | 414 | struct MatchExpr { Expr, MatchArmList } |
413 | struct MatchArmList: AttrsOwner { arms: [MatchArm] } | 415 | struct MatchArmList: AttrsOwner { arms: [MatchArm] } |
414 | struct MatchArm: AttrsOwner { | 416 | struct MatchArm: AttrsOwner { |
415 | pats: [Pat], | 417 | pat: Pat, |
416 | guard: MatchGuard, | 418 | guard: MatchGuard, |
417 | Expr, | 419 | Expr, |
418 | } | 420 | } |
419 | struct MatchGuard { Expr } | 421 | struct MatchGuard { Expr } |
420 | 422 | ||
421 | struct RecordLit { Path, RecordFieldList } | 423 | struct RecordLit { Path, RecordFieldList } |
422 | struct RecordFieldList { | 424 | struct RecordFieldList { |
423 | fields: [RecordField], | 425 | fields: [RecordField], |
424 | spread: Expr, | 426 | spread: Expr, |
425 | } | 427 | } |
426 | struct RecordField { NameRef, Expr } | 428 | struct RecordField { NameRef, Expr } |
427 | 429 | ||
430 | struct OrPat { pats: [Pat] } | ||
431 | struct ParenPat { Pat } | ||
428 | struct RefPat { Pat } | 432 | struct RefPat { Pat } |
429 | struct BoxPat { Pat } | 433 | struct BoxPat { Pat } |
430 | struct BindPat: NameOwner { Pat } | 434 | struct BindPat: NameOwner { Pat } |
431 | struct PlaceholderPat { } | 435 | struct PlaceholderPat { } |
432 | struct DotDotPat { } | 436 | struct DotDotPat { } |
433 | struct PathPat { Path } | 437 | struct PathPat { Path } |
434 | struct SlicePat {} | 438 | struct SlicePat { args: [Pat] } |
435 | struct RangePat {} | 439 | struct RangePat {} |
436 | struct LiteralPat { Literal } | 440 | struct LiteralPat { Literal } |
437 | 441 | ||
@@ -601,6 +605,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
601 | } | 605 | } |
602 | 606 | ||
603 | enum Pat { | 607 | enum Pat { |
608 | OrPat, | ||
609 | ParenPat, | ||
604 | RefPat, | 610 | RefPat, |
605 | BoxPat, | 611 | BoxPat, |
606 | BindPat, | 612 | BindPat, |
diff --git a/xtask/src/cmd.rs b/xtask/src/cmd.rs deleted file mode 100644 index 2027f4893..000000000 --- a/xtask/src/cmd.rs +++ /dev/null | |||
@@ -1,53 +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<Output> { | ||
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<Output> { | ||
38 | do_run(cmdline, dir, &mut |_| {}) | ||
39 | } | ||
40 | |||
41 | fn do_run(cmdline: &str, dir: &str, f: &mut dyn FnMut(&mut Command)) -> Result<Output> { | ||
42 | eprintln!("\nwill run: {}", cmdline); | ||
43 | let proj_dir = project_root().join(dir); | ||
44 | let mut args = cmdline.split_whitespace(); | ||
45 | let exec = args.next().unwrap(); | ||
46 | let mut cmd = Command::new(exec); | ||
47 | f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit())); | ||
48 | let output = cmd.output().with_context(|| format!("running `{}`", cmdline))?; | ||
49 | if !output.status.success() { | ||
50 | anyhow::bail!("`{}` exited with {}", cmdline, output.status); | ||
51 | } | ||
52 | Ok(output) | ||
53 | } | ||
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 8c65b51e3..00bbabce4 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; |
@@ -24,6 +24,7 @@ pub struct ServerOpt { | |||
24 | 24 | ||
25 | impl InstallCmd { | 25 | impl InstallCmd { |
26 | pub fn run(self) -> Result<()> { | 26 | pub fn run(self) -> Result<()> { |
27 | let both = self.server.is_some() && self.client.is_some(); | ||
27 | if cfg!(target_os = "macos") { | 28 | if cfg!(target_os = "macos") { |
28 | fix_path_for_mac().context("Fix path for mac")? | 29 | fix_path_for_mac().context("Fix path for mac")? |
29 | } | 30 | } |
@@ -33,6 +34,16 @@ impl InstallCmd { | |||
33 | if let Some(client) = self.client { | 34 | if let Some(client) = self.client { |
34 | install_client(client).context("install client")?; | 35 | install_client(client).context("install client")?; |
35 | } | 36 | } |
37 | if both { | ||
38 | eprintln!( | ||
39 | " | ||
40 | Installation complete. | ||
41 | |||
42 | Add `\"rust-analyzer.raLspServerPath\": \"ra_lsp_server\",` to VS Code settings, | ||
43 | otherwise it will use the latest release from GitHub. | ||
44 | " | ||
45 | ) | ||
46 | } | ||
36 | Ok(()) | 47 | Ok(()) |
37 | } | 48 | } |
38 | } | 49 | } |
@@ -44,7 +55,7 @@ fn fix_path_for_mac() -> Result<()> { | |||
44 | const ROOT_DIR: &str = ""; | 55 | const ROOT_DIR: &str = ""; |
45 | let home_dir = match env::var("HOME") { | 56 | let home_dir = match env::var("HOME") { |
46 | Ok(home) => home, | 57 | Ok(home) => home, |
47 | Err(e) => anyhow::bail!("Failed getting HOME from environment with error: {}.", e), | 58 | Err(e) => bail!("Failed getting HOME from environment with error: {}.", e), |
48 | }; | 59 | }; |
49 | 60 | ||
50 | [ROOT_DIR, &home_dir] | 61 | [ROOT_DIR, &home_dir] |
@@ -58,7 +69,7 @@ fn fix_path_for_mac() -> Result<()> { | |||
58 | if !vscode_path.is_empty() { | 69 | if !vscode_path.is_empty() { |
59 | let vars = match env::var_os("PATH") { | 70 | let vars = match env::var_os("PATH") { |
60 | Some(path) => path, | 71 | Some(path) => path, |
61 | None => anyhow::bail!("Could not get PATH variable from env."), | 72 | None => bail!("Could not get PATH variable from env."), |
62 | }; | 73 | }; |
63 | 74 | ||
64 | let mut paths = env::split_paths(&vars).collect::<Vec<_>>(); | 75 | let mut paths = env::split_paths(&vars).collect::<Vec<_>>(); |
@@ -71,91 +82,63 @@ fn fix_path_for_mac() -> Result<()> { | |||
71 | } | 82 | } |
72 | 83 | ||
73 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { | 84 | fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { |
74 | let npm_version = Cmd { | 85 | let _dir = pushd("./editors/code"); |
75 | unix: r"npm --version", | ||
76 | windows: r"cmd.exe /c npm --version", | ||
77 | work_dir: "./editors/code", | ||
78 | } | ||
79 | .run(); | ||
80 | 86 | ||
81 | if npm_version.is_err() { | 87 | let find_code = |f: fn(&str) -> bool| -> Result<&'static str> { |
82 | eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") | 88 | ["code", "code-insiders", "codium", "code-oss"] |
83 | } | 89 | .iter() |
90 | .copied() | ||
91 | .find(|bin| f(bin)) | ||
92 | .ok_or_else(|| { | ||
93 | format_err!("Can't execute `code --version`. Perhaps it is not in $PATH?") | ||
94 | }) | ||
95 | }; | ||
84 | 96 | ||
85 | Cmd { unix: r"npm install", windows: r"cmd.exe /c npm install", work_dir: "./editors/code" } | 97 | let installed_extensions; |
86 | .run()?; | 98 | if cfg!(unix) { |
87 | Cmd { | 99 | run!("npm --version").context("`npm` is required to build the VS Code plugin")?; |
88 | unix: r"npm run package --scripts-prepend-node-path", | 100 | run!("npm install")?; |
89 | windows: r"cmd.exe /c npm run package", | ||
90 | work_dir: "./editors/code", | ||
91 | } | ||
92 | .run()?; | ||
93 | 101 | ||
94 | let code_binary = ["code", "code-insiders", "codium", "code-oss"].iter().find(|bin| { | 102 | let vsix_pkg = { |
95 | Cmd { | 103 | rm("*.vsix")?; |
96 | unix: &format!("{} --version", bin), | 104 | run!("npm run package --scripts-prepend-node-path")?; |
97 | windows: &format!("cmd.exe /c {}.cmd --version", bin), | 105 | ls("*.vsix")?.pop().unwrap() |
98 | work_dir: "./editors/code", | 106 | }; |
99 | } | ||
100 | .run() | ||
101 | .is_ok() | ||
102 | }); | ||
103 | 107 | ||
104 | let code_binary = match code_binary { | 108 | let code = find_code(|bin| run!("{} --version", bin).is_ok())?; |
105 | Some(it) => it, | 109 | run!("{} --install-extension {} --force", code, vsix_pkg.display())?; |
106 | None => anyhow::bail!("Can't execute `code --version`. Perhaps it is not in $PATH?"), | 110 | installed_extensions = run!("{} --list-extensions", code; echo = false)?; |
107 | }; | 111 | } else { |
112 | run!("cmd.exe /c npm --version") | ||
113 | .context("`npm` is required to build the VS Code plugin")?; | ||
114 | run!("cmd.exe /c npm install")?; | ||
115 | |||
116 | let vsix_pkg = { | ||
117 | rm("*.vsix")?; | ||
118 | run!("cmd.exe /c npm run package")?; | ||
119 | ls("*.vsix")?.pop().unwrap() | ||
120 | }; | ||
108 | 121 | ||
109 | Cmd { | 122 | let code = find_code(|bin| run!("cmd.exe /c {}.cmd --version", bin).is_ok())?; |
110 | unix: &format!(r"{} --install-extension ./rust-analyzer-0.1.0.vsix --force", code_binary), | 123 | run!(r"cmd.exe /c {}.cmd --install-extension {} --force", code, vsix_pkg.display())?; |
111 | windows: &format!( | 124 | installed_extensions = run!("cmd.exe /c {}.cmd --list-extensions", code; echo = false)?; |
112 | r"cmd.exe /c {}.cmd --install-extension ./rust-analyzer-0.1.0.vsix --force", | ||
113 | code_binary | ||
114 | ), | ||
115 | work_dir: "./editors/code", | ||
116 | } | 125 | } |
117 | .run()?; | ||
118 | |||
119 | let installed_extensions = { | ||
120 | let output = Cmd { | ||
121 | unix: &format!(r"{} --list-extensions", code_binary), | ||
122 | windows: &format!(r"cmd.exe /c {}.cmd --list-extensions", code_binary), | ||
123 | work_dir: ".", | ||
124 | } | ||
125 | .run_with_output()?; | ||
126 | String::from_utf8(output.stdout)? | ||
127 | }; | ||
128 | 126 | ||
129 | if !installed_extensions.contains("rust-analyzer") { | 127 | if !installed_extensions.contains("rust-analyzer") { |
130 | anyhow::bail!( | 128 | bail!( |
131 | "Could not install the Visual Studio Code extension. \ | 129 | "Could not install the Visual Studio Code extension. \ |
132 | 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 12.x together with the latest version of VS Code installed and try again." |
133 | ); | 131 | ); |
134 | } | 132 | } |
135 | 133 | ||
136 | if installed_extensions.contains("ra-lsp") { | ||
137 | Cmd { | ||
138 | unix: &format!(r"{} --uninstall-extension matklad.ra-lsp", code_binary), | ||
139 | windows: &format!( | ||
140 | r"cmd.exe /c {}.cmd --uninstall-extension matklad.ra-lsp", | ||
141 | code_binary | ||
142 | ), | ||
143 | work_dir: "./editors/code", | ||
144 | } | ||
145 | .run()?; | ||
146 | } | ||
147 | |||
148 | Ok(()) | 134 | Ok(()) |
149 | } | 135 | } |
150 | 136 | ||
151 | fn install_server(opts: ServerOpt) -> Result<()> { | 137 | fn install_server(opts: ServerOpt) -> Result<()> { |
152 | let mut old_rust = false; | 138 | let mut old_rust = false; |
153 | if let Ok(output) = run_with_output("cargo --version", ".") { | 139 | if let Ok(stdout) = run!("cargo --version") { |
154 | if let Ok(stdout) = String::from_utf8(output.stdout) { | 140 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { |
155 | println!("{}", stdout); | 141 | old_rust = true; |
156 | if !check_version(&stdout, REQUIRED_RUST_VERSION) { | ||
157 | old_rust = true; | ||
158 | } | ||
159 | } | 142 | } |
160 | } | 143 | } |
161 | 144 | ||
@@ -166,20 +149,17 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
166 | ) | 149 | ) |
167 | } | 150 | } |
168 | 151 | ||
169 | let res = if opts.jemalloc { | 152 | let jemalloc = if opts.jemalloc { "--features jemalloc" } else { "" }; |
170 | 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); |
171 | } else { | ||
172 | run("cargo install --path crates/ra_lsp_server --locked --force", ".") | ||
173 | }; | ||
174 | 154 | ||
175 | if res.is_err() && old_rust { | 155 | if res.is_err() && old_rust { |
176 | eprintln!( | 156 | eprintln!( |
177 | "\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", |
178 | REQUIRED_RUST_VERSION, | 158 | REQUIRED_RUST_VERSION, |
179 | ) | 159 | ); |
180 | } | 160 | } |
181 | 161 | ||
182 | res | 162 | res.map(drop) |
183 | } | 163 | } |
184 | 164 | ||
185 | 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 8fdf43e4a..2bcd76d60 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 | ||
@@ -9,13 +9,16 @@ mod ast_src; | |||
9 | 9 | ||
10 | use anyhow::Context; | 10 | use anyhow::Context; |
11 | use std::{ | 11 | use std::{ |
12 | env, fs, | 12 | env, |
13 | io::Write, | 13 | io::Write, |
14 | path::{Path, PathBuf}, | 14 | path::{Path, PathBuf}, |
15 | process::{Command, Stdio}, | 15 | process::{Command, Stdio}, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use crate::{cmd::run, codegen::Mode}; | 18 | use crate::{ |
19 | codegen::Mode, | ||
20 | not_bash::{fs2, pushd, rm_rf, run}, | ||
21 | }; | ||
19 | 22 | ||
20 | pub use anyhow::Result; | 23 | pub use anyhow::Result; |
21 | 24 | ||
@@ -35,9 +38,9 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> { | |||
35 | ensure_rustfmt()?; | 38 | ensure_rustfmt()?; |
36 | 39 | ||
37 | if mode == Mode::Verify { | 40 | if mode == Mode::Verify { |
38 | run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?; | 41 | run!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN)?; |
39 | } else { | 42 | } else { |
40 | run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?; | 43 | run!("rustup run {} -- cargo fmt", TOOLCHAIN)?; |
41 | } | 44 | } |
42 | Ok(()) | 45 | Ok(()) |
43 | } | 46 | } |
@@ -67,8 +70,9 @@ fn ensure_rustfmt() -> Result<()> { | |||
67 | Ok(status) if status.success() => return Ok(()), | 70 | Ok(status) if status.success() => return Ok(()), |
68 | _ => (), | 71 | _ => (), |
69 | }; | 72 | }; |
70 | run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; | 73 | run!("rustup toolchain install {}", TOOLCHAIN)?; |
71 | run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".") | 74 | run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?; |
75 | Ok(()) | ||
72 | } | 76 | } |
73 | 77 | ||
74 | pub fn run_clippy() -> Result<()> { | 78 | pub fn run_clippy() -> Result<()> { |
@@ -89,34 +93,28 @@ pub fn run_clippy() -> Result<()> { | |||
89 | "clippy::nonminimal_bool", | 93 | "clippy::nonminimal_bool", |
90 | "clippy::redundant_pattern_matching", | 94 | "clippy::redundant_pattern_matching", |
91 | ]; | 95 | ]; |
92 | run( | 96 | run!( |
93 | &format!( | 97 | "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}", |
94 | "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}", | 98 | TOOLCHAIN, |
95 | TOOLCHAIN, | 99 | allowed_lints.join(" -A ") |
96 | allowed_lints.join(" -A ") | ||
97 | ), | ||
98 | ".", | ||
99 | )?; | 100 | )?; |
100 | Ok(()) | 101 | Ok(()) |
101 | } | 102 | } |
102 | 103 | ||
103 | fn install_clippy() -> Result<()> { | 104 | fn install_clippy() -> Result<()> { |
104 | run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; | 105 | run!("rustup toolchain install {}", TOOLCHAIN)?; |
105 | run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".") | 106 | run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?; |
107 | Ok(()) | ||
106 | } | 108 | } |
107 | 109 | ||
108 | pub fn run_fuzzer() -> Result<()> { | 110 | pub fn run_fuzzer() -> Result<()> { |
109 | match Command::new("cargo") | 111 | let _d = pushd("./crates/ra_syntax"); |
110 | .args(&["fuzz", "--help"]) | 112 | if run!("cargo fuzz --help").is_err() { |
111 | .stderr(Stdio::null()) | 113 | run!("cargo install cargo-fuzz")?; |
112 | .stdout(Stdio::null()) | ||
113 | .status() | ||
114 | { | ||
115 | Ok(status) if status.success() => (), | ||
116 | _ => run("cargo install cargo-fuzz", ".")?, | ||
117 | }; | 114 | }; |
118 | 115 | ||
119 | run("rustup run nightly -- cargo fuzz run parser", "./crates/ra_syntax") | 116 | run!("rustup run nightly -- cargo fuzz run parser")?; |
117 | Ok(()) | ||
120 | } | 118 | } |
121 | 119 | ||
122 | /// Cleans the `./target` dir after the build such that only | 120 | /// Cleans the `./target` dir after the build such that only |
@@ -138,7 +136,7 @@ pub fn run_pre_cache() -> Result<()> { | |||
138 | } | 136 | } |
139 | } | 137 | } |
140 | 138 | ||
141 | fs::remove_file("./target/.rustc_info.json")?; | 139 | fs2::remove_file("./target/.rustc_info.json")?; |
142 | let to_delete = ["ra_", "heavy_test"]; | 140 | let to_delete = ["ra_", "heavy_test"]; |
143 | for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() { | 141 | for &dir in ["./target/debug/deps", "target/debug/.fingerprint"].iter() { |
144 | for entry in Path::new(dir).read_dir()? { | 142 | for entry in Path::new(dir).read_dir()? { |
@@ -152,7 +150,45 @@ pub fn run_pre_cache() -> Result<()> { | |||
152 | Ok(()) | 150 | Ok(()) |
153 | } | 151 | } |
154 | 152 | ||
155 | fn rm_rf(path: &Path) -> Result<()> { | 153 | pub fn run_release(dry_run: bool) -> Result<()> { |
156 | if path.is_file() { fs::remove_file(path) } else { fs::remove_dir_all(path) } | 154 | if !dry_run { |
157 | .with_context(|| format!("failed to remove {:?}", path)) | 155 | run!("git switch release")?; |
156 | run!("git fetch upstream")?; | ||
157 | run!("git reset --hard upstream/master")?; | ||
158 | run!("git push")?; | ||
159 | } | ||
160 | |||
161 | let website_root = project_root().join("../rust-analyzer.github.io"); | ||
162 | let changelog_dir = website_root.join("./thisweek/_posts"); | ||
163 | |||
164 | let today = run!("date --iso")?; | ||
165 | let commit = run!("git rev-parse HEAD")?; | ||
166 | let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count(); | ||
167 | |||
168 | let contents = format!( | ||
169 | "\ | ||
170 | = Changelog #{} | ||
171 | :sectanchors: | ||
172 | :page-layout: post | ||
173 | |||
174 | Commit: commit:{}[] + | ||
175 | Release: release:{}[] | ||
176 | |||
177 | == New Features | ||
178 | |||
179 | * pr:[] . | ||
180 | |||
181 | == Fixes | ||
182 | |||
183 | == Internal Improvements | ||
184 | ", | ||
185 | changelog_n, commit, today | ||
186 | ); | ||
187 | |||
188 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | ||
189 | fs2::write(&path, &contents)?; | ||
190 | |||
191 | fs2::copy(project_root().join("./docs/user/readme.adoc"), website_root.join("manual.adoc"))?; | ||
192 | |||
193 | Ok(()) | ||
158 | } | 194 | } |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c347de9ab..a7dffe2cc 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -14,7 +14,7 @@ use pico_args::Arguments; | |||
14 | use xtask::{ | 14 | use xtask::{ |
15 | codegen::{self, Mode}, | 15 | codegen::{self, Mode}, |
16 | install::{ClientOpt, InstallCmd, ServerOpt}, | 16 | install::{ClientOpt, InstallCmd, ServerOpt}, |
17 | pre_commit, run_clippy, run_fuzzer, run_pre_cache, run_rustfmt, Result, | 17 | pre_commit, run_clippy, run_fuzzer, run_pre_cache, run_release, run_rustfmt, Result, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | fn main() -> Result<()> { | 20 | fn main() -> Result<()> { |
@@ -92,6 +92,11 @@ FLAGS: | |||
92 | args.finish()?; | 92 | args.finish()?; |
93 | run_pre_cache() | 93 | run_pre_cache() |
94 | } | 94 | } |
95 | "release" => { | ||
96 | let dry_run = args.contains("--dry-run"); | ||
97 | args.finish()?; | ||
98 | run_release(dry_run) | ||
99 | } | ||
95 | _ => { | 100 | _ => { |
96 | eprintln!( | 101 | eprintln!( |
97 | "\ | 102 | "\ |
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs new file mode 100644 index 000000000..3e30e7279 --- /dev/null +++ b/xtask/src/not_bash.rs | |||
@@ -0,0 +1,165 @@ | |||
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::{Path, PathBuf}, | ||
8 | process::{Command, Stdio}, | ||
9 | }; | ||
10 | |||
11 | use anyhow::{bail, Context, Result}; | ||
12 | |||
13 | pub mod fs2 { | ||
14 | use std::{fs, path::Path}; | ||
15 | |||
16 | use anyhow::{Context, Result}; | ||
17 | |||
18 | pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<fs::ReadDir> { | ||
19 | let path = path.as_ref(); | ||
20 | fs::read_dir(path).with_context(|| format!("Failed to read {}", path.display())) | ||
21 | } | ||
22 | |||
23 | pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> { | ||
24 | let path = path.as_ref(); | ||
25 | fs::write(path, contents).with_context(|| format!("Failed to write {}", path.display())) | ||
26 | } | ||
27 | |||
28 | pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> { | ||
29 | let from = from.as_ref(); | ||
30 | let to = to.as_ref(); | ||
31 | fs::copy(from, to) | ||
32 | .with_context(|| format!("Failed to copy {} to {}", from.display(), to.display())) | ||
33 | } | ||
34 | |||
35 | pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<()> { | ||
36 | let path = path.as_ref(); | ||
37 | fs::remove_file(path).with_context(|| format!("Failed to remove file {}", path.display())) | ||
38 | } | ||
39 | |||
40 | pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> Result<()> { | ||
41 | let path = path.as_ref(); | ||
42 | fs::remove_dir_all(path).with_context(|| format!("Failed to remove dir {}", path.display())) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | macro_rules! _run { | ||
47 | ($($expr:expr),*) => { | ||
48 | run!($($expr),*; echo = true) | ||
49 | }; | ||
50 | ($($expr:expr),* ; echo = $echo:expr) => { | ||
51 | $crate::not_bash::run_process(format!($($expr),*), $echo) | ||
52 | }; | ||
53 | } | ||
54 | pub(crate) use _run as run; | ||
55 | |||
56 | pub struct Pushd { | ||
57 | _p: (), | ||
58 | } | ||
59 | |||
60 | pub fn pushd(path: impl Into<PathBuf>) -> Pushd { | ||
61 | Env::with(|env| env.pushd(path.into())); | ||
62 | Pushd { _p: () } | ||
63 | } | ||
64 | |||
65 | impl Drop for Pushd { | ||
66 | fn drop(&mut self) { | ||
67 | Env::with(|env| env.popd()) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | pub fn rm(glob: &str) -> Result<()> { | ||
72 | let cwd = Env::with(|env| env.cwd()); | ||
73 | ls(glob)?.into_iter().try_for_each(|it| fs::remove_file(cwd.join(it)))?; | ||
74 | Ok(()) | ||
75 | } | ||
76 | |||
77 | pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { | ||
78 | let path = path.as_ref(); | ||
79 | if path.is_file() { | ||
80 | fs2::remove_file(path) | ||
81 | } else { | ||
82 | fs2::remove_dir_all(path) | ||
83 | } | ||
84 | } | ||
85 | |||
86 | pub fn ls(glob: &str) -> Result<Vec<PathBuf>> { | ||
87 | let cwd = Env::with(|env| env.cwd()); | ||
88 | let mut res = Vec::new(); | ||
89 | for entry in fs::read_dir(&cwd)? { | ||
90 | let entry = entry?; | ||
91 | if matches(&entry.file_name(), glob) { | ||
92 | let path = entry.path(); | ||
93 | let path = path.strip_prefix(&cwd).unwrap(); | ||
94 | res.push(path.to_path_buf()) | ||
95 | } | ||
96 | } | ||
97 | return Ok(res); | ||
98 | |||
99 | fn matches(file_name: &OsStr, glob: &str) -> bool { | ||
100 | assert!(glob.starts_with('*')); | ||
101 | file_name.to_string_lossy().ends_with(&glob[1..]) | ||
102 | } | ||
103 | } | ||
104 | |||
105 | #[doc(hidden)] | ||
106 | pub fn run_process(cmd: String, echo: bool) -> Result<String> { | ||
107 | run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) | ||
108 | } | ||
109 | |||
110 | fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { | ||
111 | let cwd = Env::with(|env| env.cwd()); | ||
112 | let mut args = shelx(cmd); | ||
113 | let binary = args.remove(0); | ||
114 | |||
115 | if echo { | ||
116 | println!("> {}", cmd) | ||
117 | } | ||
118 | |||
119 | let output = Command::new(binary) | ||
120 | .args(args) | ||
121 | .current_dir(cwd) | ||
122 | .stdin(Stdio::null()) | ||
123 | .stderr(Stdio::inherit()) | ||
124 | .output()?; | ||
125 | let stdout = String::from_utf8(output.stdout)?; | ||
126 | |||
127 | if echo { | ||
128 | print!("{}", stdout) | ||
129 | } | ||
130 | |||
131 | if !output.status.success() { | ||
132 | bail!("{}", output.status) | ||
133 | } | ||
134 | |||
135 | Ok(stdout.trim().to_string()) | ||
136 | } | ||
137 | |||
138 | // FIXME: some real shell lexing here | ||
139 | fn shelx(cmd: &str) -> Vec<String> { | ||
140 | cmd.split_whitespace().map(|it| it.to_string()).collect() | ||
141 | } | ||
142 | |||
143 | #[derive(Default)] | ||
144 | struct Env { | ||
145 | pushd_stack: Vec<PathBuf>, | ||
146 | } | ||
147 | |||
148 | impl Env { | ||
149 | fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { | ||
150 | thread_local! { | ||
151 | static ENV: RefCell<Env> = Default::default(); | ||
152 | } | ||
153 | ENV.with(|it| f(&mut *it.borrow_mut())) | ||
154 | } | ||
155 | |||
156 | fn pushd(&mut self, dir: PathBuf) { | ||
157 | self.pushd_stack.push(dir) | ||
158 | } | ||
159 | fn popd(&mut self) { | ||
160 | self.pushd_stack.pop().unwrap(); | ||
161 | } | ||
162 | fn cwd(&self) -> PathBuf { | ||
163 | self.pushd_stack.last().cloned().unwrap_or_else(|| env::current_dir().unwrap()) | ||
164 | } | ||
165 | } | ||
diff --git a/xtask/src/pre_commit.rs b/xtask/src/pre_commit.rs index 88e868ca6..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 String::from_utf8(diff.stdout)?.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(()) |