diff --git a/src/commit.c b/src/commit.c index 1b30c5d6f..8844825b8 100644 --- a/src/commit.c +++ b/src/commit.c @@ -35,6 +35,22 @@ const git_oid *git_commit_id(git_commit *c) return &c->id; } +void git_commit_mark_uninteresting(git_commit *commit) +{ + git_commit_list *parents = commit->parents; + + commit->flags |= GIT_COMMIT_HIDE; + + /* + * FIXME: mark recursively the parents' parents? + * They are most likely not parsed yet... + */ + while (parents) { + parents->commit->flags |= GIT_COMMIT_HIDE; + parents = parents->next; + } +} + git_commit *git_commit_lookup(git_revpool *pool, const git_oid *id) { git_obj commit_obj; @@ -141,7 +157,7 @@ int git_commit__parse_buffer(git_commit *commit, void *data, size_t len) if ((parent = git_commit_lookup(commit->pool, &oid)) == NULL) return -1; - // TODO: push the new commit into the revpool + git_commit_list_insert(&commit->parents, parent); } if (git_commit__parse_time(&commit->commit_time, buffer, buffer_end) < 0) @@ -152,3 +168,30 @@ int git_commit__parse_buffer(git_commit *commit, void *data, size_t len) return 0; } +void git_commit_list_insert(git_commit_list **list, git_commit *commit) +{ + if (*list == NULL) + { + *list = git__malloc(sizeof(git_commit_list)); + + if (*list == NULL) + return; + + (*list)->commit = commit; + (*list)->next = NULL; + } + else + { + git_commit_list *new_list = NULL; + + new_list = git__malloc(sizeof(git_commit_list)); + + if (new_list == NULL) + return; + + new_list->commit = commit; + new_list->next = *list; + + *list = new_list; + } +} diff --git a/src/commit.h b/src/commit.h index fe4db4d4c..7ab2d5413 100644 --- a/src/commit.h +++ b/src/commit.h @@ -9,10 +9,19 @@ #define GIT_COMMIT_HIDE (1 << 1) #define GIT_COMMIT_DELAY (1 << 2) +struct git_commit_list { + struct git_commit *commit; + struct git_commit_list *next; +}; + +typedef struct git_commit_list git_commit_list; + struct git_commit { git_oid id; time_t commit_time; git_revpool *pool; + git_commit_list *parents; + unsigned parsed:1, flags:26; }; @@ -21,4 +30,6 @@ int git_commit__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_en int git_commit__parse_buffer(git_commit *commit, void *data, size_t len); int git_commit__parse_time(time_t *commit_time, char *buffer, const char *buffer_end); +void git_commit_list_insert(git_commit_list **list, git_commit *commit); + #endif diff --git a/src/revwalk.c b/src/revwalk.c index 11261fbff..96f34447e 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -24,6 +24,7 @@ */ #include "common.h" +#include "commit.h" #include "revwalk.h" git_revpool *gitrp_alloc(git_odb *db) @@ -32,6 +33,8 @@ git_revpool *gitrp_alloc(git_odb *db) if (!walk) return NULL; + memset(walk, 0x0, sizeof(git_revpool)); + walk->db = db; return walk; } @@ -40,3 +43,54 @@ void gitrp_free(git_revpool *walk) { free(walk); } + +void gitrp_push(git_revpool *pool, git_commit *commit) +{ + if ((commit->flags & GIT_COMMIT_SEEN) != 0) + return; + + /* FIXME: + * Unparsed commit objects? Where do these come from? + * Do we need to handle them? + */ + if (!commit->parsed) + return; + + commit->flags |= GIT_COMMIT_SEEN; + + git_commit_list_insert(&pool->commits, commit); +} + +void gitrp_prepare_walk(git_revpool *pool) +{ + // TODO: sort commit list based on walk ordering + + pool->iterator = pool->commits; + pool->walking = 1; +} + +git_commit *gitrp_next(git_revpool *pool) +{ + git_commit *next; + + if (!pool->walking) + gitrp_prepare_walk(pool); + + // Iteration finished + if (pool->iterator == NULL) + { + gitrp_reset(pool); + return NULL; + } + + next = pool->iterator->commit; + pool->iterator = pool->iterator->next; + + return next; +} + +void gitrp_reset(git_revpool *pool) +{ + pool->iterator = NULL; + pool->walking = 0; +} diff --git a/src/revwalk.h b/src/revwalk.h index 2ef4e5d83..edf57b4b9 100644 --- a/src/revwalk.h +++ b/src/revwalk.h @@ -6,6 +6,11 @@ struct git_revpool { git_odb *db; + git_commit_list *iterator; + git_commit_list *commits; + + unsigned walking:1, + topological_sort:1; }; #endif /* INCLUDE_revwalk_h__ */