Commit 6c38e60a by Russell Belfer

Merge pull request #1838 from libgit2/cmn/first-parent

revwalk: allow simplifying by first-parent
parents 68642bce 15f7b9b8
......@@ -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);
/**
* 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.
*
* @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
static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commit)
{
unsigned short i;
unsigned short i, max;
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);
return error;
......@@ -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)
{
git_commit_list_node *next;
unsigned short i;
unsigned short i, max;
for (;;) {
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
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];
if (--parent->in_degree == 0 && parent->topo_delay) {
......@@ -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 error;
......
......@@ -31,7 +31,8 @@ struct git_revwalk {
int (*get_next)(git_commit_list_node **, git_revwalk *);
int (*enqueue)(git_revwalk *, git_commit_list_node *);
unsigned walking:1;
unsigned walking:1,
first_parent: 1;
unsigned int sorting;
/* 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