fix: do not take into account gitignore in developer mcp (#5688)

This commit is contained in:
Alex Hancock
2025-11-12 08:56:29 -05:00
committed by GitHub
parent 5648799482
commit 7e3ad08db9
@@ -1238,27 +1238,16 @@ impl DeveloperServer {
}
}
// Helper method to build ignore patterns from .gooseignore or .gitignore files
fn build_ignore_patterns(cwd: &PathBuf) -> Gitignore {
let mut builder = GitignoreBuilder::new(cwd);
// Check for local .gooseignore
let local_ignore_path = cwd.join(".gooseignore");
let mut has_ignore_file = false;
if local_ignore_path.is_file() {
let _ = builder.add(local_ignore_path);
has_ignore_file = true;
} else {
// Fallback to .gitignore
let gitignore_path = cwd.join(".gitignore");
if gitignore_path.is_file() {
let _ = builder.add(gitignore_path);
has_ignore_file = true;
}
}
// Add default patterns if no ignore files found
if !has_ignore_file {
let _ = builder.add_line(None, "**/.env");
let _ = builder.add_line(None, "**/.env.*");
@@ -1933,51 +1922,6 @@ mod tests {
});
}
#[tokio::test]
#[serial]
async fn test_gitignore_fallback_when_no_gooseignore() {
let temp_dir = tempfile::tempdir().unwrap();
std::env::set_current_dir(&temp_dir).unwrap();
// Create .gitignore file (no .gooseignore)
fs::write(".gitignore", "*.log").unwrap();
let server = create_test_server();
assert!(
server.is_ignored(Path::new("debug.log")),
"*.log pattern from .gitignore should match debug.log"
);
assert!(
!server.is_ignored(Path::new("debug.txt")),
"*.log pattern should not match debug.txt"
);
}
#[tokio::test]
#[serial]
async fn test_gooseignore_takes_precedence_over_gitignore() {
let temp_dir = tempfile::tempdir().unwrap();
std::env::set_current_dir(&temp_dir).unwrap();
// Create both files
fs::write(".gitignore", "*.log").unwrap();
fs::write(".gooseignore", "*.env").unwrap();
let server = create_test_server();
// Should respect .gooseignore patterns
assert!(
server.is_ignored(Path::new("test.env")),
".gooseignore pattern should work"
);
// Should NOT respect .gitignore patterns when .gooseignore exists
assert!(
!server.is_ignored(Path::new("test.log")),
".gitignore patterns should be ignored when .gooseignore exists"
);
}
#[tokio::test]
#[serial]
async fn test_text_editor_descriptions() {
@@ -2001,136 +1945,6 @@ mod tests {
assert!(!instructions.contains("work out how to place old_str with it intelligently"));
}
#[tokio::test]
#[serial]
async fn test_text_editor_respects_gitignore_fallback() {
let temp_dir = tempfile::tempdir().unwrap();
std::env::set_current_dir(&temp_dir).unwrap();
// Create a .gitignore file but no .gooseignore
fs::write(temp_dir.path().join(".gitignore"), "*.log").unwrap();
let server = create_test_server();
// Try to write to a file ignored by .gitignore
let result = server
.text_editor(Parameters(TextEditorParams {
command: "write".to_string(),
path: temp_dir
.path()
.join("test.log")
.to_str()
.unwrap()
.to_string(),
file_text: Some("test content".parse().unwrap()),
old_str: None,
new_str: None,
view_range: None,
insert_line: None,
diff: None,
}))
.await;
assert!(
result.is_err(),
"Should not be able to write to file ignored by .gitignore fallback"
);
assert_eq!(result.unwrap_err().code, ErrorCode::INTERNAL_ERROR);
let result = server
.text_editor(Parameters(TextEditorParams {
command: "write".to_string(),
path: temp_dir
.path()
.join("allowed.txt")
.to_str()
.unwrap()
.to_string(),
file_text: Some("test content".to_string()),
old_str: None,
new_str: None,
view_range: None,
insert_line: None,
diff: None,
}))
.await;
assert!(
result.is_ok(),
"Should be able to write to non-ignored file"
);
temp_dir.close().unwrap();
}
#[test]
#[serial]
fn test_shell_respects_gitignore_fallback() {
run_shell_test(|| async {
let temp_dir = tempfile::tempdir().unwrap();
std::env::set_current_dir(&temp_dir).unwrap();
// Create a .gitignore file but no .gooseignore
std::fs::write(temp_dir.path().join(".gitignore"), "*.log").unwrap();
let server = create_test_server();
let running_service = serve_directly(server.clone(), create_test_transport(), None);
let peer = running_service.peer().clone();
// Create a file that would be ignored by .gitignore
let log_file_path = temp_dir.path().join("test.log");
std::fs::write(&log_file_path, "log content").unwrap();
// Try to cat the ignored file
let result = server
.shell(
Parameters(ShellParams {
command: format!("cat {}", log_file_path.to_str().unwrap()),
}),
RequestContext {
ct: Default::default(),
id: NumberOrString::Number(1),
meta: Default::default(),
extensions: Default::default(),
peer: peer.clone(),
},
)
.await;
assert!(
result.is_err(),
"Should not be able to cat file ignored by .gitignore fallback"
);
assert_eq!(result.unwrap_err().code, ErrorCode::INTERNAL_ERROR);
// Try to cat a non-ignored file
let allowed_file_path = temp_dir.path().join("allowed.txt");
fs::write(&allowed_file_path, "allowed content").unwrap();
let result = server
.shell(
Parameters(ShellParams {
command: format!("cat {}", allowed_file_path.to_str().unwrap()),
}),
RequestContext {
ct: Default::default(),
id: NumberOrString::Number(1),
meta: Default::default(),
extensions: Default::default(),
peer: peer.clone(),
},
)
.await;
assert!(result.is_ok(), "Should be able to cat non-ignored file");
// Force cleanup before runtime shutdown
cleanup_test_service(running_service, peer);
temp_dir.close().unwrap();
});
}
#[tokio::test]
#[serial]
async fn test_text_editor_view_range() {