mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 19:47:52 +00:00

Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Andreas Ericsson <ae@op5.se>
187 lines
4.2 KiB
C
187 lines
4.2 KiB
C
/*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* In addition to the permissions in the GNU General Public License,
|
|
* the authors give you unlimited permission to link the compiled
|
|
* version of this file into combinations with other programs,
|
|
* and to distribute those combinations without any restriction
|
|
* coming from the use of this file. (The General Public License
|
|
* restrictions do apply in other respects; for example, they cover
|
|
* modification of the file, and distribution when not linked into
|
|
* a combined executable.)
|
|
*
|
|
* This file is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#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));
|
|
if (!walk)
|
|
return NULL;
|
|
|
|
memset(walk, 0x0, sizeof(git_revpool));
|
|
|
|
walk->commits = git_revpool_table_create(default_table_size);
|
|
|
|
walk->db = db;
|
|
return walk;
|
|
}
|
|
|
|
void gitrp_free(git_revpool *walk)
|
|
{
|
|
git_commit_list_clear(&(walk->iterator), 0);
|
|
git_commit_list_clear(&(walk->roots), 0);
|
|
|
|
git_revpool_table_free(walk->commits);
|
|
|
|
free(walk);
|
|
}
|
|
|
|
void gitrp_sorting(git_revpool *pool, unsigned int sort_mode)
|
|
{
|
|
if (pool->walking)
|
|
return;
|
|
|
|
pool->sorting = sort_mode;
|
|
gitrp_reset(pool);
|
|
}
|
|
|
|
int gitrp_push(git_revpool *pool, git_commit *commit)
|
|
{
|
|
if (commit == NULL || commit->seen)
|
|
return GIT_ENOTFOUND;
|
|
|
|
if (commit->object.pool != pool || pool->walking)
|
|
return GIT_ERROR;
|
|
|
|
if (!commit->parsed) {
|
|
int error = git_commit_parse_existing(commit);
|
|
if (error < 0)
|
|
return error;
|
|
}
|
|
|
|
/*
|
|
* Sanity check: make sure that if the commit
|
|
* has been manually marked as uninteresting,
|
|
* all the parent commits are too.
|
|
*/
|
|
if (commit->uninteresting)
|
|
git_commit__mark_uninteresting(commit);
|
|
|
|
if (git_commit_list_push_back(&pool->roots, commit) < 0)
|
|
return GIT_ENOMEM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gitrp_hide(git_revpool *pool, git_commit *commit)
|
|
{
|
|
if (pool->walking)
|
|
return GIT_ERROR;
|
|
|
|
git_commit__mark_uninteresting(commit);
|
|
return gitrp_push(pool, commit);
|
|
}
|
|
|
|
int gitrp__enroot(git_revpool *pool, git_commit *commit)
|
|
{
|
|
int error;
|
|
git_commit_node *parents;
|
|
|
|
if (commit->seen)
|
|
return 0;
|
|
|
|
if (commit->parsed == 0) {
|
|
error = git_commit_parse_existing(commit);
|
|
if (error < 0)
|
|
return error;
|
|
}
|
|
|
|
commit->seen = 1;
|
|
|
|
for (parents = commit->parents.head; parents != NULL; parents = parents->next) {
|
|
parents->commit->in_degree++;
|
|
|
|
error = gitrp__enroot(pool, parents->commit);
|
|
if (error < 0)
|
|
return error;
|
|
}
|
|
|
|
if (git_commit_list_push_back(&pool->iterator, commit))
|
|
return GIT_ENOMEM;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gitrp__prepare_walk(git_revpool *pool)
|
|
{
|
|
git_commit_node *it;
|
|
|
|
for (it = pool->roots.head; it != NULL; it = it->next)
|
|
gitrp__enroot(pool, it->commit);
|
|
|
|
if (pool->sorting & GIT_RPSORT_TIME)
|
|
git_commit_list_timesort(&pool->iterator);
|
|
|
|
if (pool->sorting & GIT_RPSORT_TOPOLOGICAL)
|
|
git_commit_list_toposort(&pool->iterator);
|
|
|
|
if (pool->sorting & GIT_RPSORT_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;
|
|
}
|
|
|
|
/* No commits left to iterate */
|
|
gitrp_reset(pool);
|
|
return NULL;
|
|
}
|
|
|
|
void gitrp_reset(git_revpool *pool)
|
|
{
|
|
git_commit *commit;
|
|
git_revpool_tableit it;
|
|
|
|
git_revpool_tableit_init(pool->commits, &it);
|
|
|
|
while ((commit = (git_commit *)git_revpool_tableit_next(&it)) != NULL) {
|
|
commit->seen = 0;
|
|
commit->topo_delay = 0;
|
|
commit->in_degree = 0;
|
|
}
|
|
|
|
git_commit_list_clear(&pool->iterator, 0);
|
|
pool->walking = 0;
|
|
}
|
|
|