1- use std:: { path:: PathBuf , time:: SystemTime } ;
1+ use std:: {
2+ path:: PathBuf ,
3+ time:: { SystemTime , UNIX_EPOCH } ,
4+ } ;
5+ use time:: { OffsetDateTime , macros:: format_description} ;
26use walkdir:: { DirEntry , WalkDir } ;
37
48pub struct SyncData {
@@ -11,99 +15,117 @@ pub struct SyncData {
1115 pub hash : Option < bool > ,
1216}
1317
14- fn file_types ( source_entry : DirEntry ) {
18+ fn file_size ( source_entry : DirEntry ) -> ( f64 , & ' static str ) {
1519 if let Ok ( metadata) = source_entry. metadata ( ) {
1620 let size = metadata. len ( ) ;
17- let file_size = if size < 1024 {
18- format ! ( "{} B" , size )
21+ if size < 1024 {
22+ return ( size as f64 , "B" ) ;
1923 } else if size < 1024 * 1024 {
20- format ! ( "{:.2} KB" , size as f64 / 1024.0 )
24+ return ( size as f64 / 1024.0 , "KB" ) ;
2125 } else if size < 1024 * 1024 * 1024 {
22- format ! ( "{:.2} MB" , size as f64 / ( 1024.0 * 1024.0 ) )
26+ return ( size as f64 / ( 1024.0 * 1024.0 ) , "MB" ) ;
2327 } else {
24- format ! ( "{:.2} GB" , size as f64 / ( 1024.0 * 1024.0 * 1024.0 ) )
28+ return ( size as f64 / ( 1024.0 * 1024.0 * 1024.0 ) , "GB" ) ;
2529 } ;
26- println ! ( "Size: {:?}" , file_size) ;
2730 }
31+ ( 0.0 , "" )
2832}
2933
30- fn pretty_time ( t : SystemTime ) {
31- let utc = time :: OffsetDateTime :: UNIX_EPOCH
32- + time:: Duration :: try_from ( t. duration_since ( std :: time :: UNIX_EPOCH ) . unwrap ( ) ) . unwrap ( ) ;
34+ fn pretty_time ( t : SystemTime ) -> String {
35+ let utc = OffsetDateTime :: UNIX_EPOCH
36+ + time:: Duration :: try_from ( t. duration_since ( UNIX_EPOCH ) . unwrap ( ) ) . unwrap ( ) ;
3337 let local = utc. to_offset ( time:: UtcOffset :: local_offset_at ( utc) . unwrap ( ) ) ;
3438 local
35- . format_into (
36- & mut std:: io:: stdout ( ) . lock ( ) ,
37- time:: macros:: format_description!(
38- "[day]-[month repr:short]-[year] [hour]:[minute]:[second]\n "
39- ) ,
40- )
41- . unwrap ( ) ;
39+ . format ( & format_description ! (
40+ "[day]-[month repr:short]-[year] [hour repr:12]:[minute]:[second] [period case:upper]\n "
41+ ) )
42+ . unwrap ( )
4243}
4344
44- fn file_last_modified ( source_entry : DirEntry ) {
45- if let Ok ( time) = source_entry. metadata ( ) {
46- let last_modified = time
47- . modified ( )
48- . expect ( "Err: failed to get the last modified time" ) ;
49- pretty_time ( last_modified) ;
45+ fn file_last_modified ( source_entry : DirEntry ) -> Option < ( i64 , String ) > {
46+ if let Ok ( metadata) = source_entry. metadata ( ) {
47+ if let Ok ( modified) = metadata. modified ( ) {
48+ let numeric = modified. duration_since ( UNIX_EPOCH ) . unwrap ( ) . as_secs ( ) as i64 ;
49+ let pretty = pretty_time ( modified) ;
50+ return Some ( ( numeric, pretty) ) ;
51+ }
5052 }
53+ None
5154}
5255
5356impl SyncData {
5457 pub fn sync_output ( & self ) {
55- let mut source_files: Vec < PathBuf > = Vec :: new ( ) ;
58+ let mut files_to_be_copied = Vec :: new ( ) ;
59+ let mut files_to_be_updated = Vec :: new ( ) ;
60+ let mut source_files: Vec < ( PathBuf , i64 ) > = Vec :: new ( ) ;
61+ let mut destination_files: Vec < ( PathBuf , i64 ) > = Vec :: new ( ) ;
62+
5663 for entry in WalkDir :: new ( & self . source ) {
5764 let entry = entry. expect ( "Err: failed to get the source entry" ) ;
5865 if entry. file_type ( ) . is_file ( ) {
59- source_files. push ( entry. path ( ) . to_path_buf ( ) ) ;
60- // file_types(source_entry.clone());
61- // file_last_modified(source_entry);
66+ let path = entry. path ( ) . to_path_buf ( ) ;
67+ println ! ( "File: {}" , entry. file_name( ) . display( ) ) ;
68+ let ( size, size_type) = file_size ( entry. clone ( ) ) ;
69+ println ! ( "Size: {} {}" , size, size_type) ;
70+ if let Some ( ( num, pretty) ) = file_last_modified ( entry) {
71+ source_files. push ( ( path, num) ) ;
72+ println ! ( "Last Modified: {}" , pretty) ;
73+ }
6274 }
6375 }
6476
65- let mut destination_files: Vec < PathBuf > = Vec :: new ( ) ;
6677 for entry in WalkDir :: new ( & self . destination ) {
6778 let entry = entry. expect ( "Err: failed to get the destination entry" ) ;
6879 if entry. file_type ( ) . is_file ( ) {
69- destination_files. push ( entry. path ( ) . to_path_buf ( ) ) ;
70- // file_types(entry.clone());
71- // file_last_modified(entry);
80+ let path = entry. path ( ) . to_path_buf ( ) ;
81+ if let Some ( ( num, _) ) = file_last_modified ( entry) {
82+ destination_files. push ( ( path, num) ) ;
83+ }
7284 }
7385 }
7486
75- let mut copied_files = Vec :: new ( ) ;
76- for src in & source_files {
77- let src_file_name = src. file_name ( ) . expect ( "Err: failed to get the file name" ) ;
78-
87+ // Compare source and destination files
88+ for ( src_path, src_modified) in & source_files {
89+ let src_file_name = src_path
90+ . file_name ( )
91+ . expect ( "Err: failed to get the file name" ) ;
7992 let mut dest_path = self . destination . clone ( ) ;
8093 dest_path. push ( src_file_name) ;
8194
8295 let mut found = false ;
83- for dest in & destination_files {
84- let dest_file_name = dest. file_name ( ) . expect ( "Err: failed to get the file name" ) ;
96+ let mut needs_update = false ;
97+
98+ for ( dest_path, dest_modified) in & destination_files {
99+ let dest_file_name = dest_path
100+ . file_name ( )
101+ . expect ( "Err: failed to get the file name" ) ;
85102 if src_file_name == dest_file_name {
86103 found = true ;
104+ if src_modified > dest_modified {
105+ needs_update = true ;
106+ }
107+ break ;
87108 }
88109 }
89110
90111 if !found {
91- std:: fs:: copy ( src, dest_path) . unwrap ( ) ;
92- copied_files. push ( src_file_name. to_owned ( ) ) ;
112+ std:: fs:: copy ( src_path, & dest_path) . expect ( "Err: failed to copy file" ) ;
113+ files_to_be_copied. push ( src_file_name. to_owned ( ) ) ;
114+ } else if needs_update {
115+ std:: fs:: copy ( src_path, & dest_path) . expect ( "Err: failed to update file" ) ;
116+ files_to_be_updated. push ( src_file_name. to_owned ( ) ) ;
93117 }
94118 }
95119
96- if !copied_files. is_empty ( ) {
97- println ! ( "Missing files are copied successfully" ) ;
98- } else {
99- eprintln ! ( "No missing files to copy. Destination is up-to-date." ) ;
120+ if !files_to_be_copied. is_empty ( ) {
121+ println ! ( "Missing files copied: {:?}" , files_to_be_copied) ;
122+ }
123+ if !files_to_be_updated. is_empty ( ) {
124+ println ! ( "Files updated: {:?}" , files_to_be_updated) ;
125+ }
126+ if files_to_be_copied. is_empty ( ) && files_to_be_updated. is_empty ( ) {
127+ eprintln ! ( "No missing or outdated files. Destination is up-to-date." ) ;
100128 }
101-
102- // println!("{}", self.incremental.unwrap());
103- // println!("{}", self.delete.unwrap());
104- // println!("{}", self.dry_run.unwrap());
105- // println!("{}", self.verbose.unwrap());
106- // println!("{}", self.hash.unwrap());
107129 }
108130
109131 pub fn sync_options ( & self ) {
0 commit comments