From: Junio C Hamano Date: Mon, 3 Jul 2006 10:14:32 +0000 (-0700) Subject: Merge branch 'master' into js/merge-base X-Git-Tag: v1.4.2-rc1~77^2~4 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f23c75a8eca5eeabf9aaf303ee7e14a94da42ddc?ds=sidebyside;hp=-c Merge branch 'master' into js/merge-base This is to pull in the object-hash clean-up from the master branch. --- f23c75a8eca5eeabf9aaf303ee7e14a94da42ddc diff --combined object.c index 9caba4fac8,37277f9438..1c36759715 --- a/object.c +++ 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; } + +void clear_object_marks(unsigned mark) +{ + int i; + - for (i = 0; i < obj_allocs; i++) - if (objs[i]) - objs[i]->flags &= ~mark; ++ for (i = 0; i < obj_hash_size; i++) ++ if (obj_hash[i]) ++ obj_hash[i]->flags &= ~mark; +} diff --combined object.h index 7ac10111c6,e0125e154f..d8a76ea935 --- a/object.h +++ 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 27fc1e3075,880fb7bb30..56bc4ff0e8 --- a/revision.c +++ b/revision.c @@@ -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; @@@ -298,6 -298,7 +298,7 @@@ 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 @@@ -334,7 -335,7 +335,7 @@@ } 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); }