@@ -51,6 +51,8 @@ static open_istream_fn open_istream_tbl[] = {
5151struct git_istream {
5252 const struct stream_vtbl * vtbl ;
5353 unsigned long size ; /* inflated size of full object */
54+ z_stream z ;
55+ enum { z_unused , z_used , z_done , z_error } z_state ;
5456
5557 union {
5658 struct {
@@ -64,8 +66,8 @@ struct git_istream {
6466 } loose ;
6567
6668 struct {
67- int fd ; /* open for reading */
68- /* NEEDSWORK: what else? */
69+ struct packed_git * pack ;
70+ off_t pos ;
6971 } in_pack ;
7072 } u ;
7173};
@@ -128,6 +130,20 @@ struct git_istream *open_istream(const unsigned char *sha1,
128130 return st ;
129131}
130132
133+
134+ /*****************************************************************
135+ *
136+ * Common helpers
137+ *
138+ *****************************************************************/
139+
140+ static void close_deflated_stream (struct git_istream * st )
141+ {
142+ if (st -> z_state == z_used )
143+ git_inflate_end (& st -> z );
144+ }
145+
146+
131147/*****************************************************************
132148 *
133149 * Loose object stream
@@ -146,9 +162,92 @@ static open_method_decl(loose)
146162 *
147163 *****************************************************************/
148164
165+ static read_method_decl (pack_non_delta )
166+ {
167+ size_t total_read = 0 ;
168+
169+ switch (st -> z_state ) {
170+ case z_unused :
171+ memset (& st -> z , 0 , sizeof (st -> z ));
172+ git_inflate_init (& st -> z );
173+ st -> z_state = z_used ;
174+ break ;
175+ case z_done :
176+ return 0 ;
177+ case z_error :
178+ return -1 ;
179+ case z_used :
180+ break ;
181+ }
182+
183+ while (total_read < sz ) {
184+ int status ;
185+ struct pack_window * window = NULL ;
186+ unsigned char * mapped ;
187+
188+ mapped = use_pack (st -> u .in_pack .pack , & window ,
189+ st -> u .in_pack .pos , & st -> z .avail_in );
190+
191+ st -> z .next_out = (unsigned char * )buf + total_read ;
192+ st -> z .avail_out = sz - total_read ;
193+ st -> z .next_in = mapped ;
194+ status = git_inflate (& st -> z , Z_FINISH );
195+
196+ st -> u .in_pack .pos += st -> z .next_in - mapped ;
197+ total_read = st -> z .next_out - (unsigned char * )buf ;
198+ unuse_pack (& window );
199+
200+ if (status == Z_STREAM_END ) {
201+ git_inflate_end (& st -> z );
202+ st -> z_state = z_done ;
203+ break ;
204+ }
205+ if (status != Z_OK && status != Z_BUF_ERROR ) {
206+ git_inflate_end (& st -> z );
207+ st -> z_state = z_error ;
208+ return -1 ;
209+ }
210+ }
211+ return total_read ;
212+ }
213+
214+ static close_method_decl (pack_non_delta )
215+ {
216+ close_deflated_stream (st );
217+ return 0 ;
218+ }
219+
220+ static struct stream_vtbl pack_non_delta_vtbl = {
221+ close_istream_pack_non_delta ,
222+ read_istream_pack_non_delta ,
223+ };
224+
149225static open_method_decl (pack_non_delta )
150226{
151- return -1 ; /* for now */
227+ struct pack_window * window ;
228+ enum object_type in_pack_type ;
229+
230+ st -> u .in_pack .pack = oi -> u .packed .pack ;
231+ st -> u .in_pack .pos = oi -> u .packed .offset ;
232+ window = NULL ;
233+
234+ in_pack_type = unpack_object_header (st -> u .in_pack .pack ,
235+ & window ,
236+ & st -> u .in_pack .pos ,
237+ & st -> size );
238+ unuse_pack (& window );
239+ switch (in_pack_type ) {
240+ default :
241+ return -1 ; /* we do not do deltas for now */
242+ case OBJ_COMMIT :
243+ case OBJ_TREE :
244+ case OBJ_BLOB :
245+ case OBJ_TAG :
246+ break ;
247+ }
248+ st -> z_state = z_unused ;
249+ st -> vtbl = & pack_non_delta_vtbl ;
250+ return 0 ;
152251}
153252
154253
0 commit comments