add object_as_type helper for casting objects

When we call lookup_commit, lookup_tree, etc, the logic goes something like: 1. Look for an existing object struct. If we don't have one, allocate and return a new one. 2. Double check that any object we have is the expected type (and complain and return NULL otherwise). 3. Convert an object with type OBJ_NONE (from a prior call to lookup_unknown_object) to the expected type. We can encapsulate steps 2 and 3 in a helper function which checks whether we have the expected object type, converts OBJ_NONE as appropriate, and returns the object. Not only does this shorten the code, but it also provides one central location for converting OBJ_NONE objects into objects of other types. Future patches will use that to enforce type-specific invariants. Since this is a refactoring, we would want it to behave exactly as the current code. It takes a little reasoning to see that this is the case: - for lookup_{commit,tree,etc} functions, we are just pulling steps 2 and 3 into a function that does the same thing. - for the call in peel_object, we currently only do step 3 (but we want to consolidate it with the others, as mentioned above). However, step 2 is a noop here, as the surrounding conditional makes sure we have OBJ_NONE (which we want to keep to avoid an extraneous call to sha1_object_info). - for the call in lookup_commit_reference_gently, we are currently doing step 2 but not step 3. However, step 3 is a noop here. The object we got will have just come from deref_tag, which must have figured out the type for each object in order to know when to stop peeling. Therefore the type will never be OBJ_NONE. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 13, 2014 at 02:42 UTC 8ff226a9d5ee065fe52752e6032f63cb6e4beccb
7 files changed +25 -43
blob.c
+1 -8
@@ -8,14 +8,7 @@ struct blob *lookup_blob(const unsigned char *sha1)
8 struct object *obj = lookup_object(sha1);
9 if (!obj)
10 return create_object(sha1, alloc_blob_node());
11 - if (!obj->type)
12 - obj->type = OBJ_BLOB;
13 - if (obj->type != OBJ_BLOB) {
14 - error("Object %s is a %s, not a blob",
15 - sha1_to_hex(sha1), typename(obj->type));
16 - return NULL;
17 - }
18 - return (struct blob *) obj;
11 + return object_as_type(obj, OBJ_BLOB, 0);
12 }
13
14 int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
commit.c
+2 -17
@@ -18,19 +18,6 @@ int save_commit_buffer = 1;
18
19 const char *commit_type = "commit";
20
21 -static struct commit *check_commit(struct object *obj,
22 - const unsigned char *sha1,
23 - int quiet)
24 -{
25 - if (obj->type != OBJ_COMMIT) {
26 - if (!quiet)
27 - error("Object %s is a %s, not a commit",
28 - sha1_to_hex(sha1), typename(obj->type));
29 - return NULL;
30 - }
31 - return (struct commit *) obj;
32 -}
33 -
21 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
22 int quiet)
23 {
@@ -38,7 +25,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
25
26 if (!obj)
27 return NULL;
41 - return check_commit(obj, sha1, quiet);
28 + return object_as_type(obj, OBJ_COMMIT, quiet);
29 }
30
31 struct commit *lookup_commit_reference(const unsigned char *sha1)
@@ -63,9 +50,7 @@ struct commit *lookup_commit(const unsigned char *sha1)
50 struct object *obj = lookup_object(sha1);
51 if (!obj)
52 return create_object(sha1, alloc_commit_node());
66 - if (!obj->type)
67 - obj->type = OBJ_COMMIT;
68 - return check_commit(obj, sha1, 0);
53 + return object_as_type(obj, OBJ_COMMIT, 0);
54 }
55
56 struct commit *lookup_commit_reference_by_name(const char *name)
object.c
+17
@@ -158,6 +158,23 @@ void *create_object(const unsigned char *sha1, void *o)
158 return obj;
159 }
160
161 +void *object_as_type(struct object *obj, enum object_type type, int quiet)
162 +{
163 + if (obj->type == type)
164 + return obj;
165 + else if (obj->type == OBJ_NONE) {
166 + obj->type = type;
167 + return obj;
168 + }
169 + else {
170 + if (!quiet)
171 + error("object %s is a %s, not a %s",
172 + sha1_to_hex(obj->sha1),
173 + typename(obj->type), typename(type));
174 + return NULL;
175 + }
176 +}
177 +
178 struct object *lookup_unknown_object(const unsigned char *sha1)
179 {
180 struct object *obj = lookup_object(sha1);
object.h
+2
@@ -81,6 +81,8 @@ struct object *lookup_object(const unsigned char *sha1);
81
82 extern void *create_object(const unsigned char *sha1, void *obj);
83
84 +void *object_as_type(struct object *obj, enum object_type type, int quiet);
85 +
86 /*
87 * Returns the object, having parsed it to find out what it is.
88 *
refs.c
+1 -2
@@ -1531,9 +1531,8 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh
1531
1532 if (o->type == OBJ_NONE) {
1533 int type = sha1_object_info(name, NULL);
1534 - if (type < 0)
1534 + if (type < 0 || !object_as_type(o, type, 0))
1535 return PEEL_INVALID;
1536 - o->type = type;
1536 }
1537
1538 if (o->type != OBJ_TAG)
tag.c
+1 -8
@@ -41,14 +41,7 @@ struct tag *lookup_tag(const unsigned char *sha1)
41 struct object *obj = lookup_object(sha1);
42 if (!obj)
43 return create_object(sha1, alloc_tag_node());
44 - if (!obj->type)
45 - obj->type = OBJ_TAG;
46 - if (obj->type != OBJ_TAG) {
47 - error("Object %s is a %s, not a tag",
48 - sha1_to_hex(sha1), typename(obj->type));
49 - return NULL;
50 - }
51 - return (struct tag *) obj;
44 + return object_as_type(obj, OBJ_TAG, 0);
45 }
46
47 static unsigned long parse_tag_date(const char *buf, const char *tail)
tree.c
+1 -8
@@ -184,14 +184,7 @@ struct tree *lookup_tree(const unsigned char *sha1)
184 struct object *obj = lookup_object(sha1);
185 if (!obj)
186 return create_object(sha1, alloc_tree_node());
187 - if (!obj->type)
188 - obj->type = OBJ_TREE;
189 - if (obj->type != OBJ_TREE) {
190 - error("Object %s is a %s, not a tree",
191 - sha1_to_hex(sha1), typename(obj->type));
192 - return NULL;
193 - }
194 - return (struct tree *) obj;
187 + return object_as_type(obj, OBJ_TREE, 0);
188 }
189
190 int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)