1
0
mirror of https://github.com/j178/prek.git synced 2026-04-25 02:11:36 +02:00
Files
Jo 0253181df8 Reimplement find matching env logic (#327)
* Reimplement find matching env logic

* Fix test

* Fix
2025-08-03 20:35:03 +08:00

1111 lines
31 KiB
Rust

use std::process::Command;
use anyhow::Result;
use assert_cmd::assert::OutputAssertExt;
use assert_fs::prelude::*;
use insta::assert_snapshot;
use crate::common::{TestContext, cmd_snapshot};
mod common;
#[test]
fn run_basic() -> Result<()> {
let context = TestContext::new();
context.init_project();
let cwd = context.work_dir();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-json
"});
// Create a repository with some files.
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.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook
Fixing main.py
fix end of files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
- files were modified by this hook
Fixing valid.json
Fixing invalid.json
Fixing main.py
check json...............................................................Passed
----- stderr -----
"#);
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("trailing-whitespace"), @r#"
success: true
exit_code: 0
----- stdout -----
trim trailing whitespace.................................................Passed
----- stderr -----
"#);
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("typos").arg("--hook-stage").arg("pre-push"), @r#"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
No hook found for id `typos` and stage `pre-push`
"#);
Ok(())
}
#[test]
fn invalid_config() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config("invalid: config");
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Failed to parse `.pre-commit-config.yaml`
caused by: missing field `repos`
"#);
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: dotnet
additional_dependencies: ["dotnet@6"]
entry: echo Hello, world!
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Hook `trailing-whitespace` is invalid
caused by: Hook specified `additional_dependencies` `dotnet@6` but the language `dotnet` does not support installing dependencies for now
"#);
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: fail
language_version: '6'
entry: echo Hello, world!
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Hook `trailing-whitespace` is invalid
caused by: Hook specified `language_version` `6` but the language `fail` does not install an environment
"#);
}
/// Use same repo multiple times, with same or different revisions.
#[test]
fn same_repo() -> Result<()> {
let context = TestContext::new();
context.init_project();
let cwd = context.work_dir();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
"});
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.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook
Fixing main.py
trim trailing whitespace.................................................Passed
trim trailing whitespace.................................................Passed
----- stderr -----
"#);
Ok(())
}
#[test]
fn local() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: local
name: local
language: system
entry: echo Hello, world!
always_run: true
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: true
exit_code: 0
----- stdout -----
local....................................................................Passed
----- stderr -----
"#);
}
#[test]
fn meta_hooks() -> 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 "$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 invalid_hook_id() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -V
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("invalid-hook-id"), @r#"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
No hook found for id `invalid-hook-id`
"#);
}
/// `.pre-commit-config.yaml` is not staged.
#[test]
fn config_not_staged() -> Result<()> {
let context = TestContext::new();
context.init_project();
context
.work_dir()
.child(".pre-commit-config.yaml")
.touch()?;
context.git_add(".");
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -V
"});
cmd_snapshot!(context.filters(), context.run().arg("invalid-hook-id"), @r#"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
Your prefligit configuration file is not staged.
Run `git add .pre-commit-config.yaml` to fix this.
"#);
Ok(())
}
/// `.pre-commit-config.yaml` outside the repository should not be checked.
#[test]
fn config_outside_repo() -> Result<()> {
let context = TestContext::new();
// Initialize a git repository in ./work.
let root = context.work_dir().child("work");
root.create_dir_all()?;
Command::new("git")
.arg("init")
.current_dir(&root)
.assert()
.success();
// Create a configuration file in . (outside the repository).
context
.work_dir()
.child("c.yaml")
.write_str(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print("Hello world")'
"#})?;
cmd_snapshot!(context.filters(), context.run().current_dir(&root).arg("-c").arg("../c.yaml"), @r#"
success: true
exit_code: 0
----- stdout -----
trailing-whitespace..................................(no files to check)Skipped
----- stderr -----
"#);
Ok(())
}
/// Test the output format for a hook with a CJK name.
#[test]
fn cjk_hook_name() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: 去除行尾空格
language: system
entry: python3 -V
- id: end-of-file-fixer
name: fix end of files
language: system
entry: python3 -V
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: true
exit_code: 0
----- stdout -----
去除行尾空格.............................................................Passed
fix end of files.........................................................Passed
----- stderr -----
"#);
}
/// Skips hooks based on the `SKIP` environment variable.
#[test]
fn skips() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c "exit(1)"
- id: end-of-file-fixer
name: fix end of files
language: system
entry: python3 -c "exit(1)"
- id: check-json
name: check json
language: system
entry: python3 -c "exit(1)"
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().env("SKIP", "end-of-file-fixer"), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
fix end of files........................................................Skipped
check json...............................................................Failed
- hook id: check-json
- exit code: 1
----- stderr -----
"#);
cmd_snapshot!(context.filters(), context.run().env("SKIP", "trailing-whitespace,end-of-file-fixer"), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace.....................................................Skipped
fix end of files........................................................Skipped
check json...............................................................Failed
- hook id: check-json
- exit code: 1
----- stderr -----
"#);
}
/// Test global `files`, `exclude`, and hook level `files`, `exclude`.
#[test]
fn files_and_exclude() -> 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("{}\n ")?;
cwd.child("invalid.json").write_str("{}")?;
cwd.child("main.py").write_str(r#"print "abc" "#)?;
// Global files and exclude.
context.write_pre_commit_config(indoc::indoc! {r"
files: file.txt
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types: [text]
- id: end-of-file-fixer
name: fix end of files
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types: [text]
- id: check-json
name: check json
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types: [json]
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trailing whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
['file.txt']
fix end of files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
['file.txt']
check json...........................................(no files to check)Skipped
----- stderr -----
"#);
// Override hook level files and exclude.
context.write_pre_commit_config(indoc::indoc! {r"
files: file.txt
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
files: valid.json
- id: end-of-file-fixer
name: fix end of files
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
exclude: (valid.json|main.py)
- id: check-json
name: check json
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
"});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trailing whitespace..................................(no files to check)Skipped
fix end of files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
['file.txt']
check json...............................................................Failed
- hook id: check-json
- exit code: 1
['file.txt']
----- stderr -----
"#);
Ok(())
}
/// Test selecting files by type, `types`, `types_or`, and `exclude_types`.
#[test]
fn file_types() -> Result<()> {
let context = TestContext::new();
context.init_project();
let cwd = context.work_dir();
cwd.child("file.txt").write_str("Hello, world! ")?;
cwd.child("json.json").write_str("{}\n ")?;
cwd.child("main.py").write_str(r#"print "abc" "#)?;
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types: ["json"]
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types_or: ["json", "python"]
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
exclude_types: ["json"]
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import sys; print(sys.argv[1:]); exit(1)'
types: ["json" ]
exclude_types: ["json"]
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
['json.json']
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
['main.py', 'json.json']
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
['file.txt', '.pre-commit-config.yaml', 'main.py']
trailing-whitespace..................................(no files to check)Skipped
----- stderr -----
"#);
Ok(())
}
/// Abort the run if a hook fails.
#[test]
fn fail_fast() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print("Fixing files"); exit(1)'
always_run: true
fail_fast: false
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print("Fixing files"); exit(1)'
always_run: true
fail_fast: true
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -V
always_run: true
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -V
always_run: true
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
Fixing files
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
Fixing files
----- stderr -----
"#);
}
/// Run from a subdirectory. File arguments should be fixed to be relative to the root.
#[test]
fn subdirectory() -> Result<()> {
let context = TestContext::new();
context.init_project();
let cwd = context.work_dir();
let child = cwd.child("foo/bar/baz");
child.create_dir_all()?;
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print("Hello"); exit(1)'
always_run: true
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().current_dir(&child).arg("--files").arg("file.txt"), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
Hello
----- stderr -----
"#);
Ok(())
}
/// Test hook `log_file` option.
#[test]
fn log_file() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print("Fixing files"); exit(1)'
always_run: true
log_file: log.txt
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
trailing-whitespace......................................................Failed
- hook id: trailing-whitespace
- exit code: 1
----- stderr -----
"#);
let log = context.read("log.txt");
assert_eq!(log, "Fixing files");
}
/// Pass pre-commit environment variables to the hook.
#[test]
fn pass_env_vars() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: env-vars
name: Pass environment
language: system
entry: python3 -c "import os, sys; print(os.getenv('PRE_COMMIT')); sys.exit(1)"
always_run: true
"#});
cmd_snapshot!(context.filters(), context.run(), @r###"
success: false
exit_code: 1
----- stdout -----
Pass environment.........................................................Failed
- hook id: env-vars
- exit code: 1
1
----- stderr -----
"###);
}
#[test]
fn staged_files_only() -> Result<()> {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'print(open("file.txt", "rt").read())'
verbose: true
types: [text]
"#});
context
.work_dir()
.child("file.txt")
.write_str("Hello, world!")?;
context.git_add(".");
// Non-staged files should be stashed and restored.
context
.work_dir()
.child("file.txt")
.write_str("Hello world again!")?;
let filters: Vec<_> = context
.filters()
.into_iter()
.chain([(r"/\d+-\d+.patch", "/[TIME]-[PID].patch")])
.collect();
cmd_snapshot!(filters, context.run(), @r#"
success: true
exit_code: 0
----- stdout -----
trailing-whitespace......................................................Passed
- hook id: trailing-whitespace
- duration: [TIME]
Hello, world!
----- stderr -----
Non-staged changes detected, saving to `[HOME]/patches/[TIME]-[PID].patch`
Restored working tree changes from `[HOME]/patches/[TIME]-[PID].patch`
"#);
let content = context.read("file.txt");
assert_snapshot!(content, @"Hello world again!");
Ok(())
}
#[cfg(unix)]
#[test]
fn restore_on_interrupt() -> Result<()> {
let context = TestContext::new();
context.init_project();
// The hook will sleep for 3 seconds.
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import time; open("out.txt", "wt").write(open("file.txt", "rt").read()); time.sleep(10)'
verbose: true
types: [text]
"#});
context
.work_dir()
.child("file.txt")
.write_str("Hello, world!")?;
context.git_add(".");
// Non-staged files should be stashed and restored.
context
.work_dir()
.child("file.txt")
.write_str("Hello world again!")?;
let mut child = context.run().spawn()?;
let child_id = child.id();
// Send an interrupt signal to the process.
let handle = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(1));
#[allow(clippy::cast_possible_wrap)]
unsafe {
libc::kill(child_id as i32, libc::SIGINT)
};
});
handle.join().unwrap();
child.wait()?;
let content = context.read("out.txt");
assert_snapshot!(content, @"Hello, world!");
let content = context.read("file.txt");
assert_snapshot!(content, @"Hello world again!");
Ok(())
}
/// When in merge conflict, runs on files that have conflicts fixed.
#[test]
fn merge_conflicts() -> Result<()> {
let context = TestContext::new();
context.init_project();
// Create a merge conflict.
let cwd = context.work_dir();
cwd.child("file.txt").write_str("Hello, world!")?;
context.git_add(".");
context.configure_git_author();
context.git_commit("Initial commit");
Command::new("git")
.arg("checkout")
.arg("-b")
.arg("feature")
.current_dir(cwd)
.assert()
.success();
cwd.child("file.txt").write_str("Hello, world again!")?;
context.git_add(".");
context.git_commit("Feature commit");
Command::new("git")
.arg("checkout")
.arg("master")
.current_dir(cwd)
.assert()
.success();
cwd.child("file.txt")
.write_str("Hello, world from master!")?;
context.git_add(".");
context.git_commit("Master commit");
Command::new("git")
.arg("merge")
.arg("feature")
.current_dir(cwd)
.assert()
.code(1);
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: local
hooks:
- id: trailing-whitespace
name: trailing-whitespace
language: system
entry: python3 -c 'import sys; print(sorted(sys.argv[1:]))'
verbose: true
"});
// Abort on merge conflicts.
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
----- stderr -----
You have unmerged paths. Resolve them before running prefligit.
"#);
// Fix the conflict and run again.
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: true
exit_code: 0
----- stdout -----
trailing-whitespace......................................................Passed
- hook id: trailing-whitespace
- duration: [TIME]
['.pre-commit-config.yaml', 'file.txt']
----- stderr -----
"#);
Ok(())
}
/// Local python hook with no additional dependencies.
#[test]
fn local_python_hook() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: local-python-hook
name: local-python-hook
language: python
entry: python3 -c 'import sys; print("Hello, world!"); sys.exit(1)'
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 1
----- stdout -----
local-python-hook........................................................Failed
- hook id: local-python-hook
- exit code: 1
Hello, world!
----- stderr -----
"#);
}
/// Supports reading `pre-commit-config.yml` as well.
#[test]
fn alternate_config_file() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: local-python-hook
name: local-python-hook
language: python
entry: python3 -c 'import sys; print("Hello, world!")'
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run().arg("-v"), @r#"
success: true
exit_code: 0
----- stdout -----
local-python-hook........................................................Passed
- hook id: local-python-hook
- duration: [TIME]
Hello, world!
----- stderr -----
"#);
}
/// Invalid `entry`
#[test]
fn invalid_entry() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r#"
repos:
- repo: local
hooks:
- id: entry
name: entry
language: python
entry: '"'
"#});
context.git_add(".");
cmd_snapshot!(context.filters(), context.run(), @r#"
success: false
exit_code: 2
----- stdout -----
entry....................................................................
----- stderr -----
error: Failed to run hook `entry`
caused by: Hook `entry` is invalid
caused by: Failed to parse entry `"` as commands
"#);
}
/// Initialize a repo that does not exist.
#[test]
fn init_nonexistent_repo() {
let context = TestContext::new();
context.init_project();
context.write_pre_commit_config(indoc::indoc! {r"
repos:
- repo: https://notexistentatallnevergonnahappen.com/nonexistent/repo
rev: v1.0.0
hooks:
- id: nonexistent
name: nonexistent
"});
context.git_add(".");
let filters = context
.filters()
.into_iter()
.chain([(r"exit code: ", "exit status: ")])
.collect::<Vec<_>>();
cmd_snapshot!(filters, context.run(), @r"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
error: Failed to initialize repo `https://notexistentatallnevergonnahappen.com/nonexistent/repo`
caused by: command `git full clone` exited with an error:
[status]
exit status: 128
[stderr]
fatal: unable to access 'https://notexistentatallnevergonnahappen.com/nonexistent/repo/': Could not resolve host: notexistentatallnevergonnahappen.com
");
}