lint_docs.rs raw
1 // Copyright (c) The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://opensource.org/license/mit/.
4
5 use std::io::ErrorKind;
6 use std::process::{Command, Stdio};
7
8 use crate::util::{check_output, get_subtrees, git, LintResult};
9
10 pub fn lint_doc_release_note_snippets() -> LintResult {
11 let non_release_notes = check_output(git().args([
12 "ls-files",
13 "--",
14 "doc/release-notes/",
15 ":(exclude)doc/release-notes/*.*.md", // Assume that at least one dot implies a proper release note
16 ]))?;
17 if non_release_notes.is_empty() {
18 Ok(())
19 } else {
20 println!("{non_release_notes}");
21 Err(r#"
22 Release note snippets and other docs must be put into the doc/ folder directly.
23
24 The doc/release-notes/ folder is for archived release notes of previous releases only. Snippets are
25 expected to follow the naming "/doc/release-notes-<PR number>.md".
26 "#
27 .trim()
28 .to_string())
29 }
30 }
31
32 pub fn lint_doc_args() -> LintResult {
33 if Command::new("test/lint/check-doc.py")
34 .status()
35 .expect("command error")
36 .success()
37 {
38 Ok(())
39 } else {
40 Err("".to_string())
41 }
42 }
43
44 pub fn lint_markdown() -> LintResult {
45 let bin_name = "mlc";
46 let mut md_ignore_paths = get_subtrees();
47 md_ignore_paths.push("./doc/README_doxygen.md");
48 let md_ignore_path_str = md_ignore_paths.join(",");
49
50 let mut cmd = Command::new(bin_name);
51 cmd.args([
52 "--offline",
53 "--ignore-path",
54 md_ignore_path_str.as_str(),
55 "--gitignore",
56 "--gituntracked",
57 "--root-dir",
58 ".",
59 ])
60 .stdout(Stdio::null()); // Suppress overly-verbose output
61
62 match cmd.output() {
63 Ok(output) if output.status.success() => Ok(()),
64 Ok(output) => {
65 let stderr = String::from_utf8_lossy(&output.stderr);
66 Err(format!(
67 r#"
68 One or more markdown links are broken.
69
70 Note: relative links are preferred as jump-to-file works natively within Emacs, but they are not required.
71
72 Markdown link errors found:
73 {stderr}
74 "#
75 )
76 .trim()
77 .to_string())
78 }
79 Err(e) if e.kind() == ErrorKind::NotFound => {
80 println!("`mlc` was not found in $PATH, skipping markdown lint check.");
81 Ok(())
82 }
83 Err(e) => Err(format!("Error running mlc: {e}")), // Misc errors
84 }
85 }
86