Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 0 additions & 186 deletions crates/goose-mcp/src/developer/rmcp_developer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.*");
Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -4954,4 +4954,4 @@
}
}
}
}
}