1
0
mirror of https://github.com/j178/prek.git synced 2026-04-25 02:11:36 +02:00
Files
prek/tests/install.rs
T
2025-08-18 14:30:18 +08:00

459 lines
13 KiB
Rust

use assert_cmd::assert::OutputAssertExt;
use assert_fs::assert::PathAssert;
use assert_fs::fixture::{FileWriteStr, PathChild, PathCreateDir};
use insta::assert_snapshot;
use crate::common::{TestContext, cmd_snapshot};
mod common;
#[test]
fn install() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let filters = context
.filters()
.into_iter()
.chain([("#!/bin/sh", "#!/usr/bin/env bash")])
.collect::<Vec<_>>();
// Install `prek` hook.
cmd_snapshot!(context.filters(), context.install(), @r#"
success: true
exit_code: 0
----- stdout -----
prek installed at `.git/hooks/pre-commit`
----- stderr -----
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config=".pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
// Install `pre-commit` and `post-commit` hook.
context
.work_dir()
.child(".git/hooks/pre-commit")
.write_str("#!/bin/sh\necho 'pre-commit'\n")?;
cmd_snapshot!(filters.clone(), context.install().arg("--hook-type").arg("pre-commit").arg("--hook-type").arg("post-commit"), @r#"
success: true
exit_code: 0
----- stdout -----
Hook already exists at `.git/hooks/pre-commit`, move it to `.git/hooks/pre-commit.legacy`
prek installed at `.git/hooks/pre-commit`
prek installed at `.git/hooks/post-commit`
----- stderr -----
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config=".pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
assert_snapshot!(context.read(".git/hooks/pre-commit.legacy"), @r##"
#!/bin/sh
echo 'pre-commit'
"##);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/post-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=post-commit --config=".pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
// Overwrite existing hooks.
cmd_snapshot!(filters.clone(), context.install().arg("-t").arg("pre-commit").arg("--hook-type").arg("post-commit").arg("--overwrite"), @r#"
success: true
exit_code: 0
----- stdout -----
Overwriting existing hook at `.git/hooks/pre-commit`
prek installed at `.git/hooks/pre-commit`
Overwriting existing hook at `.git/hooks/post-commit`
prek installed at `.git/hooks/post-commit`
----- stderr -----
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config=".pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/post-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=post-commit --config=".pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
Ok(())
}
/// Run `prek install --install-hooks` to install the git hook and create prek hook environments.
#[test]
fn install_with_hooks() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
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
"});
let filters = context
.filters()
.into_iter()
.chain([("#!/bin/sh", "#!/usr/bin/env bash")])
.collect::<Vec<_>>();
context
.home_dir()
.child("repos")
.assert(predicates::path::missing());
context
.home_dir()
.child("hooks")
.assert(predicates::path::missing());
cmd_snapshot!(filters.clone(), context.install().arg("--install-hooks"), @r#"
success: true
exit_code: 0
----- stdout -----
prek installed at `.git/hooks/pre-commit`
----- stderr -----
"#);
// Check that repos and hooks are created.
assert_eq!(context.home_dir().child("repos").read_dir()?.count(), 1);
assert_eq!(context.home_dir().child("hooks").read_dir()?.count(), 1);
insta::with_settings!(
{ filters => filters },
{
assert_snapshot!(context.read(".git/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config="[TEMP_DIR]/.pre-commit-config.yaml")
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
Ok(())
}
/// Run `prek install-hooks` to create prek hook environments without installing the git hook.
#[test]
fn install_hooks_only() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
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
"});
context
.home_dir()
.child("repos")
.assert(predicates::path::missing());
context
.home_dir()
.child("hooks")
.assert(predicates::path::missing());
cmd_snapshot!(context.filters(), context.install_hooks(), @r#"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
"#);
// Check that repos and hooks are created.
assert_eq!(context.home_dir().child("repos").read_dir()?.count(), 1);
assert_eq!(context.home_dir().child("hooks").read_dir()?.count(), 1);
// Ensure the git hook is not installed.
context
.work_dir()
.child(".git/hooks/pre-commit")
.assert(predicates::path::missing());
Ok(())
}
#[test]
fn uninstall() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
// Hook does not exist.
cmd_snapshot!(context.filters(), context.uninstall(), @r#"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
`.git/hooks/pre-commit` does not exist, skipping.
"#);
// Uninstall `pre-commit` hook.
context.install().assert().success();
cmd_snapshot!(context.filters(), context.uninstall(), @r#"
success: true
exit_code: 0
----- stdout -----
Uninstalled `pre-commit`
----- stderr -----
"#);
context
.work_dir()
.child(".git/hooks/pre-commit")
.assert(predicates::path::missing());
// Hook is not managed by `pre-commit`.
context
.work_dir()
.child(".git/hooks/pre-commit")
.write_str("#!/bin/sh\necho 'pre-commit'\n")?;
cmd_snapshot!(context.filters(), context.uninstall(), @r#"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
`.git/hooks/pre-commit` is not managed by prek, skipping.
"#);
// Restore previous hook.
context.install().assert().success();
cmd_snapshot!(context.filters(), context.uninstall(), @r#"
success: true
exit_code: 0
----- stdout -----
Uninstalled `pre-commit`
Restored previous hook to `.git/hooks/pre-commit`
----- stderr -----
"#);
// Uninstall multiple hooks.
context
.install()
.arg("-t")
.arg("pre-commit")
.arg("-t")
.arg("post-commit")
.assert()
.success();
cmd_snapshot!(context.filters(), context.uninstall().arg("-t").arg("pre-commit").arg("-t").arg("post-commit"), @r#"
success: true
exit_code: 0
----- stdout -----
Uninstalled `pre-commit`
Restored previous hook to `.git/hooks/pre-commit`
Uninstalled `post-commit`
----- stderr -----
"#);
Ok(())
}
#[test]
fn init_template_dir() -> anyhow::Result<()> {
let context = TestContext::new();
context.init_project();
let filters = context
.filters()
.into_iter()
.chain([("#!/bin/sh", "#!/usr/bin/env bash")])
.collect::<Vec<_>>();
cmd_snapshot!(context.filters(), context.command().arg("init-templatedir").arg(".git"), @r#"
success: true
exit_code: 0
----- stdout -----
prek installed at `.git/hooks/pre-commit`
----- stderr -----
warning: git config `init.templateDir` not set to the target directory, try `git config --global init.templateDir '.git'`
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read(".git/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config=".pre-commit-config.yaml" --skip-on-missing-config)
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
// Run from a subdirectory.
let child = context.work_dir().child("subdir");
child.create_dir_all()?;
cmd_snapshot!(filters.clone(), context.command().arg("init-templatedir").arg("temp-dir").current_dir(child), @r#"
success: true
exit_code: 0
----- stdout -----
prek installed at `temp-dir/hooks/pre-commit`
----- stderr -----
warning: git config `init.templateDir` not set to the target directory, try `git config --global init.templateDir 'temp-dir'`
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read("subdir/temp-dir/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config=".pre-commit-config.yaml" --skip-on-missing-config)
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
// `--config` points to non-existing file.
cmd_snapshot!(filters.clone(), context.command().arg("init-templatedir").arg("-c").arg("non-exist-config").arg("subdir2"), @r#"
success: true
exit_code: 0
----- stdout -----
prek installed at `subdir2/hooks/pre-commit`
----- stderr -----
warning: git config `init.templateDir` not set to the target directory, try `git config --global init.templateDir 'subdir2'`
"#);
insta::with_settings!(
{ filters => filters.clone() },
{
assert_snapshot!(context.read("subdir2/hooks/pre-commit"), @r##"
#!/usr/bin/env bash
# File generated by prek: https://github.com/j178/prek
# ID: 182c10f181da4464a3eec51b83331688
ARGS=(hook-impl --hook-type=pre-commit --config="non-exist-config" --skip-on-missing-config)
HERE="$(cd "$(dirname "$0")" && pwd)"
ARGS+=(--hook-dir "$HERE" -- "$@")
PREK="[CURRENT_EXE]"
exec "$PREK" "${ARGS[@]}"
"##);
}
);
Ok(())
}