@@ -51,6 +51,8 @@ static open_istream_fn open_istream_tbl[] = {
51
51
struct git_istream {
52
52
const struct stream_vtbl * vtbl ;
53
53
unsigned long size ; /* inflated size of full object */
54
+ z_stream z ;
55
+ enum { z_unused , z_used , z_done , z_error } z_state ;
54
56
55
57
union {
56
58
struct {
@@ -64,8 +66,8 @@ struct git_istream {
64
66
} loose ;
65
67
66
68
struct {
67
- int fd ; /* open for reading */
68
- /* NEEDSWORK: what else? */
69
+ struct packed_git * pack ;
70
+ off_t pos ;
69
71
} in_pack ;
70
72
} u ;
71
73
};
@@ -128,6 +130,20 @@ struct git_istream *open_istream(const unsigned char *sha1,
128
130
return st ;
129
131
}
130
132
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
+
131
147
/*****************************************************************
132
148
*
133
149
* Loose object stream
@@ -146,9 +162,92 @@ static open_method_decl(loose)
146
162
*
147
163
*****************************************************************/
148
164
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
+
149
225
static open_method_decl (pack_non_delta )
150
226
{
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 ;
152
251
}
153
252
154
253
0 commit comments