Skip to content

Commit 9c40ac3

Browse files
committed
fix(reply): stabilize draft path for send-email
Signed-off-by: Chen Miao <chenmiao.ku@gmail.com>
1 parent bd9cbad commit 9c40ac3

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

src/infra/sendmail.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ fn send_with_options(
245245
);
246246
}
247247

248+
let draft_path = stabilize_child_path(&draft_path);
248249
let command_line = render_command_line(
249250
&resolved.display_name,
250251
&build_send_email_args(request, &draft_path),
@@ -740,6 +741,16 @@ fn build_send_email_args(request: &SendRequest, draft_path: &Path) -> Vec<String
740741
args
741742
}
742743

744+
fn stabilize_child_path(path: &Path) -> PathBuf {
745+
if path.is_absolute() {
746+
return path.to_path_buf();
747+
}
748+
749+
std::env::current_dir()
750+
.map(|current_dir| current_dir.join(path))
751+
.unwrap_or_else(|_| path.to_path_buf())
752+
}
753+
743754
fn generate_message_id(from: &str) -> String {
744755
// Reuse the sender domain when possible so generated ids look like normal
745756
// outbound mail and are easier to correlate in archives and mail clients.
@@ -844,7 +855,8 @@ mod tests {
844855
GitSendEmailStatus, ReplyIdentitySource, SendRequest, SendStatus, check_with_command_path,
845856
extract_email_address, generate_message_id, normalize_message_id, normalize_output,
846857
render_command_line, render_message_file, resolve_reply_identity_with_command_path,
847-
resolve_working_dir, send_with_command_path, send_with_options, summarize_failure,
858+
resolve_working_dir, send_with_command_path, send_with_options, stabilize_child_path,
859+
summarize_failure,
848860
};
849861

850862
fn temp_dir(label: &str) -> PathBuf {
@@ -1228,6 +1240,45 @@ mod tests {
12281240
let _ = fs::remove_dir_all(root);
12291241
}
12301242

1243+
#[test]
1244+
fn send_passes_absolute_draft_path_when_runtime_data_dir_is_relative() {
1245+
let root = temp_dir("send-relative-data-dir");
1246+
let kernel_tree = root.join("linux");
1247+
fs::create_dir_all(&kernel_tree).expect("create kernel tree");
1248+
let capture_arg = root.join("captured-draft-arg.txt");
1249+
let fake_git = write_fake_git(
1250+
&root,
1251+
&format!(
1252+
"#!/bin/sh\nif [ \"$1\" = \"--version\" ]; then\n echo 'git version 2.51.0'\n exit 0\nfi\nif [ \"$1\" = \"send-email\" ] && [ \"$2\" = \"-h\" ]; then\n echo 'usage: git send-email [<options>] <file|directory>...'\n exit 129\nfi\nif [ \"$1\" = \"send-email\" ]; then\n last=''\n for arg in \"$@\"; do\n last=\"$arg\"\n done\n printf '%s' \"$last\" > '{}'\n if [ -f \"$last\" ]; then\n echo 'sent'\n exit 0\n fi\n echo \"missing draft: $last\" >&2\n exit 1\nfi\nexit 1\n",
1253+
capture_arg.display()
1254+
),
1255+
);
1256+
let nonce = SystemTime::now()
1257+
.duration_since(UNIX_EPOCH)
1258+
.expect("system time")
1259+
.as_nanos();
1260+
let relative_data_dir = PathBuf::from(format!(
1261+
"target/test-relative-reply-outbox-{}-{nonce}",
1262+
std::process::id()
1263+
));
1264+
let relative_data_dir_absolute = std::env::current_dir()
1265+
.expect("current dir")
1266+
.join(&relative_data_dir);
1267+
let mut runtime = test_runtime_in(&root);
1268+
runtime.data_dir = relative_data_dir;
1269+
runtime.kernel_trees = vec![kernel_tree];
1270+
1271+
let outcome = send_with_command_path(&runtime, &sample_request(), Some(&fake_git));
1272+
1273+
assert_eq!(outcome.status, SendStatus::Sent);
1274+
let captured_arg = fs::read_to_string(&capture_arg).expect("read captured draft arg");
1275+
assert!(Path::new(&captured_arg).is_absolute());
1276+
assert!(captured_arg.starts_with(relative_data_dir_absolute.to_string_lossy().as_ref()));
1277+
1278+
let _ = fs::remove_dir_all(relative_data_dir_absolute);
1279+
let _ = fs::remove_dir_all(root);
1280+
}
1281+
12311282
#[test]
12321283
fn message_rendering_and_helper_outputs_follow_reply_contract() {
12331284
let mut request = sample_request();
@@ -1275,6 +1326,7 @@ mod tests {
12751326
);
12761327
assert_eq!(extract_email_address("invalid identity"), None);
12771328
assert!(generate_message_id("No Email").ends_with("@localhost"));
1329+
assert!(stabilize_child_path(Path::new("relative/file.eml")).is_absolute());
12781330
}
12791331

12801332
#[test]

0 commit comments

Comments
 (0)