mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Allow to set env vars and pipe stdin via not_bash
This commit is contained in:
parent
36775ef0d0
commit
5f0008040e
2 changed files with 79 additions and 92 deletions
107
xtask/src/lib.rs
107
xtask/src/lib.rs
|
@ -12,21 +12,18 @@ mod ast_src;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
io::Write,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use walkdir::{DirEntry, WalkDir};
|
use walkdir::{DirEntry, WalkDir};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::Mode,
|
codegen::Mode,
|
||||||
not_bash::{date_iso, fs2, pushd, rm_rf, run},
|
not_bash::{date_iso, fs2, pushd, pushenv, rm_rf, run},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use anyhow::{bail, Context as _, Result};
|
pub use anyhow::{bail, Context as _, Result};
|
||||||
|
|
||||||
const RUSTFMT_TOOLCHAIN: &str = "stable";
|
|
||||||
|
|
||||||
pub fn project_root() -> PathBuf {
|
pub fn project_root() -> PathBuf {
|
||||||
Path::new(
|
Path::new(
|
||||||
&env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
|
&env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
|
||||||
|
@ -54,77 +51,44 @@ pub fn rust_files(path: &Path) -> impl Iterator<Item = PathBuf> {
|
||||||
|
|
||||||
pub fn run_rustfmt(mode: Mode) -> Result<()> {
|
pub fn run_rustfmt(mode: Mode) -> Result<()> {
|
||||||
let _dir = pushd(project_root());
|
let _dir = pushd(project_root());
|
||||||
|
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
|
||||||
ensure_rustfmt()?;
|
ensure_rustfmt()?;
|
||||||
|
match mode {
|
||||||
if Command::new("cargo")
|
Mode::Overwrite => run!("cargo fmt"),
|
||||||
.env("RUSTUP_TOOLCHAIN", RUSTFMT_TOOLCHAIN)
|
Mode::Verify => run!("cargo fmt -- --check"),
|
||||||
.args(&["fmt", "--"])
|
}?;
|
||||||
.args(if mode == Mode::Verify { &["--check"][..] } else { &[] })
|
|
||||||
.stderr(Stdio::inherit())
|
|
||||||
.status()?
|
|
||||||
.success()
|
|
||||||
{
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
|
||||||
bail!("Rustfmt failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reformat(text: impl std::fmt::Display) -> Result<String> {
|
fn reformat(text: impl std::fmt::Display) -> Result<String> {
|
||||||
|
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
|
||||||
ensure_rustfmt()?;
|
ensure_rustfmt()?;
|
||||||
let mut rustfmt = Command::new("rustfmt")
|
let stdout = run!(
|
||||||
.env("RUSTUP_TOOLCHAIN", RUSTFMT_TOOLCHAIN)
|
"rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display();
|
||||||
.args(&["--config-path"])
|
<text.to_string().as_bytes()
|
||||||
.arg(project_root().join("rustfmt.toml"))
|
)?;
|
||||||
.args(&["--config", "fn_single_line=true"])
|
|
||||||
.stdin(Stdio::piped())
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.spawn()?;
|
|
||||||
write!(rustfmt.stdin.take().unwrap(), "{}", text)?;
|
|
||||||
let output = rustfmt.wait_with_output()?;
|
|
||||||
let stdout = String::from_utf8(output.stdout)?;
|
|
||||||
let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
|
let preamble = "Generated file, do not edit by hand, see `xtask/src/codegen`";
|
||||||
Ok(format!("//! {}\n\n{}", preamble, stdout))
|
Ok(format!("//! {}\n\n{}\n", preamble, stdout))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_rustfmt() -> Result<()> {
|
fn ensure_rustfmt() -> Result<()> {
|
||||||
match Command::new("rustfmt")
|
let out = run!("rustfmt --version")?;
|
||||||
.args(&["--version"])
|
if !out.contains("stable") {
|
||||||
.env("RUSTUP_TOOLCHAIN", RUSTFMT_TOOLCHAIN)
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.spawn()
|
|
||||||
.and_then(|child| child.wait_with_output())
|
|
||||||
{
|
|
||||||
Ok(output)
|
|
||||||
if output.status.success()
|
|
||||||
&& std::str::from_utf8(&output.stdout)?.contains(RUSTFMT_TOOLCHAIN) =>
|
|
||||||
{
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
bail!(
|
bail!(
|
||||||
"Failed to run rustfmt from toolchain '{0}'. \
|
"Failed to run rustfmt from toolchain 'stable'. \
|
||||||
Please run `rustup component add rustfmt --toolchain {0}` to install it.",
|
Please run `rustup component add rustfmt --toolchain stable` to install it.",
|
||||||
RUSTFMT_TOOLCHAIN,
|
)
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_clippy() -> Result<()> {
|
pub fn run_clippy() -> Result<()> {
|
||||||
match Command::new("cargo")
|
if run!("cargo clippy --version").is_err() {
|
||||||
.args(&["clippy", "--version"])
|
bail!(
|
||||||
.stderr(Stdio::null())
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.status()
|
|
||||||
{
|
|
||||||
Ok(status) if status.success() => (),
|
|
||||||
_ => bail!(
|
|
||||||
"Failed run cargo clippy. \
|
"Failed run cargo clippy. \
|
||||||
Please run `rustup component add clippy` to install it.",
|
Please run `rustup component add clippy` to install it.",
|
||||||
),
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
let allowed_lints = [
|
let allowed_lints = [
|
||||||
"clippy::collapsible_if",
|
"clippy::collapsible_if",
|
||||||
|
@ -138,33 +102,18 @@ pub fn run_clippy() -> Result<()> {
|
||||||
|
|
||||||
pub fn run_fuzzer() -> Result<()> {
|
pub fn run_fuzzer() -> Result<()> {
|
||||||
let _d = pushd("./crates/ra_syntax");
|
let _d = pushd("./crates/ra_syntax");
|
||||||
|
let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
|
||||||
if run!("cargo fuzz --help").is_err() {
|
if run!("cargo fuzz --help").is_err() {
|
||||||
run!("cargo install cargo-fuzz")?;
|
run!("cargo install cargo-fuzz")?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Expecting nightly rustc
|
// Expecting nightly rustc
|
||||||
match Command::new("rustc")
|
let out = run!("rustc --version")?;
|
||||||
.args(&["--version"])
|
if !out.contains("nightly") {
|
||||||
.env("RUSTUP_TOOLCHAIN", "nightly")
|
bail!("fuzz tests require nightly rustc")
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.spawn()
|
|
||||||
.and_then(|child| child.wait_with_output())
|
|
||||||
{
|
|
||||||
Ok(output)
|
|
||||||
if output.status.success()
|
|
||||||
&& std::str::from_utf8(&output.stdout)?.contains("nightly") => {}
|
|
||||||
_ => bail!("fuzz tests require nightly rustc"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = Command::new("cargo")
|
run!("cargo fuzz run parser")?;
|
||||||
.env("RUSTUP_TOOLCHAIN", "nightly")
|
|
||||||
.args(&["fuzz", "run", "parser"])
|
|
||||||
.stderr(Stdio::inherit())
|
|
||||||
.status()?;
|
|
||||||
if !status.success() {
|
|
||||||
bail!("{}", status);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
env,
|
env,
|
||||||
|
ffi::OsString,
|
||||||
|
io::Write,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
};
|
};
|
||||||
|
@ -57,7 +59,10 @@ macro_rules! _run {
|
||||||
run!($($expr),*; echo = true)
|
run!($($expr),*; echo = true)
|
||||||
};
|
};
|
||||||
($($expr:expr),* ; echo = $echo:expr) => {
|
($($expr:expr),* ; echo = $echo:expr) => {
|
||||||
$crate::not_bash::run_process(format!($($expr),*), $echo)
|
$crate::not_bash::run_process(format!($($expr),*), $echo, None)
|
||||||
|
};
|
||||||
|
($($expr:expr),* ; <$stdin:expr) => {
|
||||||
|
$crate::not_bash::run_process(format!($($expr),*), false, Some($stdin))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use _run as run;
|
pub(crate) use _run as run;
|
||||||
|
@ -77,6 +82,21 @@ impl Drop for Pushd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Pushenv {
|
||||||
|
_p: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pushenv(var: &str, value: &str) -> Pushenv {
|
||||||
|
Env::with(|env| env.pushenv(var.into(), value.into()));
|
||||||
|
Pushenv { _p: () }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Pushenv {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
Env::with(|env| env.popenv())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
|
pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
|
@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn run_process(cmd: String, echo: bool) -> Result<String> {
|
pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
|
||||||
run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd))
|
run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn date_iso() -> Result<String> {
|
pub fn date_iso() -> Result<String> {
|
||||||
run!("date --iso --utc")
|
run!("date --iso --utc")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_process_inner(cmd: &str, echo: bool) -> Result<String> {
|
fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
|
||||||
let mut args = shelx(cmd);
|
let mut args = shelx(cmd);
|
||||||
let binary = args.remove(0);
|
let binary = args.remove(0);
|
||||||
let current_dir = Env::with(|it| it.cwd().to_path_buf());
|
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> {
|
||||||
println!("> {}", cmd)
|
println!("> {}", cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = Command::new(binary)
|
let mut command = Command::new(binary);
|
||||||
.args(args)
|
command.args(args).current_dir(current_dir).stderr(Stdio::inherit());
|
||||||
.current_dir(current_dir)
|
let output = match stdin {
|
||||||
.stdin(Stdio::null())
|
None => command.stdin(Stdio::null()).output(),
|
||||||
.stderr(Stdio::inherit())
|
Some(stdin) => {
|
||||||
.output()?;
|
command.stdin(Stdio::piped()).stdout(Stdio::piped());
|
||||||
|
let mut process = command.spawn()?;
|
||||||
|
process.stdin.take().unwrap().write_all(stdin)?;
|
||||||
|
process.wait_with_output()
|
||||||
|
}
|
||||||
|
}?;
|
||||||
let stdout = String::from_utf8(output.stdout)?;
|
let stdout = String::from_utf8(output.stdout)?;
|
||||||
|
|
||||||
if echo {
|
if echo {
|
||||||
|
@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec<String> {
|
||||||
|
|
||||||
struct Env {
|
struct Env {
|
||||||
pushd_stack: Vec<PathBuf>,
|
pushd_stack: Vec<PathBuf>,
|
||||||
|
pushenv_stack: Vec<(OsString, Option<OsString>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Env {
|
impl Env {
|
||||||
fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
|
fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static ENV: RefCell<Env> = RefCell::new(Env {
|
static ENV: RefCell<Env> = RefCell::new(Env {
|
||||||
pushd_stack: vec![env::current_dir().unwrap()]
|
pushd_stack: vec![env::current_dir().unwrap()],
|
||||||
|
pushenv_stack: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ENV.with(|it| f(&mut *it.borrow_mut()))
|
ENV.with(|it| f(&mut *it.borrow_mut()))
|
||||||
|
@ -154,6 +181,17 @@ impl Env {
|
||||||
self.pushd_stack.pop().unwrap();
|
self.pushd_stack.pop().unwrap();
|
||||||
env::set_current_dir(self.cwd()).unwrap();
|
env::set_current_dir(self.cwd()).unwrap();
|
||||||
}
|
}
|
||||||
|
fn pushenv(&mut self, var: OsString, value: OsString) {
|
||||||
|
self.pushenv_stack.push((var.clone(), env::var_os(&var)));
|
||||||
|
env::set_var(var, value)
|
||||||
|
}
|
||||||
|
fn popenv(&mut self) {
|
||||||
|
let (var, value) = self.pushenv_stack.pop().unwrap();
|
||||||
|
match value {
|
||||||
|
None => env::remove_var(var),
|
||||||
|
Some(value) => env::set_var(var, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn cwd(&self) -> &Path {
|
fn cwd(&self) -> &Path {
|
||||||
self.pushd_stack.last().unwrap()
|
self.pushd_stack.last().unwrap()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue