blob: cc09143a92a64a0d7e14fb7195cd39c05bb0b49f [file] [log] [blame]
Linus Torvalds20222112005-04-08 15:02:42 -07001#include <sys/types.h>
2#include <dirent.h>
3
Linus Torvalds4b182422005-04-30 09:59:31 -07004#include "cache.h"
Daniel Barkalowff5ebe32005-04-18 11:39:48 -07005#include "commit.h"
6#include "tree.h"
7#include "blob.h"
Daniel Barkalowc418eda2005-04-28 07:46:33 -07008#include "tag.h"
Linus Torvalds944d8582005-07-03 10:01:38 -07009#include "refs.h"
Junio C Hamanof9253392005-06-29 02:51:27 -070010#include "pack.h"
Junio C Hamano53dc3f32006-04-25 16:37:08 -070011#include "cache-tree.h"
Daniel Barkalowff5ebe32005-04-18 11:39:48 -070012
13#define REACHABLE 0x0001
Linus Torvaldsd9839e02005-04-13 09:57:30 -070014
Linus Torvaldsab7df182005-04-25 16:34:13 -070015static int show_root = 0;
Linus Torvalds889262e2005-04-25 16:31:13 -070016static int show_tags = 0;
Linus Torvaldsd9839e02005-04-13 09:57:30 -070017static int show_unreachable = 0;
Junio C Hamano8a498a02005-06-28 14:58:33 -070018static int check_full = 0;
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -070019static int check_strict = 0;
Junio C Hamano7aaa7152006-03-09 01:44:19 -080020static int keep_cache_objects = 0;
Linus Torvaldsd9839e02005-04-13 09:57:30 -070021static unsigned char head_sha1[20];
22
Timo Hirvonen962554c2006-02-26 17:13:46 +020023#ifdef NO_D_INO_IN_DIRENT
Junio C Hamano35a730f2006-01-19 17:13:51 -080024#define SORT_DIRENT 0
25#define DIRENT_SORT_HINT(de) 0
26#else
27#define SORT_DIRENT 1
28#define DIRENT_SORT_HINT(de) ((de)->d_ino)
29#endif
Petr Baudisf1f0d082005-09-20 20:56:05 +020030
31static void objreport(struct object *obj, const char *severity,
32 const char *err, va_list params)
33{
34 fprintf(stderr, "%s in %s %s: ",
35 severity, obj->type, sha1_to_hex(obj->sha1));
36 vfprintf(stderr, err, params);
37 fputs("\n", stderr);
38}
39
Peter Hagervalla7928f82005-09-28 14:04:54 +020040static int objerror(struct object *obj, const char *err, ...)
Petr Baudisf1f0d082005-09-20 20:56:05 +020041{
42 va_list params;
43 va_start(params, err);
44 objreport(obj, "error", err, params);
45 va_end(params);
46 return -1;
47}
48
Peter Hagervalla7928f82005-09-28 14:04:54 +020049static int objwarning(struct object *obj, const char *err, ...)
Petr Baudisf1f0d082005-09-20 20:56:05 +020050{
51 va_list params;
52 va_start(params, err);
53 objreport(obj, "warning", err, params);
54 va_end(params);
55 return -1;
56}
57
58
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -070059static void check_connectivity(void)
60{
61 int i;
62
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -070063 /* Look up all the requirements, warn about missing objects.. */
Johannes Schindelin070879c2006-02-12 02:57:57 +010064 for (i = 0; i < obj_allocs; i++) {
Daniel Barkalowff5ebe32005-04-18 11:39:48 -070065 struct object *obj = objs[i];
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -070066
Johannes Schindelin070879c2006-02-12 02:57:57 +010067 if (!obj)
68 continue;
69
Linus Torvalds3a6a23e2005-04-30 11:22:26 -070070 if (!obj->parsed) {
Junio C Hamano7aaa7152006-03-09 01:44:19 -080071 if (has_sha1_file(obj->sha1))
Junio C Hamano8a498a02005-06-28 14:58:33 -070072 ; /* it is in pack */
73 else
74 printf("missing %s %s\n",
75 obj->type, sha1_to_hex(obj->sha1));
Linus Torvalds3a6a23e2005-04-30 11:22:26 -070076 continue;
77 }
78
Sergey Vlasov4a4e6fd2005-11-15 19:08:08 +030079 if (obj->refs) {
80 const struct object_refs *refs = obj->refs;
81 unsigned j;
82 for (j = 0; j < refs->count; j++) {
83 struct object *ref = refs->ref[j];
84 if (ref->parsed ||
Junio C Hamano7aaa7152006-03-09 01:44:19 -080085 (has_sha1_file(ref->sha1)))
Sergey Vlasov4a4e6fd2005-11-15 19:08:08 +030086 continue;
87 printf("broken link from %7s %s\n",
88 obj->type, sha1_to_hex(obj->sha1));
89 printf(" to %7s %s\n",
90 ref->type, sha1_to_hex(ref->sha1));
91 }
Linus Torvalds3a6a23e2005-04-30 11:22:26 -070092 }
93
Daniel Barkalowff5ebe32005-04-18 11:39:48 -070094 if (show_unreachable && !(obj->flags & REACHABLE)) {
Junio C Hamanoc4584ae2005-06-27 03:33:33 -070095 printf("unreachable %s %s\n",
96 obj->type, sha1_to_hex(obj->sha1));
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -070097 continue;
Linus Torvaldsd9839e02005-04-13 09:57:30 -070098 }
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -070099
Daniel Barkalowff5ebe32005-04-18 11:39:48 -0700100 if (!obj->used) {
101 printf("dangling %s %s\n", obj->type,
102 sha1_to_hex(obj->sha1));
Linus Torvaldsd9839e02005-04-13 09:57:30 -0700103 }
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -0700104 }
105}
106
Linus Torvalds85003492005-05-02 16:13:18 -0700107/*
108 * The entries in a tree are ordered in the _path_ order,
109 * which means that a directory entry is ordered by adding
110 * a slash to the end of it.
111 *
112 * So a directory called "a" is ordered _after_ a file
113 * called "a.c", because "a/" sorts after "a.c".
114 */
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700115#define TREE_UNORDERED (-1)
116#define TREE_HAS_DUPS (-2)
117
Linus Torvalds85003492005-05-02 16:13:18 -0700118static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b)
119{
120 int len1 = strlen(a->name);
121 int len2 = strlen(b->name);
122 int len = len1 < len2 ? len1 : len2;
123 unsigned char c1, c2;
124 int cmp;
125
126 cmp = memcmp(a->name, b->name, len);
127 if (cmp < 0)
128 return 0;
129 if (cmp > 0)
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700130 return TREE_UNORDERED;
Linus Torvalds85003492005-05-02 16:13:18 -0700131
132 /*
133 * Ok, the first <len> characters are the same.
134 * Now we need to order the next one, but turn
135 * a '\0' into a '/' for a directory entry.
136 */
137 c1 = a->name[len];
138 c2 = b->name[len];
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700139 if (!c1 && !c2)
140 /*
141 * git-write-tree used to write out a nonsense tree that has
142 * entries with the same name, one blob and one tree. Make
143 * sure we do not have duplicate entries.
144 */
145 return TREE_HAS_DUPS;
Linus Torvalds85003492005-05-02 16:13:18 -0700146 if (!c1 && a->directory)
147 c1 = '/';
148 if (!c2 && b->directory)
149 c2 = '/';
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700150 return c1 < c2 ? 0 : TREE_UNORDERED;
Linus Torvalds85003492005-05-02 16:13:18 -0700151}
152
Daniel Barkalowc418eda2005-04-28 07:46:33 -0700153static int fsck_tree(struct tree *item)
Linus Torvalds1ea34e32005-04-08 17:11:14 -0700154{
Linus Torvalds64071802005-07-27 16:08:43 -0700155 int retval;
Linus Torvalds85003492005-05-02 16:13:18 -0700156 int has_full_path = 0;
Linus Torvalds64071802005-07-27 16:08:43 -0700157 int has_zero_pad = 0;
158 int has_bad_modes = 0;
159 int has_dup_entries = 0;
160 int not_properly_sorted = 0;
Linus Torvalds85003492005-05-02 16:13:18 -0700161 struct tree_entry_list *entry, *last;
162
163 last = NULL;
164 for (entry = item->entries; entry; entry = entry->next) {
165 if (strchr(entry->name, '/'))
166 has_full_path = 1;
Linus Torvalds64071802005-07-27 16:08:43 -0700167 has_zero_pad |= entry->zeropad;
Linus Torvalds85003492005-05-02 16:13:18 -0700168
Linus Torvalds42ea9cb2005-05-05 16:18:48 -0700169 switch (entry->mode) {
170 /*
171 * Standard modes..
172 */
173 case S_IFREG | 0755:
174 case S_IFREG | 0644:
175 case S_IFLNK:
176 case S_IFDIR:
177 break;
178 /*
179 * This is nonstandard, but we had a few of these
180 * early on when we honored the full set of mode
181 * bits..
182 */
183 case S_IFREG | 0664:
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700184 if (!check_strict)
185 break;
Linus Torvalds42ea9cb2005-05-05 16:18:48 -0700186 default:
Linus Torvalds64071802005-07-27 16:08:43 -0700187 has_bad_modes = 1;
Linus Torvalds42ea9cb2005-05-05 16:18:48 -0700188 }
189
Linus Torvalds85003492005-05-02 16:13:18 -0700190 if (last) {
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700191 switch (verify_ordered(last, entry)) {
192 case TREE_UNORDERED:
Linus Torvalds64071802005-07-27 16:08:43 -0700193 not_properly_sorted = 1;
194 break;
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700195 case TREE_HAS_DUPS:
Linus Torvalds64071802005-07-27 16:08:43 -0700196 has_dup_entries = 1;
197 break;
Junio C Hamanoa4f35a22005-05-07 14:43:32 -0700198 default:
199 break;
Linus Torvalds85003492005-05-02 16:13:18 -0700200 }
Sergey Vlasov545f2292005-11-15 19:07:15 +0300201 free(last->name);
202 free(last);
Linus Torvalds85003492005-05-02 16:13:18 -0700203 }
204
205 last = entry;
206 }
Sergey Vlasov545f2292005-11-15 19:07:15 +0300207 if (last) {
208 free(last->name);
209 free(last);
210 }
211 item->entries = NULL;
Linus Torvalds85003492005-05-02 16:13:18 -0700212
Linus Torvalds64071802005-07-27 16:08:43 -0700213 retval = 0;
Linus Torvalds85003492005-05-02 16:13:18 -0700214 if (has_full_path) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200215 objwarning(&item->object, "contains full pathnames");
Linus Torvalds1ea34e32005-04-08 17:11:14 -0700216 }
Linus Torvalds64071802005-07-27 16:08:43 -0700217 if (has_zero_pad) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200218 objwarning(&item->object, "contains zero-padded file modes");
Linus Torvalds64071802005-07-27 16:08:43 -0700219 }
220 if (has_bad_modes) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200221 objwarning(&item->object, "contains bad file modes");
Linus Torvalds64071802005-07-27 16:08:43 -0700222 }
223 if (has_dup_entries) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200224 retval = objerror(&item->object, "contains duplicate file entries");
Linus Torvalds64071802005-07-27 16:08:43 -0700225 }
226 if (not_properly_sorted) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200227 retval = objerror(&item->object, "not properly sorted");
Linus Torvalds64071802005-07-27 16:08:43 -0700228 }
229 return retval;
Linus Torvalds1ea34e32005-04-08 17:11:14 -0700230}
231
Daniel Barkalowc418eda2005-04-28 07:46:33 -0700232static int fsck_commit(struct commit *commit)
Linus Torvalds1ea34e32005-04-08 17:11:14 -0700233{
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700234 char *buffer = commit->buffer;
Petr Baudisf1f0d082005-09-20 20:56:05 +0200235 unsigned char tree_sha1[20], sha1[20];
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700236
237 if (memcmp(buffer, "tree ", 5))
Petr Baudisf1f0d082005-09-20 20:56:05 +0200238 return objerror(&commit->object, "invalid format - expected 'tree' line");
239 if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n')
240 return objerror(&commit->object, "invalid 'tree' line format - bad sha1");
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700241 buffer += 46;
242 while (!memcmp(buffer, "parent ", 7)) {
243 if (get_sha1_hex(buffer+7, sha1) || buffer[47] != '\n')
Petr Baudisf1f0d082005-09-20 20:56:05 +0200244 return objerror(&commit->object, "invalid 'parent' line format - bad sha1");
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700245 buffer += 48;
246 }
247 if (memcmp(buffer, "author ", 7))
Petr Baudisf1f0d082005-09-20 20:56:05 +0200248 return objerror(&commit->object, "invalid format - expected 'author' line");
Linus Torvaldsbd1e17e2005-05-25 19:26:28 -0700249 free(commit->buffer);
250 commit->buffer = NULL;
Daniel Barkalowff5ebe32005-04-18 11:39:48 -0700251 if (!commit->tree)
Petr Baudisf1f0d082005-09-20 20:56:05 +0200252 return objerror(&commit->object, "could not load commit's tree %s", tree_sha1);
Linus Torvaldsab7df182005-04-25 16:34:13 -0700253 if (!commit->parents && show_root)
Daniel Barkalowc418eda2005-04-28 07:46:33 -0700254 printf("root %s\n", sha1_to_hex(commit->object.sha1));
Linus Torvaldse6948b62005-04-24 16:20:53 -0700255 if (!commit->date)
Daniel Barkalowc418eda2005-04-28 07:46:33 -0700256 printf("bad commit date in %s\n",
257 sha1_to_hex(commit->object.sha1));
Linus Torvalds59c1e242005-04-09 00:25:22 -0700258 return 0;
Linus Torvalds1ea34e32005-04-08 17:11:14 -0700259}
260
Daniel Barkalowc418eda2005-04-28 07:46:33 -0700261static int fsck_tag(struct tag *tag)
Linus Torvalds4728b862005-04-24 14:10:55 -0700262{
Linus Torvalds92d4c852005-05-03 07:57:56 -0700263 struct object *tagged = tag->tagged;
264
265 if (!tagged) {
Petr Baudisf1f0d082005-09-20 20:56:05 +0200266 return objerror(&tag->object, "could not load tagged object");
Linus Torvalds92d4c852005-05-03 07:57:56 -0700267 }
Linus Torvalds889262e2005-04-25 16:31:13 -0700268 if (!show_tags)
269 return 0;
270
Linus Torvalds92d4c852005-05-03 07:57:56 -0700271 printf("tagged %s %s", tagged->type, sha1_to_hex(tagged->sha1));
272 printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1));
Daniel Barkalowff5ebe32005-04-18 11:39:48 -0700273 return 0;
Linus Torvalds20222112005-04-08 15:02:42 -0700274}
275
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700276static int fsck_sha1(unsigned char *sha1)
Linus Torvalds20222112005-04-08 15:02:42 -0700277{
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700278 struct object *obj = parse_object(sha1);
279 if (!obj)
Petr Baudisf1f0d082005-09-20 20:56:05 +0200280 return error("%s: object not found", sha1_to_hex(sha1));
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700281 if (obj->type == blob_type)
282 return 0;
283 if (obj->type == tree_type)
284 return fsck_tree((struct tree *) obj);
285 if (obj->type == commit_type)
286 return fsck_commit((struct commit *) obj);
287 if (obj->type == tag_type)
288 return fsck_tag((struct tag *) obj);
Petr Baudisf1f0d082005-09-20 20:56:05 +0200289 /* By now, parse_object() would've returned NULL instead. */
290 return objerror(obj, "unknown type '%s' (internal fsck error)", obj->type);
Linus Torvalds20222112005-04-08 15:02:42 -0700291}
292
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700293/*
294 * This is the sorting chunk size: make it reasonably
295 * big so that we can sort well..
296 */
297#define MAX_SHA1_ENTRIES (1024)
298
299struct sha1_entry {
300 unsigned long ino;
301 unsigned char sha1[20];
302};
303
304static struct {
305 unsigned long nr;
306 struct sha1_entry *entry[MAX_SHA1_ENTRIES];
307} sha1_list;
308
309static int ino_compare(const void *_a, const void *_b)
310{
311 const struct sha1_entry *a = _a, *b = _b;
312 unsigned long ino1 = a->ino, ino2 = b->ino;
313 return ino1 < ino2 ? -1 : ino1 > ino2 ? 1 : 0;
314}
315
316static void fsck_sha1_list(void)
317{
318 int i, nr = sha1_list.nr;
319
Junio C Hamano35a730f2006-01-19 17:13:51 -0800320 if (SORT_DIRENT)
321 qsort(sha1_list.entry, nr,
322 sizeof(struct sha1_entry *), ino_compare);
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700323 for (i = 0; i < nr; i++) {
324 struct sha1_entry *entry = sha1_list.entry[i];
325 unsigned char *sha1 = entry->sha1;
326
327 sha1_list.entry[i] = NULL;
Petr Baudisf1f0d082005-09-20 20:56:05 +0200328 fsck_sha1(sha1);
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700329 free(entry);
330 }
331 sha1_list.nr = 0;
332}
333
334static void add_sha1_list(unsigned char *sha1, unsigned long ino)
335{
336 struct sha1_entry *entry = xmalloc(sizeof(*entry));
337 int nr;
338
339 entry->ino = ino;
340 memcpy(entry->sha1, sha1, 20);
341 nr = sha1_list.nr;
342 if (nr == MAX_SHA1_ENTRIES) {
343 fsck_sha1_list();
344 nr = 0;
345 }
346 sha1_list.entry[nr] = entry;
347 sha1_list.nr = ++nr;
348}
349
Linus Torvalds20222112005-04-08 15:02:42 -0700350static int fsck_dir(int i, char *path)
351{
352 DIR *dir = opendir(path);
353 struct dirent *de;
354
Linus Torvalds230f1322005-10-08 15:54:01 -0700355 if (!dir)
356 return 0;
Linus Torvalds20222112005-04-08 15:02:42 -0700357
358 while ((de = readdir(dir)) != NULL) {
359 char name[100];
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700360 unsigned char sha1[20];
Linus Torvalds20222112005-04-08 15:02:42 -0700361 int len = strlen(de->d_name);
362
363 switch (len) {
364 case 2:
365 if (de->d_name[1] != '.')
366 break;
367 case 1:
368 if (de->d_name[0] != '.')
369 break;
370 continue;
371 case 38:
372 sprintf(name, "%02x", i);
373 memcpy(name+2, de->d_name, len+1);
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700374 if (get_sha1_hex(name, sha1) < 0)
375 break;
Junio C Hamano35a730f2006-01-19 17:13:51 -0800376 add_sha1_list(sha1, DIRENT_SORT_HINT(de));
Linus Torvalds7e8c1742005-05-02 09:06:33 -0700377 continue;
Linus Torvalds20222112005-04-08 15:02:42 -0700378 }
379 fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
380 }
381 closedir(dir);
382 return 0;
383}
384
Linus Torvalds944d8582005-07-03 10:01:38 -0700385static int default_refs = 0;
386
387static int fsck_handle_ref(const char *refname, const unsigned char *sha1)
Linus Torvalds10249322005-05-18 10:16:14 -0700388{
Linus Torvalds10249322005-05-18 10:16:14 -0700389 struct object *obj;
390
Linus Torvalds10249322005-05-18 10:16:14 -0700391 obj = lookup_object(sha1);
Junio C Hamano8a498a02005-06-28 14:58:33 -0700392 if (!obj) {
Junio C Hamano7aaa7152006-03-09 01:44:19 -0800393 if (has_sha1_file(sha1)) {
Linus Torvalds659cacf2005-07-07 17:05:41 -0700394 default_refs++;
Linus Torvalds944d8582005-07-03 10:01:38 -0700395 return 0; /* it is in a pack */
Linus Torvalds659cacf2005-07-07 17:05:41 -0700396 }
Linus Torvalds944d8582005-07-03 10:01:38 -0700397 error("%s: invalid sha1 pointer %s", refname, sha1_to_hex(sha1));
398 /* We'll continue with the rest despite the error.. */
399 return 0;
Junio C Hamano8a498a02005-06-28 14:58:33 -0700400 }
Linus Torvalds944d8582005-07-03 10:01:38 -0700401 default_refs++;
Linus Torvalds10249322005-05-18 10:16:14 -0700402 obj->used = 1;
403 mark_reachable(obj, REACHABLE);
Linus Torvalds7c4d07c2005-05-20 07:49:17 -0700404 return 0;
Linus Torvalds10249322005-05-18 10:16:14 -0700405}
406
Linus Torvalds10249322005-05-18 10:16:14 -0700407static void get_default_heads(void)
408{
Linus Torvalds944d8582005-07-03 10:01:38 -0700409 for_each_ref(fsck_handle_ref);
410 if (!default_refs)
Linus Torvalds477606f2005-06-05 09:55:27 -0700411 die("No default references");
Linus Torvalds10249322005-05-18 10:16:14 -0700412}
413
Junio C Hamano8a498a02005-06-28 14:58:33 -0700414static void fsck_object_dir(const char *path)
415{
416 int i;
417 for (i = 0; i < 256; i++) {
418 static char dir[4096];
419 sprintf(dir, "%s/%02x", path, i);
420 fsck_dir(i, dir);
421 }
422 fsck_sha1_list();
423}
424
Linus Torvaldsc3330382005-07-03 10:40:38 -0700425static int fsck_head_link(void)
426{
Linus Torvaldsc3330382005-07-03 10:40:38 -0700427 unsigned char sha1[20];
Junio C Hamano8098a172005-09-30 14:26:57 -0700428 const char *git_HEAD = strdup(git_path("HEAD"));
429 const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 1);
430 int pfxlen = strlen(git_HEAD) - 4; /* strip .../.git/ part */
Linus Torvaldsc3330382005-07-03 10:40:38 -0700431
Junio C Hamano8098a172005-09-30 14:26:57 -0700432 if (!git_refs_heads_master)
433 return error("HEAD is not a symbolic ref");
434 if (strncmp(git_refs_heads_master + pfxlen, "refs/heads/", 11))
435 return error("HEAD points to something strange (%s)",
436 git_refs_heads_master + pfxlen);
437 if (!memcmp(null_sha1, sha1, 20))
Linus Torvaldsc3330382005-07-03 10:40:38 -0700438 return error("HEAD: not a valid git pointer");
439 return 0;
440}
441
Junio C Hamano53dc3f32006-04-25 16:37:08 -0700442static int fsck_cache_tree(struct cache_tree *it)
443{
444 int i;
445 int err = 0;
446
447 if (0 <= it->entry_count) {
448 struct object *obj = parse_object(it->sha1);
449 if (obj->type != tree_type)
450 err |= objerror(obj, "non-tree in cache-tree");
451 }
452 for (i = 0; i < it->subtree_nr; i++)
453 err |= fsck_cache_tree(it->down[i]->cache_tree);
454 return err;
455}
456
Linus Torvalds20222112005-04-08 15:02:42 -0700457int main(int argc, char **argv)
458{
Linus Torvaldsbcee6fd2005-04-13 16:42:09 -0700459 int i, heads;
Linus Torvalds20222112005-04-08 15:02:42 -0700460
Junio C Hamano61e2b012005-11-25 23:52:04 -0800461 setup_git_directory();
462
Linus Torvalds889262e2005-04-25 16:31:13 -0700463 for (i = 1; i < argc; i++) {
464 const char *arg = argv[i];
465
466 if (!strcmp(arg, "--unreachable")) {
467 show_unreachable = 1;
468 continue;
469 }
470 if (!strcmp(arg, "--tags")) {
471 show_tags = 1;
472 continue;
473 }
Linus Torvaldsab7df182005-04-25 16:34:13 -0700474 if (!strcmp(arg, "--root")) {
475 show_root = 1;
476 continue;
477 }
Junio C Hamanoae7c0c92005-05-04 01:33:33 -0700478 if (!strcmp(arg, "--cache")) {
479 keep_cache_objects = 1;
480 continue;
481 }
Junio C Hamano8a498a02005-06-28 14:58:33 -0700482 if (!strcmp(arg, "--full")) {
483 check_full = 1;
484 continue;
485 }
Linus Torvaldsde2eb7f2005-07-27 15:16:03 -0700486 if (!strcmp(arg, "--strict")) {
487 check_strict = 1;
488 continue;
489 }
Linus Torvalds889262e2005-04-25 16:31:13 -0700490 if (*arg == '-')
Junio C Hamano7aaa7152006-03-09 01:44:19 -0800491 usage("git-fsck-objects [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
Linus Torvalds889262e2005-04-25 16:31:13 -0700492 }
493
Linus Torvaldsc3330382005-07-03 10:40:38 -0700494 fsck_head_link();
Junio C Hamano8a498a02005-06-28 14:58:33 -0700495 fsck_object_dir(get_object_directory());
496 if (check_full) {
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700497 struct alternate_object_database *alt;
Junio C Hamano8a498a02005-06-28 14:58:33 -0700498 struct packed_git *p;
499 prepare_alt_odb();
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700500 for (alt = alt_odb_list; alt; alt = alt->next) {
Junio C Hamanoa3eb2502005-07-10 15:40:43 -0700501 char namebuf[PATH_MAX];
Junio C Hamanod5a63b92005-08-14 17:25:57 -0700502 int namelen = alt->name - alt->base;
503 memcpy(namebuf, alt->base, namelen);
Junio C Hamanoa3eb2502005-07-10 15:40:43 -0700504 namebuf[namelen - 1] = 0;
505 fsck_object_dir(namebuf);
Junio C Hamano8a498a02005-06-28 14:58:33 -0700506 }
507 prepare_packed_git();
Junio C Hamanof9253392005-06-29 02:51:27 -0700508 for (p = packed_git; p; p = p->next)
509 /* verify gives error messages itself */
Junio C Hamanof3bf9222005-06-30 17:15:39 -0700510 verify_pack(p, 0);
Junio C Hamanof9253392005-06-29 02:51:27 -0700511
Junio C Hamano8a498a02005-06-28 14:58:33 -0700512 for (p = packed_git; p; p = p->next) {
513 int num = num_packed_objects(p);
514 for (i = 0; i < num; i++) {
515 unsigned char sha1[20];
516 nth_packed_object_sha1(p, i, sha1);
Petr Baudisf1f0d082005-09-20 20:56:05 +0200517 fsck_sha1(sha1);
Junio C Hamano8a498a02005-06-28 14:58:33 -0700518 }
519 }
Linus Torvalds20222112005-04-08 15:02:42 -0700520 }
Linus Torvaldsbcee6fd2005-04-13 16:42:09 -0700521
522 heads = 0;
523 for (i = 1; i < argc; i++) {
Linus Torvalds889262e2005-04-25 16:31:13 -0700524 const char *arg = argv[i];
525
526 if (*arg == '-')
Linus Torvaldsbcee6fd2005-04-13 16:42:09 -0700527 continue;
Linus Torvalds889262e2005-04-25 16:31:13 -0700528
Linus Torvalds3c249c92005-05-01 16:36:56 -0700529 if (!get_sha1(arg, head_sha1)) {
Linus Torvalds770896e2005-05-04 17:03:09 -0700530 struct object *obj = lookup_object(head_sha1);
Jonas Fonsecae1a13882005-04-29 20:00:40 -0700531
Linus Torvalds770896e2005-05-04 17:03:09 -0700532 /* Error is printed by lookup_object(). */
533 if (!obj)
Jonas Fonsecae1a13882005-04-29 20:00:40 -0700534 continue;
535
Daniel Barkalowff5ebe32005-04-18 11:39:48 -0700536 obj->used = 1;
537 mark_reachable(obj, REACHABLE);
Linus Torvaldsbcee6fd2005-04-13 16:42:09 -0700538 heads++;
539 continue;
540 }
Petr Baudisf1f0d082005-09-20 20:56:05 +0200541 error("invalid parameter: expected sha1, got '%s'", arg);
Linus Torvaldsbcee6fd2005-04-13 16:42:09 -0700542 }
543
Linus Torvalds10249322005-05-18 10:16:14 -0700544 /*
Nicolas Pitred1af0022005-05-20 16:59:17 -0400545 * If we've not been given any explicit head information, do the
Linus Torvaldse7bd9072005-05-18 10:19:59 -0700546 * default ones from .git/refs. We also consider the index file
547 * in this case (ie this implies --cache).
Linus Torvalds10249322005-05-18 10:16:14 -0700548 */
Linus Torvaldse7bd9072005-05-18 10:19:59 -0700549 if (!heads) {
Linus Torvalds10249322005-05-18 10:16:14 -0700550 get_default_heads();
551 keep_cache_objects = 1;
552 }
553
Junio C Hamanoae7c0c92005-05-04 01:33:33 -0700554 if (keep_cache_objects) {
555 int i;
556 read_cache();
557 for (i = 0; i < active_nr; i++) {
558 struct blob *blob = lookup_blob(active_cache[i]->sha1);
559 struct object *obj;
560 if (!blob)
561 continue;
562 obj = &blob->object;
563 obj->used = 1;
564 mark_reachable(obj, REACHABLE);
565 }
Junio C Hamano53dc3f32006-04-25 16:37:08 -0700566 if (active_cache_tree)
567 fsck_cache_tree(active_cache_tree);
Junio C Hamanoae7c0c92005-05-04 01:33:33 -0700568 }
569
Linus Torvalds8ba0bbb2005-04-10 23:13:09 -0700570 check_connectivity();
Linus Torvalds20222112005-04-08 15:02:42 -0700571 return 0;
572}