7
7
#include "commit.h"
8
8
#include "tag.h"
9
9
#include "tree.h"
10
+ #include "tree-walk.h"
10
11
#include "progress.h"
11
12
#include "decorate.h"
13
+ #include "fsck.h"
12
14
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" ;
15
17
16
18
/* We always read in 4kB chunks. */
17
19
static unsigned char buffer [4096 ];
18
20
static unsigned int offset , len ;
19
21
static off_t consumed_bytes ;
20
22
static SHA_CTX ctx ;
21
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
+ */
22
29
struct obj_buffer {
23
30
char * buffer ;
24
31
unsigned long size ;
@@ -31,6 +38,16 @@ static struct obj_buffer *lookup_object_buffer(struct object *base)
31
38
return lookup_decoration (& obj_decorate , base );
32
39
}
33
40
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
+
34
51
/*
35
52
* Make sure at least "min" bytes are available in the buffer, and
36
53
* return the pointer to the buffer.
@@ -134,19 +151,110 @@ static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
134
151
struct obj_info {
135
152
off_t offset ;
136
153
unsigned char sha1 [20 ];
154
+ struct object * obj ;
137
155
};
138
156
157
+ #define FLAG_OPEN (1u<<20)
158
+ #define FLAG_WRITTEN (1u<<21)
159
+
139
160
static 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
+ }
140
215
141
216
static void added_object (unsigned nr , enum object_type type ,
142
217
void * data , unsigned long size );
143
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
+ */
144
224
static void write_object (unsigned nr , enum object_type type ,
145
225
void * buf , unsigned long size )
146
226
{
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
+ }
150
258
}
151
259
152
260
static void resolve_delta (unsigned nr , enum object_type type ,
@@ -163,9 +271,12 @@ static void resolve_delta(unsigned nr, enum object_type type,
163
271
die ("failed to apply delta" );
164
272
free (delta );
165
273
write_object (nr , type , result , result_size );
166
- free (result );
167
274
}
168
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
+ */
169
280
static void added_object (unsigned nr , enum object_type type ,
170
281
void * data , unsigned long size )
171
282
{
@@ -193,7 +304,24 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
193
304
194
305
if (!dry_run && buf )
195
306
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 ;
197
325
}
198
326
199
327
static 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,
202
330
void * delta_data , * base ;
203
331
unsigned long base_size ;
204
332
unsigned char base_sha1 [20 ];
205
- struct object * obj ;
206
333
207
334
if (type == OBJ_REF_DELTA ) {
208
335
hashcpy (base_sha1 , fill (20 ));
@@ -212,7 +339,13 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
212
339
free (delta_data );
213
340
return ;
214
341
}
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 */
216
349
hashcpy (obj_list [nr ].sha1 , null_sha1 );
217
350
add_delta_to_list (nr , base_sha1 , 0 , delta_data , delta_size );
218
351
return ;
@@ -258,22 +391,18 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
258
391
}
259
392
}
260
393
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
+ */
263
398
hashcpy (obj_list [nr ].sha1 , null_sha1 );
264
399
add_delta_to_list (nr , null_sha1 , base_offset , delta_data , delta_size );
265
400
return ;
266
401
}
267
402
}
268
403
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 ;
277
406
278
407
base = read_sha1_file (base_sha1 , & type , & base_size );
279
408
if (!base ) {
@@ -336,7 +465,8 @@ static void unpack_all(void)
336
465
int i ;
337
466
struct progress * progress = NULL ;
338
467
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 );
340
470
341
471
if (ntohl (hdr -> hdr_signature ) != PACK_SIGNATURE )
342
472
die ("bad pack file" );
@@ -347,6 +477,7 @@ static void unpack_all(void)
347
477
if (!quiet )
348
478
progress = start_progress ("Unpacking objects" , nr_objects );
349
479
obj_list = xmalloc (nr_objects * sizeof (* obj_list ));
480
+ memset (obj_list , 0 , nr_objects * sizeof (* obj_list ));
350
481
for (i = 0 ; i < nr_objects ; i ++ ) {
351
482
unpack_one (i );
352
483
display_progress (progress , i + 1 );
@@ -382,6 +513,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
382
513
recover = 1 ;
383
514
continue ;
384
515
}
516
+ if (!strcmp (arg , "--strict" )) {
517
+ strict = 1 ;
518
+ continue ;
519
+ }
385
520
if (!prefixcmp (arg , "--pack_header=" )) {
386
521
struct pack_header * hdr ;
387
522
char * c ;
@@ -407,6 +542,8 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
407
542
unpack_all ();
408
543
SHA1_Update (& ctx , buffer , offset );
409
544
SHA1_Final (sha1 , & ctx );
545
+ if (strict )
546
+ write_rest ();
410
547
if (hashcmp (fill (20 ), sha1 ))
411
548
die ("final sha1 did not match" );
412
549
use (20 );
0 commit comments