Update the merge scripts for the big git rename.
[git/git.git] / fsck-cache.c
1 #include "cache.h"
2
3 #include <sys/types.h>
4 #include <dirent.h>
5
6 #include "commit.h"
7 #include "tree.h"
8 #include "blob.h"
9 #include "tag.h"
10
11 #define REACHABLE 0x0001
12
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];
17
18 static void check_connectivity(void)
19 {
20 int i;
21
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;
26
27 if (show_unreachable && !(obj->flags & REACHABLE)) {
28 printf("unreachable %s %s\n", obj->type, sha1_to_hex(obj->sha1));
29 continue;
30 }
31
32 if (!obj->parsed) {
33 printf("missing %s %s\n", obj->type,
34 sha1_to_hex(obj->sha1));
35 }
36 if (!obj->used) {
37 printf("dangling %s %s\n", obj->type,
38 sha1_to_hex(obj->sha1));
39 }
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));
46 }
47 }
48 }
49 }
50
51 static int fsck_tree(struct tree *item)
52 {
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));
57 }
58 return 0;
59 }
60
61 static int fsck_commit(struct commit *commit)
62 {
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;
71 }
72
73 static int fsck_tag(struct tag *tag)
74 {
75 if (!show_tags)
76 return 0;
77
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;
84 }
85
86 static int fsck_name(char *hex)
87 {
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);
101 }
102 return -1;
103 }
104
105 static int fsck_dir(int i, char *path)
106 {
107 DIR *dir = opendir(path);
108 struct dirent *de;
109
110 if (!dir) {
111 return error("missing sha1 directory '%s'", path);
112 }
113
114 while ((de = readdir(dir)) != NULL) {
115 char name[100];
116 int len = strlen(de->d_name);
117
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;
131 }
132 fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
133 }
134 closedir(dir);
135 return 0;
136 }
137
138 int main(int argc, char **argv)
139 {
140 int i, heads;
141 char *sha1_dir;
142
143 for (i = 1; i < argc; i++) {
144 const char *arg = argv[i];
145
146 if (!strcmp(arg, "--unreachable")) {
147 show_unreachable = 1;
148 continue;
149 }
150 if (!strcmp(arg, "--tags")) {
151 show_tags = 1;
152 continue;
153 }
154 if (!strcmp(arg, "--root")) {
155 show_root = 1;
156 continue;
157 }
158 if (*arg == '-')
159 usage("fsck-cache [--tags] [[--unreachable] <head-sha1>*]");
160 }
161
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);
167 }
168
169 heads = 0;
170 for (i = 1; i < argc; i++) {
171 const char *arg = argv[i];
172
173 if (*arg == '-')
174 continue;
175
176 if (!get_sha1_hex(arg, head_sha1)) {
177 struct object *obj = &lookup_commit(head_sha1)->object;
178 obj->used = 1;
179 mark_reachable(obj, REACHABLE);
180 heads++;
181 continue;
182 }
183 error("expected sha1, got %s", arg);
184 }
185
186 if (!heads) {
187 if (show_unreachable) {
188 fprintf(stderr, "unable to do reachability without a head\n");
189 show_unreachable = 0;
190 }
191 fprintf(stderr, "expect dangling commits - potential heads - due to lack of head information\n");
192 }
193
194 check_connectivity();
195 return 0;
196 }