@@ -9,11 +9,9 @@ use flate2::{
99use ignore:: WalkBuilder ;
1010use serde:: { Deserialize , Serialize } ;
1111use sha1_checked:: { Digest , Sha1 } ;
12- use std:: {
13- collections:: HashMap ,
14- fs:: Permissions ,
15- os:: unix:: fs:: { MetadataExt , PermissionsExt } ,
16- } ;
12+ use std:: collections:: HashMap ;
13+ #[ cfg( unix) ]
14+ use std:: os:: unix:: fs:: { MetadataExt , PermissionsExt } ;
1715use std:: { collections:: HashSet , time:: SystemTime } ;
1816use std:: { fmt, fs, path:: PathBuf , str:: FromStr } ;
1917use std:: {
@@ -626,18 +624,69 @@ pub fn add(paths: Vec<String>) -> anyhow::Result<()> {
626624 . try_into ( )
627625 . map_err ( |_| anyhow:: anyhow!( "SHA1 hash must be 20 bytes" ) ) ?;
628626 let entry = IndexEntry {
627+ sha1 : sha1_bytes,
628+ flags,
629+ size : st. len ( ) as u32 ,
630+
631+ #[ cfg( unix) ]
629632 ctime_s : st. ctime ( ) as u32 ,
633+ #[ cfg( not( unix) ) ]
634+ ctime_s : st
635+ . created ( )
636+ . ok ( )
637+ . and_then ( |t| t. duration_since ( std:: time:: UNIX_EPOCH ) . ok ( ) )
638+ . map ( |d| d. as_secs ( ) as u32 )
639+ . unwrap_or ( 0 ) ,
640+
641+ #[ cfg( unix) ]
630642 ctime_n : st. ctime_nsec ( ) as u32 ,
631- mtime_n : st. mtime ( ) as u32 ,
632- mtime_s : st. mtime_nsec ( ) as u32 ,
643+ #[ cfg( not( unix) ) ]
644+ ctime_n : 0 ,
645+
646+ #[ cfg( unix) ]
647+ mtime_s : st. mtime ( ) as u32 ,
648+ #[ cfg( not( unix) ) ]
649+ mtime_s : st
650+ . modified ( )
651+ . ok ( )
652+ . and_then ( |t| t. duration_since ( std:: time:: UNIX_EPOCH ) . ok ( ) )
653+ . map ( |d| d. as_secs ( ) as u32 )
654+ . unwrap_or ( 0 ) ,
655+
656+ #[ cfg( unix) ]
657+ mtime_n : st. mtime_nsec ( ) as u32 ,
658+ #[ cfg( not( unix) ) ]
659+ mtime_n : 0 ,
660+
661+ #[ cfg( unix) ]
633662 dev : st. dev ( ) as u32 ,
663+ #[ cfg( not( unix) ) ]
664+ dev : 0 ,
665+
666+ #[ cfg( unix) ]
634667 ino : st. ino ( ) as u32 ,
635- size : st. size ( ) as u32 ,
636- gid : st. gid ( ) ,
637- uid : st. uid ( ) ,
668+ #[ cfg( not( unix) ) ]
669+ ino : 0 ,
670+
671+ #[ cfg( unix) ]
638672 mode : st. mode ( ) ,
639- flags,
640- sha1 : sha1_bytes,
673+ #[ cfg( not( unix) ) ]
674+ mode : if st. permissions ( ) . readonly ( ) {
675+ 0o100444
676+ } else {
677+ 0o100644
678+ } ,
679+
680+ #[ cfg( unix) ]
681+ uid : st. uid ( ) ,
682+ #[ cfg( not( unix) ) ]
683+ uid : 0 ,
684+
685+ #[ cfg( unix) ]
686+ gid : st. gid ( ) ,
687+ #[ cfg( not( unix) ) ]
688+ gid : 0 ,
689+
641690 path,
642691 } ;
643692 entries. push ( entry) ;
@@ -1005,7 +1054,16 @@ pub fn restore_working_tree(commit_hash: String) -> anyhow::Result<()> {
10051054 fs:: create_dir_all ( par) ?;
10061055 }
10071056 fs:: write ( path, & file_data) ?;
1008- fs:: set_permissions ( path, Permissions :: from_mode ( * mode) ) ?;
1057+ #[ cfg( unix) ]
1058+ fs:: set_permissions ( & path, fs:: Permissions :: from_mode ( * mode) ) ?;
1059+
1060+ #[ cfg( not( unix) ) ]
1061+ {
1062+ let mut perms = fs:: metadata ( & path) ?. permissions ( ) ;
1063+ let readonly = ( * mode & 0o200 ) == 0 ; // owner write bit unset = readonly
1064+ perms. set_readonly ( readonly) ;
1065+ fs:: set_permissions ( & path, perms) ?;
1066+ }
10091067 }
10101068 }
10111069
@@ -1017,21 +1075,63 @@ pub fn restore_working_tree(commit_hash: String) -> anyhow::Result<()> {
10171075 if flags >= ( 1 << 12 ) {
10181076 return Err ( anyhow ! ( "Invalid flags" ) ) ;
10191077 }
1020- let meta = fs:: metadata ( path) ?; // stat the just-written file
1078+ let st = fs:: metadata ( path) ?; // stat the just-written file
10211079 Ok ( IndexEntry {
10221080 mode : * mode,
10231081 path : path. clone ( ) ,
10241082 sha1 : hex:: decode ( sha1) ?. try_into ( ) . unwrap ( ) ,
1025- ctime_s : meta. ctime ( ) as u32 ,
1026- ctime_n : meta. ctime_nsec ( ) as u32 ,
1027- mtime_s : meta. mtime ( ) as u32 ,
1028- mtime_n : meta. mtime_nsec ( ) as u32 ,
1029- size : meta. size ( ) as u32 ,
1030- ino : meta. ino ( ) as u32 ,
1031- dev : meta. dev ( ) as u32 ,
1032- uid : meta. uid ( ) ,
1033- gid : meta. gid ( ) ,
1083+ size : st. len ( ) as u32 ,
10341084 flags,
1085+
1086+ #[ cfg( unix) ]
1087+ ctime_s : st. ctime ( ) as u32 ,
1088+ #[ cfg( not( unix) ) ]
1089+ ctime_s : st
1090+ . created ( )
1091+ . ok ( )
1092+ . and_then ( |t| t. duration_since ( std:: time:: UNIX_EPOCH ) . ok ( ) )
1093+ . map ( |d| d. as_secs ( ) as u32 )
1094+ . unwrap_or ( 0 ) ,
1095+
1096+ #[ cfg( unix) ]
1097+ ctime_n : st. ctime_nsec ( ) as u32 ,
1098+ #[ cfg( not( unix) ) ]
1099+ ctime_n : 0 ,
1100+
1101+ #[ cfg( unix) ]
1102+ mtime_s : st. mtime ( ) as u32 ,
1103+ #[ cfg( not( unix) ) ]
1104+ mtime_s : st
1105+ . modified ( )
1106+ . ok ( )
1107+ . and_then ( |t| t. duration_since ( std:: time:: UNIX_EPOCH ) . ok ( ) )
1108+ . map ( |d| d. as_secs ( ) as u32 )
1109+ . unwrap_or ( 0 ) ,
1110+
1111+ #[ cfg( unix) ]
1112+ mtime_n : st. mtime_nsec ( ) as u32 ,
1113+ #[ cfg( not( unix) ) ]
1114+ mtime_n : 0 ,
1115+
1116+ #[ cfg( unix) ]
1117+ dev : st. dev ( ) as u32 ,
1118+ #[ cfg( not( unix) ) ]
1119+ dev : 0 ,
1120+
1121+ #[ cfg( unix) ]
1122+ ino : st. ino ( ) as u32 ,
1123+ #[ cfg( not( unix) ) ]
1124+ ino : 0 ,
1125+
1126+ #[ cfg( unix) ]
1127+ uid : st. uid ( ) ,
1128+ #[ cfg( not( unix) ) ]
1129+ uid : 0 ,
1130+
1131+ #[ cfg( unix) ]
1132+ gid : st. gid ( ) ,
1133+ #[ cfg( not( unix) ) ]
1134+ gid : 0 ,
10351135 } )
10361136 } )
10371137 . collect :: < anyhow:: Result < Vec < _ > > > ( ) ?;
@@ -1210,6 +1310,7 @@ mod tests {
12101310 }
12111311
12121312 #[ test]
1313+ #[ serial_test:: serial]
12131314 fn test_read_object_roundtrip ( ) {
12141315 let data = b"roundtrip data" . to_vec ( ) ;
12151316 let hash = hash_object ( & mut data. clone ( ) , ObjectType :: Blob , true ) . unwrap ( ) ;
0 commit comments