Merge branch 'sb/parse-object-buffer-eaten'
authorJunio C Hamano <gitster@pobox.com>
Mon, 22 Jul 2013 18:23:32 +0000 (11:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Jul 2013 18:23:33 +0000 (11:23 -0700)
* sb/parse-object-buffer-eaten:
  parse_object_buffer: correct freeing the buffer

1  2 
object.c

diff --combined object.c
+++ b/object.c
@@@ -71,13 -71,13 +71,13 @@@ static unsigned int hashtable_index(con
  
  struct object *lookup_object(const unsigned char *sha1)
  {
 -      unsigned int i;
 +      unsigned int i, first;
        struct object *obj;
  
        if (!obj_hash)
                return NULL;
  
 -      i = hashtable_index(sha1);
 +      first = i = hashtable_index(sha1);
        while ((obj = obj_hash[i]) != NULL) {
                if (!hashcmp(sha1, obj->sha1))
                        break;
                if (i == obj_hash_size)
                        i = 0;
        }
 +      if (obj && i != first) {
 +              /*
 +               * Move object to where we started to look for it so
 +               * that we do not need to walk the hash table the next
 +               * time we look for it.
 +               */
 +              struct object *tmp = obj_hash[i];
 +              obj_hash[i] = obj_hash[first];
 +              obj_hash[first] = tmp;
 +      }
        return obj;
  }
  
@@@ -145,7 -135,7 +145,7 @@@ struct object *lookup_unknown_object(co
  struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p)
  {
        struct object *obj;
-       int eaten = 0;
+       *eaten_p = 0;
  
        obj = NULL;
        if (type == OBJ_BLOB) {
                        if (!tree->object.parsed) {
                                if (parse_tree_buffer(tree, buffer, size))
                                        return NULL;
-                               eaten = 1;
+                               *eaten_p = 1;
                        }
                }
        } else if (type == OBJ_COMMIT) {
                                return NULL;
                        if (!commit->buffer) {
                                commit->buffer = buffer;
-                               eaten = 1;
+                               *eaten_p = 1;
                        }
                        obj = &commit->object;
                }
        }
        if (obj && obj->type == OBJ_NONE)
                obj->type = type;
-       *eaten_p = eaten;
        return obj;
  }
  
 +struct object *parse_object_or_die(const unsigned char *sha1,
 +                                 const char *name)
 +{
 +      struct object *o = parse_object(sha1);
 +      if (o)
 +              return o;
 +
 +      die(_("unable to parse object: %s"), name ? name : sha1_to_hex(sha1));
 +}
 +
  struct object *parse_object(const unsigned char *sha1)
  {
        unsigned long size;
@@@ -270,18 -249,11 +269,18 @@@ void add_object_array(struct object *ob
        add_object_array_with_mode(obj, name, array, S_IFINVALID);
  }
  
 +/*
 + * A zero-length string to which object_array_entry::name can be
 + * initialized without requiring a malloc/free.
 + */
 +static char object_array_slopbuf[1];
 +
  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;
        struct object_array_entry *objects = array->objects;
 +      struct object_array_entry *entry;
  
        if (nr >= alloc) {
                alloc = (alloc + 32) * 2;
                array->alloc = alloc;
                array->objects = objects;
        }
 -      objects[nr].item = obj;
 -      objects[nr].name = name;
 -      objects[nr].mode = mode;
 +      entry = &objects[nr];
 +      entry->item = obj;
 +      if (!name)
 +              entry->name = NULL;
 +      else if (!*name)
 +              /* Use our own empty string instead of allocating one: */
 +              entry->name = object_array_slopbuf;
 +      else
 +              entry->name = xstrdup(name);
 +      entry->mode = mode;
        array->nr = ++nr;
  }
  
 -void object_array_remove_duplicates(struct object_array *array)
 +void object_array_filter(struct object_array *array,
 +                       object_array_each_func_t want, void *cb_data)
  {
 -      unsigned int ref, src, dst;
 +      unsigned nr = array->nr, 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;
 +      for (src = dst = 0; src < nr; src++) {
 +              if (want(&objects[src], cb_data)) {
                        if (src != dst)
                                objects[dst] = objects[src];
                        dst++;
 +              } else {
 +                      if (objects[src].name != object_array_slopbuf)
 +                              free(objects[src].name);
 +              }
 +      }
 +      array->nr = dst;
 +}
 +
 +/*
 + * Return true iff array already contains an entry with name.
 + */
 +static int contains_name(struct object_array *array, const char *name)
 +{
 +      unsigned nr = array->nr, i;
 +      struct object_array_entry *object = array->objects;
 +
 +      for (i = 0; i < nr; i++, object++)
 +              if (!strcmp(object->name, name))
 +                      return 1;
 +      return 0;
 +}
 +
 +void object_array_remove_duplicates(struct object_array *array)
 +{
 +      unsigned nr = array->nr, src;
 +      struct object_array_entry *objects = array->objects;
 +
 +      array->nr = 0;
 +      for (src = 0; src < nr; src++) {
 +              if (!contains_name(array, objects[src].name)) {
 +                      if (src != array->nr)
 +                              objects[array->nr] = objects[src];
 +                      array->nr++;
 +              } else {
 +                      if (objects[src].name != object_array_slopbuf)
 +                              free(objects[src].name);
                }
 -              array->nr = dst;
        }
  }