Create default gooseignore file when missing (#6498)

Signed-off-by: matt joyce <matt.joyce@gmail.com>
This commit is contained in:
Matt Joyce
2026-01-28 04:36:11 +11:00
committed by GitHub
parent 7bbeb362c9
commit a4959fe13b
@@ -121,6 +121,27 @@ pub struct PromptArgumentTemplate {
// Embeds the prompts directory to the build
static PROMPTS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/src/developer/prompts");
const DEFAULT_GOOSEIGNORE_CONTENT: &str = concat!(
"# This file is created automatically if no .gooseignore exists.\n",
"# Customize or uncomment the patterns below instead of deleting the file.\n",
"# Removing it will simply cause goose to recreate it on the next start.\n",
"#\n",
"# Suggested patterns you can uncomment if desired:\n",
"# **/.ssh/** # block SSH keys and configs\n",
"# **/*.key # block loose private keys\n",
"# **/*.pem # block certificates/private keys\n",
"# **/.git/** # block git metadata entirely\n",
"# **/target/** # block Rust build artifacts\n",
"# **/node_modules/** # block JS/TS dependencies\n",
"# **/*.db # block local database files\n",
"# **/*.sqlite # block SQLite databases\n",
"#\n",
"\n",
"**/.env\n",
"**/.env.*\n",
"**/secrets.*\n",
);
/// Loads prompt files from the embedded PROMPTS_DIR and returns a HashMap of prompts.
/// Ensures that each prompt name is unique.
fn load_prompt_files() -> HashMap<String, Prompt> {
@@ -1295,12 +1316,35 @@ impl DeveloperServer {
.map(|strategy| strategy.config_dir().join(".gooseignore"))
.ok();
let has_local_ignore = local_ignore_path.is_file();
let mut has_local_ignore = local_ignore_path.is_file();
let has_global_ignore = global_ignore_path
.as_ref()
.map(|p| p.is_file())
.unwrap_or(false);
if !has_local_ignore && !has_global_ignore {
match std::fs::write(&local_ignore_path, DEFAULT_GOOSEIGNORE_CONTENT) {
Ok(_) => {
has_local_ignore = true;
}
Err(err) => {
tracing::warn!(
"Failed to create default .gooseignore at {}: {}",
local_ignore_path.display(),
err
);
for pattern in DEFAULT_GOOSEIGNORE_CONTENT.lines() {
let trimmed = pattern.trim();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
let _ = builder.add_line(None, trimmed);
}
}
}
}
if has_global_ignore {
let _ = builder.add(global_ignore_path.as_ref().unwrap());
}
@@ -1309,12 +1353,6 @@ impl DeveloperServer {
let _ = builder.add(&local_ignore_path);
}
if !has_local_ignore && !has_global_ignore {
let _ = builder.add_line(None, "**/.env");
let _ = builder.add_line(None, "**/.env.*");
let _ = builder.add_line(None, "**/secrets.*");
}
builder.build().expect("Failed to build ignore patterns")
}
@@ -2959,6 +2997,11 @@ mod tests {
let server = create_test_server();
let gooseignore_path = temp_path.join(".gooseignore");
if gooseignore_path.exists() {
fs::remove_file(&gooseignore_path).unwrap();
}
let result = server
.text_editor(Parameters(TextEditorParams {
command: "view".to_string(),
@@ -3236,6 +3279,14 @@ mod tests {
// Don't create any ignore files
let server = create_test_server();
let gooseignore_path = temp_dir.path().join(".gooseignore");
assert!(
gooseignore_path.exists(),
".gooseignore should be created by default"
);
let default_contents = fs::read_to_string(gooseignore_path).unwrap();
assert_eq!(default_contents, DEFAULT_GOOSEIGNORE_CONTENT);
// Default patterns should be used
assert!(
server.is_ignored(Path::new(".env")),