@@ -21,6 +21,11 @@ static unsigned int offset, len;
21
21
static off_t consumed_bytes ;
22
22
static SHA_CTX ctx ;
23
23
24
+ /*
25
+ * When running under --strict mode, objects whose reachability are
26
+ * suspect are kept in core without getting written in the object
27
+ * store.
28
+ */
24
29
struct obj_buffer {
25
30
char * buffer ;
26
31
unsigned long size ;
@@ -155,6 +160,10 @@ struct obj_info {
155
160
static struct obj_info * obj_list ;
156
161
unsigned nr_objects ;
157
162
163
+ /*
164
+ * Called only from check_object() after it verified this object
165
+ * is Ok.
166
+ */
158
167
static void write_cached_object (struct object * obj )
159
168
{
160
169
unsigned char sha1 [20 ];
@@ -164,6 +173,11 @@ static void write_cached_object(struct object *obj)
164
173
obj -> flags |= FLAG_WRITTEN ;
165
174
}
166
175
176
+ /*
177
+ * At the very end of the processing, write_rest() scans the objects
178
+ * that have reachability requirements and calls this function.
179
+ * Verify its reachability and validity recursively and write it out.
180
+ */
167
181
static int check_object (struct object * obj , int type , void * data )
168
182
{
169
183
if (!obj )
@@ -202,35 +216,41 @@ static void write_rest(void)
202
216
static void added_object (unsigned nr , enum object_type type ,
203
217
void * data , unsigned long size );
204
218
219
+ /*
220
+ * Write out nr-th object from the list, now we know the contents
221
+ * of it. Under --strict, this buffers structured objects in-core,
222
+ * to be checked at the end.
223
+ */
205
224
static void write_object (unsigned nr , enum object_type type ,
206
225
void * buf , unsigned long size )
207
226
{
208
- added_object (nr , type , buf , size );
209
227
if (!strict ) {
210
228
if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
211
229
die ("failed to write object" );
230
+ added_object (nr , type , buf , size );
212
231
free (buf );
213
- obj_list [nr ].obj = 0 ;
232
+ obj_list [nr ].obj = NULL ;
214
233
} else if (type == OBJ_BLOB ) {
215
234
struct blob * blob ;
216
235
if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
217
236
die ("failed to write object" );
237
+ added_object (nr , type , buf , size );
218
238
free (buf );
219
239
220
240
blob = lookup_blob (obj_list [nr ].sha1 );
221
241
if (blob )
222
242
blob -> object .flags |= FLAG_WRITTEN ;
223
243
else
224
244
die ("invalid blob object" );
225
- obj_list [nr ].obj = 0 ;
245
+ obj_list [nr ].obj = NULL ;
226
246
} else {
227
247
struct object * obj ;
228
248
int eaten ;
229
249
hash_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 );
250
+ added_object (nr , type , buf , size );
230
251
obj = parse_object_buffer (obj_list [nr ].sha1 , type , size , buf , & eaten );
231
252
if (!obj )
232
253
die ("invalid %s" , typename (type ));
233
- /* buf is stored via add_object_buffer and in obj, if its a tree or commit */
234
254
add_object_buffer (obj , buf , size );
235
255
obj -> flags |= FLAG_OPEN ;
236
256
obj_list [nr ].obj = obj ;
@@ -253,6 +273,10 @@ static void resolve_delta(unsigned nr, enum object_type type,
253
273
write_object (nr , type , result , result_size );
254
274
}
255
275
276
+ /*
277
+ * We now know the contents of an object (which is nr-th in the pack);
278
+ * resolve all the deltified objects that are based on it.
279
+ */
256
280
static void added_object (unsigned nr , enum object_type type ,
257
281
void * data , unsigned long size )
258
282
{
@@ -284,13 +308,28 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
284
308
free (buf );
285
309
}
286
310
311
+ static int resolve_against_held (unsigned nr , const unsigned char * base ,
312
+ void * delta_data , unsigned long delta_size )
313
+ {
314
+ struct object * obj ;
315
+ struct obj_buffer * obj_buffer ;
316
+ obj = lookup_object (base );
317
+ if (!obj )
318
+ return 0 ;
319
+ obj_buffer = lookup_object_buffer (obj );
320
+ if (!obj_buffer )
321
+ return 0 ;
322
+ resolve_delta (nr , obj -> type , obj_buffer -> buffer ,
323
+ obj_buffer -> size , delta_data , delta_size );
324
+ return 1 ;
325
+ }
326
+
287
327
static void unpack_delta_entry (enum object_type type , unsigned long delta_size ,
288
328
unsigned nr )
289
329
{
290
330
void * delta_data , * base ;
291
331
unsigned long base_size ;
292
332
unsigned char base_sha1 [20 ];
293
- struct object * obj ;
294
333
295
334
if (type == OBJ_REF_DELTA ) {
296
335
hashcpy (base_sha1 , fill (20 ));
@@ -300,7 +339,13 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
300
339
free (delta_data );
301
340
return ;
302
341
}
303
- if (!has_sha1_file (base_sha1 )) {
342
+ if (has_sha1_file (base_sha1 ))
343
+ ; /* Ok we have this one */
344
+ else if (resolve_against_held (nr , base_sha1 ,
345
+ delta_data , delta_size ))
346
+ return ; /* we are done */
347
+ else {
348
+ /* cannot resolve yet --- queue it */
304
349
hashcpy (obj_list [nr ].sha1 , null_sha1 );
305
350
add_delta_to_list (nr , base_sha1 , 0 , delta_data , delta_size );
306
351
return ;
@@ -346,22 +391,18 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
346
391
}
347
392
}
348
393
if (!base_found ) {
349
- /* The delta base object is itself a delta that
350
- has not been resolved yet. */
394
+ /*
395
+ * The delta base object is itself a delta that
396
+ * has not been resolved yet.
397
+ */
351
398
hashcpy (obj_list [nr ].sha1 , null_sha1 );
352
399
add_delta_to_list (nr , null_sha1 , base_offset , delta_data , delta_size );
353
400
return ;
354
401
}
355
402
}
356
403
357
- obj = lookup_object (base_sha1 );
358
- if (obj ) {
359
- struct obj_buffer * obj_buf = lookup_object_buffer (obj );
360
- if (obj_buf ) {
361
- resolve_delta (nr , obj -> type , obj_buf -> buffer , obj_buf -> size , delta_data , delta_size );
362
- return ;
363
- }
364
- }
404
+ if (resolve_against_held (nr , base_sha1 , delta_data , delta_size ))
405
+ return ;
365
406
366
407
base = read_sha1_file (base_sha1 , & type , & base_size );
367
408
if (!base ) {
0 commit comments