diff --git a/src/commit.c b/src/commit.c index 226eca421..1763ca88b 100644 --- a/src/commit.c +++ b/src/commit.c @@ -100,6 +100,10 @@ git_commit *git_commit_lookup(git_revpool *pool, const git_oid *id) if (pool == NULL || pool->db == NULL) return NULL; + commit = (git_commit *)git_revpool_table_lookup(pool->commits, id); + if (commit != NULL) + return commit; + commit = git__malloc(sizeof(git_commit)); if (commit == NULL) @@ -111,6 +115,8 @@ git_commit *git_commit_lookup(git_revpool *pool, const git_oid *id) git_oid_cpy(&commit->object.id, id); commit->object.pool = pool; + git_revpool_table_insert(pool->commits, (git_revpool_object *)commit); + return commit; } diff --git a/src/revobject.c b/src/revobject.c index 7c2513775..2ed634540 100644 --- a/src/revobject.c +++ b/src/revobject.c @@ -33,7 +33,7 @@ unsigned int git_revpool_table__hash(const git_oid *id) const unsigned int m = 0x5bd1e995; const int r = 24; - unsigned int h = 0xA8A3D5 ^ (unsigned int)id; + unsigned int h = 0xA8A3D5; int i; for (i = 0; i < GIT_OID_RAWSZ / 4; ++i) @@ -165,3 +165,9 @@ void git_revpool_table_resize(git_revpool_table *table) table->size_mask = (new_size - 1); table->max_count = new_size * max_load_factor; } + + +void git_revpool_table_free(git_revpool_table *table) +{ + +} diff --git a/src/revobject.h b/src/revobject.h index 8ea17a2c5..8ec696a47 100644 --- a/src/revobject.h +++ b/src/revobject.h @@ -34,6 +34,7 @@ git_revpool_table *git_revpool_table_create(unsigned int min_size); int git_revpool_table_insert(git_revpool_table *table, git_revpool_object *object); git_revpool_object *git_revpool_table_lookup(git_revpool_table *table, const git_oid *id); void git_revpool_table_resize(git_revpool_table *table); +void git_revpool_table_free(git_revpool_table *table); #endif diff --git a/src/revwalk.c b/src/revwalk.c index cbf7144d8..b24cf42e6 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -27,6 +27,8 @@ #include "commit.h" #include "revwalk.h" +static const int default_table_size = 32; + git_revpool *gitrp_alloc(git_odb *db) { git_revpool *walk = git__malloc(sizeof(*walk)); @@ -35,6 +37,8 @@ git_revpool *gitrp_alloc(git_odb *db) memset(walk, 0x0, sizeof(git_revpool)); + walk->commits = git_revpool_table_create(default_table_size); + walk->db = db; return walk; } @@ -42,7 +46,10 @@ git_revpool *gitrp_alloc(git_odb *db) void gitrp_free(git_revpool *walk) { git_commit_list_clear(&(walk->iterator), 0); - git_commit_list_clear(&(walk->roots), 1); + git_commit_list_clear(&(walk->roots), 0); + + git_revpool_table_free(walk->commits); + free(walk); } @@ -69,7 +76,6 @@ void gitrp_push(git_revpool *pool, git_commit *commit) commit->seen = 1; git_commit_list_append(&pool->roots, commit); - git_commit_list_append(&pool->iterator, commit); } void gitrp_hide(git_revpool *pool, git_commit *commit) @@ -80,30 +86,21 @@ void gitrp_hide(git_revpool *pool, git_commit *commit) void gitrp_prepare_walk(git_revpool *pool) { - git_commit_node *roots; + git_commit_node *it; - roots = pool->roots.head; - while (roots) + for (it = pool->roots.head; it != NULL; it = it->next) { - git_commit_list_append(&pool->iterator, roots->commit); - roots = roots->next; + git_commit_list_append(&pool->iterator, it->commit); } - pool->walking = 1; -} - -git_commit *gitrp_next(git_revpool *pool) -{ - git_commit *next; - - if (!pool->walking) - gitrp_prepare_walk(pool); - - while ((next = git_commit_list_pop_front(&pool->iterator)) != NULL) + for (it = pool->iterator.head; it != NULL; it = it->next) { + git_commit *commit; git_commit_node *parents; - parents = next->parents.head; + commit = it->commit; + parents = commit->parents.head; + while (parents) { git_commit *parent = parents->commit; @@ -115,10 +112,31 @@ git_commit *gitrp_next(git_revpool *pool) if (parent->parsed == 0) git_commit_parse_existing(parent); + parent->seen = 1; git_commit_list_append(&pool->iterator, parent); } + } - if (next->uninteresting == 0) + // TODO: topo sort, time sort + + if (pool->sorting & GIT_REVPOOL_SORT_REVERSE) + pool->next_commit = &git_commit_list_pop_back; + else + pool->next_commit = &git_commit_list_pop_front; + + pool->walking = 1; +} + +git_commit *gitrp_next(git_revpool *pool) +{ + git_commit *next; + + if (!pool->walking) + gitrp_prepare_walk(pool); + + while ((next = pool->next_commit(&pool->iterator)) != NULL) + { + if (!next->uninteresting) return next; } diff --git a/src/revwalk.h b/src/revwalk.h index ae692bf0e..14599df10 100644 --- a/src/revwalk.h +++ b/src/revwalk.h @@ -4,13 +4,22 @@ #include "git/common.h" #include "git/revwalk.h" +#define GIT_REVPOOL_SORT_NONE (0) +#define GIT_REVPOOL_SORT_TOPO (1 << 0) +#define GIT_REVPOOL_SORT_TIME (1 << 1) +#define GIT_REVPOOL_SORT_REVERSE (1 << 2) + struct git_revpool { git_odb *db; - git_commit_list iterator; - git_commit_list roots; - unsigned walking:1, - topological_sort:1; + git_commit_list iterator; + git_commit *(*next_commit)(git_commit_list *); + + git_commit_list roots; + git_revpool_table *commits; + + unsigned walking:1; + unsigned char sorting; }; #endif /* INCLUDE_revwalk_h__ */