Skip to content

Commit

Permalink
add object_as_type helper for casting objects
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
peff authored and gitster committed Jul 14, 2014
1 parent 5af01ca commit 8ff226a
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 43 deletions.
9 changes: 1 addition & 8 deletions blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 2 additions & 17 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,14 @@ 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)
{
struct object *obj = deref_tag(parse_object(sha1), NULL, 0);

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)
Expand All @@ -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)
Expand Down
17 changes: 17 additions & 0 deletions object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
3 changes: 1 addition & 2 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1531,9 +1531,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)
Expand Down
9 changes: 1 addition & 8 deletions tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 1 addition & 8 deletions tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 8ff226a

Please sign in to comment.