77#include "commit.h"
88#include "tag.h"
99#include "tree.h"
10+ #include "tree-walk.h"
1011#include "progress.h"
1112#include "decorate.h"
13+ #include "fsck.h"
1214
13- static int dry_run , quiet , recover , has_errors ;
14- static const char unpack_usage [] = "git-unpack-objects [-n] [-q] [-r] < pack-file" ;
15+ static int dry_run , quiet , recover , has_errors , strict ;
16+ static const char unpack_usage [] = "git-unpack-objects [-n] [-q] [-r] [--strict] < pack-file" ;
1517
1618/* We always read in 4kB chunks. */
1719static unsigned char buffer [4096 ];
1820static unsigned int offset , len ;
1921static off_t consumed_bytes ;
2022static SHA_CTX ctx ;
2123
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+ */
2229struct obj_buffer {
2330 char * buffer ;
2431 unsigned long size ;
@@ -31,6 +38,16 @@ static struct obj_buffer *lookup_object_buffer(struct object *base)
3138 return lookup_decoration (& obj_decorate , base );
3239}
3340
41+ static void add_object_buffer (struct object * object , char * buffer , unsigned long size )
42+ {
43+ struct obj_buffer * obj ;
44+ obj = xcalloc (1 , sizeof (struct obj_buffer ));
45+ obj -> buffer = buffer ;
46+ obj -> size = size ;
47+ if (add_decoration (& obj_decorate , object , obj ))
48+ die ("object %s tried to add buffer twice!" , sha1_to_hex (object -> sha1 ));
49+ }
50+
3451/*
3552 * Make sure at least "min" bytes are available in the buffer, and
3653 * return the pointer to the buffer.
@@ -134,19 +151,110 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
134151struct obj_info {
135152 off_t offset ;
136153 unsigned char sha1 [20 ];
154+ struct object * obj ;
137155};
138156
157+ #define FLAG_OPEN (1u<<20)
158+ #define FLAG_WRITTEN (1u<<21)
159+
139160static struct obj_info * obj_list ;
161+ unsigned nr_objects ;
162+
163+ /*
164+ * Called only from check_object() after it verified this object
165+ * is Ok.
166+ */
167+ static void write_cached_object (struct object * obj )
168+ {
169+ unsigned char sha1 [20 ];
170+ struct obj_buffer * obj_buf = lookup_object_buffer (obj );
171+ if (write_sha1_file (obj_buf -> buffer , obj_buf -> size , typename (obj -> type ), sha1 ) < 0 )
172+ die ("failed to write object %s" , sha1_to_hex (obj -> sha1 ));
173+ obj -> flags |= FLAG_WRITTEN ;
174+ }
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+ */
181+ static int check_object (struct object * obj , int type , void * data )
182+ {
183+ if (!obj )
184+ return 0 ;
185+
186+ if (obj -> flags & FLAG_WRITTEN )
187+ return 1 ;
188+
189+ if (type != OBJ_ANY && obj -> type != type )
190+ die ("object type mismatch" );
191+
192+ if (!(obj -> flags & FLAG_OPEN )) {
193+ unsigned long size ;
194+ int type = sha1_object_info (obj -> sha1 , & size );
195+ if (type != obj -> type || type <= 0 )
196+ die ("object of unexpected type" );
197+ obj -> flags |= FLAG_WRITTEN ;
198+ return 1 ;
199+ }
200+
201+ if (fsck_object (obj , 1 , fsck_error_function ))
202+ die ("Error in object" );
203+ if (!fsck_walk (obj , check_object , 0 ))
204+ die ("Error on reachable objects of %s" , sha1_to_hex (obj -> sha1 ));
205+ write_cached_object (obj );
206+ return 1 ;
207+ }
208+
209+ static void write_rest (void )
210+ {
211+ unsigned i ;
212+ for (i = 0 ; i < nr_objects ; i ++ )
213+ check_object (obj_list [i ].obj , OBJ_ANY , 0 );
214+ }
140215
141216static void added_object (unsigned nr , enum object_type type ,
142217 void * data , unsigned long size );
143218
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+ */
144224static void write_object (unsigned nr , enum object_type type ,
145225 void * buf , unsigned long size )
146226{
147- if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
148- die ("failed to write object" );
149- added_object (nr , type , buf , size );
227+ if (!strict ) {
228+ if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
229+ die ("failed to write object" );
230+ added_object (nr , type , buf , size );
231+ free (buf );
232+ obj_list [nr ].obj = NULL ;
233+ } else if (type == OBJ_BLOB ) {
234+ struct blob * blob ;
235+ if (write_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 ) < 0 )
236+ die ("failed to write object" );
237+ added_object (nr , type , buf , size );
238+ free (buf );
239+
240+ blob = lookup_blob (obj_list [nr ].sha1 );
241+ if (blob )
242+ blob -> object .flags |= FLAG_WRITTEN ;
243+ else
244+ die ("invalid blob object" );
245+ obj_list [nr ].obj = NULL ;
246+ } else {
247+ struct object * obj ;
248+ int eaten ;
249+ hash_sha1_file (buf , size , typename (type ), obj_list [nr ].sha1 );
250+ added_object (nr , type , buf , size );
251+ obj = parse_object_buffer (obj_list [nr ].sha1 , type , size , buf , & eaten );
252+ if (!obj )
253+ die ("invalid %s" , typename (type ));
254+ add_object_buffer (obj , buf , size );
255+ obj -> flags |= FLAG_OPEN ;
256+ obj_list [nr ].obj = obj ;
257+ }
150258}
151259
152260static void resolve_delta (unsigned nr , enum object_type type ,
@@ -163,9 +271,12 @@ static void resolve_delta(unsigned nr, enum object_type type,
163271 die ("failed to apply delta" );
164272 free (delta );
165273 write_object (nr , type , result , result_size );
166- free (result );
167274}
168275
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+ */
169280static void added_object (unsigned nr , enum object_type type ,
170281 void * data , unsigned long size )
171282{
@@ -193,7 +304,24 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
193304
194305 if (!dry_run && buf )
195306 write_object (nr , type , buf , size );
196- free (buf );
307+ else
308+ free (buf );
309+ }
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 ;
197325}
198326
199327static void unpack_delta_entry (enum object_type type , unsigned long delta_size ,
@@ -202,7 +330,6 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
202330 void * delta_data , * base ;
203331 unsigned long base_size ;
204332 unsigned char base_sha1 [20 ];
205- struct object * obj ;
206333
207334 if (type == OBJ_REF_DELTA ) {
208335 hashcpy (base_sha1 , fill (20 ));
@@ -212,7 +339,13 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
212339 free (delta_data );
213340 return ;
214341 }
215- 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 */
216349 hashcpy (obj_list [nr ].sha1 , null_sha1 );
217350 add_delta_to_list (nr , base_sha1 , 0 , delta_data , delta_size );
218351 return ;
@@ -258,22 +391,18 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
258391 }
259392 }
260393 if (!base_found ) {
261- /* The delta base object is itself a delta that
262- has not been resolved yet. */
394+ /*
395+ * The delta base object is itself a delta that
396+ * has not been resolved yet.
397+ */
263398 hashcpy (obj_list [nr ].sha1 , null_sha1 );
264399 add_delta_to_list (nr , null_sha1 , base_offset , delta_data , delta_size );
265400 return ;
266401 }
267402 }
268403
269- obj = lookup_object (base_sha1 );
270- if (obj ) {
271- struct obj_buffer * obj_buf = lookup_object_buffer (obj );
272- if (obj_buf ) {
273- resolve_delta (nr , obj -> type , obj_buf -> buffer , obj_buf -> size , delta_data , delta_size );
274- return ;
275- }
276- }
404+ if (resolve_against_held (nr , base_sha1 , delta_data , delta_size ))
405+ return ;
277406
278407 base = read_sha1_file (base_sha1 , & type , & base_size );
279408 if (!base ) {
@@ -336,7 +465,8 @@ static void unpack_all(void)
336465 int i ;
337466 struct progress * progress = NULL ;
338467 struct pack_header * hdr = fill (sizeof (struct pack_header ));
339- unsigned nr_objects = ntohl (hdr -> hdr_entries );
468+
469+ nr_objects = ntohl (hdr -> hdr_entries );
340470
341471 if (ntohl (hdr -> hdr_signature ) != PACK_SIGNATURE )
342472 die ("bad pack file" );
@@ -347,6 +477,7 @@ static void unpack_all(void)
347477 if (!quiet )
348478 progress = start_progress ("Unpacking objects" , nr_objects );
349479 obj_list = xmalloc (nr_objects * sizeof (* obj_list ));
480+ memset (obj_list , 0 , nr_objects * sizeof (* obj_list ));
350481 for (i = 0 ; i < nr_objects ; i ++ ) {
351482 unpack_one (i );
352483 display_progress (progress , i + 1 );
@@ -382,6 +513,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
382513 recover = 1 ;
383514 continue ;
384515 }
516+ if (!strcmp (arg , "--strict" )) {
517+ strict = 1 ;
518+ continue ;
519+ }
385520 if (!prefixcmp (arg , "--pack_header=" )) {
386521 struct pack_header * hdr ;
387522 char * c ;
@@ -407,6 +542,8 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
407542 unpack_all ();
408543 SHA1_Update (& ctx , buffer , offset );
409544 SHA1_Final (sha1 , & ctx );
545+ if (strict )
546+ write_rest ();
410547 if (hashcmp (fill (20 ), sha1 ))
411548 die ("final sha1 did not match" );
412549 use (20 );
0 commit comments