aboutsummaryrefslogtreecommitdiff
path: root/xtask/src
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src')
-rw-r--r--xtask/src/ast_src.rs2
-rw-r--r--xtask/src/lib.rs89
-rw-r--r--xtask/src/not_bash.rs60
3 files changed, 86 insertions, 65 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 9c02f7c6f..98c8644e4 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -595,7 +595,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
595 qualifier: Path, 595 qualifier: Path,
596 } 596 }
597 struct PathSegment { 597 struct PathSegment {
598 T![::], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] 598 T![::], T![crate], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
599 } 599 }
600 struct TypeArgList { 600 struct TypeArgList {
601 T![::], 601 T![::],
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index ec824a518..2b7a461e5 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -10,23 +10,19 @@ pub mod pre_commit;
10pub mod codegen; 10pub mod codegen;
11mod ast_src; 11mod ast_src;
12 12
13use anyhow::Context;
14use std::{ 13use std::{
15 env, 14 env,
16 io::Write,
17 path::{Path, PathBuf}, 15 path::{Path, PathBuf},
18 process::{Command, Stdio},
19}; 16};
17
20use walkdir::{DirEntry, WalkDir}; 18use walkdir::{DirEntry, WalkDir};
21 19
22use crate::{ 20use crate::{
23 codegen::Mode, 21 codegen::Mode,
24 not_bash::{date_iso, fs2, pushd, rm_rf, run}, 22 not_bash::{date_iso, fs2, pushd, pushenv, rm_rf, run},
25}; 23};
26 24
27pub use anyhow::Result; 25pub use anyhow::{bail, Context as _, Result};
28
29const TOOLCHAIN: &str = "stable";
30 26
31pub fn project_root() -> PathBuf { 27pub fn project_root() -> PathBuf {
32 Path::new( 28 Path::new(
@@ -55,54 +51,44 @@ pub fn rust_files(path: &Path) -> impl Iterator<Item = PathBuf> {
55 51
56pub fn run_rustfmt(mode: Mode) -> Result<()> { 52pub fn run_rustfmt(mode: Mode) -> Result<()> {
57 let _dir = pushd(project_root()); 53 let _dir = pushd(project_root());
54 let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
58 ensure_rustfmt()?; 55 ensure_rustfmt()?;
59 56 match mode {
60 let check = if mode == Mode::Verify { "--check" } else { "" }; 57 Mode::Overwrite => run!("cargo fmt"),
61 run!("rustup run {} -- cargo fmt -- {}", TOOLCHAIN, check)?; 58 Mode::Verify => run!("cargo fmt -- --check"),
59 }?;
62 Ok(()) 60 Ok(())
63} 61}
64 62
65fn reformat(text: impl std::fmt::Display) -> Result<String> { 63fn reformat(text: impl std::fmt::Display) -> Result<String> {
64 let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
66 ensure_rustfmt()?; 65 ensure_rustfmt()?;
67 let mut rustfmt = Command::new("rustup") 66 let stdout = run!(
68 .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"]) 67 "rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display();
69 .arg(project_root().join("rustfmt.toml")) 68 <text.to_string().as_bytes()
70 .args(&["--config", "fn_single_line=true"]) 69 )?;
71 .stdin(Stdio::piped())
72 .stdout(Stdio::piped())
73 .spawn()?;
74 write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
75 let output = rustfmt.wait_with_output()?;
76 let stdout = String::from_utf8(output.stdout)?;
77 let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`"; 70 let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
78 Ok(format!("//! {}\n\n{}", preamble, stdout)) 71 Ok(format!("//! {}\n\n{}\n", preamble, stdout))
79} 72}
80 73
81fn ensure_rustfmt() -> Result<()> { 74fn ensure_rustfmt() -> Result<()> {
82 match Command::new("rustup") 75 let out = run!("rustfmt --version")?;
83 .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"]) 76 if !out.contains("stable") {
84 .stderr(Stdio::null()) 77 bail!(
85 .stdout(Stdio::null()) 78 "Failed to run rustfmt from toolchain 'stable'. \
86 .status() 79 Please run `rustup component add rustfmt --toolchain stable` to install it.",
87 { 80 )
88 Ok(status) if status.success() => return Ok(()), 81 }
89 _ => (),
90 };
91 run!("rustup toolchain install {}", TOOLCHAIN)?;
92 run!("rustup component add rustfmt --toolchain {}", TOOLCHAIN)?;
93 Ok(()) 82 Ok(())
94} 83}
95 84
96pub fn run_clippy() -> Result<()> { 85pub fn run_clippy() -> Result<()> {
97 match Command::new("rustup") 86 if run!("cargo clippy --version").is_err() {
98 .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"]) 87 bail!(
99 .stderr(Stdio::null()) 88 "Failed run cargo clippy. \
100 .stdout(Stdio::null()) 89 Please run `rustup component add clippy` to install it.",
101 .status() 90 )
102 { 91 }
103 Ok(status) if status.success() => (),
104 _ => install_clippy().context("install clippy")?,
105 };
106 92
107 let allowed_lints = [ 93 let allowed_lints = [
108 "clippy::collapsible_if", 94 "clippy::collapsible_if",
@@ -110,27 +96,24 @@ pub fn run_clippy() -> Result<()> {
110 "clippy::nonminimal_bool", 96 "clippy::nonminimal_bool",
111 "clippy::redundant_pattern_matching", 97 "clippy::redundant_pattern_matching",
112 ]; 98 ];
113 run!( 99 run!("cargo clippy --all-features --all-targets -- -A {}", allowed_lints.join(" -A "))?;
114 "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
115 TOOLCHAIN,
116 allowed_lints.join(" -A ")
117 )?;
118 Ok(())
119}
120
121fn install_clippy() -> Result<()> {
122 run!("rustup toolchain install {}", TOOLCHAIN)?;
123 run!("rustup component add clippy --toolchain {}", TOOLCHAIN)?;
124 Ok(()) 100 Ok(())
125} 101}
126 102
127pub fn run_fuzzer() -> Result<()> { 103pub fn run_fuzzer() -> Result<()> {
128 let _d = pushd("./crates/ra_syntax"); 104 let _d = pushd("./crates/ra_syntax");
105 let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
129 if run!("cargo fuzz --help").is_err() { 106 if run!("cargo fuzz --help").is_err() {
130 run!("cargo install cargo-fuzz")?; 107 run!("cargo install cargo-fuzz")?;
131 }; 108 };
132 109
133 run!("rustup run nightly -- cargo fuzz run parser")?; 110 // Expecting nightly rustc
111 let out = run!("rustc --version")?;
112 if !out.contains("nightly") {
113 bail!("fuzz tests require nightly rustc")
114 }
115
116 run!("cargo fuzz run parser")?;
134 Ok(()) 117 Ok(())
135} 118}
136 119
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs
index ef1699934..a6431e586 100644
--- a/xtask/src/not_bash.rs
+++ b/xtask/src/not_bash.rs
@@ -3,6 +3,8 @@
3use std::{ 3use std::{
4 cell::RefCell, 4 cell::RefCell,
5 env, 5 env,
6 ffi::OsString,
7 io::Write,
6 path::{Path, PathBuf}, 8 path::{Path, PathBuf},
7 process::{Command, Stdio}, 9 process::{Command, Stdio},
8}; 10};
@@ -57,7 +59,10 @@ macro_rules! _run {
57 run!($($expr),*; echo = true) 59 run!($($expr),*; echo = true)
58 }; 60 };
59 ($($expr:expr),* ; echo = $echo:expr) => { 61 ($($expr:expr),* ; echo = $echo:expr) => {
60 $crate::not_bash::run_process(format!($($expr),*), $echo) 62 $crate::not_bash::run_process(format!($($expr),*), $echo, None)
63 };
64 ($($expr:expr),* ; <$stdin:expr) => {
65 $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin))
61 }; 66 };
62} 67}
63pub(crate) use _run as run; 68pub(crate) use _run as run;
@@ -77,6 +82,21 @@ impl Drop for Pushd {
77 } 82 }
78} 83}
79 84
85pub struct Pushenv {
86 _p: (),
87}
88
89pub fn pushenv(var: &str, value: &str) -> Pushenv {
90 Env::with(|env| env.pushenv(var.into(), value.into()));
91 Pushenv { _p: () }
92}
93
94impl Drop for Pushenv {
95 fn drop(&mut self) {
96 Env::with(|env| env.popenv())
97 }
98}
99
80pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> { 100pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
81 let path = path.as_ref(); 101 let path = path.as_ref();
82 if !path.exists() { 102 if !path.exists() {
@@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
90} 110}
91 111
92#[doc(hidden)] 112#[doc(hidden)]
93pub fn run_process(cmd: String, echo: bool) -> Result<String> { 113pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
94 run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd)) 114 run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd))
95} 115}
96 116
97pub fn date_iso() -> Result<String> { 117pub fn date_iso() -> Result<String> {
98 run!("date --iso --utc") 118 run!("date --iso --utc")
99} 119}
100 120
101fn run_process_inner(cmd: &str, echo: bool) -> Result<String> { 121fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
102 let mut args = shelx(cmd); 122 let mut args = shelx(cmd);
103 let binary = args.remove(0); 123 let binary = args.remove(0);
104 let current_dir = Env::with(|it| it.cwd().to_path_buf()); 124 let current_dir = Env::with(|it| it.cwd().to_path_buf());
@@ -107,12 +127,17 @@ fn run_process_inner(cmd: &str, echo: bool) -> Result<String> {
107 println!("> {}", cmd) 127 println!("> {}", cmd)
108 } 128 }
109 129
110 let output = Command::new(binary) 130 let mut command = Command::new(binary);
111 .args(args) 131 command.args(args).current_dir(current_dir).stderr(Stdio::inherit());
112 .current_dir(current_dir) 132 let output = match stdin {
113 .stdin(Stdio::null()) 133 None => command.stdin(Stdio::null()).output(),
114 .stderr(Stdio::inherit()) 134 Some(stdin) => {
115 .output()?; 135 command.stdin(Stdio::piped()).stdout(Stdio::piped());
136 let mut process = command.spawn()?;
137 process.stdin.take().unwrap().write_all(stdin)?;
138 process.wait_with_output()
139 }
140 }?;
116 let stdout = String::from_utf8(output.stdout)?; 141 let stdout = String::from_utf8(output.stdout)?;
117 142
118 if echo { 143 if echo {
@@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec<String> {
133 158
134struct Env { 159struct Env {
135 pushd_stack: Vec<PathBuf>, 160 pushd_stack: Vec<PathBuf>,
161 pushenv_stack: Vec<(OsString, Option<OsString>)>,
136} 162}
137 163
138impl Env { 164impl Env {
139 fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T { 165 fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
140 thread_local! { 166 thread_local! {
141 static ENV: RefCell<Env> = RefCell::new(Env { 167 static ENV: RefCell<Env> = RefCell::new(Env {
142 pushd_stack: vec![env::current_dir().unwrap()] 168 pushd_stack: vec![env::current_dir().unwrap()],
169 pushenv_stack: vec![],
143 }); 170 });
144 } 171 }
145 ENV.with(|it| f(&mut *it.borrow_mut())) 172 ENV.with(|it| f(&mut *it.borrow_mut()))
@@ -154,6 +181,17 @@ impl Env {
154 self.pushd_stack.pop().unwrap(); 181 self.pushd_stack.pop().unwrap();
155 env::set_current_dir(self.cwd()).unwrap(); 182 env::set_current_dir(self.cwd()).unwrap();
156 } 183 }
184 fn pushenv(&mut self, var: OsString, value: OsString) {
185 self.pushenv_stack.push((var.clone(), env::var_os(&var)));
186 env::set_var(var, value)
187 }
188 fn popenv(&mut self) {
189 let (var, value) = self.pushenv_stack.pop().unwrap();
190 match value {
191 None => env::remove_var(var),
192 Some(value) => env::set_var(var, value),
193 }
194 }
157 fn cwd(&self) -> &Path { 195 fn cwd(&self) -> &Path {
158 self.pushd_stack.last().unwrap() 196 self.pushd_stack.last().unwrap()
159 } 197 }