@@ -9,7 +9,7 @@ use std::{
99 collections:: BTreeMap ,
1010 error:: Error ,
1111 ffi:: OsString ,
12- fs:: { self , Permissions } ,
12+ fs:: { self , File , Permissions } ,
1313 io:: { self , Write } ,
1414 os:: unix:: {
1515 ffi:: OsStrExt ,
@@ -192,13 +192,13 @@ fn create(line: &Line) -> eyre::Result<()> {
192192 create_parents ( file, line_type. force ) ?;
193193 let mut fp = fs:: File :: create ( file) . wrap_err ( "Creating file" ) ?;
194194 fp. write ( contents) . wrap_err ( "Writing contents" ) ?;
195- if let Some ( specmode ) = line . mode . data . as_ref ( ) {
196- fp . set_permissions ( Permissions :: from_mode ( specmode . value ) )
197- . wrap_err ( "Setting permissions of new file" ) ? ;
198- }
199- let uid = line. owner . data . as_ref ( ) . map ( |o| o . as_uid ( ) ) . transpose ( ) ? ;
200- let gid = line . owner . data . as_ref ( ) . map ( |o| o . as_gid ( ) ) . transpose ( ) ? ;
201- std :: os :: unix :: fs :: fchown ( & fp , uid , gid ) . wrap_err ( "Setting ownership of new file" ) ?;
195+ set_attrs (
196+ & fp ,
197+ line . mode . data . as_ref ( ) ,
198+ line . owner . data . as_ref ( ) ,
199+ line. group . data . as_ref ( ) ,
200+ "new file" ,
201+ ) ?;
202202 }
203203 config_file:: LineAction :: WriteFile => todo ! ( ) ,
204204 config_file:: LineAction :: CreateAndCleanUpDirectory => {
@@ -240,12 +240,11 @@ fn create(line: &Line) -> eyre::Result<()> {
240240 }
241241 create_parents ( dir, line_type. force ) ?;
242242 fs:: DirBuilder :: new ( ) . create ( dir) ?;
243- fixup_attrs (
243+ set_attrs (
244244 dir,
245- & fs:: symlink_metadata ( dir) ?,
246- & line. mode ,
247- & line. owner ,
248- & line. group ,
245+ line. mode . data . as_ref ( ) ,
246+ line. owner . data . as_ref ( ) ,
247+ line. group . data . as_ref ( ) ,
249248 "Setting mode of new directory" ,
250249 ) ?;
251250 }
@@ -311,32 +310,73 @@ fn create(line: &Line) -> eyre::Result<()> {
311310 Ok ( ( ) )
312311}
313312
313+ // Abstraction over `File` and `Path` to use handle both in shared code
314+ trait FileRef {
315+ fn set_permissions ( & self , permissions : Permissions ) -> io:: Result < ( ) > ;
316+ fn set_ownership ( & self , uid : Option < u32 > , gid : Option < u32 > ) -> io:: Result < ( ) > ;
317+ }
318+
319+ impl FileRef for Path {
320+ fn set_permissions ( & self , permissions : Permissions ) -> io:: Result < ( ) > {
321+ fs:: set_permissions ( self , permissions)
322+ }
323+
324+ fn set_ownership ( & self , uid : Option < u32 > , gid : Option < u32 > ) -> io:: Result < ( ) > {
325+ std:: os:: unix:: fs:: chown ( self , uid, gid)
326+ }
327+ }
328+
329+ impl FileRef for File {
330+ fn set_permissions ( & self , permissions : Permissions ) -> io:: Result < ( ) > {
331+ self . set_permissions ( permissions)
332+ }
333+
334+ fn set_ownership ( & self , uid : Option < u32 > , gid : Option < u32 > ) -> io:: Result < ( ) > {
335+ std:: os:: unix:: fs:: fchown ( self , uid, gid)
336+ }
337+ }
338+
314339fn fixup_attrs (
315- path : & Path ,
340+ path : & ( impl FileRef + ? Sized ) ,
316341 meta : & fs:: Metadata ,
317342 mode : & Option < Mode > ,
318343 owner : & Option < FileOwner > ,
319344 group : & Option < FileOwner > ,
320345 name_in_error : & str ,
321346) -> Result < ( ) , eyre:: Error > {
322- if let Some ( specmode) = mode {
323- if specmode. value != meta. mode ( ) {
324- fs:: set_permissions ( path, Permissions :: from_mode ( specmode. value ) )
325- . wrap_err_with ( || format ! ( "Setting mode of {name_in_error}" ) ) ?;
326- }
327- }
328- let uid = owner
347+ let mode = mode
348+ . as_ref ( )
349+ . filter ( |specmode| specmode. value != meta. mode ( ) ) ;
350+ let owner = owner
329351 . as_ref ( )
330352 . map ( FileOwner :: as_uid)
331353 . transpose ( ) ?
332- . filter ( |& uid| uid != meta. uid ( ) ) ;
333- let gid = group
354+ . filter ( |& o| o != meta. uid ( ) )
355+ . map ( FileOwner :: Id ) ;
356+ let group = group
334357 . as_ref ( )
335358 . map ( FileOwner :: as_gid)
336359 . transpose ( ) ?
337- . filter ( |& gid| gid != meta. gid ( ) ) ;
360+ . filter ( |& g| g != meta. gid ( ) )
361+ . map ( FileOwner :: Id ) ;
362+ set_attrs ( path, mode, owner. as_ref ( ) , group. as_ref ( ) , name_in_error)
363+ }
364+
365+ fn set_attrs (
366+ path : & ( impl FileRef + ?Sized ) ,
367+ mode : Option < & Mode > ,
368+ owner : Option < & FileOwner > ,
369+ group : Option < & FileOwner > ,
370+ name_in_error : & str ,
371+ ) -> Result < ( ) , eyre:: Error > {
372+ if let Some ( specmode) = mode {
373+ path. set_permissions ( Permissions :: from_mode ( specmode. value ) )
374+ . wrap_err_with ( || format ! ( "Setting mode of {name_in_error}" ) ) ?;
375+ }
376+ let uid = owner. map ( FileOwner :: as_uid) . transpose ( ) ?;
377+ let gid = group. map ( FileOwner :: as_gid) . transpose ( ) ?;
338378 if uid. is_some ( ) || gid. is_some ( ) {
339- std :: os :: unix :: fs :: chown ( path, uid, gid)
379+ path. set_ownership ( uid, gid)
340380 . wrap_err_with ( || format ! ( "Setting ownership of {name_in_error}" ) ) ?;
341381 }
342382 Ok ( ( ) )
0 commit comments