fix: Corrected a rare edge case on how tool files are generated during parallel executions

This commit is contained in:
2026-08-15 18:41:13 -06:00
parent 95a8c3df44
commit ede87df960
3 changed files with 240 additions and 80 deletions
+33 -3
View File
@@ -1,11 +1,11 @@
use crate::function::{FunctionDeclaration, JsonSchema};
use crate::function::{self, FunctionDeclaration, JsonSchema};
use anyhow::{Context, Result, bail};
use argc::{ChoiceValue, CommandValue, FlagOptionValue};
use indexmap::IndexMap;
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::{env, fs};
pub fn generate_bash_declarations(
mut tool_file: File,
@@ -24,7 +24,7 @@ pub fn generate_bash_declarations(
env::var("TERM_WIDTH").ok().and_then(|v| v.parse().ok()),
)?;
let build_script = allow_empty_required_values(&build_script);
fs::write(tools_file_path, &build_script)
function::write_file_atomic(tools_file_path, &build_script, Some(0o755))
.with_context(|| format!("Failed to write built script to '{tools_file_path:?}'"))?;
let command_value = argc::export(&build_script, file_name)
@@ -181,4 +181,34 @@ mod tests {
assert!(fixed.contains(r#"if [[ -z "${!name+x}" ]]; then"#));
assert!(!fixed.contains(r#"if [[ -z "${!name:-}" ]]; then"#));
}
#[cfg(unix)]
#[test]
fn second_build_does_not_rewrite_tool_file_test() {
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
let src = "# @describe test tool\n# @option --content! The content\nmain() { :; }\n";
let path = crate::utils::temp_file("bash-build", ".sh");
fs::write(&path, src).expect("failed to write temp script");
let declarations = generate_bash_declarations(File::open(&path).unwrap(), &path, "test")
.expect("first build failed");
assert!(!declarations.is_empty());
let first_ino = fs::metadata(&path).unwrap().ino();
let declarations = generate_bash_declarations(File::open(&path).unwrap(), &path, "test")
.expect("second build failed");
assert!(!declarations.is_empty());
let metadata = fs::metadata(&path).unwrap();
assert_eq!(
metadata.ino(),
first_ino,
"second build rewrote an already-built tool file"
);
assert_eq!(metadata.permissions().mode() & 0o777, 0o755);
fs::remove_file(&path).unwrap();
}
}