Skip to content

Commit

Permalink
Properly supporte nested globs when there are conflicts (#310)
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Dec 3, 2022
1 parent 028823b commit 72ba9a8
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 2 deletions.
43 changes: 41 additions & 2 deletions src/glob.rs
@@ -1,5 +1,5 @@
use std::env;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::Mutex;

use globset::{GlobBuilder, GlobMatcher};
Expand Down Expand Up @@ -55,6 +55,8 @@ pub fn glob_exec<F: FnMut(&Path)>(base: &Path, pattern: &str, mut f: F) {
fail_fast: std::env::var("INSTA_GLOB_FAIL_FAST").as_deref() == Ok("1"),
});

// step 1: collect all matching files
let mut matching_files = vec![];
for file in walker {
let file = file.unwrap();
let path = file.path();
Expand All @@ -71,9 +73,26 @@ pub fn glob_exec<F: FnMut(&Path)>(base: &Path, pattern: &str, mut f: F) {
continue;
}

matching_files.push(path.to_path_buf());
}

// step 2: sort, determine common prefix and run assertions
matching_files.sort();
let common_prefix = find_common_prefix(&matching_files);
for path in &matching_files {
settings.set_input_file(path);
settings.set_snapshot_suffix(path.file_name().unwrap().to_str().unwrap());

// if there is a common prefix, use that stirp down the input file. That way we
// can ensure that a glob like inputs/*/*.txt with a/file.txt and b/file.txt
// does not create two identical snapshot suffixes. Instead of file.txt for both
// it would end up as a/file.txt and b/file.txt.
let snapshot_suffix = if let Some(prefix) = common_prefix {
path.strip_prefix(prefix).unwrap().as_os_str()
} else {
path.file_name().unwrap()
};

settings.set_snapshot_suffix(snapshot_suffix.to_str().unwrap());
settings.bind(|| {
f(path);
});
Expand Down Expand Up @@ -104,3 +123,23 @@ pub fn glob_exec<F: FnMut(&Path)>(base: &Path, pattern: &str, mut f: F) {
);
}
}

fn find_common_prefix(sorted_paths: &[PathBuf]) -> Option<&Path> {
let first = sorted_paths.first()?;
let last = sorted_paths.last()?;
let prefix_len = first
.components()
.zip(last.components())
.take_while(|(a, b)| a == b)
.count();

if prefix_len == 0 {
None
} else {
let mut prefix = first.components();
for _ in 0..first.components().count() - prefix_len {
prefix.next_back();
}
Some(prefix.as_path())
}
}
1 change: 1 addition & 0 deletions tests/inputs-nested/a/file.txt
@@ -0,0 +1 @@
Hello A
1 change: 1 addition & 0 deletions tests/inputs-nested/b/file.txt
@@ -0,0 +1 @@
Hello B
@@ -0,0 +1,7 @@
---
source: tests/test_glob.rs
expression: "&contents"
input_file: tests/inputs-nested/a/file.txt
---
Hello A

@@ -0,0 +1,7 @@
---
source: tests/test_glob.rs
expression: "&contents"
input_file: tests/inputs-nested/b/file.txt
---
Hello B

8 changes: 8 additions & 0 deletions tests/test_glob.rs
Expand Up @@ -8,6 +8,14 @@ fn test_basic_globbing() {
});
}

#[test]
fn test_basic_globbing_nested() {
insta::glob!("inputs-nested/*/*.txt", |path| {
let contents = std::fs::read_to_string(path).unwrap();
insta::assert_snapshot!(&contents);
});
}

#[test]
fn test_globs_follow_links() {
insta::glob!("link-to-inputs/*.txt", |path| {
Expand Down

0 comments on commit 72ba9a8

Please sign in to comment.