@@ -12,6 +12,7 @@ use deno_core::error::AnyError;
12
12
use deno_core:: resolve_url_or_path;
13
13
use deno_graph:: GraphKind ;
14
14
use deno_terminal:: colors;
15
+ use rand:: Rng ;
15
16
use std:: path:: Path ;
16
17
use std:: path:: PathBuf ;
17
18
use std:: sync:: Arc ;
@@ -97,8 +98,20 @@ pub async fn compile(
97
98
) ;
98
99
validate_output_path ( & output_path) ?;
99
100
100
- let mut file = std:: fs:: File :: create ( & output_path)
101
- . with_context ( || format ! ( "Opening file '{}'" , output_path. display( ) ) ) ?;
101
+ let mut temp_filename = output_path. file_name ( ) . unwrap ( ) . to_owned ( ) ;
102
+ temp_filename. push ( format ! (
103
+ ".tmp-{}" ,
104
+ faster_hex:: hex_encode(
105
+ & rand:: thread_rng( ) . gen :: <[ u8 ; 8 ] >( ) ,
106
+ & mut [ 0u8 ; 16 ]
107
+ )
108
+ . unwrap( )
109
+ ) ) ;
110
+ let temp_path = output_path. with_file_name ( temp_filename) ;
111
+
112
+ let mut file = std:: fs:: File :: create ( & temp_path) . with_context ( || {
113
+ format ! ( "Opening temporary file '{}'" , temp_path. display( ) )
114
+ } ) ?;
102
115
let write_result = binary_writer
103
116
. write_bin (
104
117
& mut file,
@@ -108,20 +121,38 @@ pub async fn compile(
108
121
cli_options,
109
122
)
110
123
. await
111
- . with_context ( || format ! ( "Writing {}" , output_path. display( ) ) ) ;
124
+ . with_context ( || {
125
+ format ! ( "Writing temporary file '{}'" , temp_path. display( ) )
126
+ } ) ;
112
127
drop ( file) ;
113
- if let Err ( err) = write_result {
114
- // errored, so attempt to remove the output path
115
- let _ = std:: fs:: remove_file ( output_path) ;
116
- return Err ( err) ;
117
- }
118
128
119
129
// set it as executable
120
130
#[ cfg( unix) ]
121
- {
131
+ let write_result = write_result . and_then ( |_| {
122
132
use std:: os:: unix:: fs:: PermissionsExt ;
123
- let perms = std:: fs:: Permissions :: from_mode ( 0o777 ) ;
124
- std:: fs:: set_permissions ( output_path, perms) ?;
133
+ let perms = std:: fs:: Permissions :: from_mode ( 0o755 ) ;
134
+ std:: fs:: set_permissions ( & temp_path, perms) . with_context ( || {
135
+ format ! (
136
+ "Setting permissions on temporary file '{}'" ,
137
+ temp_path. display( )
138
+ )
139
+ } )
140
+ } ) ;
141
+
142
+ let write_result = write_result. and_then ( |_| {
143
+ std:: fs:: rename ( & temp_path, & output_path) . with_context ( || {
144
+ format ! (
145
+ "Renaming temporary file '{}' to '{}'" ,
146
+ temp_path. display( ) ,
147
+ output_path. display( )
148
+ )
149
+ } )
150
+ } ) ;
151
+
152
+ if let Err ( err) = write_result {
153
+ // errored, so attempt to remove the temporary file
154
+ let _ = std:: fs:: remove_file ( temp_path) ;
155
+ return Err ( err) ;
125
156
}
126
157
127
158
Ok ( ( ) )
0 commit comments