mirror of
https://github.com/j178/prek.git
synced 2026-05-05 18:25:21 +02:00
59230a7a72
* Add deduplicate feature # Conflicts: # src/cli/run/filter.rs * Linting * Linting * Fix failed test * Fix failed test * More testing * Revert "More testing" This reverts commit 40304335c49d27f7024703da4f3ac4d775af52f7. * Linting * Support orphan projects * Support orphan projects * Fix filter * Add a failing test * "orphan" is an static attribute, always in effect --------- Co-authored-by: Jo <10510431+j178@users.noreply.github.com>
1244 lines
36 KiB
Rust
1244 lines
36 KiB
Rust
mod common;
|
|
|
|
use std::process::Command;
|
|
|
|
use anyhow::Result;
|
|
use assert_cmd::assert::OutputAssertExt;
|
|
use assert_fs::fixture::{FileWriteStr, PathChild};
|
|
use indoc::indoc;
|
|
use prek_consts::env_vars::EnvVars;
|
|
|
|
use crate::common::{TestContext, cmd_snapshot};
|
|
|
|
#[test]
|
|
fn basic_discovery() -> Result<()> {
|
|
let context = TestContext::new();
|
|
let cwd = context.work_dir();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
|
|
context.setup_workspace(
|
|
&[
|
|
"project2",
|
|
"project3",
|
|
"nested/project4",
|
|
"project3/project5",
|
|
],
|
|
config,
|
|
)?;
|
|
context.git_add(".");
|
|
|
|
// Run from the root directory
|
|
cmd_snapshot!(context.filters(), context.run(), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `nested/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/nested/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3/project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Run from a subdirectory
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.join("project2")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.join("project2")).arg("--all-files"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.join("project3")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--cd").arg(cwd.join("project3")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Ignore `project5` in `project3`
|
|
context
|
|
.work_dir()
|
|
.child("project3/.prekignore")
|
|
.write_str("project5/\n")?;
|
|
context.git_add(".");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--refresh").arg("--cd").arg(cwd.join("project3")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['.prekignore', '.pre-commit-config.yaml', 'project5/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Ignoring everything under project3, but when runs from project3, it’s still getting picked up.
|
|
context
|
|
.work_dir()
|
|
.child("project3/.prekignore")
|
|
.write_str("*\n")?;
|
|
context.git_add(".");
|
|
cmd_snapshot!(context.filters(), context.run().arg("--refresh").arg("--cd").arg(cwd.join("project3")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['.prekignore', '.pre-commit-config.yaml', 'project5/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn config_not_staged() -> Result<()> {
|
|
let context = TestContext::new();
|
|
let cwd = context.work_dir();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
context.setup_workspace(
|
|
&[
|
|
"project2",
|
|
"project3",
|
|
"nested/project4",
|
|
"project3/project5",
|
|
],
|
|
config,
|
|
)?;
|
|
context.git_add(".");
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd-modified
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
// Setup again to modify files after git add
|
|
context.setup_workspace(
|
|
&[
|
|
"project2",
|
|
"project3",
|
|
"nested/project4",
|
|
"project3/project5",
|
|
],
|
|
config,
|
|
)?;
|
|
|
|
// Run from the root directory
|
|
cmd_snapshot!(context.filters(), context.run(), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: The following configuration files are not staged, `git add` them first:
|
|
.pre-commit-config.yaml
|
|
nested/project4/.pre-commit-config.yaml
|
|
project2/.pre-commit-config.yaml
|
|
project3/.pre-commit-config.yaml
|
|
project3/project5/.pre-commit-config.yaml
|
|
");
|
|
|
|
// Run from a subdirectory
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.join("project3")), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: The following configuration files are not staged, `git add` them first:
|
|
.pre-commit-config.yaml
|
|
project5/.pre-commit-config.yaml
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.join("project2")), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: prek configuration file is not staged, run `git add .pre-commit-config.yaml` to stage it
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn run_with_selectors() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
|
|
context.setup_workspace(
|
|
&[
|
|
"project2",
|
|
"project3",
|
|
"nested/project4",
|
|
"project3/project5",
|
|
],
|
|
config,
|
|
)?;
|
|
context.git_add(".");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("project2/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("project2/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `nested/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/nested/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3/project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("nested/").arg("--skip").arg("project3/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("show-cwd"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `nested/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/nested/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3/project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("project2:show-cwd"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg(".:show-cwd"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("show-cwd"), @r"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: No hooks found after filtering with the given selectors
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("project2:show-cwd").arg("--skip").arg("nested:show-cwd"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `nested/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/nested/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3/project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
warning: selector `--skip=nested:show-cwd` did not match any hooks
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("non-exist"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `nested/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/nested/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3/project5`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project5
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project5/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['nested/project4/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project5/.pre-commit-config.yaml', 'project2/.pre-commit-config.yaml']
|
|
[TEMP_DIR]/
|
|
['project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
warning: selector `--skip=non-exist` did not match any hooks
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("../"), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: Invalid selector: `../`
|
|
caused by: Invalid project path: `../`
|
|
caused by: path is outside the workspace root
|
|
");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(context.work_dir().join("project2")), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn skips() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
|
|
context.setup_workspace(&["project2", "project3", "project3/project4"], config)?;
|
|
context.git_add(".");
|
|
|
|
// Test CLI skip
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("project2/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project3/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project4/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Test PREK_SKIP environment variable
|
|
cmd_snapshot!(context.filters(), context.run().env(EnvVars::PREK_SKIP, "project2/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project3/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project4/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Test SKIP environment variable
|
|
cmd_snapshot!(context.filters(), context.run().env(EnvVars::SKIP, "project2/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project3/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project4/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Test precedence: CLI --skip overrides PREK_SKIP
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("project2/").env(EnvVars::PREK_SKIP, "project3/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project3/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project4/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Test precedence: PREK_SKIP overrides SKIP
|
|
cmd_snapshot!(context.filters(), context.run().env(EnvVars::PREK_SKIP, "project2/").env(EnvVars::SKIP, "project3/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project3/project4`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3/project4
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `project3`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project3
|
|
['project4/.pre-commit-config.yaml', '.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Test multiple selectors in environment variable
|
|
cmd_snapshot!(context.filters(), context.run().env("PREK_SKIP", "project2/,project3/,non-exist-hook"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
warning: selector `PREK_SKIP=non-exist-hook` did not match any hooks
|
|
");
|
|
|
|
// Add an invalid config
|
|
context
|
|
.work_dir()
|
|
.child("project3/.pre-commit-config.yaml")
|
|
.write_str("invalid_yaml: [")?;
|
|
context.git_add(".");
|
|
|
|
// Should error out because of the invalid config
|
|
cmd_snapshot!(context.filters(), context.run(), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: Failed to parse `project3/.pre-commit-config.yaml`
|
|
caused by: did not find expected node content at line 2 column 1, while parsing a flow node
|
|
");
|
|
|
|
// Should skip the invalid config
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("project3/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['project2/.pre-commit-config.yaml', '.pre-commit-config.yaml', 'project3/project4/.pre-commit-config.yaml', 'project3/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn workspace_no_projects() {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
context.write_pre_commit_config("repos: []");
|
|
context.git_add(".");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().arg("--skip").arg("."), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: No `.pre-commit-config.yaml` found in the current directory or parent directories.
|
|
|
|
hint: If you just added one, rerun your command with the `--refresh` flag to rescan the workspace.
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn gitignore_respected() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sorted(sys.argv[1:]))'
|
|
verbose: true
|
|
"};
|
|
|
|
// Create a project structure with directories that should be ignored
|
|
context.setup_workspace(
|
|
&[
|
|
"src",
|
|
"node_modules/ignored", // Should be ignored by .gitignore
|
|
"target/ignored", // Should be ignored by .gitignore
|
|
],
|
|
config,
|
|
)?;
|
|
|
|
// Create .gitignore that ignores node_modules and target
|
|
context
|
|
.work_dir()
|
|
.child(".gitignore")
|
|
.write_str("node_modules/\ntarget/\n")?;
|
|
|
|
context.git_add(".");
|
|
|
|
// Run from the root - should not discover projects in node_modules or target
|
|
cmd_snapshot!(context.filters(), context.run(), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `src`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/src
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['.gitignore', '.pre-commit-config.yaml', 'src/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Tests that `--files` arguments references files in other projects, should be filtered out properly.
|
|
#[test]
|
|
fn reference_files_across_projects() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: echo
|
|
name: echo
|
|
language: system
|
|
entry: echo
|
|
verbose: true
|
|
"};
|
|
|
|
// Create a project structure with directories that should be ignored
|
|
context.setup_workspace(&["frontend", "backend"], config)?;
|
|
|
|
let cwd = context.work_dir();
|
|
cwd.child("backend/app.py")
|
|
.write_str("print('Hello from backend')")?;
|
|
context.git_add(".");
|
|
// Run with --files referencing a file in another project
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(cwd.child("frontend")).arg("--files").arg("../backend/app.py").arg("../backend/non-exist.py"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
echo.................................................(no files to check)Skipped
|
|
|
|
----- stderr -----
|
|
warning: This file does not exist and will be ignored: `../backend/non-exist.py`
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn submodule_discovery() -> Result<()> {
|
|
let context = TestContext::new();
|
|
let cwd = context.work_dir();
|
|
context.init_project();
|
|
|
|
let config = indoc! {r"
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-cwd
|
|
name: Show CWD
|
|
language: python
|
|
entry: python -c 'import sys, os; print(os.getcwd()); print(sys.argv[1:])'
|
|
verbose: true
|
|
"};
|
|
|
|
context.setup_workspace(&["project2"], config)?;
|
|
|
|
// Create a submodule
|
|
let submodule_path = cwd.child("submodule");
|
|
let submodule_context = TestContext::new_at(submodule_path.to_path_buf());
|
|
|
|
submodule_context.init_project();
|
|
submodule_context.configure_git_author();
|
|
submodule_context.write_pre_commit_config(config);
|
|
submodule_context.git_add(".");
|
|
submodule_context.git_commit("Initial commit");
|
|
|
|
// Add submodule to the main project
|
|
Command::new("git")
|
|
.args(["submodule", "add", "./submodule"])
|
|
.current_dir(cwd)
|
|
.assert()
|
|
.success();
|
|
context.git_add(".");
|
|
|
|
// 1. Test that workspace discovery does not recurse into git submodules
|
|
cmd_snapshot!(context.filters(), context.run().arg("--all-files"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `project2`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/project2
|
|
['.pre-commit-config.yaml']
|
|
|
|
Running hooks for `.`:
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/
|
|
['.pre-commit-config.yaml', '.gitmodules', 'project2/.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// 2. Test that current directory is in the submodule with a .pre-commit-config
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(&submodule_path).arg("--all-files"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show CWD.................................................................Passed
|
|
- hook id: show-cwd
|
|
- duration: [TIME]
|
|
|
|
[TEMP_DIR]/submodule
|
|
['.pre-commit-config.yaml']
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// 3. Test that current directory is in the submodule without .pre-commit-config
|
|
// Remove the config file in the submodule
|
|
std::fs::remove_file(submodule_path.join(".pre-commit-config.yaml"))?;
|
|
submodule_context.git_add(".");
|
|
submodule_context.git_commit("Remove config");
|
|
|
|
cmd_snapshot!(context.filters(), context.run().current_dir(&submodule_path), @r"
|
|
success: false
|
|
exit_code: 2
|
|
----- stdout -----
|
|
|
|
----- stderr -----
|
|
error: No `.pre-commit-config.yaml` found in the current directory or parent directories.
|
|
|
|
hint: If you just added one, rerun your command with the `--refresh` flag to rescan the workspace.
|
|
");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn orphan_projects() -> Result<()> {
|
|
let context = TestContext::new();
|
|
context.init_project();
|
|
|
|
// Create a hook that shows which files it processes
|
|
let config = indoc! {r#"
|
|
exclude: \.pre-commit-config\.yaml$
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-files
|
|
name: Show Files
|
|
language: python
|
|
entry: python -c 'import sys; print("Processing {} files".format(len(sys.argv[1:]))); [print(" - {}".format(f)) for f in sys.argv[1:]]'
|
|
pass_filenames: true
|
|
verbose: true
|
|
"#};
|
|
|
|
// Setup workspace with nested projects
|
|
context
|
|
.work_dir()
|
|
.child("src/backend/.pre-commit-config.yaml")
|
|
.write_str(config)?;
|
|
context
|
|
.work_dir()
|
|
.child("src/.pre-commit-config.yaml")
|
|
.write_str(config)?;
|
|
context
|
|
.work_dir()
|
|
.child(".pre-commit-config.yaml")
|
|
.write_str(config)?;
|
|
|
|
// Create test files
|
|
context
|
|
.work_dir()
|
|
.child("src/backend/test.py")
|
|
.write_str("")?;
|
|
context.work_dir().child("src/test.py").write_str("")?;
|
|
context.work_dir().child("test.py").write_str("")?;
|
|
context.git_add(".");
|
|
|
|
// Without `orphan`: files in subprojects are processed multiple times
|
|
cmd_snapshot!(context.filters(), context.run().arg("--all-files"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `src/backend`:
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 1 files
|
|
- test.py
|
|
|
|
Running hooks for `src`:
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 2 files
|
|
- test.py
|
|
- backend/test.py
|
|
|
|
Running hooks for `.`:
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 3 files
|
|
- src/test.py
|
|
- src/backend/test.py
|
|
- test.py
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// Enable `orphan`
|
|
context
|
|
.work_dir()
|
|
.child("src/backend/.pre-commit-config.yaml")
|
|
.write_str(indoc! {r#"
|
|
orphan: true
|
|
exclude: \.pre-commit-config\.yaml$
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-files
|
|
name: Show Files
|
|
language: python
|
|
entry: python -c 'import sys; print("Processing {} files".format(len(sys.argv[1:]))); [print(" - {}".format(f)) for f in sys.argv[1:]]'
|
|
pass_filenames: true
|
|
verbose: true
|
|
"#})?;
|
|
|
|
// `files` match nothing, but files are still "consumed"
|
|
context
|
|
.work_dir()
|
|
.child("src/.pre-commit-config.yaml")
|
|
.write_str(indoc! {r#"
|
|
orphan: true
|
|
files: ^$
|
|
exclude: \.pre-commit-config\.yaml$
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-files
|
|
name: Show Files
|
|
language: python
|
|
entry: python -c 'import sys; print("Processing {} files".format(len(sys.argv[1:]))); [print(" - {}".format(f)) for f in sys.argv[1:]]'
|
|
pass_filenames: true
|
|
verbose: true
|
|
"#})?;
|
|
|
|
context
|
|
.work_dir()
|
|
.child(".pre-commit-config.yaml")
|
|
.write_str(indoc! {r#"
|
|
orphan: false
|
|
exclude: \.pre-commit-config\.yaml$
|
|
repos:
|
|
- repo: local
|
|
hooks:
|
|
- id: show-files
|
|
name: Show Files
|
|
language: python
|
|
entry: python -c 'import sys; print("Processing {} files".format(len(sys.argv[1:]))); [print(" - {}".format(f)) for f in sys.argv[1:]]'
|
|
pass_filenames: true
|
|
verbose: true
|
|
"#})?;
|
|
|
|
// In orphan project, files are "consumed" and not processed again in parent projects
|
|
cmd_snapshot!(context.filters(), context.run().arg("--all-files"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Running hooks for `src/backend`:
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 1 files
|
|
- test.py
|
|
|
|
Running hooks for `src`:
|
|
Show Files...........................................(no files to check)Skipped
|
|
|
|
Running hooks for `.`:
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 1 files
|
|
- test.py
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
// If hooks in orphan projects are not selected, files should be "consumed" as well
|
|
cmd_snapshot!(context.filters(), context.run().arg("--all-files").arg("--skip").arg("src/"), @r"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Show Files...............................................................Passed
|
|
- hook id: show-files
|
|
- duration: [TIME]
|
|
|
|
Processing 1 files
|
|
- test.py
|
|
|
|
----- stderr -----
|
|
");
|
|
|
|
Ok(())
|
|
}
|