add generic, type aware object chain walker
The requirements are: * it may not crash on NULL pointers * a callback function is needed, as index-pack/unpack-objects need to do different things * the type information is needed to check the expected <-> real type and print better error messages Signed-off-by: Martin Koegler <mkoegler@auto.tuwien.ac.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Martin Koegler committed
Feb 25, 2008 at 22:46 UTC
355885d531568e144ce5c9a2f65792a3aa8b5528
4 files changed
+117
-2
Makefile
+2
-2
@@ -297,7 +297,7 @@ LIB_H = \
297
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
298
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
299
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
300
- mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
300
+ mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h fsck.h
301
302
DIFF_OBJS = \
303
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -320,7 +320,7 @@ LIB_OBJS = \
320
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
321
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
322
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
323
- transport.o bundle.o walker.o parse-options.o ws.o archive.o
323
+ transport.o bundle.o walker.o parse-options.o ws.o archive.o fsck.o
324
325
BUILTIN_OBJS = \
326
builtin-add.o \
cache.h
+1
@@ -189,6 +189,7 @@ enum object_type {
189
/* 5 for future expansion */
190
OBJ_OFS_DELTA = 6,
191
OBJ_REF_DELTA = 7,
192
+ OBJ_ANY,
193
OBJ_MAX,
194
};
195
fsck.c
new
+91
@@ -0,0 +1,91 @@
1
+#include "cache.h"
2
+#include "object.h"
3
+#include "blob.h"
4
+#include "tree.h"
5
+#include "tree-walk.h"
6
+#include "commit.h"
7
+#include "tag.h"
8
+#include "fsck.h"
9
+
10
+static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data)
11
+{
12
+ struct tree_desc desc;
13
+ struct name_entry entry;
14
+ int res = 0;
15
+
16
+ if (parse_tree(tree))
17
+ return -1;
18
+
19
+ init_tree_desc(&desc, tree->buffer, tree->size);
20
+ while (tree_entry(&desc, &entry)) {
21
+ int result;
22
+
23
+ if (S_ISGITLINK(entry.mode))
24
+ continue;
25
+ if (S_ISDIR(entry.mode))
26
+ result = walk(&lookup_tree(entry.sha1)->object, OBJ_TREE, data);
27
+ else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode))
28
+ result = walk(&lookup_blob(entry.sha1)->object, OBJ_BLOB, data);
29
+ else {
30
+ result = error("in tree %s: entry %s has bad mode %.6o\n",
31
+ sha1_to_hex(tree->object.sha1), entry.path, entry.mode);
32
+ }
33
+ if (result < 0)
34
+ return result;
35
+ if (!res)
36
+ res = result;
37
+ }
38
+ return res;
39
+}
40
+
41
+static int fsck_walk_commit(struct commit *commit, fsck_walk_func walk, void *data)
42
+{
43
+ struct commit_list *parents;
44
+ int res;
45
+ int result;
46
+
47
+ if (parse_commit(commit))
48
+ return -1;
49
+
50
+ result = walk((struct object *)commit->tree, OBJ_TREE, data);
51
+ if (result < 0)
52
+ return result;
53
+ res = result;
54
+
55
+ parents = commit->parents;
56
+ while (parents) {
57
+ result = walk((struct object *)parents->item, OBJ_COMMIT, data);
58
+ if (result < 0)
59
+ return result;
60
+ if (!res)
61
+ res = result;
62
+ parents = parents->next;
63
+ }
64
+ return res;
65
+}
66
+
67
+static int fsck_walk_tag(struct tag *tag, fsck_walk_func walk, void *data)
68
+{
69
+ if (parse_tag(tag))
70
+ return -1;
71
+ return walk(tag->tagged, OBJ_ANY, data);
72
+}
73
+
74
+int fsck_walk(struct object *obj, fsck_walk_func walk, void *data)
75
+{
76
+ if (!obj)
77
+ return -1;
78
+ switch (obj->type) {
79
+ case OBJ_BLOB:
80
+ return 0;
81
+ case OBJ_TREE:
82
+ return fsck_walk_tree((struct tree *)obj, walk, data);
83
+ case OBJ_COMMIT:
84
+ return fsck_walk_commit((struct commit *)obj, walk, data);
85
+ case OBJ_TAG:
86
+ return fsck_walk_tag((struct tag *)obj, walk, data);
87
+ default:
88
+ error("Unknown object type for %s", sha1_to_hex(obj->sha1));
89
+ return -1;
90
+ }
91
+}
fsck.h
new
+23
@@ -0,0 +1,23 @@
1
+#ifndef GIT_FSCK_H
2
+#define GIT_FSCK_H
3
+
4
+/*
5
+ * callback function for fsck_walk
6
+ * type is the expected type of the object or OBJ_ANY
7
+ * the return value is:
8
+ * 0 everything OK
9
+ * <0 error signaled and abort
10
+ * >0 error signaled and do not abort
11
+ */
12
+typedef int (*fsck_walk_func)(struct object *obj, int type, void *data);
13
+
14
+/* descend in all linked child objects
15
+ * the return value is:
16
+ * -1 error in processing the object
17
+ * <0 return value of the callback, which lead to an abort
18
+ * >0 return value of the first sigaled error >0 (in the case of no other errors)
19
+ * 0 everything OK
20
+ */
21
+int fsck_walk(struct object *obj, fsck_walk_func walk, void *data);
22
+
23
+#endif