From fad09e77dbe521eb35206cd72536619225b18550 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 18 Dec 2025 11:24:42 +0100 Subject: [PATCH] lint: [move-only] Move text related lints to text_format.rs --- test/lint/test_runner/src/lint_text_format.rs | 159 ++++++++++++++++++ test/lint/test_runner/src/main.rs | 159 +----------------- 2 files changed, 165 insertions(+), 153 deletions(-) create mode 100644 test/lint/test_runner/src/lint_text_format.rs diff --git a/test/lint/test_runner/src/lint_text_format.rs b/test/lint/test_runner/src/lint_text_format.rs new file mode 100644 index 00000000000..ca51e6db081 --- /dev/null +++ b/test/lint/test_runner/src/lint_text_format.rs @@ -0,0 +1,159 @@ +// 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::fs::File; +use std::io::{Read, Seek, SeekFrom}; + +use crate::util::{check_output, commit_range, get_pathspecs_default_excludes, git, LintResult}; + +/// Return the pathspecs for whitespace related excludes +fn get_pathspecs_exclude_whitespace() -> Vec { + let mut list = get_pathspecs_default_excludes(); + list.extend( + [ + // Permanent excludes + "*.patch", + "src/qt/locale", + "contrib/windeploy/win-codesign.cert", + "doc/README_windows.txt", + // Temporary excludes, or existing violations + "contrib/init/bitcoind.openrc", + "contrib/macdeploy/macdeployqtplus", + "src/crypto/sha256_sse4.cpp", + "src/qt/res/src/*.svg", + "test/functional/test_framework/crypto/ellswift_decode_test_vectors.csv", + "test/functional/test_framework/crypto/xswiftec_inv_test_vectors.csv", + "contrib/qos/tc.sh", + "contrib/verify-commits/gpg.sh", + "src/univalue/include/univalue_escapes.h", + "src/univalue/test/object.cpp", + "test/lint/git-subtree-check.sh", + ] + .iter() + .map(|s| format!(":(exclude){s}")), + ); + list +} + +pub fn lint_trailing_whitespace() -> LintResult { + let trailing_space = git() + .args(["grep", "-I", "--line-number", "\\s$", "--"]) + .args(get_pathspecs_exclude_whitespace()) + .status() + .expect("command error") + .success(); + if trailing_space { + Err(r#" +Trailing whitespace (including Windows line endings [CR LF]) is problematic, because git may warn +about it, or editors may remove it by default, forcing developers in the future to either undo the +changes manually or spend time on review. + +Thus, it is best to remove the trailing space now. + +Please add any false positives, such as subtrees, Windows-related files, patch files, or externally +sourced files to the exclude list. + "# + .trim() + .to_string()) + } else { + Ok(()) + } +} + +pub fn lint_trailing_newline() -> LintResult { + let files = check_output( + git() + .args([ + "ls-files", "--", "*.py", "*.cpp", "*.h", "*.md", "*.rs", "*.sh", "*.cmake", + ]) + .args(get_pathspecs_default_excludes()), + )?; + let mut missing_newline = false; + for path in files.lines() { + let mut file = File::open(path).expect("must be able to open file"); + if file.seek(SeekFrom::End(-1)).is_err() { + continue; // Allow fully empty files + } + let mut buffer = [0u8; 1]; + file.read_exact(&mut buffer) + .expect("must be able to read the last byte"); + if buffer[0] != b'\n' { + missing_newline = true; + println!("{path}"); + } + } + if missing_newline { + Err(r#" +A trailing newline is required, because git may warn about it missing. Also, it can make diffs +verbose and can break git blame after appending lines. + +Thus, it is best to add the trailing newline now. + +Please add any false positives to the exclude list. + "# + .trim() + .to_string()) + } else { + Ok(()) + } +} + +pub fn lint_tabs_whitespace() -> LintResult { + let tabs = git() + .args(["grep", "-I", "--line-number", "--perl-regexp", "^\\t", "--"]) + .args(["*.cpp", "*.h", "*.md", "*.py", "*.sh"]) + .args(get_pathspecs_exclude_whitespace()) + .status() + .expect("command error") + .success(); + if tabs { + Err(r#" +Use of tabs in this codebase is problematic, because existing code uses spaces and tabs will cause +display issues and conflict with editor settings. + +Please remove the tabs. + +Please add any false positives, such as subtrees, or externally sourced files to the exclude list. + "# + .trim() + .to_string()) + } else { + Ok(()) + } +} + +pub fn lint_commit_msg() -> LintResult { + let mut good = true; + let commit_hashes = check_output(git().args([ + "-c", + "log.showSignature=false", + "log", + &commit_range(), + "--format=%H", + ]))?; + for hash in commit_hashes.lines() { + let commit_info = check_output(git().args([ + "-c", + "log.showSignature=false", + "log", + "--format=%B", + "-n", + "1", + hash, + ]))?; + if let Some(line) = commit_info.lines().nth(1) { + if !line.is_empty() { + println!( + "The subject line of commit hash {hash} is followed by a non-empty line. Subject lines should always be followed by a blank line." + ); + good = false; + } + } + } + if good { + Ok(()) + } else { + Err("".to_string()) + } +} diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs index 3a870b941d9..ddcdd178e24 100644 --- a/test/lint/test_runner/src/main.rs +++ b/test/lint/test_runner/src/main.rs @@ -2,13 +2,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/license/mit/. +mod lint_text_format; mod util; use std::env; -use std::fs::{self, File}; -use std::io::{ErrorKind, Read, Seek, SeekFrom}; +use std::fs; +use std::io::ErrorKind; use std::process::{Command, ExitCode, Stdio}; +use lint_text_format::{ + lint_commit_msg, lint_tabs_whitespace, lint_trailing_newline, lint_trailing_whitespace, +}; use util::{ check_output, commit_range, get_git_root, get_pathspecs_default_excludes, get_subtrees, git, LintFn, LintResult, @@ -187,41 +191,6 @@ fn lint_scripted_diff() -> LintResult { } } -fn lint_commit_msg() -> LintResult { - let mut good = true; - let commit_hashes = check_output(git().args([ - "-c", - "log.showSignature=false", - "log", - &commit_range(), - "--format=%H", - ]))?; - for hash in commit_hashes.lines() { - let commit_info = check_output(git().args([ - "-c", - "log.showSignature=false", - "log", - "--format=%B", - "-n", - "1", - hash, - ]))?; - if let Some(line) = commit_info.lines().nth(1) { - if !line.is_empty() { - println!( - "The subject line of commit hash {hash} is followed by a non-empty line. Subject lines should always be followed by a blank line." - ); - good = false; - } - } - } - if good { - Ok(()) - } else { - Err("".to_string()) - } -} - fn lint_py_lint() -> LintResult { let bin_name = "ruff"; let checks = format!( @@ -397,122 +366,6 @@ expected to follow the naming "/doc/release-notes-.md". } } -/// Return the pathspecs for whitespace related excludes -fn get_pathspecs_exclude_whitespace() -> Vec { - let mut list = get_pathspecs_default_excludes(); - list.extend( - [ - // Permanent excludes - "*.patch", - "src/qt/locale", - "contrib/windeploy/win-codesign.cert", - "doc/README_windows.txt", - // Temporary excludes, or existing violations - "contrib/init/bitcoind.openrc", - "contrib/macdeploy/macdeployqtplus", - "src/crypto/sha256_sse4.cpp", - "src/qt/res/src/*.svg", - "test/functional/test_framework/crypto/ellswift_decode_test_vectors.csv", - "test/functional/test_framework/crypto/xswiftec_inv_test_vectors.csv", - "contrib/qos/tc.sh", - "contrib/verify-commits/gpg.sh", - "src/univalue/include/univalue_escapes.h", - "src/univalue/test/object.cpp", - "test/lint/git-subtree-check.sh", - ] - .iter() - .map(|s| format!(":(exclude){s}")), - ); - list -} - -fn lint_trailing_whitespace() -> LintResult { - let trailing_space = git() - .args(["grep", "-I", "--line-number", "\\s$", "--"]) - .args(get_pathspecs_exclude_whitespace()) - .status() - .expect("command error") - .success(); - if trailing_space { - Err(r#" -Trailing whitespace (including Windows line endings [CR LF]) is problematic, because git may warn -about it, or editors may remove it by default, forcing developers in the future to either undo the -changes manually or spend time on review. - -Thus, it is best to remove the trailing space now. - -Please add any false positives, such as subtrees, Windows-related files, patch files, or externally -sourced files to the exclude list. - "# - .trim() - .to_string()) - } else { - Ok(()) - } -} - -fn lint_trailing_newline() -> LintResult { - let files = check_output( - git() - .args([ - "ls-files", "--", "*.py", "*.cpp", "*.h", "*.md", "*.rs", "*.sh", "*.cmake", - ]) - .args(get_pathspecs_default_excludes()), - )?; - let mut missing_newline = false; - for path in files.lines() { - let mut file = File::open(path).expect("must be able to open file"); - if file.seek(SeekFrom::End(-1)).is_err() { - continue; // Allow fully empty files - } - let mut buffer = [0u8; 1]; - file.read_exact(&mut buffer) - .expect("must be able to read the last byte"); - if buffer[0] != b'\n' { - missing_newline = true; - println!("{path}"); - } - } - if missing_newline { - Err(r#" -A trailing newline is required, because git may warn about it missing. Also, it can make diffs -verbose and can break git blame after appending lines. - -Thus, it is best to add the trailing newline now. - -Please add any false positives to the exclude list. - "# - .trim() - .to_string()) - } else { - Ok(()) - } -} - -fn lint_tabs_whitespace() -> LintResult { - let tabs = git() - .args(["grep", "-I", "--line-number", "--perl-regexp", "^\\t", "--"]) - .args(["*.cpp", "*.h", "*.md", "*.py", "*.sh"]) - .args(get_pathspecs_exclude_whitespace()) - .status() - .expect("command error") - .success(); - if tabs { - Err(r#" -Use of tabs in this codebase is problematic, because existing code uses spaces and tabs will cause -display issues and conflict with editor settings. - -Please remove the tabs. - -Please add any false positives, such as subtrees, or externally sourced files to the exclude list. - "# - .trim() - .to_string()) - } else { - Ok(()) - } -} - fn lint_includes_build_config() -> LintResult { let config_path = "./cmake/bitcoin-build-config.h.in"; let defines_regex = format!(