@@ -171,22 +171,63 @@ fn print_success(src_path: &Path, dst_path: &Path, different_paths: bool, lock:
171171 }
172172}
173173
174- /// Prints an error message to `stdout`.
174+ /// Sets the flag `has_error`. Prints an error message to `stdout`.
175175///
176176/// Wraps around the received error message,
177177/// and notifies the end user that the image file will be skipped.
178178#[ inline]
179- fn print_error ( src_path : & Path , err : Box < dyn Error > , lock : & mut StdoutLock ) {
179+ fn set_and_print_error (
180+ src_path : & Path ,
181+ err : Box < dyn Error > ,
182+ lock : & mut StdoutLock ,
183+ has_error : & mut bool ,
184+ ) {
185+ * has_error = true ;
186+
180187 writeln ! (
181188 lock,
182189 "\t [ERROR] Trying to reduce size of \" {}\" failed with the following error: {}.\n \
183190 \t Skipping that file.\n ",
184191 src_path. display( ) ,
185192 err
186193 )
187- . expect ( "Failed to write to stdout." )
194+ . expect ( "Failed to write to stdout." ) ;
195+ }
196+
197+ /// Copies a file in case of different source and destination paths.
198+ ///
199+ /// Skips a file in case of same source and destination path.
200+ ///
201+ /// Prints an info message in either case.
202+ fn copy_or_skip (
203+ src_path : & Path ,
204+ dst_path : & Path ,
205+ different_paths : bool ,
206+ lock : & mut StdoutLock ,
207+ err : Option < Box < dyn Error > > ,
208+ has_error : & mut bool ,
209+ ) {
210+ if let Some ( error) = err {
211+ writeln ! ( lock, "{}" , error) . expect ( "Failed to write to stdout." ) ;
212+ } ;
213+
214+ if different_paths {
215+ match fs:: copy ( src_path, dst_path) {
216+ Ok ( _) => writeln ! (
217+ lock,
218+ "Copied \" {}\" to \" {}\" ." ,
219+ src_path. display( ) ,
220+ dst_path. display( )
221+ )
222+ . expect ( "Failed to write to stdout." ) ,
223+ Err ( e) => set_and_print_error ( src_path, Box :: from ( e) , lock, has_error) ,
224+ } ;
225+ } else {
226+ writeln ! ( lock, "Skipped \" {}\" ." , src_path. display( ) ) . expect ( "Failed to write to stdout." ) ;
227+ }
188228}
189229
230+ // TODO: Get file size and compare. Then copy_or_skip(), but without `err`. It can be Optional. Pass `None`.
190231/// The main business logic.
191232/// Loops over files and calls appropriate functions for processing images.
192233/// Processing consists of optional resizing first, and of optimizing images
@@ -198,15 +239,20 @@ fn print_error(src_path: &Path, err: Box<dyn Error>, lock: &mut StdoutLock) {
198239/// * `recursive` - Whether to look into entire directory sub-tree.
199240/// * `resize` - Whether to resize image dimensions.
200241/// * `quality` - JPEG image quality. Ignored in case of PNGs.
242+ ///
243+ /// Returns `bool` stating whether there was any error in trying to reduce size of a file or to copy it.
244+ /// This `bool` can be `true` only in case where source and destination directories are different,
245+ /// because in case where they are same and a file cannot have its size reduced, it will be left intact
246+ /// in its source directory.
201247pub fn process_images (
202248 src_dir : PathBuf ,
203249 dst_dir : PathBuf ,
204250 recursive : bool ,
205251 resize : bool ,
206252 quality : i32 ,
207- ) {
208- println ! ( "JPEG quality = {quality} \n " ) ;
209- stdout ( ) . flush ( ) . expect ( "Failed to flush stdout." ) ;
253+ _size : i32 ,
254+ ) -> bool {
255+ let mut has_error = false ;
210256
211257 let different_paths = src_dir != dst_dir;
212258
@@ -219,6 +265,10 @@ pub fn process_images(
219265 if let Some ( extension) = src_path. extension ( ) {
220266 let mut dst_path = PathBuf :: from ( src_path) ;
221267
268+ // TODO: Extract this into a function? See at the end. The `continue`s can be problematic.
269+ // TODO: Return a Boolean flag? Or Option<PathBuf>, for dst_path?
270+ // TODO: But, we shouldn't skip a file! We should copy it. Alright, but what if `mkdir` fails?
271+ // TODO: Well, we can then abort the program. Currently, we are reporting the failure, which could be not only okay, but perhaps a better option.
222272 if different_paths {
223273 dst_path = dst_dir. as_path ( ) . join (
224274 diff_paths (
@@ -236,13 +286,18 @@ pub fn process_images(
236286 "\n \t Failed to create the subdirectory {:?} with the following error: {}" ,
237287 parent, err
238288 ) ;
239- print_error ( src_path, Box :: from ( err) , & mut lock) ;
289+ set_and_print_error (
290+ src_path,
291+ Box :: from ( err) ,
292+ & mut lock,
293+ & mut has_error,
294+ ) ;
240295 continue ;
241296 }
242297 } ;
243298 } else {
244299 let err_msg = format ! ( "Destination path {:?} doesn't have a parent." , dst_path) ;
245- print_error ( src_path, Box :: from ( err_msg) , & mut lock) ;
300+ set_and_print_error ( src_path, Box :: from ( err_msg) , & mut lock, & mut has_error ) ;
246301 continue ;
247302 } ;
248303 }
@@ -251,15 +306,25 @@ pub fn process_images(
251306 "jpg" | "jpeg" => {
252307 match process_jpeg ( src_path, & dst_path, resize, quality, & mut lock) {
253308 Ok ( _) => print_success ( src_path, & dst_path, different_paths, & mut lock) ,
254- Err ( err) => print_error ( src_path, err, & mut lock) ,
309+ Err ( err) => set_and_print_error ( src_path, err, & mut lock, & mut has_error ) , // TODO: Or copy_or_skip()? Pass `err` in and print it first, like in Python.
255310 }
256311 }
257312 "png" => match process_png ( src_path, & dst_path, resize, & mut lock) {
258313 Ok ( _) => print_success ( src_path, & dst_path, different_paths, & mut lock) ,
259- Err ( err) => print_error ( src_path, err, & mut lock) ,
314+ Err ( err) => set_and_print_error ( src_path, err, & mut lock, & mut has_error ) , // TODO: Or copy_or_skip()? Pass `err` in and print it first, like in Python.
260315 } ,
261- _ => ( ) ,
316+ // _ => (), // TODO: copy_or_skip(), but without `err`? Pass `None`.
317+ _ => copy_or_skip (
318+ src_path,
319+ & dst_path,
320+ different_paths,
321+ & mut lock,
322+ None ,
323+ & mut has_error,
324+ ) ,
262325 }
263326 }
264327 }
328+
329+ has_error
265330}
0 commit comments