8 static int show_unreachable
= 0;
9 static unsigned char head_sha1
[20];
11 static void check_connectivity(void)
15 /* Look up all the requirements, warn about missing objects.. */
16 for (i
= 0; i
< nr_revs
; i
++) {
17 struct revision
*rev
= revs
[i
];
19 if (show_unreachable
&& !(rev
->flags
& REACHABLE
)) {
20 printf("unreachable %s\n", sha1_to_hex(rev
->sha1
));
24 switch (rev
->flags
& (SEEN
| USED
)) {
26 printf("bad %s\n", sha1_to_hex(rev
->sha1
));
29 printf("missing %s\n", sha1_to_hex(rev
->sha1
));
32 printf("dangling %s\n", sha1_to_hex(rev
->sha1
));
38 static void mark_needs_sha1(unsigned char *parent
, const char * tag
, unsigned char *child
)
40 struct revision
* child_rev
= add_relationship(lookup_rev(parent
), child
);
41 child_rev
->flags
|= USED
;
44 static int mark_sha1_seen(unsigned char *sha1
, char *tag
)
46 struct revision
*rev
= lookup_rev(sha1
);
52 static int fsck_tree(unsigned char *sha1
, void *data
, unsigned long size
)
54 int warn_old_tree
= 1;
57 int len
= 1+strlen(data
);
58 unsigned char *file_sha1
= data
+ len
;
59 char *path
= strchr(data
, ' ');
61 if (size
< len
+ 20 || !path
|| sscanf(data
, "%o", &mode
) != 1)
64 /* Warn about trees that don't do the recursive thing.. */
65 if (warn_old_tree
&& strchr(path
, '/')) {
66 fprintf(stderr
, "warning: fsck-cache: tree %s has full pathnames in it\n", sha1_to_hex(sha1
));
72 mark_needs_sha1(sha1
, S_ISDIR(mode
) ? "tree" : "blob", file_sha1
);
77 static int fsck_commit(unsigned char *sha1
, void *data
, unsigned long size
)
80 unsigned char tree_sha1
[20];
81 unsigned char parent_sha1
[20];
83 if (memcmp(data
, "tree ", 5))
85 if (get_sha1_hex(data
+ 5, tree_sha1
) < 0)
87 mark_needs_sha1(sha1
, "tree", tree_sha1
);
88 data
+= 5 + 40 + 1; /* "tree " + <hex sha1> + '\n' */
90 while (!memcmp(data
, "parent ", 7)) {
91 if (get_sha1_hex(data
+ 7, parent_sha1
) < 0)
93 mark_needs_sha1(sha1
, "commit", parent_sha1
);
94 data
+= 7 + 40 + 1; /* "parent " + <hex sha1> + '\n' */
98 printf("root %s\n", sha1_to_hex(sha1
));
102 static int fsck_entry(unsigned char *sha1
, char *tag
, void *data
, unsigned long size
)
104 if (!strcmp(tag
, "blob")) {
105 /* Nothing to check */;
106 } else if (!strcmp(tag
, "tree")) {
107 if (fsck_tree(sha1
, data
, size
) < 0)
109 } else if (!strcmp(tag
, "commit")) {
110 if (fsck_commit(sha1
, data
, size
) < 0)
114 return mark_sha1_seen(sha1
, tag
);
117 static int fsck_name(char *hex
)
119 unsigned char sha1
[20];
120 if (!get_sha1_hex(hex
, sha1
)) {
121 unsigned long mapsize
;
122 void *map
= map_sha1_file(sha1
, &mapsize
);
127 if (!check_sha1_signature(sha1
, map
, mapsize
))
128 buffer
= unpack_sha1_file(map
, mapsize
, type
, &size
);
129 munmap(map
, mapsize
);
130 if (buffer
&& !fsck_entry(sha1
, type
, buffer
, size
))
137 static int fsck_dir(int i
, char *path
)
139 DIR *dir
= opendir(path
);
143 return error("missing sha1 directory '%s'", path
);
146 while ((de
= readdir(dir
)) != NULL
) {
148 int len
= strlen(de
->d_name
);
152 if (de
->d_name
[1] != '.')
155 if (de
->d_name
[0] != '.')
159 sprintf(name
, "%02x", i
);
160 memcpy(name
+2, de
->d_name
, len
+1);
161 if (!fsck_name(name
))
164 fprintf(stderr
, "bad sha1 file: %s/%s\n", path
, de
->d_name
);
170 int main(int argc
, char **argv
)
175 sha1_dir
= getenv(DB_ENVIRONMENT
) ? : DEFAULT_DB_ENVIRONMENT
;
176 for (i
= 0; i
< 256; i
++) {
177 static char dir
[4096];
178 sprintf(dir
, "%s/%02x", sha1_dir
, i
);
183 for (i
= 1; i
< argc
; i
++) {
184 if (!strcmp(argv
[i
], "--unreachable")) {
185 show_unreachable
= 1;
188 if (!get_sha1_hex(argv
[i
], head_sha1
)) {
189 mark_reachable(lookup_rev(head_sha1
));
193 error("fsck-cache [[--unreachable] <head-sha1>*]");
197 if (show_unreachable
) {
198 fprintf(stderr
, "unable to do reachability without a head\n");
199 show_unreachable
= 0;
201 fprintf(stderr
, "expect dangling commits - potential heads - due to lack of head information\n");
204 check_connectivity();