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 00000000000..7063b508447 --- /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-.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 ddcdd178e24..9adbe369ffc 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-.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");