@@ -21,6 +21,11 @@ static unsigned int offset, len;
2121static off_t consumed_bytes ;
2222static SHA_CTX ctx ;
2323
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+ */
2429struct obj_buffer {
2530 char * buffer ;
2631 unsigned long size ;
@@ -155,6 +160,10 @@ struct obj_info {
155160static struct obj_info * obj_list ;
156161unsigned nr_objects ;
157162
163+ /*
164+ * Called only from check_object() after it verified this object
165+ * is Ok.
166+ */
158167static void write_cached_object (struct object * obj )
159168{
160169 unsigned char sha1 [20 ];
@@ -164,6 +173,11 @@ static void write_cached_object(struct object *obj)
164173 obj -> flags |= FLAG_WRITTEN ;
165174}
166175
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+ */
167181static int check_object (struct object * obj , int type , void * data )
168182{
169183 if (!obj )
@@ -202,35 +216,41 @@ static void write_rest(void)
202216static void added_object (unsigned nr , enum object_type type ,
203217 void * data , unsigned long size );
204218
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+ */
205224static void write_object (unsigned nr , enum object_type type ,
206225 void * buf , unsigned long size )
207226{
208- added_object (nr , type , buf , size );
209227 if (!strict ) {
210228 if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
211229 die ("failed to write object" );
230+ added_object (nr , type , buf , size );
212231 free (buf );
213- obj_list [nr ].obj = 0 ;
232+ obj_list [nr ].obj = NULL ;
214233 } else if (type == OBJ_BLOB ) {
215234 struct blob * blob ;
216235 if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
217236 die ("failed to write object" );
237+ added_object (nr , type , buf , size );
218238 free (buf );
219239
220240 blob = lookup_blob (obj_list [nr ].sha1 );
221241 if (blob )
222242 blob -> object .flags |= FLAG_WRITTEN ;
223243 else
224244 die ("invalid blob object" );
225- obj_list [nr ].obj = 0 ;
245+ obj_list [nr ].obj = NULL ;
226246 } else {
227247 struct object * obj ;
228248 int eaten ;
229249 hash_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 );
250+ added_object (nr , type , buf , size );
230251 obj = parse_object_buffer (obj_list [nr ].sha1 , type , size , buf , & eaten );
231252 if (!obj )
232253 die ("invalid %s" , typename (type ));
233- /* buf is stored via add_object_buffer and in obj, if its a tree or commit */
234254 add_object_buffer (obj , buf , size );
235255 obj -> flags |= FLAG_OPEN ;
236256 obj_list [nr ].obj = obj ;
@@ -253,6 +273,10 @@ static void resolve_delta(unsigned nr, enum object_type type,
253273 write_object (nr , type , result , result_size );
254274}
255275
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+ */
256280static void added_object (unsigned nr , enum object_type type ,
257281 void * data , unsigned long size )
258282{
@@ -284,13 +308,28 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
284308 free (buf );
285309}
286310
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+
287327static void unpack_delta_entry (enum object_type type , unsigned long delta_size ,
288328 unsigned nr )
289329{
290330 void * delta_data , * base ;
291331 unsigned long base_size ;
292332 unsigned char base_sha1 [20 ];
293- struct object * obj ;
294333
295334 if (type == OBJ_REF_DELTA ) {
296335 hashcpy (base_sha1 , fill (20 ));
@@ -300,7 +339,13 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
300339 free (delta_data );
301340 return ;
302341 }
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 */
304349 hashcpy (obj_list [nr ].sha1 , null_sha1 );
305350 add_delta_to_list (nr , base_sha1 , 0 , delta_data , delta_size );
306351 return ;
@@ -346,22 +391,18 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
346391 }
347392 }
348393 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+ */
351398 hashcpy (obj_list [nr ].sha1 , null_sha1 );
352399 add_delta_to_list (nr , null_sha1 , base_offset , delta_data , delta_size );
353400 return ;
354401 }
355402 }
356403
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 ;
365406
366407 base = read_sha1_file (base_sha1 , & type , & base_size );
367408 if (!base ) {
0 commit comments