@@ -6,11 +6,13 @@ use blake3::Hash;
66use color_eyre:: {
77 Result ,
88 eyre:: {
9+ Context ,
910 OptionExt ,
1011 eyre,
1112 } ,
1213} ;
1314use log:: {
15+ debug,
1416 info,
1517 warn,
1618} ;
@@ -68,15 +70,15 @@ impl From<&File> for FileWithMetadata {
6870}
6971impl FileWithMetadata {
7072 pub fn activate ( & mut self , clobber_by_default : bool , prefix : & str ) -> Result < ( ) > {
71- if self . missing_source ( ) {
73+ if self . check_source ( ) {
7274 return Ok ( ( ) ) ;
7375 }
7476
7577 self . set_metadata ( ) ?;
7678
7779 let clobber = self . clobber . unwrap_or ( clobber_by_default) ;
7880
79- if clobber && self . metadata . is_some ( ) && self . atomic_activate ( ) ? {
81+ if clobber && self . metadata . is_some ( ) && self . atomic_activate ( ) . wrap_err ( "(atomic)" ) ? {
8082 return Ok ( ( ) ) ;
8183 } ;
8284
@@ -110,7 +112,7 @@ impl FileWithMetadata {
110112
111113 match self . kind {
112114 FileKind :: Directory => self . directory ( ) ,
113- FileKind :: File => self . copy ( ) ,
115+ FileKind :: Copy => self . copy ( ) ,
114116 FileKind :: Symlink => self . symlink ( ) ,
115117 FileKind :: Modify => self . chmod_chown ( ) ,
116118 FileKind :: Delete => delete ( & self . target , self . metadata . as_ref ( ) . unwrap ( ) ) ,
@@ -119,14 +121,14 @@ impl FileWithMetadata {
119121
120122 pub fn atomic_activate ( & mut self ) -> Result < bool > {
121123 match self . kind {
122- FileKind :: Symlink | FileKind :: File => {
124+ FileKind :: Symlink | FileKind :: Copy => {
123125 let target_is_dir = self . metadata . as_ref ( ) . unwrap ( ) . is_dir ( ) ;
124- let target_is_empty = self . source . as_ref ( ) . unwrap ( ) . read_dir ( ) ?. next ( ) . is_none ( ) ;
125-
126126 let source_is_dir = fs:: symlink_metadata ( self . source . as_ref ( ) . unwrap ( ) ) ?. is_dir ( ) ;
127127
128128 if target_is_dir != source_is_dir
129- || target_is_dir && source_is_dir && !target_is_empty
129+ || target_is_dir
130+ && source_is_dir
131+ && self . source . as_ref ( ) . unwrap ( ) . read_dir ( ) ?. next ( ) . is_some ( )
130132 {
131133 return Ok ( false ) ;
132134 } ;
@@ -136,7 +138,7 @@ impl FileWithMetadata {
136138 self . target . set_extension ( "smfh-temp" ) ;
137139 match self . kind {
138140 FileKind :: Symlink => self . symlink ( ) ,
139- FileKind :: File => self . copy ( ) ,
141+ FileKind :: Copy => self . copy ( ) ,
140142 _ => panic ! ( "This should never happen" ) ,
141143 } ?;
142144 info ! (
@@ -172,9 +174,17 @@ impl FileWithMetadata {
172174 // no-op on deactivation
173175 FileKind :: Delete | FileKind :: Modify => Ok ( ( ) ) ,
174176 // delete only if directory is empty
175- FileKind :: Directory => rmdir ( & self . target ) ,
177+ FileKind :: Directory => match self . metadata . as_ref ( ) {
178+ Some ( x) if x. is_dir ( ) => {
179+ fs:: remove_dir ( & self . target ) ?;
180+ info ! ( "Deleting directory '{}'" , self . target. display( ) ) ;
181+ Ok ( ( ) )
182+ }
183+ Some ( _) => Err ( eyre ! ( "File is not directory" ) ) ,
184+ None => Err ( eyre ! ( "Cannot access file" ) ) ,
185+ } ,
176186 // delete only if types match
177- FileKind :: Symlink | FileKind :: File => {
187+ FileKind :: Symlink | FileKind :: Copy => {
178188 delete ( & self . target , self . metadata . as_ref ( ) . unwrap ( ) )
179189 }
180190 }
@@ -197,12 +207,12 @@ impl FileWithMetadata {
197207 // function is ever called
198208 FileWithMetadata {
199209 source : None ,
200- kind : FileKind :: Symlink | FileKind :: File ,
210+ kind : FileKind :: Symlink | FileKind :: Copy ,
201211 ref target,
202212 ..
203213 } => Err ( eyre ! ( "File '{}' missing_source" , target. display( ) ) ) ,
204214 FileWithMetadata {
205- kind : FileKind :: File | FileKind :: Directory | FileKind :: Modify ,
215+ kind : FileKind :: Copy | FileKind :: Directory | FileKind :: Modify ,
206216 permissions : Some ( perms) ,
207217 metadata : Some ( ref metadata) ,
208218 ..
@@ -237,12 +247,12 @@ impl FileWithMetadata {
237247 ..
238248 } => Ok ( metadata. is_dir ( ) ) ,
239249 FileWithMetadata {
240- kind : FileKind :: File ,
241- metadata : Some ( ref metadata) ,
250+ kind : FileKind :: Copy ,
251+ metadata : Some ( ref metadata) ,
242252 ..
243253 } if !metadata. is_file ( ) => Ok ( false ) ,
244254 FileWithMetadata {
245- kind : FileKind :: File ,
255+ kind : FileKind :: Copy ,
246256 ref target,
247257 source : Some ( ref source) ,
248258 ..
@@ -264,29 +274,61 @@ impl FileWithMetadata {
264274 }
265275
266276 pub fn set_metadata ( & mut self ) -> Result < ( ) > {
267- let metadata = fs:: symlink_metadata ( & self . target ) ;
268- if let Err ( ref e) = metadata {
269- if e. kind ( ) == std:: io:: ErrorKind :: NotFound {
277+ match fs:: symlink_metadata ( & self . target ) {
278+ Ok ( x) => {
279+ self . metadata = Some ( x) ;
280+ Ok ( ( ) )
281+ }
282+ Err ( e) if e. kind ( ) == std:: io:: ErrorKind :: NotFound => {
270283 self . metadata = None ;
271- return Ok ( ( ) ) ;
272- } ;
284+ Ok ( ( ) )
285+ }
286+ Err ( e) => Err ( e) . wrap_err ( "while setting metadata" ) ,
273287 }
274- self . metadata = Some ( metadata?) ;
275- Ok ( ( ) )
276288 }
277- pub fn missing_source ( & self ) -> bool {
289+ pub fn check_source ( & self ) -> bool {
278290 match * self {
291+ FileWithMetadata {
292+ source : Some ( ref s) ,
293+ kind : FileKind :: Copy | FileKind :: Symlink ,
294+ ..
295+ } if fs:: symlink_metadata ( s)
296+ . is_err_and ( |e| e. kind ( ) == std:: io:: ErrorKind :: NotFound ) =>
297+ {
298+ warn ! (
299+ "{} with target '{}' source '{}' does not exist" ,
300+ self . kind,
301+ self . target. display( ) ,
302+ s. display( )
303+ ) ;
304+ true
305+ }
279306 FileWithMetadata {
280307 source : None ,
281- kind : FileKind :: File | FileKind :: Symlink ,
308+ kind : FileKind :: Copy | FileKind :: Symlink ,
282309 ..
283310 } => {
284311 warn ! (
285- "File '{}' missing source, skipping..." ,
312+ "{} with target '{}' missing source, skipping..." ,
313+ self . kind,
286314 self . target. display( )
287315 ) ;
288316 true
289317 }
318+ FileWithMetadata {
319+ source : Some ( ref s) ,
320+ kind : FileKind :: Copy ,
321+ ..
322+ } if fs:: symlink_metadata ( s) . is_ok_and ( |x| !x. is_file ( ) ) => {
323+ warn ! (
324+ "{} with target '{}' source '{}' is a directory, only files are permitted. Skipping..." ,
325+ self . kind,
326+ self . target. display( ) ,
327+ s. display( )
328+ ) ;
329+ true
330+ }
331+
290332 _ => false ,
291333 }
292334 }
@@ -397,7 +439,7 @@ pub fn mkdir(path: &Path) -> Result<()> {
397439 if !x. is_dir ( ) {
398440 return Err ( eyre ! ( "File in way of '{}'" , path. display( ) ) ) ;
399441 } ;
400- info ! ( "Directory '{}' already exists" , path. display( ) ) ;
442+ debug ! ( "Directory '{}' already exists" , path. display( ) ) ;
401443 }
402444 } ;
403445 Ok ( ( ) )
@@ -421,27 +463,15 @@ pub fn prefix_move(path: &Path, prefix: &str) -> Result<()> {
421463 . ok_or_eyre ( format ! ( "Failed to get parent of file '{}'" , path. display( ) ) ) ?
422464 . join ( PathBuf :: from ( appended_path) ) ;
423465
424- if fs:: symlink_metadata ( & new_path) . is_ok ( ) {
425- prefix_move ( & new_path, prefix ) ?;
466+ if let Ok ( metadata ) = fs:: symlink_metadata ( & new_path) {
467+ delete ( & new_path, & metadata ) ?;
426468 } ;
427469
428470 fs:: rename ( canon_path, & new_path) ?;
429471 info ! ( "Renaming '{}' -> '{}'" , path. display( ) , new_path. display( ) ) ;
430472 Ok ( ( ) )
431473}
432474
433- pub fn rmdir ( path : & Path ) -> Result < ( ) > {
434- let Ok ( metadata) = fs:: symlink_metadata ( path) else {
435- return Ok ( ( ) ) ;
436- } ;
437- if !metadata. is_dir ( ) {
438- return Err ( eyre ! ( "Path '{}' is not a directory" , path. display( ) ) ) ;
439- }
440- fs:: remove_dir ( path) ?;
441- info ! ( "Deleting directory '{}'" , path. display( ) ) ;
442- Ok ( ( ) )
443- }
444-
445475pub fn hash_file ( filepath : & Path ) -> Option < Hash > {
446476 let mut hasher = blake3:: Hasher :: new ( ) ;
447477
0 commit comments