@@ -2,7 +2,9 @@ use crate::run_state::TaskRunState;
22use crate :: task_runner_error:: TaskRunnerError ;
33use miette:: IntoDiagnostic ;
44use moon_app_context:: AppContext ;
5- use moon_cache:: { Manifest , ManifestFile , ManifestSource , ManifestSymlink , StorageOptions } ;
5+ use moon_cache:: {
6+ Manifest , ManifestFile , ManifestSource , StorageOptions , grant_owner_write_access,
7+ } ;
68use moon_common:: {
79 color,
810 path:: { WorkspaceRelativePath , clean_components} ,
@@ -157,7 +159,6 @@ impl OutputHydrater<'_> {
157159 }
158160 } ) ?,
159161 output_path,
160- link,
161162 ) ?;
162163 }
163164
@@ -257,6 +258,12 @@ impl OutputHydrater<'_> {
257258 let fd = if let Some ( source) = & file. source_path {
258259 fs:: reflink_file ( source, & output_path) ?;
259260
261+ // The reflink clones the source's permissions, which may lack the
262+ // write bit (stores populated before objects were normalized may
263+ // contain read-only blobs), so restore it before opening a handle
264+ // to apply the mtime/mode below
265+ grant_owner_write_access ( & output_path) ?;
266+
260267 fs:: open_file_for_writing ( & output_path) ?
261268 }
262269 // Otherwise write the bytes from the manifest
@@ -284,14 +291,10 @@ impl OutputHydrater<'_> {
284291 Ok ( ( ) )
285292 }
286293
287- // Windows lint!
288- #[ allow( unused_variables) ]
289- fn link_output_file (
290- & self ,
291- from_path : PathBuf ,
292- to_path : PathBuf ,
293- link : & ManifestSymlink ,
294- ) -> miette:: Result < ( ) > {
294+ // The manifest's unix mode is deliberately not applied: it records the
295+ // followed target's mode (which the target's own manifest entry restores),
296+ // and a chmod through the link would modify the target, not the link
297+ fn link_output_file ( & self , from_path : PathBuf , to_path : PathBuf ) -> miette:: Result < ( ) > {
295298 if let Some ( parent) = to_path. parent ( ) {
296299 fs:: create_dir_all ( parent) ?;
297300 }
@@ -314,19 +317,9 @@ impl OutputHydrater<'_> {
314317
315318 #[ cfg( unix) ]
316319 {
317- use std:: os:: unix:: fs:: { PermissionsExt , symlink} ;
320+ use std:: os:: unix:: fs:: symlink;
318321
319322 symlink ( & from_path, & to_path) . map_err ( map_error) ?;
320-
321- if let Some ( mode) = & link. unix_mode {
322- let fd = fs:: open_file_for_writing ( & to_path) ?;
323-
324- fd. set_permissions ( std:: fs:: Permissions :: from_mode ( * mode) )
325- . map_err ( |error| FsError :: Write {
326- path : to_path. clone ( ) ,
327- error : Box :: new ( error) ,
328- } ) ?;
329- }
330323 }
331324
332325 Ok ( ( ) )
0 commit comments