SubmittingPatches: explain rationale for using --notes with format-patch
[gitweb.git] / object.c
index 57a0890a87b66ea493337409606e57fd44d29f90..23d6c9671904cfe273fc16de8a4d2db56b91c3b4 100644 (file)
--- a/object.c
+++ b/object.c
@@ -33,13 +33,20 @@ const char *typename(unsigned int type)
        return object_type_strings[type];
 }
 
-int type_from_string(const char *str)
+int type_from_string_gently(const char *str, ssize_t len, int gentle)
 {
        int i;
 
+       if (len < 0)
+               len = strlen(str);
+
        for (i = 1; i < ARRAY_SIZE(object_type_strings); i++)
-               if (!strcmp(str, object_type_strings[i]))
+               if (!strncmp(str, object_type_strings[i], len))
                        return i;
+
+       if (gentle)
+               return -1;
+
        die("invalid object type \"%s\"", str);
 }
 
@@ -50,18 +57,7 @@ int type_from_string(const char *str)
  */
 static unsigned int hash_obj(const unsigned char *sha1, unsigned int n)
 {
-       unsigned int hash;
-
-       /*
-        * Since the sha1 is essentially random, we just take the
-        * required number of bits directly from the first
-        * sizeof(unsigned int) bytes of sha1.  First we have to copy
-        * the bytes into a properly aligned integer.  If we cared
-        * about getting consistent results across architectures, we
-        * would have to call ntohl() here, too.
-        */
-       memcpy(&hash, sha1, sizeof(unsigned int));
-       return hash & (n - 1);
+       return sha1hash(sha1) & (n - 1);
 }
 
 /*
@@ -141,13 +137,12 @@ static void grow_object_hash(void)
        obj_hash_size = new_hash_size;
 }
 
-void *create_object(const unsigned char *sha1, int type, void *o)
+void *create_object(const unsigned char *sha1, void *o)
 {
        struct object *obj = o;
 
        obj->parsed = 0;
        obj->used = 0;
-       obj->type = type;
        obj->flags = 0;
        hashcpy(obj->sha1, sha1);
 
@@ -159,11 +154,30 @@ void *create_object(const unsigned char *sha1, int type, 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) {
+               if (type == OBJ_COMMIT)
+                       ((struct commit *)obj)->index = alloc_commit_index();
+               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);
        if (!obj)
-               obj = create_object(sha1, OBJ_NONE, alloc_object_node());
+               obj = create_object(sha1, alloc_object_node());
        return obj;
 }
 
@@ -197,8 +211,8 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
                if (commit) {
                        if (parse_commit_buffer(commit, buffer, size))
                                return NULL;
-                       if (!commit->buffer) {
-                               commit->buffer = buffer;
+                       if (!get_cached_commit_buffer(commit, NULL)) {
+                               set_commit_buffer(commit, buffer, size);
                                *eaten_p = 1;
                        }
                        obj = &commit->object;
@@ -214,8 +228,6 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
                warning("object %s has unknown type id %d", sha1_to_hex(sha1), type);
                obj = NULL;
        }
-       if (obj && obj->type == OBJ_NONE)
-               obj->type = type;
        return obj;
 }
 
@@ -295,10 +307,9 @@ int object_list_contains(struct object_list *list, struct object *obj)
  */
 static char object_array_slopbuf[1];
 
-static void add_object_array_with_mode_context(struct object *obj, const char *name,
-                                              struct object_array *array,
-                                              unsigned mode,
-                                              struct object_context *context)
+void add_object_array_with_path(struct object *obj, const char *name,
+                               struct object_array *array,
+                               unsigned mode, const char *path)
 {
        unsigned nr = array->nr;
        unsigned alloc = array->alloc;
@@ -307,7 +318,7 @@ static void add_object_array_with_mode_context(struct object *obj, const char *n
 
        if (nr >= alloc) {
                alloc = (alloc + 32) * 2;
-               objects = xrealloc(objects, alloc * sizeof(*objects));
+               REALLOC_ARRAY(objects, alloc);
                array->alloc = alloc;
                array->objects = objects;
        }
@@ -321,26 +332,27 @@ static void add_object_array_with_mode_context(struct object *obj, const char *n
        else
                entry->name = xstrdup(name);
        entry->mode = mode;
-       entry->context = context;
+       if (path)
+               entry->path = xstrdup(path);
+       else
+               entry->path = NULL;
        array->nr = ++nr;
 }
 
 void add_object_array(struct object *obj, const char *name, struct object_array *array)
 {
-       add_object_array_with_mode(obj, name, array, S_IFINVALID);
+       add_object_array_with_path(obj, name, array, S_IFINVALID, NULL);
 }
 
-void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode)
-{
-       add_object_array_with_mode_context(obj, name, array, mode, NULL);
-}
-
-void add_object_array_with_context(struct object *obj, const char *name, struct object_array *array, struct object_context *context)
+/*
+ * Free all memory associated with an entry; the result is
+ * in an unspecified state and should not be examined.
+ */
+static void object_array_release_entry(struct object_array_entry *ent)
 {
-       if (context)
-               add_object_array_with_mode_context(obj, name, array, context->mode, context);
-       else
-               add_object_array_with_mode_context(obj, name, array, S_IFINVALID, context);
+       if (ent->name != object_array_slopbuf)
+               free(ent->name);
+       free(ent->path);
 }
 
 void object_array_filter(struct object_array *array,
@@ -355,13 +367,22 @@ void object_array_filter(struct object_array *array,
                                objects[dst] = objects[src];
                        dst++;
                } else {
-                       if (objects[src].name != object_array_slopbuf)
-                               free(objects[src].name);
+                       object_array_release_entry(&objects[src]);
                }
        }
        array->nr = dst;
 }
 
+void object_array_clear(struct object_array *array)
+{
+       int i;
+       for (i = 0; i < array->nr; i++)
+               object_array_release_entry(&array->objects[i]);
+       free(array->objects);
+       array->objects = NULL;
+       array->nr = array->alloc = 0;
+}
+
 /*
  * Return true iff array already contains an entry with name.
  */
@@ -388,8 +409,7 @@ void object_array_remove_duplicates(struct object_array *array)
                                objects[array->nr] = objects[src];
                        array->nr++;
                } else {
-                       if (objects[src].name != object_array_slopbuf)
-                               free(objects[src].name);
+                       object_array_release_entry(&objects[src]);
                }
        }
 }