@@ -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+
743754fn 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\n if [ \" $1\" = \" --version\" ]; then\n echo 'git version 2.51.0'\n exit 0\n fi\n if [ \" $1\" = \" send-email\" ] && [ \" $2\" = \" -h\" ]; then\n echo 'usage: git send-email [<options>] <file|directory>...'\n exit 129\n fi\n if [ \" $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\n fi\n exit 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