diff --git a/crates/cli_bin/fixtures/match_filename/.grit/patterns/rewrite_filename.md b/crates/cli_bin/fixtures/match_filename/.grit/patterns/rewrite_filename.md new file mode 100644 index 000000000..a5f7ae222 --- /dev/null +++ b/crates/cli_bin/fixtures/match_filename/.grit/patterns/rewrite_filename.md @@ -0,0 +1,11 @@ +--- +name: rewrite_filename +language: js +engine: marzano(0.1) +--- + +```grit +file($name, $body) where { + $name <: `index.js` +} +``` diff --git a/crates/cli_bin/fixtures/windows_path_match/.grit/grit.yaml b/crates/cli_bin/fixtures/windows_path_match/.grit/grit.yaml new file mode 100644 index 000000000..3a8b4b6f8 --- /dev/null +++ b/crates/cli_bin/fixtures/windows_path_match/.grit/grit.yaml @@ -0,0 +1,35 @@ +version: 0.0.1 +patterns: + - name: windows_path_match + body: | + engine marzano(0.1) + language js + + file($name, $body) where { + $name <: `src/index.js` + } + samples: + - input: | + // @filename: src/index.js + + console.log('hello from unix path'); + output: | + // @filename: src/index.js + + console.log('hello from unix path'); + - input: | + // @filename: src\index.js + + console.log('hello from windows path'); + output: | + // @filename: src\index.js + + console.log('hello from windows path'); + - input: | + // @filename: src\nested\index.js + + // This should not match + - input: | + // @filename: other/index.js + + // This should not match diff --git a/crates/cli_bin/fixtures/windows_path_match/.grit/patterns/windows_path_match.md b/crates/cli_bin/fixtures/windows_path_match/.grit/patterns/windows_path_match.md new file mode 100644 index 000000000..2639f25ab --- /dev/null +++ b/crates/cli_bin/fixtures/windows_path_match/.grit/patterns/windows_path_match.md @@ -0,0 +1,9 @@ +--- +name: windows_path_match +language: js +engine: marzano(0.1) +--- + +file($name, $body) where { + $name <: `src/index.js` +} diff --git a/crates/cli_bin/tests/patterns_test.rs b/crates/cli_bin/tests/patterns_test.rs index 3a524d253..a2eaf4a90 100644 --- a/crates/cli_bin/tests/patterns_test.rs +++ b/crates/cli_bin/tests/patterns_test.rs @@ -326,6 +326,22 @@ fn tests_match_only_with_file_name() -> Result<()> { Ok(()) } +#[test] +fn test_windows_path_match() -> Result<()> { + // Verifies the fix for GitHub Issue #639: + // Filename checks should work regardless of Windows (`\`) vs Unix (`/`) separators. + let (_temp_dir, dir) = get_fixture("windows_path_match", false)?; + + let mut test = get_test_cmd()?; + test.arg("patterns").arg("test").current_dir(dir); + + let output = test.output()?; + + assert!(output.status.success()); + + Ok(()) +} + #[test] fn tests_python_pattern_with_file_name() -> Result<()> { let (_temp_dir, dir) = get_fixture("python_filename", false)?; diff --git a/crates/core/src/api.rs b/crates/core/src/api.rs index 1558e1fa7..b8d8213a0 100644 --- a/crates/core/src/api.rs +++ b/crates/core/src/api.rs @@ -61,16 +61,20 @@ impl MatchResult { /// Make a path look the way provolone expects it to /// Removes leading "./", or the root path if it's provided -fn normalize_path_in_project<'a>(path: &'a str, root_path: Option<&'a PathBuf>) -> &'a str { - if let Some(root_path) = root_path { +fn normalize_path_in_project(path: &str, root_path: Option<&PathBuf>) -> String { + // First, trim project prefix / leading "./" + let trimmed = if let Some(root_path) = root_path { let basic = path .strip_prefix(root_path.to_string_lossy().as_ref()) .unwrap_or(path); - // Stip the leading / if it's there + // Strip the leading '/' if it's there basic.strip_prefix('/').unwrap_or(basic) } else { path.strip_prefix("./").unwrap_or(path) - } + }; + + // Finally, ensure we always use forward slashes for path separators + trimmed.replace('\\', "/") } impl MatchResult { @@ -861,4 +865,24 @@ mod tests { let path = "src/main.rs"; assert_eq!(normalize_path_in_project(path, None), "src/main.rs"); } + + #[test] + fn test_normalize_path_in_project_windows_separators() { + // Simulate a Windows-style relative path with back-slashes + let path = ".\\src\\module\\main.rs"; + assert_eq!( + normalize_path_in_project(path, None), + "src/module/main.rs" + ); + } + + #[test] + fn test_normalize_path_in_project_mixed_separators() { + // A path that has mixed separators should still normalize correctly + let path = "./src\\nested/main.rs"; + assert_eq!( + normalize_path_in_project(path, None), + "src/nested/main.rs" + ); + } }