lint: [move-only] Move docs related lints to lint_docs.rs
What changed, and why it matters
This commit is a straightforward code reorganization: it moves three documentation-related lint checks from the main test runner file into a new dedicated Rust module, and renames one function from lint_doc to lint_doc_args. No behavior changes, security fixes, or vulnerability patches are present.
No security action needed. This is a non-security refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is a pure refactor (move-only) in the Bitcoin Core lint test runner. Functions lint_doc_release_note_snippets, lint_doc (renamed lint_doc_args), and lint_markdown are relocated from test/lint/test_runner/src/main.rs to a new module test/lint/test_runner/src/lint_docs.rs. main.rs now declares mod lint_docs and imports the functions. The function bodies, error messages, command invocations, and logic are identical to the originals. No functional or security-relevant changes are introduced.
Changed components
test/lint/test_runner/src/main.rstest/lint/test_runner/src/lint_docs.rsInspect captured patch +89 / −79
diff --git a/test/lint/test_runner/src/lint_docs.rs b/test/lint/test_runner/src/lint_docs.rs
new file mode 100644
index 00000000..7063b508
--- /dev/null
+++ b/test/lint/test_runner/src/lint_docs.rs
@@ -0,0 +1,85 @@
+// 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::io::ErrorKind;
+use std::process::{Command, Stdio};
+
+use crate::util::{check_output, get_subtrees, git, LintResult};
+
+pub fn lint_doc_release_note_snippets() -> LintResult {
+ let non_release_notes = check_output(git().args([
+ "ls-files",
+ "--",
+ "doc/release-notes/",
+ ":(exclude)doc/release-notes/*.*.md", // Assume that at least one dot implies a proper release note
+ ]))?;
+ if non_release_notes.is_empty() {
+ Ok(())
+ } else {
+ println!("{non_release_notes}");
+ Err(r#"
+Release note snippets and other docs must be put into the doc/ folder directly.
+
+The doc/release-notes/ folder is for archived release notes of previous releases only. Snippets are
+expected to follow the naming "/doc/release-notes-<PR number>.md".
+ "#
+ .trim()
+ .to_string())
+ }
+}
+
+pub fn lint_doc_args() -> LintResult {
+ if Command::new("test/lint/check-doc.py")
+ .status()
+ .expect("command error")
+ .success()
+ {
+ Ok(())
+ } else {
+ Err("".to_string())
+ }
+}
+
+pub fn lint_markdown() -> LintResult {
+ let bin_name = "mlc";
+ let mut md_ignore_paths = get_subtrees();
+ md_ignore_paths.push("./doc/README_doxygen.md");
+ let md_ignore_path_str = md_ignore_paths.join(",");
+
+ let mut cmd = Command::new(bin_name);
+ cmd.args([
+ "--offline",
+ "--ignore-path",
+ md_ignore_path_str.as_str(),
+ "--gitignore",
+ "--gituntracked",
+ "--root-dir",
+ ".",
+ ])
+ .stdout(Stdio::null()); // Suppress overly-verbose output
+
+ match cmd.output() {
+ Ok(output) if output.status.success() => Ok(()),
+ Ok(output) => {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ Err(format!(
+ r#"
+One or more markdown links are broken.
+
+Note: relative links are preferred as jump-to-file works natively within Emacs, but they are not required.
+
+Markdown link errors found:
+{stderr}
+ "#
+ )
+ .trim()
+ .to_string())
+ }
+ Err(e) if e.kind() == ErrorKind::NotFound => {
+ println!("`mlc` was not found in $PATH, skipping markdown lint check.");
+ Ok(())
+ }
+ Err(e) => Err(format!("Error running mlc: {e}")), // Misc errors
+ }
+}
diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs
index ddcdd178..9adbe369 100644
--- a/test/lint/test_runner/src/main.rs
+++ b/test/lint/test_runner/src/main.rs
@@ -2,14 +2,16 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://opensource.org/license/mit/.
+mod lint_docs;
mod lint_text_format;
mod util;
use std::env;
use std::fs;
use std::io::ErrorKind;
-use std::process::{Command, ExitCode, Stdio};
+use std::process::{Command, ExitCode};
+use lint_docs::{lint_doc_args, lint_doc_release_note_snippets, lint_markdown};
use lint_text_format::{
lint_commit_msg, lint_tabs_whitespace, lint_trailing_newline, lint_trailing_whitespace,
};
@@ -29,7 +31,7 @@ fn get_linter_list() -> Vec<&'static Linter> {
&Linter {
description: "Check that all command line arguments are documented.",
name: "doc",
- lint_fn: lint_doc
+ lint_fn: lint_doc_args
},
&Linter {
description: "Check that no symbol from bitcoin-build-config.h is used without the header being included",
@@ -344,28 +346,6 @@ include of the boost/assert.hpp dependency.
}
}
-fn lint_doc_release_note_snippets() -> LintResult {
- let non_release_notes = check_output(git().args([
- "ls-files",
- "--",
- "doc/release-notes/",
- ":(exclude)doc/release-notes/*.*.md", // Assume that at least one dot implies a proper release note
- ]))?;
- if non_release_notes.is_empty() {
- Ok(())
- } else {
- println!("{non_release_notes}");
- Err(r#"
-Release note snippets and other docs must be put into the doc/ folder directly.
-
-The doc/release-notes/ folder is for archived release notes of previous releases only. Snippets are
-expected to follow the naming "/doc/release-notes-<PR number>.md".
- "#
- .trim()
- .to_string())
- }
-}
-
fn lint_includes_build_config() -> LintResult {
let config_path = "./cmake/bitcoin-build-config.h.in";
let defines_regex = format!(
@@ -455,61 +435,6 @@ the header. Consider removing the unused include.
Ok(())
}
-fn lint_doc() -> LintResult {
- if Command::new("test/lint/check-doc.py")
- .status()
- .expect("command error")
- .success()
- {
- Ok(())
- } else {
- Err("".to_string())
- }
-}
-
-fn lint_markdown() -> LintResult {
- let bin_name = "mlc";
- let mut md_ignore_paths = get_subtrees();
- md_ignore_paths.push("./doc/README_doxygen.md");
- let md_ignore_path_str = md_ignore_paths.join(",");
-
- let mut cmd = Command::new(bin_name);
- cmd.args([
- "--offline",
- "--ignore-path",
- md_ignore_path_str.as_str(),
- "--gitignore",
- "--gituntracked",
- "--root-dir",
- ".",
- ])
- .stdout(Stdio::null()); // Suppress overly-verbose output
-
- match cmd.output() {
- Ok(output) if output.status.success() => Ok(()),
- Ok(output) => {
- let stderr = String::from_utf8_lossy(&output.stderr);
- Err(format!(
- r#"
-One or more markdown links are broken.
-
-Note: relative links are preferred as jump-to-file works natively within Emacs, but they are not required.
-
-Markdown link errors found:
-{stderr}
- "#
- )
- .trim()
- .to_string())
- }
- Err(e) if e.kind() == ErrorKind::NotFound => {
- println!("`mlc` was not found in $PATH, skipping markdown lint check.");
- Ok(())
- }
- Err(e) => Err(format!("Error running mlc: {e}")), // Misc errors
- }
-}
-
fn run_all_python_linters() -> LintResult {
let mut good = true;
let lint_dir = get_git_root().join("test/lint");
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.