lint_docs.rs
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 }