[PATCH] compat: support pre-1.2 zlib
[alt-git.git] / fsck-cache.c
blob164fc2eaeeac42a5bbec45845d852da8104e2459
1 #include "cache.h"
3 #include <sys/types.h>
4 #include <dirent.h>
6 #include "commit.h"
7 #include "tree.h"
8 #include "blob.h"
9 #include "tag.h"
11 #define REACHABLE 0x0001
13 static int show_root = 0;
14 static int show_tags = 0;
15 static int show_unreachable = 0;
16 static unsigned char head_sha1[20];
18 static void check_connectivity(void)
20 int i;
22 /* Look up all the requirements, warn about missing objects.. */
23 for (i = 0; i < nr_objs; i++) {
24 struct object *obj = objs[i];
25 struct object_list *refs;
27 if (show_unreachable && !(obj->flags & REACHABLE)) {
28 printf("unreachable %s %s\n", obj->type, sha1_to_hex(obj->sha1));
29 continue;
32 if (!obj->parsed) {
33 printf("missing %s %s\n", obj->type,
34 sha1_to_hex(obj->sha1));
36 if (!obj->used) {
37 printf("dangling %s %s\n", obj->type,
38 sha1_to_hex(obj->sha1));
40 for (refs = obj->refs; refs; refs = refs->next) {
41 if (!refs->item->parsed) {
42 printf("broken link from %s\n",
43 sha1_to_hex(obj->sha1));
44 printf(" to %s\n",
45 sha1_to_hex(refs->item->sha1));
51 static int fsck_tree(struct tree *item)
53 if (item->has_full_path) {
54 fprintf(stderr, "warning: fsck-cache: tree %s "
55 "has full pathnames in it\n",
56 sha1_to_hex(item->object.sha1));
58 return 0;
61 static int fsck_commit(struct commit *commit)
63 if (!commit->tree)
64 return -1;
65 if (!commit->parents && show_root)
66 printf("root %s\n", sha1_to_hex(commit->object.sha1));
67 if (!commit->date)
68 printf("bad commit date in %s\n",
69 sha1_to_hex(commit->object.sha1));
70 return 0;
73 static int fsck_tag(struct tag *tag)
75 if (!show_tags)
76 return 0;
78 printf("tagged %s %s",
79 tag->tagged->type,
80 sha1_to_hex(tag->tagged->sha1));
81 printf(" (%s) in %s\n",
82 tag->tag, sha1_to_hex(tag->object.sha1));
83 return 0;
86 static int fsck_name(char *hex)
88 unsigned char sha1[20];
89 if (!get_sha1_hex(hex, sha1)) {
90 struct object *obj = parse_object(sha1);
91 if (!obj)
92 return -1;
93 if (obj->type == blob_type)
94 return 0;
95 if (obj->type == tree_type)
96 return fsck_tree((struct tree *) obj);
97 if (obj->type == commit_type)
98 return fsck_commit((struct commit *) obj);
99 if (obj->type == tag_type)
100 return fsck_tag((struct tag *) obj);
102 return -1;
105 static int fsck_dir(int i, char *path)
107 DIR *dir = opendir(path);
108 struct dirent *de;
110 if (!dir) {
111 return error("missing sha1 directory '%s'", path);
114 while ((de = readdir(dir)) != NULL) {
115 char name[100];
116 int len = strlen(de->d_name);
118 switch (len) {
119 case 2:
120 if (de->d_name[1] != '.')
121 break;
122 case 1:
123 if (de->d_name[0] != '.')
124 break;
125 continue;
126 case 38:
127 sprintf(name, "%02x", i);
128 memcpy(name+2, de->d_name, len+1);
129 if (!fsck_name(name))
130 continue;
132 fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
134 closedir(dir);
135 return 0;
138 int main(int argc, char **argv)
140 int i, heads;
141 char *sha1_dir;
143 for (i = 1; i < argc; i++) {
144 const char *arg = argv[i];
146 if (!strcmp(arg, "--unreachable")) {
147 show_unreachable = 1;
148 continue;
150 if (!strcmp(arg, "--tags")) {
151 show_tags = 1;
152 continue;
154 if (!strcmp(arg, "--root")) {
155 show_root = 1;
156 continue;
158 if (*arg == '-')
159 usage("fsck-cache [--tags] [[--unreachable] <head-sha1>*]");
162 sha1_dir = getenv(DB_ENVIRONMENT) ? : DEFAULT_DB_ENVIRONMENT;
163 for (i = 0; i < 256; i++) {
164 static char dir[4096];
165 sprintf(dir, "%s/%02x", sha1_dir, i);
166 fsck_dir(i, dir);
169 heads = 0;
170 for (i = 1; i < argc; i++) {
171 const char *arg = argv[i];
173 if (*arg == '-')
174 continue;
176 if (!get_sha1_hex(arg, head_sha1)) {
177 struct commit *commit = lookup_commit(head_sha1);
178 struct object *obj;
180 /* Error is printed by lookup_commit(). */
181 if (!commit)
182 continue;
184 obj = &commit->object;
185 obj->used = 1;
186 mark_reachable(obj, REACHABLE);
187 heads++;
188 continue;
190 error("expected sha1, got %s", arg);
193 if (!heads) {
194 if (show_unreachable) {
195 fprintf(stderr, "unable to do reachability without a head\n");
196 show_unreachable = 0;
198 fprintf(stderr, "expect dangling commits - potential heads - due to lack of head information\n");
201 check_connectivity();
202 return 0;