From a7d5bd32666163fc6069a74cf7ee6efca022f0a4 Mon Sep 17 00:00:00 2001 From: Alex Ley Date: Sun, 27 Oct 2024 22:26:10 +0000 Subject: [PATCH] test(apply): add `apply_to_folder_with_nested_gitignore()` test to ensure the `ignore::Walk` is correctly skipping files based on nested .gitignore files see #539 --- Cargo.lock | 1 + crates/cli_bin/Cargo.toml | 1 + .../fixtures/nested_gitignore/.gitignore | 3 + .../fixtures/nested_gitignore/docs/guide.md | 1 + .../fixtures/nested_gitignore/src/.gitignore | 2 + .../nested_gitignore/src/module1/.gitignore | 1 + .../nested_gitignore/src/module1/file1.py | 1 + .../nested_gitignore/src/module1/file2.pyi | 1 + .../nested_gitignore/src/module1/file3.py | 1 + .../nested_gitignore/src/module1/readme.rst | 0 .../nested_gitignore/src/module2/.gitignore | 2 + .../nested_gitignore/src/module2/file1.py | 1 + .../nested_gitignore/src/module2/file2.pyi | 1 + .../nested_gitignore/src/module2/file3.py | 1 + .../nested_gitignore/src/module2/readme.rst | 0 crates/cli_bin/tests/apply.rs | 77 ++++++++++++++++++- ...ply_to_folder_with_nested_gitignore-2.snap | 5 ++ ...apply_to_folder_with_nested_gitignore.snap | 5 ++ 18 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 crates/cli_bin/fixtures/nested_gitignore/.gitignore create mode 100644 crates/cli_bin/fixtures/nested_gitignore/docs/guide.md create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/.gitignore create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module1/.gitignore create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module1/file1.py create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module1/file2.pyi create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module1/file3.py create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module1/readme.rst create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module2/.gitignore create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module2/file1.py create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module2/file2.pyi create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module2/file3.py create mode 100644 crates/cli_bin/fixtures/nested_gitignore/src/module2/readme.rst create mode 100644 crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore-2.snap create mode 100644 crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore.snap diff --git a/Cargo.lock b/Cargo.lock index ae8a5b98b..bc814f15a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2159,6 +2159,7 @@ dependencies = [ "assert_cmd", "fs-err", "fs_extra", + "git2", "insta", "marzano-cli", "marzano-gritmodule", diff --git a/crates/cli_bin/Cargo.toml b/crates/cli_bin/Cargo.toml index d8fdfd225..95444ff15 100644 --- a/crates/cli_bin/Cargo.toml +++ b/crates/cli_bin/Cargo.toml @@ -37,6 +37,7 @@ tracing-subscriber = { version = "0.3", default-features = false, optional = tru serde_json = "1.0.96" tempfile = "3.1" rayon = "1.8.0" +git2 = "0.19.0" insta = { version = "1.30.0", features = ["yaml", "redactions", "filters"] } predicates = "3.0.3" fs_extra = "1.3" diff --git a/crates/cli_bin/fixtures/nested_gitignore/.gitignore b/crates/cli_bin/fixtures/nested_gitignore/.gitignore new file mode 100644 index 000000000..17f817273 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/.gitignore @@ -0,0 +1,3 @@ +*.rst +*.pyi +file3.py \ No newline at end of file diff --git a/crates/cli_bin/fixtures/nested_gitignore/docs/guide.md b/crates/cli_bin/fixtures/nested_gitignore/docs/guide.md new file mode 100644 index 000000000..b2a6218fa --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/docs/guide.md @@ -0,0 +1 @@ +### Hello World diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/.gitignore b/crates/cli_bin/fixtures/nested_gitignore/src/.gitignore new file mode 100644 index 000000000..1f548a536 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/.gitignore @@ -0,0 +1,2 @@ +!module1/*.pyi +!module2/*.rst diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module1/.gitignore b/crates/cli_bin/fixtures/nested_gitignore/src/module1/.gitignore new file mode 100644 index 000000000..670c90c51 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module1/.gitignore @@ -0,0 +1 @@ +!*.rst diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module1/file1.py b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file1.py new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file1.py @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module1/file2.pyi b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file2.pyi new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file2.pyi @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module1/file3.py b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file3.py new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module1/file3.py @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module1/readme.rst b/crates/cli_bin/fixtures/nested_gitignore/src/module1/readme.rst new file mode 100644 index 000000000..e69de29bb diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module2/.gitignore b/crates/cli_bin/fixtures/nested_gitignore/src/module2/.gitignore new file mode 100644 index 000000000..73bd510ee --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module2/.gitignore @@ -0,0 +1,2 @@ +file1.py +!file3.py diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module2/file1.py b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file1.py new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file1.py @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module2/file2.pyi b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file2.pyi new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file2.pyi @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module2/file3.py b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file3.py new file mode 100644 index 000000000..c3b2f5ec2 --- /dev/null +++ b/crates/cli_bin/fixtures/nested_gitignore/src/module2/file3.py @@ -0,0 +1 @@ +class MyClass(object): ... diff --git a/crates/cli_bin/fixtures/nested_gitignore/src/module2/readme.rst b/crates/cli_bin/fixtures/nested_gitignore/src/module2/readme.rst new file mode 100644 index 000000000..e69de29bb diff --git a/crates/cli_bin/tests/apply.rs b/crates/cli_bin/tests/apply.rs index 7fbb857e6..c492a3016 100644 --- a/crates/cli_bin/tests/apply.rs +++ b/crates/cli_bin/tests/apply.rs @@ -6,6 +6,7 @@ use anyhow::bail; use anyhow::{anyhow, Result}; use assert_cmd::Command; use common::get_test_cmd; +use git2::Repository; use insta::{assert_snapshot, assert_yaml_snapshot}; use marzano_gritmodule::config::{ CONFIG_FILE_NAMES, GRIT_GLOBAL_DIR_ENV, GRIT_MODULE_DIR, REPO_CONFIG_DIR_NAME, @@ -2913,6 +2914,80 @@ fn apply_stdin_with_invalid_lang_alias() -> Result<()> { Ok(()) } +/// test that we can apply to a folder which contains multiple nested .gitignore files +/// see https://github.com/getgrit/gritql/issues/539 +#[test] +fn apply_to_folder_with_nested_gitignore() -> Result<()> { + let (_temp_dir, fixture_dir) = get_fixture("nested_gitignore", false)?; + // make sure the .git files are in place which defines the highest level folder to be considered + Repository::init(&fixture_dir)?; + + // root .gitignore has *.rst and *.pyi and file3.py + // src .gitignore has !module1/*.pyi and !module2/*.rst + // src/module1 .gitignore has !*.rst + // src/module2 .gitignore has file1.py and !file3.py + + // in this folder we should process file1.py and file2.pyi BUT NOT file3.py + let module1 = fixture_dir.join("src/module1"); + let mut cmd = get_test_cmd()?; + cmd.arg("apply") + .arg("`object` => ``") + .arg(".") + .arg("--lang=py") + .arg("--force") + .current_dir(&module1); + + let result = cmd.output()?; + + let stderr = String::from_utf8(result.stderr)?; + println!("stderr: {:?}", stderr); + let stdout = String::from_utf8(result.stdout)?; + println!("stdout: {:?}", stdout); + + assert!(result.status.success(), "Command failed"); + // Read back the file1.pyi file to ensure it was processed + let target_file = fixture_dir.join("src/module1/file2.pyi"); + let content: String = fs_err::read_to_string(target_file)?; + assert_snapshot!(content); + + // ensure we process the correct number of files: + assert!(stdout.contains("file1.py")); + assert!(stdout.contains("file2.pyi")); + assert!(!stdout.contains("file3.py")); + assert!(stdout.contains("Processed 2 files and found 2 matches")); + + // in this folder we should ONLY process file3.py and NOT file2.pyi NOR file1.py + let module2 = fixture_dir.join("src/module2"); + let mut cmd = get_test_cmd()?; + cmd.arg("apply") + .arg("`object` => ``") + .arg(".") + .arg("--lang=py") + .arg("--force") + .current_dir(&module2); + + let result = cmd.output()?; + + let stderr = String::from_utf8(result.stderr)?; + println!("stderr: {:?}", stderr); + let stdout = String::from_utf8(result.stdout)?; + println!("stdout: {:?}", stdout); + + assert!(result.status.success(), "Command failed"); + // Read back the file1.pyi file to ensure it was NOT processed + let target_file = fixture_dir.join("src/module2/file2.pyi"); + let content: String = fs_err::read_to_string(target_file)?; + assert_snapshot!(content); + + // ensure we process the correct number of files: + assert!(!stdout.contains("file1.py")); + assert!(!stdout.contains("file2.pyi")); + assert!(stdout.contains("file3.py")); + assert!(stdout.contains("Processed 1 files and found 1 matches")); + + Ok(()) +} + /// test that we can apply to a folder which contains valid and invalid python extensions /// see https://github.com/getgrit/gritql/issues/485 #[test] @@ -2935,7 +3010,7 @@ fn apply_to_folder_with_invalid_python_extension() -> Result<()> { println!("stdout: {:?}", stdout); assert!(result.status.success(), "Command failed"); - // Read back the file3.nopy file to ensure it was processed + // Read back the file3.nopy file to ensure it was NOT processed let target_file = fixture_dir.join("some_folder/file3.nopy"); let content: String = fs_err::read_to_string(target_file)?; assert_snapshot!(content); diff --git a/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore-2.snap b/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore-2.snap new file mode 100644 index 000000000..78fb7009d --- /dev/null +++ b/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore-2.snap @@ -0,0 +1,5 @@ +--- +source: crates/cli_bin/tests/apply.rs +expression: content +--- +class MyClass(object): ... diff --git a/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore.snap b/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore.snap new file mode 100644 index 000000000..6adc19fd5 --- /dev/null +++ b/crates/cli_bin/tests/snapshots/apply__apply_to_folder_with_nested_gitignore.snap @@ -0,0 +1,5 @@ +--- +source: crates/cli_bin/tests/apply.rs +expression: content +--- +class MyClass(): ...