]> git.lizzy.rs Git - rust.git/commitdiff
Allow to set env vars and pipe stdin via not_bash
authorAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 30 Apr 2020 13:14:55 +0000 (15:14 +0200)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 30 Apr 2020 13:20:47 +0000 (15:20 +0200)
xtask/src/lib.rs
xtask/src/not_bash.rs

index bf4d85dcb08d4c5e64cf2d1371b3fb723034d345..2b7a461e568d3b0cebb429a1a2d74e1c2327b598 100644 (file)
 
 use std::{
     env,
-    io::Write,
     path::{Path, PathBuf},
-    process::{Command, Stdio},
 };
+
 use walkdir::{DirEntry, WalkDir};
 
 use crate::{
     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};
 
-const RUSTFMT_TOOLCHAIN: &str = "stable";
-
 pub fn project_root() -> PathBuf {
     Path::new(
         &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
@@ -54,77 +51,44 @@ fn is_hidden(entry: &DirEntry) -> bool {
 
 pub fn run_rustfmt(mode: Mode) -> Result<()> {
     let _dir = pushd(project_root());
+    let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
     ensure_rustfmt()?;
-
-    if Command::new("cargo")
-        .env("RUSTUP_TOOLCHAIN", RUSTFMT_TOOLCHAIN)
-        .args(&["fmt", "--"])
-        .args(if mode == Mode::Verify { &["--check"][..] } else { &[] })
-        .stderr(Stdio::inherit())
-        .status()?
-        .success()
-    {
-        Ok(())
-    } else {
-        bail!("Rustfmt failed");
-    }
+    match mode {
+        Mode::Overwrite => run!("cargo fmt"),
+        Mode::Verify => run!("cargo fmt -- --check"),
+    }?;
+    Ok(())
 }
 
 fn reformat(text: impl std::fmt::Display) -> Result<String> {
+    let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
     ensure_rustfmt()?;
-    let mut rustfmt = Command::new("rustfmt")
-        .env("RUSTUP_TOOLCHAIN", RUSTFMT_TOOLCHAIN)
-        .args(&["--config-path"])
-        .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 stdout = run!(
+        "rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display();
+        <text.to_string().as_bytes()
+    )?;
     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<()> {
-    match Command::new("rustfmt")
-        .args(&["--version"])
-        .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!(
-                "Failed to run rustfmt from toolchain '{0}'. \
-                Please run `rustup component add rustfmt --toolchain {0}` to install it.",
-                RUSTFMT_TOOLCHAIN,
-            );
-        }
+    let out = run!("rustfmt --version")?;
+    if !out.contains("stable") {
+        bail!(
+            "Failed to run rustfmt from toolchain 'stable'. \
+             Please run `rustup component add rustfmt --toolchain stable` to install it.",
+        )
     }
+    Ok(())
 }
 
 pub fn run_clippy() -> Result<()> {
-    match Command::new("cargo")
-        .args(&["clippy", "--version"])
-        .stderr(Stdio::null())
-        .stdout(Stdio::null())
-        .status()
-    {
-        Ok(status) if status.success() => (),
-        _ => bail!(
+    if run!("cargo clippy --version").is_err() {
+        bail!(
             "Failed run cargo clippy. \
             Please run `rustup component add clippy` to install it.",
-        ),
-    };
+        )
+    }
 
     let allowed_lints = [
         "clippy::collapsible_if",
@@ -138,33 +102,18 @@ pub fn run_clippy() -> Result<()> {
 
 pub fn run_fuzzer() -> Result<()> {
     let _d = pushd("./crates/ra_syntax");
+    let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
     if run!("cargo fuzz --help").is_err() {
         run!("cargo install cargo-fuzz")?;
     };
 
     // Expecting nightly rustc
-    match Command::new("rustc")
-        .args(&["--version"])
-        .env("RUSTUP_TOOLCHAIN", "nightly")
-        .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 out = run!("rustc --version")?;
+    if !out.contains("nightly") {
+        bail!("fuzz tests require nightly rustc")
     }
 
-    let status = Command::new("cargo")
-        .env("RUSTUP_TOOLCHAIN", "nightly")
-        .args(&["fuzz", "run", "parser"])
-        .stderr(Stdio::inherit())
-        .status()?;
-    if !status.success() {
-        bail!("{}", status);
-    }
+    run!("cargo fuzz run parser")?;
     Ok(())
 }
 
index ef1699934918f1eea460cd6a6206e545c4f71b51..a6431e58633c18b0cad2b6244eb70c0212476e09 100644 (file)
@@ -3,6 +3,8 @@
 use std::{
     cell::RefCell,
     env,
+    ffi::OsString,
+    io::Write,
     path::{Path, PathBuf},
     process::{Command, Stdio},
 };
@@ -57,7 +59,10 @@ macro_rules! _run {
         run!($($expr),*; echo = true)
     };
     ($($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;
@@ -77,6 +82,21 @@ fn drop(&mut self) {
     }
 }
 
+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<()> {
     let path = path.as_ref();
     if !path.exists() {
@@ -90,15 +110,15 @@ pub fn rm_rf(path: impl AsRef<Path>) -> Result<()> {
 }
 
 #[doc(hidden)]
-pub fn run_process(cmd: String, echo: bool) -> Result<String> {
-    run_process_inner(&cmd, echo).with_context(|| format!("process `{}` failed", cmd))
+pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
+    run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd))
 }
 
 pub fn date_iso() -> Result<String> {
     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 binary = args.remove(0);
     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)
     }
 
-    let output = Command::new(binary)
-        .args(args)
-        .current_dir(current_dir)
-        .stdin(Stdio::null())
-        .stderr(Stdio::inherit())
-        .output()?;
+    let mut command = Command::new(binary);
+    command.args(args).current_dir(current_dir).stderr(Stdio::inherit());
+    let output = match stdin {
+        None => command.stdin(Stdio::null()).output(),
+        Some(stdin) => {
+            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)?;
 
     if echo {
@@ -133,13 +158,15 @@ fn shelx(cmd: &str) -> Vec<String> {
 
 struct Env {
     pushd_stack: Vec<PathBuf>,
+    pushenv_stack: Vec<(OsString, Option<OsString>)>,
 }
 
 impl Env {
     fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
         thread_local! {
             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()))
@@ -154,6 +181,17 @@ fn popd(&mut self) {
         self.pushd_stack.pop().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 {
         self.pushd_stack.last().unwrap()
     }