lint: [move-only] Move util functions to util.rs
What changed, and why it matters
This commit simply moves existing helper functions from one Rust source file to a new utility file. It is a code cleanup change with no functional or security impact on the Bitcoin Core software itself. The moved code is part of the internal lint test runner, not the Bitcoin node that users run.
No security action needed. Treat as routine code maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit is a move-only refactor in test/lint/test_runner/src/main.rs and the newly created test/lint/test_runner/src/util.rs. It extracts type aliases (LintError, LintResult, LintFn) and helper functions (git, check_output, get_git_root, commit_range, get_subtrees, get_pathspecs_default_excludes) into a new util module, adds pub visibility, and imports them back into main.rs. No logic was changed.
Changed components
test/lint/test_runner/src/main.rstest/lint/test_runner/src/util.rsInspect captured patch +90 / −77
diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs
index 171c9807..3a870b94 100644
--- a/test/lint/test_runner/src/main.rs
+++ b/test/lint/test_runner/src/main.rs
@@ -2,18 +2,17 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://opensource.org/license/mit/.
+mod util;
+
use std::env;
use std::fs::{self, File};
use std::io::{ErrorKind, Read, Seek, SeekFrom};
-use std::path::PathBuf;
use std::process::{Command, ExitCode, Stdio};
-/// A possible error returned by any of the linters.
-///
-/// The error string should explain the failure type and list all violations.
-type LintError = String;
-type LintResult = Result<(), LintError>;
-type LintFn = fn() -> LintResult;
+use util::{
+ check_output, commit_range, get_git_root, get_pathspecs_default_excludes, get_subtrees, git,
+ LintFn, LintResult,
+};
struct Linter {
pub description: &'static str,
@@ -157,76 +156,6 @@ fn parse_lint_args(args: &[String]) -> Vec<&'static Linter> {
lint_values
}
-/// Return the git command
-///
-/// Lint functions should use this command, so that only files tracked by git are considered and
-/// temporary and untracked files are ignored. For example, instead of 'grep', 'git grep' should be
-/// used.
-fn git() -> Command {
- let mut git = Command::new("git");
- git.arg("--no-pager");
- git
-}
-
-/// Return stdout on success and a LintError on failure, when invalid UTF8 was detected or the
-/// command did not succeed.
-fn check_output(cmd: &mut std::process::Command) -> Result<String, LintError> {
- let out = cmd.output().expect("command error");
- if !out.status.success() {
- return Err(String::from_utf8_lossy(&out.stderr).to_string());
- }
- Ok(String::from_utf8(out.stdout)
- .map_err(|e| {
- format!("All path names, source code, messages, and output must be valid UTF8!\n{e}")
- })?
- .trim()
- .to_string())
-}
-
-/// Return the git root as utf8, or panic
-fn get_git_root() -> PathBuf {
- PathBuf::from(check_output(git().args(["rev-parse", "--show-toplevel"])).unwrap())
-}
-
-/// Return the commit range, or panic
-fn commit_range() -> String {
- // Use the env var, if set. E.g. COMMIT_RANGE='HEAD~n..HEAD' for the last 'n' commits.
- env::var("COMMIT_RANGE").unwrap_or_else(|_| {
- // Otherwise, assume that a merge commit exists. This merge commit is assumed
- // to be the base, after which linting will be done. If the merge commit is
- // HEAD, the range will be empty.
- format!(
- "{}..HEAD",
- check_output(git().args(["rev-list", "--max-count=1", "--merges", "HEAD"]))
- .expect("check_output failed")
- )
- })
-}
-
-/// Return all subtree paths
-fn get_subtrees() -> Vec<&'static str> {
- // Keep in sync with [test/lint/README.md#git-subtree-checksh]
- vec![
- "src/crc32c",
- "src/crypto/ctaes",
- "src/ipc/libmultiprocess",
- "src/leveldb",
- "src/minisketch",
- "src/secp256k1",
- ]
-}
-
-/// Return the pathspecs to exclude by default
-fn get_pathspecs_default_excludes() -> Vec<String> {
- get_subtrees()
- .iter()
- .chain(&[
- "doc/release-notes/release-notes-*", // archived notes
- ])
- .map(|s| format!(":(exclude){s}"))
- .collect()
-}
-
fn lint_subtree() -> LintResult {
// This only checks that the trees are pure subtrees, it is not doing a full
// check with -r to not have to fetch all the remotes.
diff --git a/test/lint/test_runner/src/util.rs b/test/lint/test_runner/src/util.rs
new file mode 100644
index 00000000..11e332e4
--- /dev/null
+++ b/test/lint/test_runner/src/util.rs
@@ -0,0 +1,84 @@
+// Copyright (c) The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://opensource.org/license/mit/.
+
+use std::env;
+use std::path::PathBuf;
+use std::process::Command;
+
+/// A possible error returned by any of the linters.
+///
+/// The error string should explain the failure type and list all violations.
+pub type LintError = String;
+pub type LintResult = Result<(), LintError>;
+pub type LintFn = fn() -> LintResult;
+
+/// Return the git command
+///
+/// Lint functions should use this command, so that only files tracked by git are considered and
+/// temporary and untracked files are ignored. For example, instead of 'grep', 'git grep' should be
+/// used.
+pub fn git() -> Command {
+ let mut git = Command::new("git");
+ git.arg("--no-pager");
+ git
+}
+
+/// Return stdout on success and a LintError on failure, when invalid UTF8 was detected or the
+/// command did not succeed.
+pub fn check_output(cmd: &mut Command) -> Result<String, LintError> {
+ let out = cmd.output().expect("command error");
+ if !out.status.success() {
+ return Err(String::from_utf8_lossy(&out.stderr).to_string());
+ }
+ Ok(String::from_utf8(out.stdout)
+ .map_err(|e| {
+ format!("All path names, source code, messages, and output must be valid UTF8!\n{e}")
+ })?
+ .trim()
+ .to_string())
+}
+
+/// Return the git root as utf8, or panic
+pub fn get_git_root() -> PathBuf {
+ PathBuf::from(check_output(git().args(["rev-parse", "--show-toplevel"])).unwrap())
+}
+
+/// Return the commit range, or panic
+pub fn commit_range() -> String {
+ // Use the env var, if set. E.g. COMMIT_RANGE='HEAD~n..HEAD' for the last 'n' commits.
+ env::var("COMMIT_RANGE").unwrap_or_else(|_| {
+ // Otherwise, assume that a merge commit exists. This merge commit is assumed
+ // to be the base, after which linting will be done. If the merge commit is
+ // HEAD, the range will be empty.
+ format!(
+ "{}..HEAD",
+ check_output(git().args(["rev-list", "--max-count=1", "--merges", "HEAD"]))
+ .expect("check_output failed")
+ )
+ })
+}
+
+/// Return all subtree paths
+pub fn get_subtrees() -> Vec<&'static str> {
+ // Keep in sync with [test/lint/README.md#git-subtree-checksh]
+ vec![
+ "src/crc32c",
+ "src/crypto/ctaes",
+ "src/ipc/libmultiprocess",
+ "src/leveldb",
+ "src/minisketch",
+ "src/secp256k1",
+ ]
+}
+
+/// Return the pathspecs to exclude by default
+pub fn get_pathspecs_default_excludes() -> Vec<String> {
+ get_subtrees()
+ .iter()
+ .chain(&[
+ "doc/release-notes/release-notes-*", // archived notes
+ ])
+ .map(|s| format!(":(exclude){s}"))
+ .collect()
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.