Skip to content

Commit e9b6a50

Browse files
committed
tidy now installs typos-cli as-needed via cargo
1 parent ad55f21 commit e9b6a50

File tree

2 files changed

+45
-28
lines changed

2 files changed

+45
-28
lines changed

src/build_helper/src/util.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use std::env;
12
use std::fs::File;
2-
use std::io::{BufRead, BufReader};
3-
use std::path::Path;
3+
use std::io::{self, BufRead, BufReader};
4+
use std::path::{Path, PathBuf};
45
use std::process::Command;
56

67
/// Invokes `build_helper::util::detail_exit` with `cfg!(test)`
@@ -66,3 +67,39 @@ pub fn parse_gitmodules(target_dir: &Path) -> Vec<String> {
6667

6768
submodules_paths
6869
}
70+
71+
/// If the given executible is installed with the given version, use that,
72+
/// otherwise install via cargo.
73+
pub fn ensure_version_or_cargo_install(
74+
build_dir: &Path,
75+
pkg_name: &str,
76+
bin_name: &str,
77+
version: &str,
78+
) -> io::Result<PathBuf> {
79+
let tool_root_dir = build_dir.join("misc-tools");
80+
let tool_bin_dir = tool_root_dir.join("bin");
81+
// use --force to ensure that if the required version is bumped, we update it.
82+
// use --target-dir to ensure we have a build cache so repeated invocations aren't slow.
83+
// modify PATH so that cargo doesn't print a warning telling the user to modify the path.
84+
let cargo_exit_code = Command::new("cargo")
85+
.args(["install", "--locked", "--force", "--quiet"])
86+
.arg("--root")
87+
.arg(&tool_root_dir)
88+
.arg("--target-dir")
89+
.arg(tool_root_dir.join("target"))
90+
.arg(format!("{pkg_name}@{version}"))
91+
.env(
92+
"PATH",
93+
env::join_paths(
94+
env::split_paths(&env::var("PATH").unwrap())
95+
.chain(std::iter::once(tool_bin_dir.clone())),
96+
)
97+
.expect("build dir contains invalid char"),
98+
)
99+
.spawn()?
100+
.wait()?;
101+
if !cargo_exit_code.success() {
102+
return Err(io::Error::other("cargo install failed"));
103+
}
104+
return Ok(tool_bin_dir.join(bin_name));
105+
}

src/tools/tidy/src/extra_checks/mod.rs

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use std::process::Command;
2323
use std::str::FromStr;
2424
use std::{fmt, fs, io};
2525

26+
use build_helper::util::ensure_version_or_cargo_install;
27+
2628
use crate::CiInfo;
2729

2830
mod rustdoc_js;
@@ -293,7 +295,7 @@ fn check_impl(
293295
} else {
294296
eprintln!("spellcheck files");
295297
}
296-
spellcheck_runner(&args)?;
298+
spellcheck_runner(&outdir, &args)?;
297299
}
298300

299301
if js_lint || js_typecheck {
@@ -577,32 +579,10 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> {
577579
}
578580

579581
/// Check that spellchecker is installed then run it at the given path
580-
fn spellcheck_runner(args: &[&str]) -> Result<(), Error> {
581-
// sync version with .github/workflows/spellcheck.yml
582-
let expected_version = "typos-cli 1.34.0";
583-
match Command::new("typos").arg("--version").output() {
584-
Ok(o) => {
585-
let stdout = String::from_utf8_lossy(&o.stdout);
586-
if stdout.trim() != expected_version {
587-
return Err(Error::Version {
588-
program: "typos",
589-
required: expected_version,
590-
installed: stdout.trim().to_string(),
591-
});
592-
}
593-
}
594-
Err(e) if e.kind() == io::ErrorKind::NotFound => {
595-
return Err(Error::MissingReq(
596-
"typos",
597-
"spellcheck file checks",
598-
// sync version with .github/workflows/spellcheck.yml
599-
Some("install tool via `cargo install [email protected]`".to_owned()),
600-
));
601-
}
602-
Err(e) => return Err(e.into()),
603-
}
582+
fn spellcheck_runner(outdir: &Path, args: &[&str]) -> Result<(), Error> {
583+
let bin_path = ensure_version_or_cargo_install(outdir, "typos-cli", "typos", "1.34.0")?;
604584

605-
let status = Command::new("typos").args(args).status()?;
585+
let status = Command::new(bin_path).args(args).status()?;
606586
if status.success() { Ok(()) } else { Err(Error::FailedCheck("typos")) }
607587
}
608588

0 commit comments

Comments
 (0)