t9010 (svn-fe): Eliminate dependency on svn perl bindings
[gitweb.git] / object.c
index ccd7dd796e6b528d5cd08a04ba9d6105086035d6..277b3ddba7dc5387cd97cb35c23d3358727898be 100644 (file)
--- a/object.c
+++ b/object.c
@@ -45,13 +45,14 @@ int type_from_string(const char *str)
 
 static unsigned int hash_obj(struct object *obj, unsigned int n)
 {
-       unsigned int hash = *(unsigned int *)obj->sha1;
+       unsigned int hash;
+       memcpy(&hash, obj->sha1, sizeof(unsigned int));
        return hash % n;
 }
 
 static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
 {
-       int j = hash_obj(obj, size);
+       unsigned int j = hash_obj(obj, size);
 
        while (hash[j]) {
                j++;
@@ -61,16 +62,16 @@ static void insert_obj_hash(struct object *obj, struct object **hash, unsigned i
        hash[j] = obj;
 }
 
-static int hashtable_index(const unsigned char *sha1)
+static unsigned int hashtable_index(const unsigned char *sha1)
 {
        unsigned int i;
        memcpy(&i, sha1, sizeof(unsigned int));
-       return (int)(i % obj_hash_size);
+       return i % obj_hash_size;
 }
 
 struct object *lookup_object(const unsigned char *sha1)
 {
-       int i;
+       unsigned int i;
        struct object *obj;
 
        if (!obj_hash)
@@ -105,11 +106,13 @@ static void grow_object_hash(void)
        obj_hash_size = new_hash_size;
 }
 
-void created_object(const unsigned char *sha1, struct object *obj)
+void *create_object(const unsigned char *sha1, int type, void *o)
 {
+       struct object *obj = o;
+
        obj->parsed = 0;
        obj->used = 0;
-       obj->type = OBJ_NONE;
+       obj->type = type;
        obj->flags = 0;
        hashcpy(obj->sha1, sha1);
 
@@ -118,25 +121,14 @@ void created_object(const unsigned char *sha1, struct object *obj)
 
        insert_obj_hash(obj, obj_hash, obj_hash_size);
        nr_objs++;
+       return obj;
 }
 
-union any_object {
-       struct object object;
-       struct commit commit;
-       struct tree tree;
-       struct blob blob;
-       struct tag tag;
-};
-
 struct object *lookup_unknown_object(const unsigned char *sha1)
 {
        struct object *obj = lookup_object(sha1);
-       if (!obj) {
-               union any_object *ret = xcalloc(1, sizeof(*ret));
-               created_object(sha1, &ret->object);
-               ret->object.type = OBJ_NONE;
-               return &ret->object;
-       }
+       if (!obj)
+               obj = create_object(sha1, OBJ_NONE, alloc_object_node());
        return obj;
 }
 
@@ -145,32 +137,48 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
        struct object *obj;
        int eaten = 0;
 
+       obj = NULL;
        if (type == OBJ_BLOB) {
                struct blob *blob = lookup_blob(sha1);
-               parse_blob_buffer(blob, buffer, size);
-               obj = &blob->object;
+               if (blob) {
+                       if (parse_blob_buffer(blob, buffer, size))
+                               return NULL;
+                       obj = &blob->object;
+               }
        } else if (type == OBJ_TREE) {
                struct tree *tree = lookup_tree(sha1);
-               obj = &tree->object;
-               if (!tree->object.parsed) {
-                       parse_tree_buffer(tree, buffer, size);
-                       eaten = 1;
+               if (tree) {
+                       obj = &tree->object;
+                       if (!tree->object.parsed) {
+                               if (parse_tree_buffer(tree, buffer, size))
+                                       return NULL;
+                               eaten = 1;
+                       }
                }
        } else if (type == OBJ_COMMIT) {
                struct commit *commit = lookup_commit(sha1);
-               parse_commit_buffer(commit, buffer, size);
-               if (!commit->buffer) {
-                       commit->buffer = buffer;
-                       eaten = 1;
+               if (commit) {
+                       if (parse_commit_buffer(commit, buffer, size))
+                               return NULL;
+                       if (!commit->buffer) {
+                               commit->buffer = buffer;
+                               eaten = 1;
+                       }
+                       obj = &commit->object;
                }
-               obj = &commit->object;
        } else if (type == OBJ_TAG) {
                struct tag *tag = lookup_tag(sha1);
-               parse_tag_buffer(tag, buffer, size);
-               obj = &tag->object;
+               if (tag) {
+                       if (parse_tag_buffer(tag, buffer, size))
+                              return NULL;
+                       obj = &tag->object;
+               }
        } else {
+               warning("object %s has unknown type id %d\n", sha1_to_hex(sha1), type);
                obj = NULL;
        }
+       if (obj && obj->type == OBJ_NONE)
+               obj->type = type;
        *eaten_p = eaten;
        return obj;
 }
@@ -180,17 +188,18 @@ struct object *parse_object(const unsigned char *sha1)
        unsigned long size;
        enum object_type type;
        int eaten;
-       void *buffer = read_sha1_file(sha1, &type, &size);
+       const unsigned char *repl;
+       void *buffer = read_sha1_file_repl(sha1, &type, &size, &repl);
 
        if (buffer) {
                struct object *obj;
-               if (check_sha1_signature(sha1, buffer, size, typename(type)) < 0) {
+               if (check_sha1_signature(repl, buffer, size, typename(type)) < 0) {
                        free(buffer);
-                       error("sha1 mismatch %s\n", sha1_to_hex(sha1));
+                       error("sha1 mismatch %s\n", sha1_to_hex(repl));
                        return NULL;
                }
 
-               obj = parse_object_buffer(sha1, type, size, buffer, &eaten);
+               obj = parse_object_buffer(repl, type, size, buffer, &eaten);
                if (!eaten)
                        free(buffer);
                return obj;
@@ -208,27 +217,6 @@ struct object_list *object_list_insert(struct object *item,
         return new_list;
 }
 
-void object_list_append(struct object *item,
-                       struct object_list **list_p)
-{
-       while (*list_p) {
-               list_p = &((*list_p)->next);
-       }
-       *list_p = xmalloc(sizeof(struct object_list));
-       (*list_p)->next = NULL;
-       (*list_p)->item = item;
-}
-
-unsigned object_list_length(struct object_list *list)
-{
-       unsigned ret = 0;
-       while (list) {
-               list = list->next;
-               ret++;
-       }
-       return ret;
-}
-
 int object_list_contains(struct object_list *list, struct object *obj)
 {
        while (list) {
@@ -240,6 +228,11 @@ int object_list_contains(struct object_list *list, struct object *obj)
 }
 
 void add_object_array(struct object *obj, const char *name, struct object_array *array)
+{
+       add_object_array_with_mode(obj, name, array, S_IFINVALID);
+}
+
+void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode)
 {
        unsigned nr = array->nr;
        unsigned alloc = array->alloc;
@@ -253,5 +246,25 @@ void add_object_array(struct object *obj, const char *name, struct object_array
        }
        objects[nr].item = obj;
        objects[nr].name = name;
+       objects[nr].mode = mode;
        array->nr = ++nr;
 }
+
+void object_array_remove_duplicates(struct object_array *array)
+{
+       unsigned int ref, src, dst;
+       struct object_array_entry *objects = array->objects;
+
+       for (ref = 0; ref + 1 < array->nr; ref++) {
+               for (src = ref + 1, dst = src;
+                    src < array->nr;
+                    src++) {
+                       if (!strcmp(objects[ref].name, objects[src].name))
+                               continue;
+                       if (src != dst)
+                               objects[dst] = objects[src];
+                       dst++;
+               }
+               array->nr = dst;
+       }
+}