Added new error codes. Improved error handling.
[libgit2.git] / src / revwalk.c
blob186a08f4b6d4a08b1692365cfef59755bd8c0485
1 /*
2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
26 #include "common.h"
27 #include "commit.h"
28 #include "revwalk.h"
30 static const int default_table_size = 32;
32 git_revpool *gitrp_alloc(git_odb *db)
34 git_revpool *walk = git__malloc(sizeof(*walk));
35 if (!walk)
36 return NULL;
38 memset(walk, 0x0, sizeof(git_revpool));
40 walk->commits = git_revpool_table_create(default_table_size);
42 walk->db = db;
43 return walk;
46 void gitrp_free(git_revpool *walk)
48 git_commit_list_clear(&(walk->iterator), 0);
49 git_commit_list_clear(&(walk->roots), 0);
51 git_revpool_table_free(walk->commits);
53 free(walk);
56 void gitrp_sorting(git_revpool *pool, unsigned int sort_mode)
58 if (pool->walking)
59 return;
61 pool->sorting = sort_mode;
62 gitrp_reset(pool);
65 int gitrp_push(git_revpool *pool, git_commit *commit)
67 if (commit == NULL || commit->seen)
68 return GIT_ENOTFOUND;
70 if (commit->object.pool != pool || pool->walking)
71 return GIT_ERROR;
73 if (!commit->parsed) {
74 if (git_commit_parse_existing(commit) < 0)
75 return GIT_EOBJCORRUPTED;
78 // Sanity check: make sure that if the commit
79 // has been manually marked as uninteresting,
80 // all the parent commits are too.
81 if (commit->uninteresting)
82 git_commit__mark_uninteresting(commit);
84 if (git_commit_list_push_back(&pool->roots, commit) < 0)
85 return GIT_ENOMEM;
87 return 0;
90 int gitrp_hide(git_revpool *pool, git_commit *commit)
92 if (pool->walking)
93 return GIT_ERROR;
95 git_commit__mark_uninteresting(commit);
96 return gitrp_push(pool, commit);
99 int gitrp__enroot(git_revpool *pool, git_commit *commit)
101 int error;
102 git_commit_node *parents;
104 if (commit->seen)
105 return 0;
107 if (commit->parsed == 0) {
108 if (git_commit_parse_existing(commit))
109 return GIT_EOBJCORRUPTED;
112 commit->seen = 1;
114 for (parents = commit->parents.head; parents != NULL; parents = parents->next) {
115 parents->commit->in_degree++;
117 error = gitrp__enroot(pool, parents->commit);
118 if (error < 0)
119 return error;
122 if (git_commit_list_push_back(&pool->iterator, commit))
123 return GIT_ENOMEM;
125 return 0;
128 void gitrp__prepare_walk(git_revpool *pool)
130 git_commit_node *it;
132 for (it = pool->roots.head; it != NULL; it = it->next)
133 gitrp__enroot(pool, it->commit);
135 if (pool->sorting & GIT_RPSORT_TIME)
136 git_commit_list_timesort(&pool->iterator);
138 if (pool->sorting & GIT_RPSORT_TOPOLOGICAL)
139 git_commit_list_toposort(&pool->iterator);
141 if (pool->sorting & GIT_RPSORT_REVERSE)
142 pool->next_commit = &git_commit_list_pop_back;
143 else
144 pool->next_commit = &git_commit_list_pop_front;
146 pool->walking = 1;
149 git_commit *gitrp_next(git_revpool *pool)
151 git_commit *next;
153 if (!pool->walking)
154 gitrp__prepare_walk(pool);
156 while ((next = pool->next_commit(&pool->iterator)) != NULL) {
157 if (!next->uninteresting)
158 return next;
161 // No commits left to iterate
162 gitrp_reset(pool);
163 return NULL;
166 void gitrp_reset(git_revpool *pool)
168 git_commit *commit;
169 git_revpool_tableit it;
171 git_revpool_tableit_init(pool->commits, &it);
173 while ((commit = (git_commit *)git_revpool_tableit_next(&it)) != NULL) {
174 commit->seen = 0;
175 commit->topo_delay = 0;
176 commit->in_degree = 0;
179 git_commit_list_clear(&pool->iterator, 0);
180 pool->walking = 0;