11use rand:: seq:: SliceRandom ;
22use sha2:: { Digest , Sha256 } ;
33use std:: borrow:: Cow ;
4- use std:: cell:: RefCell ;
54use std:: collections:: HashMap ;
65use std:: fs:: { self } ;
76use std:: io:: { self , Write } ;
@@ -29,14 +28,25 @@ pub struct DirectoryEntry {
2928 pub node_id : NodeId ,
3029}
3130
31+ enum PathOrData {
32+ Path (
33+ (
34+ PathBuf ,
35+ Mutex < Arc < dyn Fn ( & Path , & mut Vec < u8 > ) + Sync + Send > > ,
36+ usize ,
37+ ) ,
38+ ) ,
39+ Data ( Arc < Vec < u8 > > ) ,
40+ }
41+
3242pub struct File {
33- contents : RefCell < PathOrData > ,
43+ contents : PathOrData ,
3444}
3545
3646impl File {
3747 pub fn from_data ( data : Vec < u8 > ) -> Self {
3848 Self {
39- contents : RefCell :: new ( PathOrData :: Data ( Arc :: new ( data) ) ) ,
49+ contents : PathOrData :: Data ( Arc :: new ( data) ) ,
4050 }
4151 }
4252
@@ -46,46 +56,31 @@ impl File {
4656 len : usize ,
4757 ) -> Self {
4858 Self {
49- contents : RefCell :: new ( PathOrData :: Path ( ( path, Mutex :: new ( data_filter) , len) ) ) ,
59+ contents : PathOrData :: Path ( ( path, Mutex :: new ( data_filter) , len) ) ,
5060 }
5161 }
5262
5363 fn len ( & self ) -> usize {
54- match & * self . contents . borrow ( ) {
64+ match & self . contents {
5565 PathOrData :: Path ( ( _, _, len) ) => * len,
5666 PathOrData :: Data ( data) => data. len ( ) ,
57- _ => unreachable ! ( ) ,
5867 }
5968 }
6069
6170 fn data ( & self ) -> io:: Result < FileData > {
62- {
63- let mut contents = self . contents . borrow_mut ( ) ;
64-
65- if let PathOrData :: Path ( ( path, data_filter, _) ) = & * contents {
71+ match & self . contents {
72+ PathOrData :: Path ( ( path, data_filter, _) ) => {
6673 let mut data = fs:: read ( & path) ?;
6774 {
6875 let data_filter = data_filter. lock ( ) . unwrap ( ) ;
6976 ( data_filter) ( & path, & mut data) ;
7077 }
7178
72- * contents = PathOrData :: Data ( Arc :: new ( data) ) ;
79+ Ok ( FileData ( Arc :: new ( data) ) )
7380 }
74- }
75-
76- let contents = self . contents . borrow ( ) ;
77-
78- match & * contents {
7981 PathOrData :: Data ( data) => Ok ( FileData ( data. clone ( ) ) ) ,
80- _ => unreachable ! ( ) ,
8182 }
8283 }
83-
84- fn reset ( & self ) {
85- let mut contents = self . contents . borrow_mut ( ) ;
86-
87- * contents = PathOrData :: None ;
88- }
8984}
9085
9186pub struct FileData ( Arc < Vec < u8 > > ) ;
@@ -96,18 +91,6 @@ impl AsRef<[u8]> for FileData {
9691 }
9792}
9893
99- enum PathOrData {
100- Path (
101- (
102- PathBuf ,
103- Mutex < Arc < dyn Fn ( & Path , & mut Vec < u8 > ) + Sync + Send > > ,
104- usize ,
105- ) ,
106- ) ,
107- Data ( Arc < Vec < u8 > > ) ,
108- None ,
109- }
110-
11194impl Node {
11295 fn hash ( & mut self ) -> [ u8 ; 32 ] {
11396 let mut hash = Sha256 :: new ( ) ;
@@ -140,14 +123,18 @@ pub struct Tree {
140123 nodes : HashMap < NodeId , Node > ,
141124 hash_dedup : HashMap < [ u8 ; 32 ] , NodeId > ,
142125 next_id : u64 ,
126+ work_dir : PathBuf ,
127+ next_dir : u64 ,
143128}
144129
145130impl Tree {
146- pub fn new ( ) -> Self {
131+ pub fn new ( work_dir : PathBuf ) -> Self {
147132 Self {
148133 nodes : HashMap :: new ( ) ,
149134 hash_dedup : HashMap :: new ( ) ,
150135 next_id : 0 ,
136+ work_dir : work_dir,
137+ next_dir : 0 ,
151138 }
152139 }
153140
@@ -175,6 +162,24 @@ impl Tree {
175162 path : & Path ,
176163 file_filter : & Box < dyn Fn ( & Path ) -> bool > ,
177164 data_filter : & Arc < dyn Fn ( & Path , & mut Vec < u8 > ) + Send + Sync > ,
165+ ) -> io:: Result < Option < NodeId > > {
166+ let to = self
167+ . work_dir
168+ . join ( self . next_dir . to_string ( ) )
169+ . join ( path. file_name ( ) . unwrap ( ) ) ;
170+
171+ fs:: create_dir_all ( to. parent ( ) . unwrap ( ) ) ?;
172+ fs:: rename ( path, & to) ?;
173+
174+ self . next_dir += 1 ;
175+ self . pack_inner ( & to, file_filter, data_filter)
176+ }
177+
178+ fn pack_inner (
179+ & mut self ,
180+ path : & Path ,
181+ file_filter : & Box < dyn Fn ( & Path ) -> bool > ,
182+ data_filter : & Arc < dyn Fn ( & Path , & mut Vec < u8 > ) + Send + Sync > ,
178183 ) -> io:: Result < Option < NodeId > > {
179184 let path = path. canonicalize ( ) ?;
180185
@@ -195,7 +200,7 @@ impl Tree {
195200 continue ;
196201 }
197202
198- let Some ( node_id) = self . pack ( & child, & file_filter, & data_filter) ? else {
203+ let Some ( node_id) = self . pack_inner ( & child, & file_filter, & data_filter) ? else {
199204 continue ;
200205 } ;
201206 let name = entry. file_name ( ) . to_string_lossy ( ) . to_string ( ) ;
@@ -279,6 +284,8 @@ impl Tree {
279284 let root = w. write ( root) ?;
280285 w. finish ( root) ?;
281286
287+ fs:: remove_dir_all ( & self . work_dir ) ?;
288+
282289 Ok ( ( ) )
283290 }
284291}
@@ -319,7 +326,6 @@ impl<'a> Writer<'a> {
319326 }
320327 Node :: File ( file) => {
321328 let result = self . write_node ( file. data ( ) . unwrap ( ) ) ?;
322- file. reset ( ) ; // Hack to drop the data without having to restructure the recursion
323329
324330 result
325331 }
0 commit comments