mod common;
use crate::common::{TestContext, cmd_snapshot};
use assert_fs::fixture::{FileWriteStr, PathChild, PathCreateDir};
use prek_consts::PRE_COMMIT_CONFIG_YAML;
#[test]
fn meta_hooks() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let cwd = context.work_dir();
cwd.child("file.txt").write_str("Hello, world!\n")?;
cwd.child("valid.json").write_str("{}")?;
cwd.child("invalid.json").write_str("{}")?;
cwd.child("main.py").write_str(r#"print "abc" "#)?;
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
- id: identity
- repo: local
hooks:
- id: match-no-files
name: match no files
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
files: ^nonexistent$
- id: useless-exclude
name: useless exclude
language: system
entry: python3 -c 'import sys; sys.exit(0)'
exclude: $nonexistent^
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r"
success: false
exit_code: 1
----- stdout -----
Check hooks apply........................................................Failed
- hook id: check-hooks-apply
- exit code: 1
match-no-files does not apply to this repository
Check useless excludes...................................................Failed
- hook id: check-useless-excludes
- exit code: 1
The exclude pattern `regex: $nonexistent^` for `useless-exclude` does not match any files
identity.................................................................Passed
- hook id: identity
- duration: [TIME]
file.txt
.pre-commit-config.yaml
valid.json
invalid.json
main.py
match no files.......................................(no files to check)Skipped
useless exclude..........................................................Passed
----- stderr -----
");
Ok(())
}
#[test]
fn meta_hooks_unknown_hook() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: meta
hooks:
- id: this-hook-does-not-exist
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Failed to parse `.pre-commit-config.yaml`
caused by: error: line 4 column 9: unknown meta hook id `this-hook-does-not-exist`
--> <input>:4:9
|
2 | - repo: meta
3 | hooks:
4 | - id: this-hook-does-not-exist
| ^ unknown meta hook id `this-hook-does-not-exist`
");
}
#[test]
fn check_useless_excludes_remote() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let pre_commit_config = indoc::formatdoc! {r"
repos:
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 25.1.0
hooks:
- id: black
exclude: '^html/'
- repo: local
hooks:
- id: echo
name: echo
entry: echo 'echoing'
language: system
exclude: '^useless/$'
- repo: meta
hooks:
- id: check-useless-excludes
"};
context.work_dir().child("html").create_dir_all()?;
context
.work_dir()
.child("html")
.child("file1.html")
.write_str("<!DOCTYPE html>")?;
context.write_pre_commit_config(&pre_commit_config);
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("check-useless-excludes"), @r"
success: false
exit_code: 1
----- stdout -----
Check useless excludes...................................................Failed
- hook id: check-useless-excludes
- exit code: 1
The exclude pattern `regex: ^useless/$` for `echo` does not match any files
----- stderr -----
");
Ok(())
}
#[test]
fn meta_hooks_workspace() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let app = context.work_dir().child("app");
app.create_dir_all()?;
app.child(PRE_COMMIT_CONFIG_YAML)
.write_str(indoc::indoc! {r"
repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
- id: identity
- repo: local
hooks:
- id: match-no-files
name: match no files
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
files: ^nonexistent$
- id: useless-exclude
name: useless exclude
language: system
entry: python3 -c 'import sys; sys.exit(0)'
exclude: $nonexistent^
"})?;
app.child("file.txt").write_str("Hello, world!\n")?;
app.child("valid.json").write_str("{}")?;
app.child("invalid.json").write_str("{x}")?;
app.child("main.py").write_str(r#"print "abc" "#)?;
context.write_pre_commit_config("repos: []");
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r"
success: false
exit_code: 1
----- stdout -----
Running hooks for `app`:
Check hooks apply........................................................Failed
- hook id: check-hooks-apply
- exit code: 1
match-no-files does not apply to this repository
Check useless excludes...................................................Failed
- hook id: check-useless-excludes
- exit code: 1
The exclude pattern `regex: $nonexistent^` for `useless-exclude` does not match any files
identity.................................................................Passed
- hook id: identity
- duration: [TIME]
file.txt
.pre-commit-config.yaml
valid.json
invalid.json
main.py
match no files.......................................(no files to check)Skipped
useless exclude..........................................................Passed
----- stderr -----
");
Ok(())
}
#[test]
fn check_useless_excludes_workspace_paths_are_project_relative() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let app = context.work_dir().child("app");
app.create_dir_all()?;
app.child(PRE_COMMIT_CONFIG_YAML)
.write_str(indoc::indoc! {r"
exclude: '^global_excluded$'
repos:
- repo: meta
hooks:
- id: check-useless-excludes
- repo: local
hooks:
- id: ok
name: ok
language: system
entry: python3 -c 'import sys; sys.exit(0)'
exclude: '^hook_excluded$'
"})?;
app.child("global_excluded").write_str("ignored\n")?;
app.child("hook_excluded").write_str("ignored\n")?;
context.write_pre_commit_config("repos: []");
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("check-useless-excludes"), @r"
success: true
exit_code: 0
----- stdout -----
Running hooks for `app`:
Check useless excludes...................................................Passed
----- stderr -----
");
Ok(())
}