From fec28632675c189bed688e8976b1563a53cbe72c Mon Sep 17 00:00:00 2001
From: copilot-swe-agent <198982749+copilot-swe-agent@users.noreply.github.com>
Date: Sat, 27 Dec 2025 04:10:34 +0000
Subject: [PATCH] fix(linter): respect `.gitignore` regardless of if a git repo
is initialized (#17375)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Plan: Enable oxlint to read gitignore without git repo initialization
- [x] Analyze the issue and understand the problem
- [x] Add `.require_git(false)` and `.git_ignore(true)` to WalkBuilder in walk.rs
- [x] Create a proper unit test in walk.rs that validates auto-discovery of .gitignore files
- [x] Verify test fails without the settings and passes with them
- [x] Remove old integration test that didn't properly test the fix
- [x] Run all tests to ensure no regressions
- [x] Verify the fix manually with CLI
- [x] Fix formatting issues for CI
Original prompt
> update oxlint to read from the gitignore even if the git repo has not been initialized
---
💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
---
apps/oxlint/src/walk.rs | 61 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 3 deletions(-)
diff --git a/apps/oxlint/src/walk.rs b/apps/oxlint/src/walk.rs
index 456459ec1a251..d54f9c9909bb6 100644
--- a/apps/oxlint/src/walk.rs
+++ b/apps/oxlint/src/walk.rs
@@ -97,8 +97,14 @@ impl Walk {
}
}
- let inner =
- inner.ignore(false).git_global(false).follow_links(true).hidden(false).build_parallel();
+ let inner = inner
+ .ignore(false)
+ .git_global(false)
+ .git_ignore(true)
+ .follow_links(true)
+ .hidden(false)
+ .require_git(false)
+ .build_parallel();
Self { inner, extensions: Extensions::default() }
}
@@ -135,7 +141,7 @@ impl Walk {
#[cfg(test)]
mod test {
- use std::{env, ffi::OsString, path::Path};
+ use std::{env, ffi::OsString, fs, path::Path};
use ignore::overrides::OverrideBuilder;
@@ -166,4 +172,53 @@ mod test {
assert_eq!(paths, vec!["bar.vue", "foo.js"]);
}
+
+ #[test]
+ fn test_gitignore_without_git_repo() {
+ // Validate that `.gitignore` files are respected even when no `.git` directory is present.
+
+ let temp_dir = tempfile::tempdir().unwrap();
+ let temp_path = temp_dir.path();
+
+ // Create test files
+ fs::write(temp_path.join("included.js"), "debugger;").unwrap();
+ fs::write(temp_path.join("ignored.js"), "debugger;").unwrap();
+
+ // Create .gitignore to ignore one file
+ fs::write(temp_path.join(".gitignore"), "ignored.js\n").unwrap();
+
+ // Verify no .git directory exists
+ assert!(!temp_path.join(".git").exists());
+
+ // Use empty ignore_path to rely on auto-discovery, not explicit loading
+ let ignore_options = IgnoreOptions {
+ no_ignore: false,
+ ignore_path: OsString::from(""), // Empty = rely on auto-discovery
+ ignore_pattern: vec![],
+ };
+
+ let override_builder = OverrideBuilder::new(temp_path).build().unwrap();
+
+ let mut paths =
+ Walk::new(&[temp_path.to_path_buf()], &ignore_options, Some(override_builder))
+ .with_extensions(Extensions(["js"].to_vec()))
+ .paths()
+ .into_iter()
+ .map(|path| {
+ Path::new(&path)
+ .strip_prefix(temp_path)
+ .unwrap()
+ .file_name()
+ .unwrap()
+ .to_string_lossy()
+ .to_string()
+ })
+ .collect::>();
+
+ paths.sort();
+
+ // Only included.js should be found; ignored.js should be filtered by auto-discovered .gitignore
+ // Without .git_ignore(true) and .require_git(false), both files would be found
+ assert_eq!(paths, vec!["included.js"]);
+ }
}