Repository: bitcoin/bitcoin
File: test/lint/test_runner/src/main.rs (Rust)

Code before:
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_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!(
        r"^\s*(?!//).*({})",
        check_output(Command::new("grep").args(["define", "--", config_path]))
            .expect("grep failed")
            .lines()
            .map(|line| {
                line.split_whitespace()
                    .nth(1)
                    .unwrap_or_else(|| panic!("Could not extract name in line: {line}"))
            })
            .collect::<Vec<_>>()

Review comment (performance):
Should we add any other ones here?
```bash
$ find . -type f -exec grep -Il . {} + | rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr
1266 json
 721 cpp
 704 h
 461 d
 344 py
 275 cmake
 228 md
 162 ts
 145 make
  89 cc
  73 txt
  49 sh
  43 mk
  32 patch
  32 hex
  28 c
  27 in
  26 internal
  20 svg
  19 ui
  16 yml
  14 sample
  14 gitignore
  13 marks
  11 m4
  10 capnp
   9 sage
   8 xml
   8 1
   6 rc
   6 ninja
   6 include
   6 fish
   6 bash
   5 xpm
   4 yaml
   4 log
   4 ini
   4 check_cache
   4 bt
   3 x
   3 toml
   3 rs
   3 mm
   3 lock
   3 csv
   3 conf
   3 clang-format
   3 TAG
   2 sub
   2 s
   2 qrc
   2 html
   2 guess
   2 gitattributes
   2 clang-tidy
   2 am
   2 ac
   2 Dockerfile
   ...
```

Code after:
        .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.