Merge branch 'master' into js/merge-base
authorJunio C Hamano <junkio@cox.net>
Mon, 3 Jul 2006 10:14:32 +0000 (03:14 -0700)
committerJunio C Hamano <junkio@cox.net>
Mon, 3 Jul 2006 10:16:52 +0000 (03:16 -0700)
This is to pull in the object-hash clean-up from the master branch.

1  2 
object.c
object.h
revision.c
diff --combined object.c
index 9caba4fac857d82e12416b3d579aa4fe79722e1f,37277f94384fff1320381a370dd4d6c91a4ded2c..1c3675971599c1edfbc5752e2a56dce1a2322e7c
+++ b/object.c
@@@ -5,79 -5,97 +5,97 @@@
  #include "commit.h"
  #include "tag.h"
  
- struct object **objs;
- static int nr_objs;
- int obj_allocs;
+ static struct object **obj_hash;
+ static int nr_objs, obj_hash_size;
+ unsigned int get_max_object_index(void)
+ {
+       return obj_hash_size;
+ }
+ struct object *get_indexed_object(unsigned int idx)
+ {
+       return obj_hash[idx];
+ }
  
  const char *type_names[] = {
        "none", "blob", "tree", "commit", "bad"
  };
  
+ static unsigned int hash_obj(struct object *obj, unsigned int n)
+ {
+       unsigned int hash = *(unsigned int *)obj->sha1;
+       return hash % n;
+ }
+ static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
+ {
+       int j = hash_obj(obj, size);
+       while (hash[j]) {
+               j++;
+               if (j >= size)
+                       j = 0;
+       }
+       hash[j] = obj;
+ }
  static int hashtable_index(const unsigned char *sha1)
  {
        unsigned int i;
        memcpy(&i, sha1, sizeof(unsigned int));
-       return (int)(i % obj_allocs);
+       return (int)(i % obj_hash_size);
  }
  
- static int find_object(const unsigned char *sha1)
+ struct object *lookup_object(const unsigned char *sha1)
  {
        int i;
+       struct object *obj;
  
-       if (!objs)
-               return -1;
+       if (!obj_hash)
+               return NULL;
  
        i = hashtable_index(sha1);
-       while (objs[i]) {
-               if (memcmp(sha1, objs[i]->sha1, 20) == 0)
-                       return i;
+       while ((obj = obj_hash[i]) != NULL) {
+               if (!memcmp(sha1, obj->sha1, 20))
+                       break;
                i++;
-               if (i == obj_allocs)
+               if (i == obj_hash_size)
                        i = 0;
        }
-       return -1 - i;
+       return obj;
  }
  
- struct object *lookup_object(const unsigned char *sha1)
+ static void grow_object_hash(void)
  {
-       int pos = find_object(sha1);
-       if (pos >= 0)
-               return objs[pos];
-       return NULL;
+       int i;
+       int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
+       struct object **new_hash;
+       new_hash = calloc(new_hash_size, sizeof(struct object *));
+       for (i = 0; i < obj_hash_size; i++) {
+               struct object *obj = obj_hash[i];
+               if (!obj)
+                       continue;
+               insert_obj_hash(obj, new_hash, new_hash_size);
+       }
+       free(obj_hash);
+       obj_hash = new_hash;
+       obj_hash_size = new_hash_size;
  }
  
  void created_object(const unsigned char *sha1, struct object *obj)
  {
-       int pos;
        obj->parsed = 0;
-       memcpy(obj->sha1, sha1, 20);
-       obj->type = TYPE_NONE;
        obj->used = 0;
+       obj->type = TYPE_NONE;
+       obj->flags = 0;
+       memcpy(obj->sha1, sha1, 20);
  
-       if (obj_allocs - 1 <= nr_objs * 2) {
-               int i, count = obj_allocs;
-               obj_allocs = (obj_allocs < 32 ? 32 : 2 * obj_allocs);
-               objs = xrealloc(objs, obj_allocs * sizeof(struct object *));
-               memset(objs + count, 0, (obj_allocs - count)
-                               * sizeof(struct object *));
-               for (i = 0; i < obj_allocs; i++)
-                       if (objs[i]) {
-                               int j = find_object(objs[i]->sha1);
-                               if (j != i) {
-                                       j = -1 - j;
-                                       objs[j] = objs[i];
-                                       objs[i] = NULL;
-                               }
-                       }
-       }
-       pos = find_object(sha1);
-       if (pos >= 0)
-               die("Inserting %s twice\n", sha1_to_hex(sha1));
-       pos = -pos-1;
+       if (obj_hash_size - 1 <= nr_objs * 2)
+               grow_object_hash();
  
-       objs[pos] = obj;
+       insert_obj_hash(obj, obj_hash, obj_hash_size);
        nr_objs++;
  }
  
@@@ -217,12 -235,3 +235,12 @@@ void add_object_array(struct object *ob
        objects[nr].name = name;
        array->nr = ++nr;
  }
-       for (i = 0; i < obj_allocs; i++)
-               if (objs[i])
-                       objs[i]->flags &= ~mark;
 +
 +void clear_object_marks(unsigned mark)
 +{
 +      int i;
 +
++      for (i = 0; i < obj_hash_size; i++)
++              if (obj_hash[i])
++                      obj_hash[i]->flags &= ~mark;
 +}
diff --combined object.h
index 7ac10111c67fde71f89e4d1b93367c6ca90dd5c8,e0125e154fd970209d30138858f31ef2017651ac..d8a76ea93552e0896d4d0c1dfbf60fa01436e6f5
+++ b/object.h
@@@ -40,10 -40,11 +40,11 @@@ struct object 
  };
  
  extern int track_object_refs;
- extern int obj_allocs;
- extern struct object **objs;
  extern const char *type_names[];
  
+ extern unsigned int get_max_object_index(void);
+ extern struct object *get_indexed_object(unsigned int);
  static inline const char *typename(unsigned int type)
  {
        return type_names[type > TYPE_TAG ? TYPE_BAD : type];
@@@ -83,6 -84,4 +84,6 @@@ int object_list_contains(struct object_
  /* Object array handling .. */
  void add_object_array(struct object *obj, const char *name, struct object_array *array);
  
 +void clear_object_marks(unsigned);
 +
  #endif /* OBJECT_H */
diff --combined revision.c
index 27fc1e30753a07ba686958168ce2c682c7376b53,880fb7bb30b75d9c5bb6a8aa037a6048cba5c922..56bc4ff0e83b4cfedee6b0893f921be0c0bfcc31
@@@ -280,7 -280,7 +280,7 @@@ int rev_same_tree_as_empty(struct rev_i
  static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
  {
        struct commit_list **pp, *parent;
-       int tree_changed = 0;
+       int tree_changed = 0, tree_same = 0;
  
        if (!commit->tree)
                return;
                parse_commit(p);
                switch (rev_compare_tree(revs, p->tree, commit->tree)) {
                case REV_TREE_SAME:
+                       tree_same = 1;
                        if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
                                /* Even if a merge with an uninteresting
                                 * side branch brought the entire change
                }
                die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
        }
-       if (tree_changed)
+       if (tree_changed && !tree_same)
                commit->object.flags |= TREECHANGE;
  }
  
@@@ -536,18 -537,6 +537,18 @@@ void init_revisions(struct rev_info *re
        diff_setup(&revs->diffopt);
  }
  
 +static void add_pending_commit_list(struct rev_info *revs,
 +                                    struct commit_list *commit_list,
 +                                    unsigned int flags)
 +{
 +      while (commit_list) {
 +              struct object *object = &commit_list->item->object;
 +              object->flags |= flags;
 +              add_pending_object(revs, object, sha1_to_hex(object->sha1));
 +              commit_list = commit_list->next;
 +      }
 +}
 +
  /*
   * Parse revision information, filling in the "rev_info" structure,
   * and removing the used arguments from the argument list.
@@@ -783,45 -772,27 +784,45 @@@ int setup_revisions(int argc, const cha
                        unsigned char from_sha1[20];
                        const char *next = dotdot + 2;
                        const char *this = arg;
 +                      int symmetric = *next == '.';
 +                      unsigned int flags_exclude = flags ^ UNINTERESTING;
 +
                        *dotdot = 0;
 +                      next += symmetric;
 +
                        if (!*next)
                                next = "HEAD";
                        if (dotdot == arg)
                                this = "HEAD";
                        if (!get_sha1(this, from_sha1) &&
                            !get_sha1(next, sha1)) {
 -                              struct object *exclude;
 -                              struct object *include;
 -
 -                              exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING);
 -                              include = get_reference(revs, next, sha1, flags);
 -                              if (!exclude || !include)
 -                                      die("Invalid revision range %s..%s", arg, next);
 +                              struct commit *a, *b;
 +                              struct commit_list *exclude;
 +
 +                              a = lookup_commit_reference(from_sha1);
 +                              b = lookup_commit_reference(sha1);
 +                              if (!a || !b) {
 +                                      die(symmetric ?
 +                                          "Invalid symmetric difference expression %s...%s" :
 +                                          "Invalid revision range %s..%s",
 +                                          arg, next);
 +                              }
  
                                if (!seen_dashdash) {
                                        *dotdot = '.';
                                        verify_non_filename(revs->prefix, arg);
                                }
 -                              add_pending_object(revs, exclude, this);
 -                              add_pending_object(revs, include, next);
 +
 +                              if (symmetric) {
 +                                      exclude = get_merge_bases(a, b, 1);
 +                                      add_pending_commit_list(revs, exclude,
 +                                                              flags_exclude);
 +                                      a->object.flags |= flags;
 +                              } else
 +                                      a->object.flags |= flags_exclude;
 +                              b->object.flags |= flags;
 +                              add_pending_object(revs, &a->object, this);
 +                              add_pending_object(revs, &b->object, next);
                                continue;
                        }
                        *dotdot = '.';
@@@ -926,6 -897,8 +927,8 @@@ static int rewrite_one(struct rev_info 
                struct commit *p = *pp;
                if (!revs->limited)
                        add_parents_to_list(revs, p, &revs->commits);
+               if (p->parents && p->parents->next)
+                       return 0;
                if (p->object.flags & (TREECHANGE | UNINTERESTING))
                        return 0;
                if (!p->parents)
@@@ -1018,8 -991,15 +1021,15 @@@ struct commit *get_revision(struct rev_
                    commit->parents && commit->parents->next)
                        continue;
                if (revs->prune_fn && revs->dense) {
-                       if (!(commit->object.flags & TREECHANGE))
-                               continue;
+                       /* Commit without changes? */
+                       if (!(commit->object.flags & TREECHANGE)) {
+                               /* drop merges unless we want parenthood */
+                               if (!revs->parents)
+                                       continue;
+                               /* non-merge - always ignore it */
+                               if (!commit->parents || !commit->parents->next)
+                                       continue;
+                       }
                        if (revs->parents)
                                rewrite_parents(revs, commit);
                }