[PATCH] Rename and extend read_tree_with_tree_or_commit_sha1
[git/git.git] / fsck-cache.c
CommitLineData
20222118
LT
1#include "cache.h"
2
3#include <sys/types.h>
4#include <dirent.h>
5
ff5ebe39
DB
6#include "commit.h"
7#include "tree.h"
8#include "blob.h"
c418eda4 9#include "tag.h"
ff5ebe39
DB
10
11#define REACHABLE 0x0001
d9839e03 12
ab7df187 13static int show_root = 0;
889262ea 14static int show_tags = 0;
d9839e03 15static int show_unreachable = 0;
d9839e03
LT
16static unsigned char head_sha1[20];
17
8ba0bbb2
LT
18static void check_connectivity(void)
19{
20 int i;
21
8ba0bbb2 22 /* Look up all the requirements, warn about missing objects.. */
ff5ebe39
DB
23 for (i = 0; i < nr_objs; i++) {
24 struct object *obj = objs[i];
c418eda4 25 struct object_list *refs;
8ba0bbb2 26
ff5ebe39 27 if (show_unreachable && !(obj->flags & REACHABLE)) {
f43b8abc 28 printf("unreachable %s %s\n", obj->type, sha1_to_hex(obj->sha1));
8ba0bbb2 29 continue;
d9839e03 30 }
8ba0bbb2 31
ff5ebe39
DB
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));
d9839e03 39 }
c418eda4
DB
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 }
8ba0bbb2
LT
48 }
49}
50
c418eda4 51static int fsck_tree(struct tree *item)
20222118 52{
ff5ebe39
DB
53 if (item->has_full_path) {
54 fprintf(stderr, "warning: fsck-cache: tree %s "
c418eda4
DB
55 "has full pathnames in it\n",
56 sha1_to_hex(item->object.sha1));
1ea34e36 57 }
59c1e249 58 return 0;
1ea34e36
LT
59}
60
c418eda4 61static int fsck_commit(struct commit *commit)
1ea34e36 62{
ff5ebe39 63 if (!commit->tree)
1ea34e36 64 return -1;
ab7df187 65 if (!commit->parents && show_root)
c418eda4 66 printf("root %s\n", sha1_to_hex(commit->object.sha1));
e6948b6d 67 if (!commit->date)
c418eda4
DB
68 printf("bad commit date in %s\n",
69 sha1_to_hex(commit->object.sha1));
4728b861
LT
70 return 0;
71}
72
c418eda4 73static int fsck_tag(struct tag *tag)
ec4465ad 74{
889262ea
LT
75 if (!show_tags)
76 return 0;
77
c418eda4
DB
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));
ff5ebe39 83 return 0;
20222118
LT
84}
85
86static int fsck_name(char *hex)
87{
88 unsigned char sha1[20];
89 if (!get_sha1_hex(hex, sha1)) {
c418eda4
DB
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);
20222118
LT
101 }
102 return -1;
103}
104
105static int fsck_dir(int i, char *path)
106{
107 DIR *dir = opendir(path);
108 struct dirent *de;
109
110 if (!dir) {
2de381f9 111 return error("missing sha1 directory '%s'", path);
20222118
LT
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
138int main(int argc, char **argv)
139{
bcee6fd8 140 int i, heads;
20222118
LT
141 char *sha1_dir;
142
889262ea
LT
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 }
ab7df187
LT
154 if (!strcmp(arg, "--root")) {
155 show_root = 1;
156 continue;
157 }
889262ea
LT
158 if (*arg == '-')
159 usage("fsck-cache [--tags] [[--unreachable] <head-sha1>*]");
160 }
161
bcee6fd8
LT
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;
d9839e03 170 for (i = 1; i < argc; i++) {
889262ea
LT
171 const char *arg = argv[i];
172
173 if (*arg == '-')
d9839e03 174 continue;
889262ea
LT
175
176 if (!get_sha1_hex(arg, head_sha1)) {
b51ad431 177 struct object *obj = &lookup_commit(head_sha1)->object;
ff5ebe39
DB
178 obj->used = 1;
179 mark_reachable(obj, REACHABLE);
bcee6fd8 180 heads++;
d9839e03
LT
181 continue;
182 }
889262ea 183 error("expected sha1, got %s", arg);
d9839e03 184 }
d9839e03 185
bcee6fd8
LT
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");
20222118 192 }
bcee6fd8 193
8ba0bbb2 194 check_connectivity();
20222118
LT
195 return 0;
196}