]> git.lizzy.rs Git - rust.git/commitdiff
Rewrite update-all-references bash scripts in Rust
authorPhilipp Hansch <dev@phansch.net>
Wed, 2 Dec 2020 17:20:02 +0000 (18:20 +0100)
committerPhilipp Hansch <dev@phansch.net>
Sat, 12 Dec 2020 14:09:57 +0000 (15:09 +0100)
This replaces the `update-all-references` scripts with a single

    cargo dev bless

command.

cc #5394

clippy_dev/src/bless.rs [new file with mode: 0644]
clippy_dev/src/lib.rs
clippy_dev/src/main.rs
doc/adding_lints.md
doc/basics.md
tests/ui-cargo/update-all-references.sh
tests/ui-cargo/update-references.sh [deleted file]
tests/ui-toml/update-all-references.sh
tests/ui-toml/update-references.sh [deleted file]
tests/ui/update-all-references.sh
tests/ui/update-references.sh [deleted file]

diff --git a/clippy_dev/src/bless.rs b/clippy_dev/src/bless.rs
new file mode 100644 (file)
index 0000000..45e403f
--- /dev/null
@@ -0,0 +1,71 @@
+//! `bless` updates the 'expected output' files in the repo with changed output files
+//! from the last test run.
+
+use std::env;
+use std::ffi::OsStr;
+use std::fs;
+use std::lazy::SyncLazy;
+use std::path::PathBuf;
+use walkdir::WalkDir;
+
+use crate::clippy_project_root;
+
+// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
+pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
+    Some(v) => v.into(),
+    None => env::current_dir().unwrap().join("target"),
+});
+
+pub fn bless() {
+    let test_dirs = [
+        clippy_project_root().join("tests").join("ui"),
+        clippy_project_root().join("tests").join("ui-toml"),
+        clippy_project_root().join("tests").join("ui-cargo"),
+    ];
+    for test_dir in &test_dirs {
+        WalkDir::new(test_dir)
+            .into_iter()
+            .filter_map(Result::ok)
+            .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
+            .for_each(|f| {
+                update_test_file(f.path().with_extension("stdout"));
+                update_test_file(f.path().with_extension("stderr"));
+                update_test_file(f.path().with_extension("fixed"));
+            });
+    }
+}
+
+fn update_test_file(test_file_path: PathBuf) {
+    let build_output_path = build_dir().join(PathBuf::from(test_file_path.file_name().unwrap()));
+    let relative_test_file_path = test_file_path.strip_prefix(clippy_project_root()).unwrap();
+
+    // If compiletest did not write any changes during the test run,
+    // we don't have to update anything
+    if !build_output_path.exists() {
+        return;
+    }
+
+    let build_output = fs::read(&build_output_path).expect("Unable to read build output file");
+    let test_file = fs::read(&test_file_path).expect("Unable to read test file");
+
+    if build_output != test_file {
+        // If a test run caused an output file to change, update the test file
+        println!("updating {}", &relative_test_file_path.display());
+        fs::copy(build_output_path, &test_file_path).expect("Could not update test file");
+
+        if test_file.is_empty() {
+            // If we copied over an empty output file, we remove it
+            println!("removing {}", &relative_test_file_path.display());
+            fs::remove_file(test_file_path).expect("Could not remove test file");
+        }
+    }
+}
+
+fn build_dir() -> PathBuf {
+    let profile = format!("{}", env::var("PROFILE").unwrap_or("debug".to_string()));
+    let mut path = PathBuf::new();
+    path.push(CARGO_TARGET_DIR.clone());
+    path.push(profile);
+    path.push("test_build_base");
+    path
+}
index f51c45e9eb5931a170c16c0dd187364fc2d510c7..17cc08ee10fea312f5b3d392991f61326be4f362 100644 (file)
@@ -10,6 +10,7 @@
 use std::path::{Path, PathBuf};
 use walkdir::WalkDir;
 
+pub mod bless;
 pub mod fmt;
 pub mod new_lint;
 pub mod ra_setup;
index 7a8cbd5251da9012f2dc4d2c82f5182ca06882cb..f66855620e734c7290d80fb1977be8cccacebf0e 100644 (file)
@@ -1,10 +1,11 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 
 use clap::{App, Arg, SubCommand};
-use clippy_dev::{fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
+use clippy_dev::{bless, fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
 
 fn main() {
     let matches = App::new("Clippy developer tooling")
+        .subcommand(SubCommand::with_name("bless").about("bless the test output changes"))
         .subcommand(
             SubCommand::with_name("fmt")
                 .about("Run rustfmt on all projects and tests")
@@ -116,6 +117,9 @@ fn main() {
         .get_matches();
 
     match matches.subcommand() {
+        ("bless", Some(_)) => {
+            bless::bless();
+        },
         ("fmt", Some(matches)) => {
             fmt::run(matches.is_present("check"), matches.is_present("verbose"));
         },
index a723b0a4c20f7ba1e33cd088c6992d2ed3d7e31a..60dfdb76650a1e2d0363ecd5786560a9da9990a2 100644 (file)
@@ -98,12 +98,12 @@ While we are working on implementing our lint, we can keep running the UI
 test. That allows us to check if the output is turning into what we want.
 
 Once we are satisfied with the output, we need to run
-`tests/ui/update-all-references.sh` to update the `.stderr` file for our lint.
+`cargo dev bless` to update the `.stderr` file for our lint.
 Please note that, we should run `TESTNAME=foo_functions cargo uitest`
-every time before running `tests/ui/update-all-references.sh`.
+every time before running `cargo dev bless`.
 Running `TESTNAME=foo_functions cargo uitest` should pass then. When we commit
 our lint, we need to commit the generated `.stderr` files, too. In general, you
-should only commit files changed by `tests/ui/update-all-references.sh` for the
+should only commit files changed by `cargo dev bless` for the
 specific lint you are creating/editing. Note that if the generated files are
 empty, they should be removed.
 
@@ -122,8 +122,7 @@ we will find by default two new crates, each with its manifest file:
 If you need more cases, you can copy one of those crates (under `foo_categories`) and rename it.
 
 The process of generating the `.stderr` file is the same, and prepending the `TESTNAME`
-variable to `cargo uitest` works too, but the script to update the references
-is in another path: `tests/ui-cargo/update-all-references.sh`.
+variable to `cargo uitest` works too.
 
 ## Rustfix tests
 
@@ -133,7 +132,7 @@ additionally run [rustfix] for that test. Rustfix will apply the suggestions
 from the lint to the code of the test file and compare that to the contents of
 a `.fixed` file.
 
-Use `tests/ui/update-all-references.sh` to automatically generate the
+Use `cargo dev bless` to automatically generate the
 `.fixed` file after running the tests.
 
 [rustfix]: https://github.com/rust-lang/rustfix
@@ -368,7 +367,7 @@ fn is_foo_fn(fn_kind: FnKind<'_>) -> bool {
 
 Now we should also run the full test suite with `cargo test`. At this point
 running `cargo test` should produce the expected output. Remember to run
-`tests/ui/update-all-references.sh` to update the `.stderr` file.
+`cargo dev bless` to update the `.stderr` file.
 
 `cargo test` (as opposed to `cargo uitest`) will also ensure that our lint
 implementation is not violating any Clippy lints itself.
index 8b2a8a238900a7aab09f24bb6e7be16d807a8cc8..dc71f022773cc4ca6899e1dd0aa1f2f62bf0c5e3 100644 (file)
@@ -61,7 +61,7 @@ If the output of a [UI test] differs from the expected output, you can update th
 reference file with:
 
 ```bash
-sh tests/ui/update-all-references.sh
+cargo dev bless
 ```
 
 For example, this is necessary, if you fix a typo in an error message of a lint
index 7028b251ea0307bb669524afb702a8d62a038924..4391499a1e1f8e779470f3d1927dcd95c88eadd1 100755 (executable)
@@ -1,18 +1,3 @@
 #!/bin/bash
-#
-# A script to update the references for all tests. The idea is that
-# you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. You then
-# run this script, which will copy those files over. If you find
-# yourself manually editing a foo.stderr file, you're doing it wrong.
-#
-# See all `update-references.sh`, if you just want to update a single test.
 
-if [[ "$1" == "--help" || "$1" == "-h" ]]; then
-    echo "usage: $0"
-fi
-
-BUILD_DIR=$PWD/target/debug/test_build_base
-MY_DIR=$(dirname "$0")
-cd "$MY_DIR" || exit
-find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
+echo "Please use 'cargo dev bless' instead."
diff --git a/tests/ui-cargo/update-references.sh b/tests/ui-cargo/update-references.sh
deleted file mode 100755 (executable)
index 2ab5116..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-# A script to update the references for particular tests. The idea is
-# that you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. This
-# script will then copy that output and replace the "expected output"
-# files. You can then commit the changes.
-#
-# If you find yourself manually editing a foo.stderr file, you're
-# doing it wrong.
-
-if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
-    echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
-    echo ""
-    echo "For example:"
-    echo "   $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
-fi
-
-MYDIR=$(dirname "$0")
-
-BUILD_DIR="$1"
-shift
-
-while [[ "$1" != "" ]]; do
-    STDERR_NAME="${1/%.rs/.stderr}"
-    STDOUT_NAME="${1/%.rs/.stdout}"
-    shift
-    if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
-        echo updating "$MYDIR"/"$STDOUT_NAME"
-        cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
-        if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDOUT_NAME"
-            rm "$MYDIR"/"$STDOUT_NAME"
-        fi
-    fi
-    if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
-        echo updating "$MYDIR"/"$STDERR_NAME"
-        cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
-        if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDERR_NAME"
-            rm "$MYDIR"/"$STDERR_NAME"
-        fi
-    fi
-done
index 7028b251ea0307bb669524afb702a8d62a038924..4391499a1e1f8e779470f3d1927dcd95c88eadd1 100755 (executable)
@@ -1,18 +1,3 @@
 #!/bin/bash
-#
-# A script to update the references for all tests. The idea is that
-# you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. You then
-# run this script, which will copy those files over. If you find
-# yourself manually editing a foo.stderr file, you're doing it wrong.
-#
-# See all `update-references.sh`, if you just want to update a single test.
 
-if [[ "$1" == "--help" || "$1" == "-h" ]]; then
-    echo "usage: $0"
-fi
-
-BUILD_DIR=$PWD/target/debug/test_build_base
-MY_DIR=$(dirname "$0")
-cd "$MY_DIR" || exit
-find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
+echo "Please use 'cargo dev bless' instead."
diff --git a/tests/ui-toml/update-references.sh b/tests/ui-toml/update-references.sh
deleted file mode 100755 (executable)
index 2ab5116..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-# A script to update the references for particular tests. The idea is
-# that you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. This
-# script will then copy that output and replace the "expected output"
-# files. You can then commit the changes.
-#
-# If you find yourself manually editing a foo.stderr file, you're
-# doing it wrong.
-
-if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
-    echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
-    echo ""
-    echo "For example:"
-    echo "   $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
-fi
-
-MYDIR=$(dirname "$0")
-
-BUILD_DIR="$1"
-shift
-
-while [[ "$1" != "" ]]; do
-    STDERR_NAME="${1/%.rs/.stderr}"
-    STDOUT_NAME="${1/%.rs/.stdout}"
-    shift
-    if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
-        echo updating "$MYDIR"/"$STDOUT_NAME"
-        cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
-        if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDOUT_NAME"
-            rm "$MYDIR"/"$STDOUT_NAME"
-        fi
-    fi
-    if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
-        echo updating "$MYDIR"/"$STDERR_NAME"
-        cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
-        if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDERR_NAME"
-            rm "$MYDIR"/"$STDERR_NAME"
-        fi
-    fi
-done
index 30ba9188db43d35079838dd84f56c72e46987965..4391499a1e1f8e779470f3d1927dcd95c88eadd1 100755 (executable)
@@ -1,21 +1,3 @@
 #!/bin/bash
 
-# A script to update the references for all tests. The idea is that
-# you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. You then
-# run this script, which will copy those files over. If you find
-# yourself manually editing a foo.stderr file, you're doing it wrong.
-#
-# See all `update-references.sh`, if you just want to update a single test.
-
-if [[ "$1" == "--help" || "$1" == "-h" ]]; then
-    echo "usage: $0"
-fi
-
-CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-$PWD/target}
-PROFILE=${PROFILE:-debug}
-BUILD_DIR=${CARGO_TARGET_DIR}/${PROFILE}/test_build_base
-
-MY_DIR=$(dirname "$0")
-cd "$MY_DIR" || exit
-find . -name '*.rs' -exec ./update-references.sh "$BUILD_DIR" {} +
+echo "Please use 'cargo dev bless' instead."
diff --git a/tests/ui/update-references.sh b/tests/ui/update-references.sh
deleted file mode 100755 (executable)
index e16ed60..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-
-# A script to update the references for particular tests. The idea is
-# that you do a run, which will generate files in the build directory
-# containing the (normalized) actual output of the compiler. This
-# script will then copy that output and replace the "expected output"
-# files. You can then commit the changes.
-#
-# If you find yourself manually editing a `foo.stderr` file, you're
-# doing it wrong.
-
-if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then
-    echo "usage: $0 <build-directory> <relative-path-to-rs-files>"
-    echo ""
-    echo "For example:"
-    echo "   $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs"
-fi
-
-MYDIR=$(dirname "$0")
-
-BUILD_DIR="$1"
-shift
-
-while [[ "$1" != "" ]]; do
-    STDERR_NAME="${1/%.rs/.stderr}"
-    STDOUT_NAME="${1/%.rs/.stdout}"
-    FIXED_NAME="${1/%.rs/.fixed}"
-    shift
-    if [[ -f "$BUILD_DIR"/"$STDOUT_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"); then
-        echo updating "$MYDIR"/"$STDOUT_NAME"
-        cp "$BUILD_DIR"/"$STDOUT_NAME" "$MYDIR"/"$STDOUT_NAME"
-        if [[ ! -s "$MYDIR"/"$STDOUT_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDOUT_NAME"
-            rm "$MYDIR"/"$STDOUT_NAME"
-        fi
-    fi
-    if [[ -f "$BUILD_DIR"/"$STDERR_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"); then
-        echo updating "$MYDIR"/"$STDERR_NAME"
-        cp "$BUILD_DIR"/"$STDERR_NAME" "$MYDIR"/"$STDERR_NAME"
-        if [[ ! -s "$MYDIR"/"$STDERR_NAME" ]]; then
-            echo removing "$MYDIR"/"$STDERR_NAME"
-            rm "$MYDIR"/"$STDERR_NAME"
-        fi
-    fi
-    if [[ -f "$BUILD_DIR"/"$FIXED_NAME" ]] && \
-           ! (cmp -s -- "$BUILD_DIR"/"$FIXED_NAME" "$MYDIR"/"$FIXED_NAME"); then
-        echo updating "$MYDIR"/"$FIXED_NAME"
-        cp "$BUILD_DIR"/"$FIXED_NAME" "$MYDIR"/"$FIXED_NAME"
-        if [[ ! -s "$MYDIR"/"$FIXED_NAME" ]]; then
-            echo removing "$MYDIR"/"$FIXED_NAME"
-            rm "$MYDIR"/"$FIXED_NAME"
-        fi
-    fi
-done