@@ -7,6 +7,7 @@ use common::{
77 CompressionLevel , FileEntryData , RawEntryData , SourceFileEntryData , HEADER ,
88 } ,
99 object_body:: Object as OtherObject ,
10+ primitives:: { FileMetadata , Timestamp , RWX } ,
1011 read_header_and_body, read_header_from_file, read_header_from_slice,
1112 read_object_into_headers_sync, Hash , Header , Mode , ObjectType , BLOB_KEY , INDEX_KEY , TREE_KEY ,
1213} ;
@@ -37,23 +38,6 @@ impl<T: Object> Deref for Hashed<T> {
3738}
3839
3940impl < T : Object > Hashed < T > {
40- // fn from_hash(cache: &PathBuf, hash: Hash) -> Self {
41- // let (dir, file) = hash.get_parts();
42-
43- // let file_path = cache.join(dir).join(file);
44-
45- // assert!(file_path.exists());
46-
47- // let reader = T::read_file_and_verify_type(&file_path);
48-
49- // drop(reader);
50-
51- // Self {
52- // inner: T::from_file(cache, &file_path),
53- // hash,
54- // }
55- // }
56-
5741 fn from_object ( value : T ) -> Self {
5842 Self {
5943 hash : value. get_hash ( ) ,
@@ -67,30 +51,6 @@ trait Object {
6751 fn get_hash ( & self ) -> Hash ;
6852 fn get_prefix ( & self ) -> String ;
6953 fn write_to ( & self , path : & Path ) ;
70-
71- // fn from_file(cache: &PathBuf, file: &PathBuf) -> Self;
72-
73- // fn read_file_and_verify_type(path: &PathBuf) -> BufReader<File> {
74- // let f = File::open(file_path).unwrap();
75- // let mut reader = BufReader::new(f);
76-
77- // let mut data = Vec::new();
78- // reader.read_until(0, &mut data);
79-
80- // if data.last() == Some(&0) {
81- // data.pop();
82- // }
83-
84- // let name = String::from_utf8(data).unwrap();
85-
86- // let (typ, size) = name.split_once(' ').unwrap();
87-
88- // let object_type = ObjectType::from_str(typ);
89-
90- // assert!(object_type == T::get_object_type());
91-
92- // reader
93- // }
9454}
9555
9656struct CacheObject < ' a > {
@@ -202,6 +162,17 @@ impl<'a> CacheObject<'a> {
202162
203163 let mode = Mode :: from_str ( mode) . expect ( "valid mode" ) ;
204164
165+ let mut timestamp: [ u8 ; 8 ] = [ 0 ; 8 ] ;
166+ file. read_exact ( & mut timestamp)
167+ . expect ( "file to contain timestamp" ) ;
168+
169+ let timestamp = Timestamp :: from ( timestamp) ;
170+
171+ let mut metadata = [ 0u8 ; 1 ] ;
172+ file. read_exact ( & mut metadata)
173+ . expect ( "file to contain metadata" ) ;
174+ let metadata = FileMetadata :: from_u8 ( metadata[ 0 ] ) ;
175+
205176 let mut hash: [ u8 ; 32 ] = [ 0 ; 32 ] ;
206177 file. read_exact ( & mut hash) . expect ( "file to contain hash" ) ;
207178
@@ -212,7 +183,9 @@ impl<'a> CacheObject<'a> {
212183 let cache_object = CacheObject :: from_file ( self . cache , & object_file) ;
213184
214185 vec. push ( match cache_object. object_type {
215- ObjectType :: Blob => TreeObject :: Blob ( cache_object. to_blob ( mode, name) ) ,
186+ ObjectType :: Blob => {
187+ TreeObject :: Blob ( cache_object. to_blob ( mode, timestamp, metadata, name) )
188+ }
216189 ObjectType :: Tree => TreeObject :: Tree ( cache_object. to_tree ( mode, name) ) ,
217190 ObjectType :: Index => panic ! ( "Invalid ObjectType in tree" ) ,
218191 } )
@@ -228,7 +201,13 @@ impl<'a> CacheObject<'a> {
228201 }
229202 }
230203
231- fn to_blob ( & self , mode : Mode , path : & str ) -> Hashed < Blob > {
204+ fn to_blob (
205+ & self ,
206+ mode : Mode ,
207+ timestamp : Timestamp ,
208+ metadata : FileMetadata ,
209+ path : & str ,
210+ ) -> Hashed < Blob > {
232211 assert ! ( self . object_type == ObjectType :: Blob ) ;
233212
234213 let file = File :: open ( & self . file ) . unwrap ( ) ;
@@ -246,6 +225,8 @@ impl<'a> CacheObject<'a> {
246225 path : path. to_string ( ) ,
247226 file : self . file . clone ( ) ,
248227 size,
228+ timestamp,
229+ metadata,
249230 } ,
250231 }
251232 }
@@ -346,6 +327,8 @@ impl Object for Index {
346327
347328trait WithPath {
348329 fn get_path_component ( & self ) -> & String ;
330+ fn get_metadata ( & self ) -> & FileMetadata ;
331+ fn get_timestamp ( & self ) -> & Timestamp ;
349332 fn get_mode ( & self ) -> & Mode ;
350333}
351334
@@ -408,6 +391,20 @@ impl Tree {
408391 }
409392}
410393
394+ const ZERO_TIMESTAMP : Timestamp = Timestamp :: from_nanos ( 0 ) ;
395+ const ZERO_METADATA : FileMetadata = FileMetadata {
396+ user_permissions : RWX {
397+ read : false ,
398+ write : false ,
399+ execute : false ,
400+ } ,
401+ other_permissions : RWX {
402+ read : false ,
403+ write : false ,
404+ execute : false ,
405+ } ,
406+ hidden_flag : false ,
407+ } ;
411408impl WithPath for Tree {
412409 fn get_path_component ( & self ) -> & String {
413410 & self . path
@@ -416,6 +413,15 @@ impl WithPath for Tree {
416413 fn get_mode ( & self ) -> & Mode {
417414 & self . mode
418415 }
416+
417+ fn get_metadata ( & self ) -> & FileMetadata {
418+ // Trees don't have metadata but we need to return something so we can encode the hidden flag
419+ & ZERO_METADATA
420+ }
421+
422+ fn get_timestamp ( & self ) -> & Timestamp {
423+ & ZERO_TIMESTAMP
424+ }
419425}
420426
421427impl Object for Tree {
@@ -459,6 +465,8 @@ impl Object for Tree {
459465#[ derive( Debug ) ]
460466struct Blob {
461467 mode : Mode ,
468+ timestamp : Timestamp ,
469+ metadata : FileMetadata ,
462470 path : String ,
463471 file : PathBuf ,
464472 size : u64 ,
@@ -474,6 +482,9 @@ impl Blob {
474482 path : path. file_name ( ) . unwrap ( ) . to_string_lossy ( ) . to_string ( ) ,
475483 size : path. metadata ( ) . unwrap ( ) . len ( ) ,
476484 file : path. to_path_buf ( ) ,
485+ timestamp : Timestamp :: from_system_time ( path. metadata ( ) . unwrap ( ) . modified ( ) . unwrap ( ) )
486+ . unwrap ( ) ,
487+ metadata : FileMetadata :: from ( path. metadata ( ) . unwrap ( ) ) ,
477488 }
478489 }
479490
@@ -484,7 +495,10 @@ impl Blob {
484495 fn hash_and_write ( src : & Path , cache : Option < & Path > ) -> Hashed < Self > {
485496 assert ! ( src. is_file( ) ) ;
486497
487- let size = src. metadata ( ) . unwrap ( ) . len ( ) ;
498+ let metadata = src. metadata ( ) . unwrap ( ) ;
499+ let size = metadata. len ( ) ;
500+ let timestamp: Timestamp = metadata. modified ( ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;
501+ let metadata = FileMetadata :: from ( metadata) ;
488502 let prefix = format ! ( "{} {}\0 " , BLOB_KEY , size) ;
489503
490504 let mut hasher = Sha256 :: new ( ) ;
@@ -521,6 +535,8 @@ impl Blob {
521535 mode : Mode :: Normal ,
522536 path : src. file_name ( ) . unwrap ( ) . to_string_lossy ( ) . to_string ( ) ,
523537 file : src. to_path_buf ( ) ,
538+ timestamp,
539+ metadata,
524540 size,
525541 } ,
526542 }
@@ -535,6 +551,14 @@ impl WithPath for Blob {
535551 fn get_mode ( & self ) -> & Mode {
536552 & self . mode
537553 }
554+
555+ fn get_metadata ( & self ) -> & FileMetadata {
556+ & self . metadata
557+ }
558+
559+ fn get_timestamp ( & self ) -> & Timestamp {
560+ & self . timestamp
561+ }
538562}
539563
540564impl Object for Blob {
@@ -607,6 +631,8 @@ fn get_bytes_from_thing<T: WithPath>(object: &T, hash: &Hash) -> Vec<u8> {
607631 path. push ( b' ' ) ;
608632 path. extend_from_slice ( object. get_path_component ( ) . as_bytes ( ) ) ;
609633 path. push ( 0 ) ;
634+ path. extend_from_slice ( & object. get_timestamp ( ) . as_bytes ( ) ) ;
635+ path. push ( object. get_metadata ( ) . to_u8 ( ) ) ;
610636 path. extend_from_slice ( & hash. hash ) ;
611637
612638 path
@@ -728,20 +754,30 @@ fn write_tree(tree: &Tree, path: &Path) {
728754 let blob_path = path. join ( & blob. path ) ;
729755
730756 let file = File :: create ( blob_path) . expect ( "File to be created" ) ;
731- let mut writer = BufWriter :: new ( file) ;
757+ {
758+ let mut writer = BufWriter :: new ( file. try_clone ( ) . unwrap ( ) ) ;
732759
733- let cache_file = File :: open ( & blob. file ) . unwrap ( ) ;
734- let mut reader = BufReader :: new ( cache_file) ;
760+ let cache_file = File :: open ( & blob. file ) . unwrap ( ) ;
761+ let mut reader = BufReader :: new ( cache_file) ;
735762
736- let _ = read_header_from_file ( & mut reader) ;
763+ let _ = read_header_from_file ( & mut reader) ;
737764
738- let mut data: [ u8 ; 1024 ] = [ 0 ; 1024 ] ;
739- while let Ok ( num) = reader. read ( & mut data) {
740- if num == 0 {
741- break ;
765+ let mut data: [ u8 ; 1024 ] = [ 0 ; 1024 ] ;
766+ while let Ok ( num) = reader. read ( & mut data) {
767+ if num == 0 {
768+ break ;
769+ }
770+ writer. write_all ( & data[ ..num] ) . unwrap ( ) ;
742771 }
743- writer. write_all ( & data[ ..num] ) . unwrap ( ) ;
744772 }
773+
774+ let mut permissions = file. metadata ( ) . unwrap ( ) . permissions ( ) ;
775+
776+ blob. metadata . modify_permissions ( & mut permissions) ;
777+
778+ file. set_permissions ( permissions) . unwrap ( ) ;
779+
780+ file. set_modified ( blob. timestamp . into ( ) ) . unwrap ( ) ;
745781 }
746782}
747783
0 commit comments