mirror of
https://github.com/j178/prek.git
synced 2026-04-03 17:34:03 +02:00
A version number could look like a float, e.g., 0.49 is a valid version number. Serde YAML serialization already renders such version numbers in quotes so types match the expectation. When doing an autoupdate we were explicitly adding more quotes if they were present in the input. This could have caused incorrect quoting if existing quoting clashed with serde's quoting style, e.g., if `"` where used but serde defaulted to quoting with `'`. This patch removes any extra quoting here and fully defers to serde. Closes #866.
939 lines
24 KiB
Rust
939 lines
24 KiB
Rust
use std::process::Command;
|
|
|
|
use anyhow::Result;
|
|
use assert_cmd::assert::OutputAssertExt;
|
|
use assert_fs::fixture::ChildPath;
|
|
use assert_fs::prelude::*;
|
|
use constants::CONFIG_FILE;
|
|
use insta::assert_snapshot;
|
|
|
|
use crate::common::{TestContext, cmd_snapshot};
|
|
|
|
mod common;
|
|
|
|
/// Helper function to create a local git repository with hooks
|
|
fn create_local_git_repo(context: &TestContext, repo_name: &str, tags: &[&str]) -> Result<String> {
|
|
let repo_dir = context.home_dir().child(format!("test-repos/{repo_name}"));
|
|
repo_dir.create_dir_all()?;
|
|
|
|
Command::new("git")
|
|
.arg("-c")
|
|
.arg("init.defaultBranch=master")
|
|
.arg("init")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("config")
|
|
.arg("user.name")
|
|
.arg("Prek Test")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("config")
|
|
.arg("user.email")
|
|
.arg("test@prek.dev")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("config")
|
|
.arg("core.autocrlf")
|
|
.arg("false")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
// Create .pre-commit-hooks.yaml
|
|
repo_dir
|
|
.child(".pre-commit-hooks.yaml")
|
|
.write_str(indoc::indoc! {r#"
|
|
- id: test-hook
|
|
name: Test Hook
|
|
entry: echo
|
|
language: system
|
|
- id: another-hook
|
|
name: Another Hook
|
|
entry: python3 -c 'print("hello")'
|
|
language: python
|
|
"#})?;
|
|
|
|
Command::new("git")
|
|
.arg("add")
|
|
.arg(".")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
Command::new("git")
|
|
.arg("commit")
|
|
.arg("-m")
|
|
.arg("Initial commit")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
// Create tags
|
|
for tag in tags {
|
|
Command::new("git")
|
|
.arg("commit")
|
|
.arg("-m")
|
|
.arg(format!("Release {tag}"))
|
|
.arg("--allow-empty")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("tag")
|
|
.arg(tag)
|
|
.arg("-m")
|
|
.arg(tag)
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
}
|
|
|
|
// Add an extra commit to the tip
|
|
Command::new("git")
|
|
.arg("commit")
|
|
.arg("-m")
|
|
.arg("tip")
|
|
.arg("--allow-empty")
|
|
.current_dir(&repo_dir)
|
|
.assert()
|
|
.success();
|
|
|
|
Ok(repo_dir.to_string_lossy().to_string())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_basic() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "test-repo", &["v1.0.0", "v1.1.0", "v2.0.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/test-repo] updating v1.0.0 -> v2.0.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/test-repo
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_already_up_to_date() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "up-to-date-repo", &["v1.0.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/up-to-date-repo] already up to date
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/up-to-date-repo
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_multiple_repos_mixed() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo1_path = create_local_git_repo(&context, "repo1", &["v1.0.0", "v1.1.0"])?;
|
|
let repo2_path = create_local_git_repo(&context, "repo2", &["v2.0.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: same-hook
|
|
- repo: {}
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
", repo1_path, repo1_path, repo2_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/repo1] updating v1.0.0 -> v1.1.0
|
|
[[HOME]/test-repos/repo2] already up to date
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r"
|
|
repos:
|
|
- repo: [HOME]/test-repos/repo1
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: [HOME]/test-repos/repo1
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: same-hook
|
|
- repo: [HOME]/test-repos/repo2
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
");
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_specific_repos() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo1_path = create_local_git_repo(&context, "repo1", &["v1.0.0", "v1.1.0"])?;
|
|
let repo2_path = create_local_git_repo(&context, "repo2", &["v2.0.0", "v2.1.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: {}
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
", repo1_path, repo2_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
// Update only repo1
|
|
cmd_snapshot!(filters.clone(), context.auto_update().arg("--repo").arg(&repo1_path), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/repo1] updating v1.0.0 -> v1.1.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/repo1
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: [HOME]/test-repos/repo2
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
// Update both repo1 and repo2
|
|
cmd_snapshot!(filters.clone(), context.auto_update().arg("--repo").arg(&repo1_path).arg("--repo").arg(&repo2_path), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/repo1] already up to date
|
|
[[HOME]/test-repos/repo2] updating v2.0.0 -> v2.1.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/repo1
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: [HOME]/test-repos/repo2
|
|
rev: v2.1.0
|
|
hooks:
|
|
- id: another-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_bleeding_edge() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "bleeding-repo", &["v1.0.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context
|
|
.filters()
|
|
.into_iter()
|
|
.chain([("[a-f0-9]{40}", "[COMMIT_SHA]")])
|
|
.collect::<Vec<_>>();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update().arg("--bleeding-edge"), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/bleeding-repo] updating v1.0.0 -> [COMMIT_SHA]
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/bleeding-repo
|
|
rev: [COMMIT_SHA]
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_freeze() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "freeze-repo", &["v1.0.0", "v1.1.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context
|
|
.filters()
|
|
.into_iter()
|
|
.chain([(r" [a-f0-9]{40}", r" [COMMIT_SHA]")])
|
|
.collect::<Vec<_>>();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update().arg("--freeze"), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/freeze-repo] updating v1.0.0 -> [COMMIT_SHA]
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
// Should contain frozen comment
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r##"
|
|
repos:
|
|
- repo: [HOME]/test-repos/freeze-repo
|
|
rev: [COMMIT_SHA] # frozen: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
"##);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_preserve_formatting() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo1_path = create_local_git_repo(&context, "repo1", &["v1.0.0", "v1.1.0"])?;
|
|
let repo2_path = create_local_git_repo(&context, "repo2", &["v1.0.0", "v1.1.0"])?;
|
|
|
|
// Use specific formatting with comments
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r#"
|
|
# Pre-commit configuration
|
|
repos:
|
|
- repo: {} # Test repository
|
|
rev: 'v1.0.0' # Current version
|
|
hooks:
|
|
- id: test-hook
|
|
# Hook configuration
|
|
name: Test Hook
|
|
- repo: {}
|
|
rev: "v1.0.0" # Current version
|
|
hooks:
|
|
- id: test-hook
|
|
# Hook configuration
|
|
name: Test Hook
|
|
"#, repo1_path, repo2_path });
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/repo1] updating v1.0.0 -> v1.1.0
|
|
[[HOME]/test-repos/repo2] updating v1.0.0 -> v1.1.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r"
|
|
# Pre-commit configuration
|
|
repos:
|
|
- repo: [HOME]/test-repos/repo1 # Test repository
|
|
rev: v1.1.0 # Current version
|
|
hooks:
|
|
- id: test-hook
|
|
# Hook configuration
|
|
name: Test Hook
|
|
- repo: [HOME]/test-repos/repo2
|
|
rev: v1.1.0 # Current version
|
|
hooks:
|
|
- id: test-hook
|
|
# Hook configuration
|
|
name: Test Hook
|
|
");
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_with_existing_frozen_comment() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path =
|
|
create_local_git_repo(&context, "frozen-repo", &["v1.0.0", "v1.1.0", "v1.2.0"])?;
|
|
|
|
let commit_sha = "1234567890abcdef1234567890abcdef12345678";
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: {} # frozen: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path, commit_sha});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context
|
|
.filters()
|
|
.into_iter()
|
|
.chain([(commit_sha, "[COMMIT_SHA]")])
|
|
.collect::<Vec<_>>();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/frozen-repo] updating [COMMIT_SHA] -> v1.2.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/frozen-repo
|
|
rev: v1.2.0
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_local_repo_ignored() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "remote-repo", &["v1.0.0", "v1.1.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: local-hook
|
|
name: Local Hook
|
|
language: system
|
|
entry: echo
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/remote-repo] updating v1.0.0 -> v1.1.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: local-hook
|
|
name: Local Hook
|
|
language: system
|
|
entry: echo
|
|
- repo: [HOME]/test-repos/remote-repo
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn missing_hook_ids() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "missing-hook-repo", &["v1.0.0"])?;
|
|
|
|
// Remove the 'test-hook' from the hooks file
|
|
ChildPath::new(&repo_path)
|
|
.child(".pre-commit-hooks.yaml")
|
|
.write_str(indoc::indoc! {r#"
|
|
- id: another-hook
|
|
name: Another Hook
|
|
entry: python3 -c 'print("hello")'
|
|
language: python
|
|
"#})?;
|
|
|
|
Command::new("git")
|
|
.arg("add")
|
|
.arg(".")
|
|
.current_dir(&repo_path)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("commit")
|
|
.arg("-m")
|
|
.arg("Remove test-hook")
|
|
.current_dir(&repo_path)
|
|
.assert()
|
|
.success();
|
|
Command::new("git")
|
|
.arg("tag")
|
|
.arg("v2.0.0")
|
|
.arg("-m")
|
|
.arg("v2.0.0")
|
|
.current_dir(&repo_path)
|
|
.assert()
|
|
.success();
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
[[HOME]/test-repos/missing-hook-repo] update failed: Cannot update to rev `v2.0.0`, hook is missing: test-hook
|
|
"#);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_workspace() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo1_path =
|
|
create_local_git_repo(&context, "workspace-repo1", &["v1.0.0", "v1.1.0", "v2.0.0"])?;
|
|
let repo2_path = create_local_git_repo(&context, "workspace-repo2", &["v1.0.0", "v1.5.0"])?;
|
|
let repo3_path = create_local_git_repo(&context, "workspace-repo3", &["v2.0.0"])?;
|
|
|
|
context.setup_workspace(
|
|
&["project-a", "project-b"],
|
|
"repos: []", // Minimal valid config for root
|
|
)?;
|
|
|
|
context
|
|
.work_dir()
|
|
.child("project-a/.pre-commit-config.yaml")
|
|
.write_str(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
", repo1_path, repo2_path})?;
|
|
|
|
context
|
|
.work_dir()
|
|
.child("project-b/.pre-commit-config.yaml")
|
|
.write_str(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: another-hook
|
|
- repo: {}
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo2_path, repo3_path})?;
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/workspace-repo1] updating v1.0.0 -> v2.0.0
|
|
[[HOME]/test-repos/workspace-repo2] updating v1.0.0 -> v1.5.0
|
|
[[HOME]/test-repos/workspace-repo3] already up to date
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read("project-a/.pre-commit-config.yaml"), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/workspace-repo1
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
- repo: [HOME]/test-repos/workspace-repo2
|
|
rev: v1.5.0
|
|
hooks:
|
|
- id: another-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read("project-b/.pre-commit-config.yaml"), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/workspace-repo2
|
|
rev: v1.5.0
|
|
hooks:
|
|
- id: another-hook
|
|
- repo: [HOME]/test-repos/workspace-repo3
|
|
rev: v2.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// When there are multiple tags pointing to the same object,
|
|
// prek prefer picking a tag with a dot and is closest to the current rev according
|
|
// to Levenshtein distance.
|
|
#[test]
|
|
fn prefer_similar_tags() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "remote-repo", &["v1.0.0", "v1.1.0"])?;
|
|
// Add tag foo-v1.0.0 pointing to the same commit as v1.1.0
|
|
// v1.0.0 distance to v1.1.0 is 1
|
|
// v1.0.0 distance to foo-v1.0.0 is 4
|
|
// So we choose v1.1.0 as the update target
|
|
// But if the newest tag is v1.1.1111 (distance is 5), then we would choose foo-v1.0.0 instead
|
|
Command::new("git")
|
|
.arg("tag")
|
|
.arg("foo-v1.0.0")
|
|
.arg("-m")
|
|
.arg("foo-v1.0.0")
|
|
.arg("v1.1.0^{}")
|
|
.current_dir(&repo_path)
|
|
.assert()
|
|
.success();
|
|
// Add tag v1 pointing to the same commit as v1.1.0
|
|
Command::new("git")
|
|
.arg("tag")
|
|
.arg("v1")
|
|
.arg("-m")
|
|
.arg("v1")
|
|
.arg("v1.1.0^{}")
|
|
.current_dir(&repo_path)
|
|
.assert()
|
|
.success();
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: local-hook
|
|
name: Local Hook
|
|
language: system
|
|
entry: echo
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/remote-repo] updating v1.0.0 -> v1.1.0
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: local-hook
|
|
name: Local Hook
|
|
language: system
|
|
entry: echo
|
|
- repo: [HOME]/test-repos/remote-repo
|
|
rev: v1.1.0
|
|
hooks:
|
|
- id: test-hook
|
|
");
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn auto_update_dry_run() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "test-repo", &["v1.0.0", "v1.1.0", "v2.0.0"])?;
|
|
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r"
|
|
repos:
|
|
- repo: {}
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
", repo_path});
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update().arg("--dry-run"), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/test-repo] updating v1.0.0 -> v2.0.0
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r"
|
|
repos:
|
|
- repo: [HOME]/test-repos/test-repo
|
|
rev: v1.0.0
|
|
hooks:
|
|
- id: test-hook
|
|
");
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn quoting_float_like_version_number() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let repo_path = create_local_git_repo(&context, "test-repo", &["0.49", "0.50"])?;
|
|
|
|
// Our serialize by default quotes this floats with single quotes, e.g., '0.49'. Use
|
|
// a different quotaing style here to validate that this does not create conflicts.
|
|
context.write_pre_commit_config(&indoc::formatdoc! {r#"
|
|
repos:
|
|
- repo: {}
|
|
rev: "0.49"
|
|
hooks:
|
|
- id: test-hook
|
|
"#, repo_path});
|
|
context.git_add(".");
|
|
|
|
let filters = context.filters();
|
|
|
|
cmd_snapshot!(filters.clone(), context.auto_update(), @r#"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
[[HOME]/test-repos/test-repo] updating 0.49 -> 0.50
|
|
|
|
----- stderr -----
|
|
"#);
|
|
|
|
insta::with_settings!(
|
|
{ filters => filters.clone() },
|
|
{
|
|
assert_snapshot!(context.read(CONFIG_FILE), @r#"
|
|
repos:
|
|
- repo: [HOME]/test-repos/test-repo
|
|
rev: '0.50'
|
|
hooks:
|
|
- id: test-hook
|
|
"#);
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|