add object_as_type helper for casting objects
authorJeff King <peff@peff.net>
Sun, 13 Jul 2014 06:42:03 +0000 (02:42 -0400)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Jul 2014 17:14:33 +0000 (10:14 -0700)
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>
blob.c
commit.c
object.c
object.h
refs.c
tag.c
tree.c
diff --git a/blob.c b/blob.c
index 5720a38ca270b48f2dde81472cee3642f72d89f6..1fcb8e44b00f3b9eedbe92da8abe47c2bebca7c7 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -8,14 +8,7 @@ struct blob *lookup_blob(const unsigned char *sha1)
        struct object *obj = lookup_object(sha1);
        if (!obj)
                return create_object(sha1, alloc_blob_node());
-       if (!obj->type)
-               obj->type = OBJ_BLOB;
-       if (obj->type != OBJ_BLOB) {
-               error("Object %s is a %s, not a blob",
-                     sha1_to_hex(sha1), typename(obj->type));
-               return NULL;
-       }
-       return (struct blob *) obj;
+       return object_as_type(obj, OBJ_BLOB, 0);
 }
 
 int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
index eb24add86688705901ba0b71a7f025289df03c9d..65179f96eecc85082f9bf3f0312676878d92861d 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -18,19 +18,6 @@ int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
 
-static struct commit *check_commit(struct object *obj,
-                                  const unsigned char *sha1,
-                                  int quiet)
-{
-       if (obj->type != OBJ_COMMIT) {
-               if (!quiet)
-                       error("Object %s is a %s, not a commit",
-                             sha1_to_hex(sha1), typename(obj->type));
-               return NULL;
-       }
-       return (struct commit *) obj;
-}
-
 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
                                              int quiet)
 {
@@ -38,7 +25,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
 
        if (!obj)
                return NULL;
-       return check_commit(obj, sha1, quiet);
+       return object_as_type(obj, OBJ_COMMIT, quiet);
 }
 
 struct commit *lookup_commit_reference(const unsigned char *sha1)
@@ -63,9 +50,7 @@ struct commit *lookup_commit(const unsigned char *sha1)
        struct object *obj = lookup_object(sha1);
        if (!obj)
                return create_object(sha1, alloc_commit_node());
-       if (!obj->type)
-               obj->type = OBJ_COMMIT;
-       return check_commit(obj, sha1, 0);
+       return object_as_type(obj, OBJ_COMMIT, 0);
 }
 
 struct commit *lookup_commit_reference_by_name(const char *name)
index 472aa8d5befff0ebb80281fd6d69120d542d2baa..b2319f62468c76134e84c157c2035654b38e17fc 100644 (file)
--- a/object.c
+++ b/object.c
@@ -158,6 +158,23 @@ void *create_object(const unsigned char *sha1, void *o)
        return obj;
 }
 
+void *object_as_type(struct object *obj, enum object_type type, int quiet)
+{
+       if (obj->type == type)
+               return obj;
+       else if (obj->type == OBJ_NONE) {
+               obj->type = type;
+               return obj;
+       }
+       else {
+               if (!quiet)
+                       error("object %s is a %s, not a %s",
+                             sha1_to_hex(obj->sha1),
+                             typename(obj->type), typename(type));
+               return NULL;
+       }
+}
+
 struct object *lookup_unknown_object(const unsigned char *sha1)
 {
        struct object *obj = lookup_object(sha1);
index 8020ace566c9c826a907490ac57c4d5aa425c2ae..5e8d8ee5485a5825c4dc0a0bba1911061723e161 100644 (file)
--- a/object.h
+++ b/object.h
@@ -81,6 +81,8 @@ struct object *lookup_object(const unsigned char *sha1);
 
 extern void *create_object(const unsigned char *sha1, void *obj);
 
+void *object_as_type(struct object *obj, enum object_type type, int quiet);
+
 /*
  * Returns the object, having parsed it to find out what it is.
  *
diff --git a/refs.c b/refs.c
index 59fb70087a438a763cdbfb2c4e75de36d533aead..f0bd7ac0e94653ffed45b6e3418a60c3031a65c3 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1520,9 +1520,8 @@ static enum peel_status peel_object(const unsigned char *name, unsigned char *sh
 
        if (o->type == OBJ_NONE) {
                int type = sha1_object_info(name, NULL);
-               if (type < 0)
+               if (type < 0 || !object_as_type(o, type, 0))
                        return PEEL_INVALID;
-               o->type = type;
        }
 
        if (o->type != OBJ_TAG)
diff --git a/tag.c b/tag.c
index 79552c716cf63d454d6fdcd75845db91c609c92a..82d841bf2df0990f124ca9020673352124f20561 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -41,14 +41,7 @@ struct tag *lookup_tag(const unsigned char *sha1)
        struct object *obj = lookup_object(sha1);
        if (!obj)
                return create_object(sha1, alloc_tag_node());
-       if (!obj->type)
-               obj->type = OBJ_TAG;
-       if (obj->type != OBJ_TAG) {
-               error("Object %s is a %s, not a tag",
-                     sha1_to_hex(sha1), typename(obj->type));
-               return NULL;
-       }
-       return (struct tag *) obj;
+       return object_as_type(obj, OBJ_TAG, 0);
 }
 
 static unsigned long parse_tag_date(const char *buf, const char *tail)
diff --git a/tree.c b/tree.c
index ed6657507937b26c702ff322b99182c688487d50..bb02c1caa4ff6a8af40b89498de3af3381272999 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -184,14 +184,7 @@ struct tree *lookup_tree(const unsigned char *sha1)
        struct object *obj = lookup_object(sha1);
        if (!obj)
                return create_object(sha1, alloc_tree_node());
-       if (!obj->type)
-               obj->type = OBJ_TREE;
-       if (obj->type != OBJ_TREE) {
-               error("Object %s is a %s, not a tree",
-                     sha1_to_hex(sha1), typename(obj->type));
-               return NULL;
-       }
-       return (struct tree *) obj;
+       return object_as_type(obj, OBJ_TREE, 0);
 }
 
 int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)