2023-02-14 17:42:12 +01:00
|
|
|
// 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::env;
|
2024-01-11 14:30:28 +01:00
|
|
|
use std::fs;
|
2023-02-14 17:42:12 +01:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::process::Command;
|
|
|
|
use std::process::ExitCode;
|
|
|
|
|
2023-11-13 16:54:20 +01:00
|
|
|
type LintError = String;
|
|
|
|
type LintResult = Result<(), LintError>;
|
|
|
|
type LintFn = fn() -> LintResult;
|
2023-02-14 17:42:12 +01:00
|
|
|
|
|
|
|
/// Return the git command
|
|
|
|
fn git() -> Command {
|
|
|
|
Command::new("git")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return stdout
|
|
|
|
fn check_output(cmd: &mut std::process::Command) -> Result<String, LintError> {
|
|
|
|
let out = cmd.output().expect("command error");
|
|
|
|
if !out.status.success() {
|
|
|
|
return Err(String::from_utf8_lossy(&out.stderr).to_string());
|
|
|
|
}
|
|
|
|
Ok(String::from_utf8(out.stdout)
|
|
|
|
.map_err(|e| format!("{e}"))?
|
|
|
|
.trim()
|
|
|
|
.to_string())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the git root as utf8, or panic
|
2024-01-11 14:30:28 +01:00
|
|
|
fn get_git_root() -> PathBuf {
|
|
|
|
PathBuf::from(check_output(git().args(["rev-parse", "--show-toplevel"])).unwrap())
|
2023-02-14 17:42:12 +01:00
|
|
|
}
|
|
|
|
|
2023-11-13 16:54:20 +01:00
|
|
|
fn lint_subtree() -> LintResult {
|
|
|
|
// This only checks that the trees are pure subtrees, it is not doing a full
|
|
|
|
// check with -r to not have to fetch all the remotes.
|
|
|
|
let mut good = true;
|
|
|
|
for subtree in [
|
|
|
|
"src/crypto/ctaes",
|
|
|
|
"src/secp256k1",
|
|
|
|
"src/minisketch",
|
|
|
|
"src/leveldb",
|
|
|
|
"src/crc32c",
|
|
|
|
] {
|
|
|
|
good &= Command::new("test/lint/git-subtree-check.sh")
|
|
|
|
.arg(subtree)
|
|
|
|
.status()
|
|
|
|
.expect("command_error")
|
|
|
|
.success();
|
|
|
|
}
|
|
|
|
if good {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err("".to_string())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lint_std_filesystem() -> LintResult {
|
2023-02-14 17:42:12 +01:00
|
|
|
let found = git()
|
|
|
|
.args([
|
|
|
|
"grep",
|
|
|
|
"std::filesystem",
|
|
|
|
"--",
|
|
|
|
"./src/",
|
|
|
|
":(exclude)src/util/fs.h",
|
|
|
|
])
|
|
|
|
.status()
|
|
|
|
.expect("command error")
|
|
|
|
.success();
|
|
|
|
if found {
|
|
|
|
Err(r#"
|
|
|
|
^^^
|
|
|
|
Direct use of std::filesystem may be dangerous and buggy. Please include <util/fs.h> and use the
|
|
|
|
fs:: namespace, which has unsafe filesystem functions marked as deleted.
|
|
|
|
"#
|
|
|
|
.to_string())
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-13 16:54:20 +01:00
|
|
|
fn lint_doc() -> LintResult {
|
|
|
|
if Command::new("test/lint/check-doc.py")
|
|
|
|
.status()
|
|
|
|
.expect("command error")
|
|
|
|
.success()
|
|
|
|
{
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err("".to_string())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lint_all() -> LintResult {
|
2024-01-11 14:30:28 +01:00
|
|
|
let mut good = true;
|
|
|
|
let lint_dir = get_git_root().join("test/lint");
|
|
|
|
for entry in fs::read_dir(lint_dir).unwrap() {
|
|
|
|
let entry = entry.unwrap();
|
|
|
|
let entry_fn = entry.file_name().into_string().unwrap();
|
|
|
|
if entry_fn.starts_with("lint-")
|
|
|
|
&& entry_fn.ends_with(".py")
|
|
|
|
&& !Command::new("python3")
|
|
|
|
.arg(entry.path())
|
|
|
|
.status()
|
|
|
|
.expect("command error")
|
|
|
|
.success()
|
|
|
|
{
|
|
|
|
good = false;
|
|
|
|
println!("^---- failure generated from {}", entry_fn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if good {
|
2023-11-13 16:54:20 +01:00
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err("".to_string())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-14 17:42:12 +01:00
|
|
|
fn main() -> ExitCode {
|
2023-11-13 16:54:20 +01:00
|
|
|
let test_list: Vec<(&str, LintFn)> = vec![
|
|
|
|
("subtree check", lint_subtree),
|
|
|
|
("std::filesystem check", lint_std_filesystem),
|
|
|
|
("-help=1 documentation check", lint_doc),
|
2024-01-11 14:30:28 +01:00
|
|
|
("lint-*.py scripts", lint_all),
|
2023-11-13 16:54:20 +01:00
|
|
|
];
|
2023-02-14 17:42:12 +01:00
|
|
|
|
2024-01-11 14:30:28 +01:00
|
|
|
let git_root = get_git_root();
|
2023-02-14 17:42:12 +01:00
|
|
|
|
|
|
|
let mut test_failed = false;
|
|
|
|
for (lint_name, lint_fn) in test_list {
|
|
|
|
// chdir to root before each lint test
|
|
|
|
env::set_current_dir(&git_root).unwrap();
|
|
|
|
if let Err(err) = lint_fn() {
|
|
|
|
println!("{err}\n^---- Failure generated from {lint_name}!");
|
|
|
|
test_failed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if test_failed {
|
|
|
|
ExitCode::FAILURE
|
|
|
|
} else {
|
|
|
|
ExitCode::SUCCESS
|
|
|
|
}
|
|
|
|
}
|