Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/license/mit/.5mod lint_cpp;6mod lint_docs;7mod lint_py;8mod lint_repo_hygiene;9mod lint_text_format;10mod util;12use std::env;13use std::fs;14use std::process::{Command, ExitCode};16use lint_cpp::{17lint_boost_assert, lint_includes_build_config, lint_remove_all, lint_rpc_assert,18lint_std_filesystem,19};20use lint_docs::{lint_doc_args, lint_doc_release_note_snippets, lint_markdown};21use lint_py::{lint_py_lint, lint_rmtree};22use lint_repo_hygiene::{lint_scripted_diff, lint_subtree};23use lint_text_format::{24lint_commit_msg, lint_tabs_whitespace, lint_trailing_newline, lint_trailing_whitespace,25};26use util::{check_output, commit_range, get_git_root, git, LintFn, LintResult};28struct Linter {29pub description: &'static str,30pub name: &'static str,31pub lint_fn: LintFn,32}34fn get_linter_list() -> Vec<&'static Linter> {35vec![36&Linter {37description: "Check that all command line arguments are documented.",38name: "doc",39lint_fn: lint_doc_args40},41&Linter {42description: "Check that no symbol from bitcoin-build-config.h is used without the header being included",43name: "includes_build_config",44lint_fn: lint_includes_build_config45},46&Linter {47description: "Check that markdown links resolve",48name: "markdown",49lint_fn: lint_markdown50},51&Linter {52description: "Lint Python code",53name: "py_lint",54lint_fn: lint_py_lint,55},56&Linter {57description: "Check that shutil.rmtree is not used",58name: "rmtree",59lint_fn: lint_rmtree,60},61&Linter {62description: "Check that std::filesystem is not used directly",63name: "std_filesystem",64lint_fn: lint_std_filesystem65},66&Linter {67description: "Check that remove_all is not used",68name: "remove_all",69lint_fn: lint_remove_all70},71&Linter {72description: "Check that fatal assertions are not used in RPC code",73name: "rpc_assert",74lint_fn: lint_rpc_assert75},76&Linter {77description: "Check that boost assertions are not used",78name: "boost_assert",79lint_fn: lint_boost_assert80},81&Linter {82description: "Check that release note snippets are in the right folder",83name: "doc_release_note_snippets",84lint_fn: lint_doc_release_note_snippets85},86&Linter {87description: "Check that subtrees are pure subtrees",88name: "subtree",89lint_fn: lint_subtree90},91&Linter {92description: "Check scripted-diffs",93name: "scripted_diff",94lint_fn: lint_scripted_diff95},96&Linter {97description: "Check that commit messages have a new line before the body or no body at all.",98name: "commit_msg",99lint_fn: lint_commit_msg100},101&Linter {102description: "Check that tabs are not used as whitespace",103name: "tabs_whitespace",104lint_fn: lint_tabs_whitespace105},106&Linter {107description: "Check for trailing whitespace",108name: "trailing_whitespace",109lint_fn: lint_trailing_whitespace110},111&Linter {112description: "Check for trailing newline",113name: "trailing_newline",114lint_fn: lint_trailing_newline115},116&Linter {117description: "Run all linters of the form: test/lint/lint-*.py",118name: "all_python_linters",119lint_fn: run_all_python_linters120},121]122}124fn print_help_and_exit() {125print!(126r#"127Usage: test_runner [--lint=LINTER_TO_RUN]128Runs all linters in the lint test suite, printing any errors129they detect.131If you wish to only run some particular lint tests, pass132'--lint=' with the name of the lint test you wish to run.133You can set as many '--lint=' values as you wish, e.g.:134test_runner --lint=doc --lint=subtree136The individual linters available to run are:137"#138);139for linter in get_linter_list() {140println!("{}: \"{}\"", linter.name, linter.description)141}143std::process::exit(1);144}146fn parse_lint_args(args: &[String]) -> Vec<&'static Linter> {147let linter_list = get_linter_list();148let mut lint_values = Vec::new();150for arg in args {151#[allow(clippy::if_same_then_else)]152if arg.starts_with("--lint=") {153let lint_arg_value = arg154.trim_start_matches("--lint=")155.trim_matches('"')156.trim_matches('\'');158let try_find_linter = linter_list159.iter()160.find(|linter| linter.name == lint_arg_value);161match try_find_linter {162Some(linter) => {163lint_values.push(*linter);164}165None => {166println!("No linter {lint_arg_value} found!");167print_help_and_exit();168}169}170} else if arg.eq("--help") || arg.eq("-h") {171print_help_and_exit();172} else {173print_help_and_exit();174}175}177lint_values178}180fn run_all_python_linters() -> LintResult {181let mut good = true;182let lint_dir = get_git_root().join("test/lint");183for entry in fs::read_dir(lint_dir).unwrap() {184let entry = entry.unwrap();185let entry_fn = entry.file_name().into_string().unwrap();186if entry_fn.starts_with("lint-")187&& entry_fn.ends_with(".py")188&& !Command::new("python3")189.arg(entry.path())190.status()191.expect("command error")192.success()193{194good = false;195println!("^---- ⚠️ Failure generated from {entry_fn}");196}197}198if good {199Ok(())200} else {201Err("".to_string())202}203}205fn main() -> ExitCode {206let linters_to_run: Vec<&Linter> = if env::args().count() > 1 {207let args: Vec<String> = env::args().skip(1).collect();208parse_lint_args(&args)209} else {210// If no arguments are passed, run all linters.211get_linter_list()212};214let git_root = get_git_root();215let commit_range = commit_range();216let commit_log = check_output(git().args(["log", "--no-merges", "--oneline", &commit_range]))217.expect("check_output failed");218println!("Checking commit range ({commit_range}):\n{commit_log}\n");220let mut test_failed = false;221for linter in linters_to_run {222// chdir to root before each lint test223env::set_current_dir(&git_root).unwrap();224if let Err(err) = (linter.lint_fn)() {225println!(226"^^^\n{err}\n^---- ⚠️ Failure generated from lint check '{}' ({})!\n\n",227linter.name, linter.description,228);229test_failed = true;230}231}232if test_failed {233ExitCode::FAILURE234} else {235ExitCode::SUCCESS236}237}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.