index-pack: introduce checking mode
Adds strict option, which bails out if the pack would introduces broken object or links in the repository. Signed-off-by: Martin Koegler <mkoegler@auto.tuwien.ac.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Martin Koegler committed
Feb 25, 2008 at 22:46 UTC
0153be05ae332b8df9bb21d8d249881323e30725
2 files changed
+90
-1
Documentation/git-index-pack.txt
+3
@@ -75,6 +75,9 @@ OPTIONS
75
to force the version for the generated pack index, and to force
76
64-bit index entries on objects located above the given offset.
77
78
+--strict::
79
+ Die, if the pack contains broken objects or links.
80
+
81
82
Note
83
----
index-pack.c
+87
-1
@@ -7,9 +7,10 @@
7
#include "tag.h"
8
#include "tree.h"
9
#include "progress.h"
10
+#include "fsck.h"
11
12
static const char index_pack_usage[] =
12
-"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
13
+"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
14
15
struct object_entry
16
{
@@ -31,6 +32,9 @@ union delta_base {
32
*/
33
#define UNION_BASE_SZ 20
34
35
+#define FLAG_LINK (1u<<20)
36
+#define FLAG_CHECKED (1u<<21)
37
+
38
struct delta_entry
39
{
40
union delta_base base;
@@ -44,6 +48,7 @@ static int nr_deltas;
48
static int nr_resolved_deltas;
49
50
static int from_stdin;
51
+static int strict;
52
static int verbose;
53
54
static struct progress *progress;
@@ -56,6 +61,48 @@ static SHA_CTX input_ctx;
61
static uint32_t input_crc32;
62
static int input_fd, output_fd, pack_fd;
63
64
+static int mark_link(struct object *obj, int type, void *data)
65
+{
66
+ if (!obj)
67
+ return -1;
68
+
69
+ if (type != OBJ_ANY && obj->type != type)
70
+ die("object type mismatch at %s", sha1_to_hex(obj->sha1));
71
+
72
+ obj->flags |= FLAG_LINK;
73
+ return 0;
74
+}
75
+
76
+/* The content of each linked object must have been checked
77
+ or it must be already present in the object database */
78
+static void check_object(struct object *obj)
79
+{
80
+ if (!obj)
81
+ return;
82
+
83
+ if (!(obj->flags & FLAG_LINK))
84
+ return;
85
+
86
+ if (!(obj->flags & FLAG_CHECKED)) {
87
+ unsigned long size;
88
+ int type = sha1_object_info(obj->sha1, &size);
89
+ if (type != obj->type || type <= 0)
90
+ die("object of unexpected type");
91
+ obj->flags |= FLAG_CHECKED;
92
+ return;
93
+ }
94
+}
95
+
96
+static void check_objects(void)
97
+{
98
+ unsigned i, max;
99
+
100
+ max = get_max_object_index();
101
+ for (i = 0; i < max; i++)
102
+ check_object(get_indexed_object(i));
103
+}
104
+
105
+
106
/* Discard current buffer used content. */
107
static void flush(void)
108
{
@@ -341,6 +388,41 @@ static void sha1_object(const void *data, unsigned long size,
388
die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1));
389
free(has_data);
390
}
391
+ if (strict) {
392
+ if (type == OBJ_BLOB) {
393
+ struct blob *blob = lookup_blob(sha1);
394
+ if (blob)
395
+ blob->object.flags |= FLAG_CHECKED;
396
+ else
397
+ die("invalid blob object %s", sha1_to_hex(sha1));
398
+ } else {
399
+ struct object *obj;
400
+ int eaten;
401
+ void *buf = (void *) data;
402
+
403
+ /*
404
+ * we do not need to free the memory here, as the
405
+ * buf is deleted by the caller.
406
+ */
407
+ obj = parse_object_buffer(sha1, type, size, buf, &eaten);
408
+ if (!obj)
409
+ die("invalid %s", typename(type));
410
+ if (fsck_object(obj, 1, fsck_error_function))
411
+ die("Error in object");
412
+ if (fsck_walk(obj, mark_link, 0))
413
+ die("Not all child objects of %s are reachable", sha1_to_hex(obj->sha1));
414
+
415
+ if (obj->type == OBJ_TREE) {
416
+ struct tree *item = (struct tree *) obj;
417
+ item->buffer = NULL;
418
+ }
419
+ if (obj->type == OBJ_COMMIT) {
420
+ struct commit *commit = (struct commit *) obj;
421
+ commit->buffer = NULL;
422
+ }
423
+ obj->flags |= FLAG_CHECKED;
424
+ }
425
+ }
426
}
427
428
static void resolve_delta(struct object_entry *delta_obj, void *base_data,
@@ -714,6 +796,8 @@ int main(int argc, char **argv)
796
from_stdin = 1;
797
} else if (!strcmp(arg, "--fix-thin")) {
798
fix_thin_pack = 1;
799
+ } else if (!strcmp(arg, "--strict")) {
800
+ strict = 1;
801
} else if (!strcmp(arg, "--keep")) {
802
keep_msg = "";
803
} else if (!prefixcmp(arg, "--keep=")) {
@@ -812,6 +896,8 @@ int main(int argc, char **argv)
896
nr_deltas - nr_resolved_deltas);
897
}
898
free(deltas);
899
+ if (strict)
900
+ check_objects();
901
902
idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));
903
for (i = 0; i < nr_objects; i++)