Commit 15f7b9b8 by Carlos Martín Nieto

revwalk: allow simplifying by first-parent

When enabled, only the first parent of each commit will be queued,
enabling a simple way of using first-parent simplification.
parent ef6389ad
...@@ -232,6 +232,14 @@ GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode); ...@@ -232,6 +232,14 @@ GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode);
GIT_EXTERN(int) git_revwalk_push_range(git_revwalk *walk, const char *range); GIT_EXTERN(int) git_revwalk_push_range(git_revwalk *walk, const char *range);
/** /**
* Simplify the history by first-parent
*
* No parents other than the first for each commit will be enqueued.
*/
GIT_EXTERN(void) git_revwalk_simplify_first_parent(git_revwalk *walk);
/**
* Free a revision walker previously allocated. * Free a revision walker previously allocated.
* *
* @param walk traversal handle to close. If NULL nothing occurs. * @param walk traversal handle to close. If NULL nothing occurs.
......
...@@ -99,10 +99,14 @@ static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int h ...@@ -99,10 +99,14 @@ static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int h
static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commit) static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commit)
{ {
unsigned short i; unsigned short i, max;
int error = 0; int error = 0;
for (i = 0; i < commit->out_degree && !error; ++i) max = commit->out_degree;
if (walk->first_parent && commit->out_degree)
max = 1;
for (i = 0; i < max && !error; ++i)
error = process_commit(walk, commit->parents[i], commit->uninteresting); error = process_commit(walk, commit->parents[i], commit->uninteresting);
return error; return error;
...@@ -333,7 +337,7 @@ static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk ...@@ -333,7 +337,7 @@ static int revwalk_next_unsorted(git_commit_list_node **object_out, git_revwalk
static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk *walk) static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk *walk)
{ {
git_commit_list_node *next; git_commit_list_node *next;
unsigned short i; unsigned short i, max;
for (;;) { for (;;) {
next = git_commit_list_pop(&walk->iterator_topo); next = git_commit_list_pop(&walk->iterator_topo);
...@@ -347,7 +351,12 @@ static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk ...@@ -347,7 +351,12 @@ static int revwalk_next_toposort(git_commit_list_node **object_out, git_revwalk
continue; continue;
} }
for (i = 0; i < next->out_degree; ++i) {
max = next->out_degree;
if (walk->first_parent && next->out_degree)
max = 1;
for (i = 0; i < max; ++i) {
git_commit_list_node *parent = next->parents[i]; git_commit_list_node *parent = next->parents[i];
if (--parent->in_degree == 0 && parent->topo_delay) { if (--parent->in_degree == 0 && parent->topo_delay) {
...@@ -505,6 +514,11 @@ void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode) ...@@ -505,6 +514,11 @@ void git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode)
} }
} }
void git_revwalk_simplify_first_parent(git_revwalk *walk)
{
walk->first_parent = 1;
}
int git_revwalk_next(git_oid *oid, git_revwalk *walk) int git_revwalk_next(git_oid *oid, git_revwalk *walk)
{ {
int error; int error;
......
...@@ -31,7 +31,8 @@ struct git_revwalk { ...@@ -31,7 +31,8 @@ struct git_revwalk {
int (*get_next)(git_commit_list_node **, git_revwalk *); int (*get_next)(git_commit_list_node **, git_revwalk *);
int (*enqueue)(git_revwalk *, git_commit_list_node *); int (*enqueue)(git_revwalk *, git_commit_list_node *);
unsigned walking:1; unsigned walking:1,
first_parent: 1;
unsigned int sorting; unsigned int sorting;
/* merge base calculation */ /* merge base calculation */
......
#include "clar_libgit2.h"
/*
* a4a7dce [0] Merge branch 'master' into br2
|\
| * 9fd738e [1] a fourth commit
| * 4a202b3 [2] a third commit
* | c47800c [3] branch commit one
|/
* 5b5b025 [5] another commit
* 8496071 [4] testing
*/
static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f";
static const char *expected_str[] = {
"a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */
"c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */
"8496071c1b46c854b31185ea97743be6a8774479", /* 4 */
"5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */
};
void test_revwalk_simplify__first_parent(void)
{
git_repository *repo;
git_revwalk *walk;
git_oid id, expected[4];
int i, error;
for (i = 0; i < 4; i++) {
git_oid_fromstr(&expected[i], expected_str[i]);
}
repo = cl_git_sandbox_init("testrepo.git");
cl_git_pass(git_revwalk_new(&walk, repo));
git_oid_fromstr(&id, commit_head);
cl_git_pass(git_revwalk_push(walk, &id));
git_revwalk_simplify_first_parent(walk);
i = 0;
while ((error = git_revwalk_next(&id, walk)) == 0) {
git_oid_cmp(&id, &expected[i]);
i++;
}
cl_assert_equal_i(i, 4);
cl_assert_equal_i(error, GIT_ITEROVER);
git_revwalk_free(walk);
git_repository_free(repo);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment