about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-01-20 21:33:22 -0500
committerGitHub <noreply@github.com>2023-01-20 21:33:22 -0500
commitd26c88c75231ab90b522fb061383f8e0156f1f20 (patch)
tree25afc1d1406b1e089aba16dcc52c8a4107691bfc
parent68b390ae2a099a598bfe44d4ec36ae15159c283f (diff)
parent540ca2ff2acf5539868b1f1c156f6c895fdc9ffc (diff)
downloadrust-d26c88c75231ab90b522fb061383f8e0156f1f20.tar.gz
rust-d26c88c75231ab90b522fb061383f8e0156f1f20.zip
Rollup merge of #107048 - DebugSteven:newer-x-check-cargo, r=albertlarsan68
check for x version updates

This PR adds a check to tidy to assert that the installed version of `x` is equal to the version in `src/tools/x/Cargo.toml`. It checks the installed version of `x` by parsing the output of `cargo install --list` (as an option proposed in this [issue](https://github.com/rust-lang/rust/issues/106469)).

It does not warn if `x` has not yet been installed, on the assumption that the user isn't interested in using it.
-rw-r--r--Cargo.lock1
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/x_version.rs68
5 files changed, 73 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b3afaaa35c0..7654f9c713c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5608,6 +5608,7 @@ dependencies = [
  "lazy_static",
  "miropt-test-tools",
  "regex",
+ "semver",
  "termcolor",
  "walkdir",
 ]
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 19812fc6f55..cdf1dd36604 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -12,6 +12,7 @@ miropt-test-tools = { path = "../miropt-test-tools" }
 lazy_static = "1"
 walkdir = "2"
 ignore = "0.4.18"
+semver = "1.0"
 termcolor = "1.1.3"
 
 [[bin]]
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 97e56720b98..35000320d1a 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -70,3 +70,4 @@ pub mod ui_tests;
 pub mod unit_tests;
 pub mod unstable_book;
 pub mod walk;
+pub mod x_version;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 0b9a1b37e94..4c446b72a44 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -114,6 +114,8 @@ fn main() {
         check!(alphabetical, &compiler_path);
         check!(alphabetical, &library_path);
 
+        check!(x_version, &root_path, &cargo);
+
         let collected = {
             drain_handles(&mut handles);
 
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
new file mode 100644
index 00000000000..c470d502a65
--- /dev/null
+++ b/src/tools/tidy/src/x_version.rs
@@ -0,0 +1,68 @@
+use semver::Version;
+use std::path::Path;
+use std::process::{Command, Stdio};
+
+pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
+    let cargo_list = Command::new(cargo).args(["install", "--list"]).stdout(Stdio::piped()).spawn();
+
+    let child = match cargo_list {
+        Ok(child) => child,
+        Err(e) => return tidy_error!(bad, "failed to run `cargo`: {}", e),
+    };
+
+    let cargo_list = child.wait_with_output().unwrap();
+
+    if cargo_list.status.success() {
+        let exe_list = String::from_utf8_lossy(&cargo_list.stdout);
+        let exe_list = exe_list.lines();
+
+        let mut installed: Option<Version> = None;
+
+        for line in exe_list {
+            let mut iter = line.split_whitespace();
+            if iter.next() == Some("x") {
+                if let Some(version) = iter.next() {
+                    // Check this is the rust-lang/rust x tool installation since it should be
+                    // installed at a path containing `src/tools/x`.
+                    if let Some(path) = iter.next() {
+                        if path.contains(&"src/tools/x") {
+                            let version = version.strip_prefix("v").unwrap();
+                            installed = Some(Version::parse(version).unwrap());
+                            break;
+                        }
+                    };
+                }
+            } else {
+                continue;
+            }
+        }
+        // Unwrap the some if x is installed, otherwise return because it's fine if x isn't installed.
+        let installed = if let Some(i) = installed { i } else { return };
+
+        if let Some(expected) = get_x_wrapper_version(root, cargo) {
+            if installed < expected {
+                return println!(
+                    "Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`"
+                );
+            }
+        } else {
+            return tidy_error!(
+                bad,
+                "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`"
+            );
+        }
+    } else {
+        return tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status);
+    }
+}
+
+// Parse latest version out of `x` Cargo.toml
+fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option<Version> {
+    let mut cmd = cargo_metadata::MetadataCommand::new();
+    cmd.cargo_path(cargo)
+        .manifest_path(root.join("src/tools/x/Cargo.toml"))
+        .no_deps()
+        .features(cargo_metadata::CargoOpt::AllFeatures);
+    let mut metadata = t!(cmd.exec());
+    metadata.packages.pop().map(|x| x.version)
+}