Skip to content

Commit 451aaf8

Browse files
committed
Merge pull request libgit2#2181 from anuraggup/hide_cb
Callback function to hide commit and its parents in revision walker
2 parents f210cb5 + 34ffe22 commit 451aaf8

File tree

4 files changed

+251
-5
lines changed

4 files changed

+251
-5
lines changed

include/git2/revwalk.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,30 @@ GIT_EXTERN(void) git_revwalk_free(git_revwalk *walk);
261261
*/
262262
GIT_EXTERN(git_repository *) git_revwalk_repository(git_revwalk *walk);
263263

264+
/**
265+
* This is a callback function that user can provide to hide a
266+
* commit and its parents. If the callback function returns non-zero value,
267+
* then this commit and its parents will be hidden.
268+
*
269+
* @param commit_id oid of Commit
270+
* @param payload User-specified pointer to data to be passed as data payload
271+
*/
272+
typedef int(*git_revwalk_hide_cb)(
273+
const git_oid *commit_id,
274+
void *payload);
275+
276+
/**
277+
* Adds a callback function to hide a commit and its parents
278+
*
279+
* @param walk the revision walker
280+
* @param hide_cb callback function to hide a commit and its parents
281+
* @param payload data payload to be passed to callback function
282+
*/
283+
GIT_EXTERN(int) git_revwalk_add_hide_cb(
284+
git_revwalk *walk,
285+
git_revwalk_hide_cb hide_cb,
286+
void *payload);
287+
264288
/** @} */
265289
GIT_END_DECL
266290
#endif

src/revwalk.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static int process_commit(git_revwalk *walk, git_commit_list_node *commit, int h
8181
{
8282
int error;
8383

84+
if (!hide && walk->hide_cb)
85+
hide = walk->hide_cb(&commit->oid, walk->hide_cb_payload);
86+
8487
if (hide && mark_uninteresting(commit) < 0)
8588
return -1;
8689

@@ -178,11 +181,6 @@ static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_g
178181
return push_commit(walk, &oid, hide, from_glob);
179182
}
180183

181-
struct push_cb_data {
182-
git_revwalk *walk;
183-
int hide;
184-
};
185-
186184
static int push_glob(git_revwalk *walk, const char *glob, int hide)
187185
{
188186
int error = 0;
@@ -575,3 +573,25 @@ void git_revwalk_reset(git_revwalk *walk)
575573
git_vector_clear(&walk->twos);
576574
}
577575

576+
int git_revwalk_add_hide_cb(
577+
git_revwalk *walk,
578+
git_revwalk_hide_cb hide_cb,
579+
void *payload)
580+
{
581+
assert(walk);
582+
583+
if (walk->walking)
584+
git_revwalk_reset(walk);
585+
586+
if (walk->hide_cb) {
587+
/* There is already a callback added */
588+
giterr_set(GITERR_INVALID, "There is already a callback added to hide commits in revision walker.");
589+
return -1;
590+
}
591+
592+
walk->hide_cb = hide_cb;
593+
walk->hide_cb_payload = payload;
594+
595+
return 0;
596+
}
597+

src/revwalk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ struct git_revwalk {
3939
/* merge base calculation */
4040
git_commit_list_node *one;
4141
git_vector twos;
42+
43+
/* hide callback */
44+
git_revwalk_hide_cb hide_cb;
45+
void *hide_cb_payload;
4246
};
4347

4448
git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid);

tests/revwalk/hidecb.c

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#include "clar_libgit2.h"
2+
/*
3+
* a4a7dce [0] Merge branch 'master' into br2
4+
|\
5+
| * 9fd738e [1] a fourth commit
6+
| * 4a202b3 [2] a third commit
7+
* | c47800c [3] branch commit one
8+
|/
9+
* 5b5b025 [5] another commit
10+
* 8496071 [4] testing
11+
*/
12+
static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f";
13+
14+
static const char *commit_strs[] = {
15+
"a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */
16+
"9fd738e8f7967c078dceed8190330fc8648ee56a", /* 1 */
17+
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045", /* 2 */
18+
"c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */
19+
"8496071c1b46c854b31185ea97743be6a8774479", /* 4 */
20+
"5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */
21+
};
22+
23+
#define commit_count 6
24+
25+
static git_oid commit_ids[commit_count];
26+
static git_oid _head_id;
27+
static git_repository *_repo;
28+
29+
30+
void test_revwalk_hidecb__initialize(void)
31+
{
32+
int i;
33+
34+
cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
35+
cl_git_pass(git_oid_fromstr(&_head_id, commit_head));
36+
37+
for (i = 0; i < commit_count; i++)
38+
cl_git_pass(git_oid_fromstr(&commit_ids[i], commit_strs[i]));
39+
40+
}
41+
42+
void test_revwalk_hidecb__cleanup(void)
43+
{
44+
git_repository_free(_repo);
45+
_repo = NULL;
46+
}
47+
48+
/* Hide all commits */
49+
static int hide_every_commit_cb(const git_oid *commit_id, void *data)
50+
{
51+
return 1;
52+
}
53+
54+
/* Do not hide anything */
55+
static int hide_none_cb(const git_oid *commit_id, void *data)
56+
{
57+
return 0;
58+
}
59+
60+
/* Hide some commits */
61+
static int hide_commit_cb(const git_oid *commit_id, void *data)
62+
{
63+
if (0 == git_oid_cmp(commit_id, &commit_ids[5]))
64+
return 1;
65+
else
66+
return 0;
67+
68+
}
69+
70+
/* In payload data, pointer to a commit id is passed */
71+
static int hide_commit_use_payload_cb(const git_oid *commit_id, void *data)
72+
{
73+
git_oid *hide_commit_id = data;
74+
if (git_oid_cmp(commit_id, hide_commit_id) == 0)
75+
return 1;
76+
else
77+
return 0;
78+
}
79+
80+
void test_revwalk_hidecb__hide_all_cb(void)
81+
{
82+
git_revwalk *walk;
83+
git_oid id;
84+
85+
cl_git_pass(git_revwalk_new(&walk, _repo));
86+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_every_commit_cb, NULL));
87+
cl_git_pass(git_revwalk_push(walk, &_head_id));
88+
89+
/* First call to git_revwalk_next should return GIT_ITEROVER */
90+
cl_assert_equal_i(GIT_ITEROVER, git_revwalk_next(&id, walk));
91+
92+
git_revwalk_free(walk);
93+
}
94+
95+
96+
void test_revwalk_hidecb__hide_none_cb(void)
97+
{
98+
git_revwalk *walk;
99+
int i, error;
100+
git_oid id;
101+
102+
cl_git_pass(git_revwalk_new(&walk, _repo));
103+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_none_cb, NULL));
104+
cl_git_pass(git_revwalk_push(walk, &_head_id));
105+
106+
/* It should return all 6 commits */
107+
i = 0;
108+
while ((error = git_revwalk_next(&id, walk)) == 0)
109+
i++;
110+
111+
cl_assert_equal_i(i, 6);
112+
cl_assert_equal_i(error, GIT_ITEROVER);
113+
114+
git_revwalk_free(walk);
115+
}
116+
117+
void test_revwalk_hidecb__add_hide_cb_multiple_times(void)
118+
{
119+
git_revwalk *walk;
120+
121+
cl_git_pass(git_revwalk_new(&walk, _repo));
122+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_every_commit_cb, NULL));
123+
cl_git_fail(git_revwalk_add_hide_cb(walk, hide_every_commit_cb, NULL));
124+
125+
git_revwalk_free(walk);
126+
}
127+
128+
void test_revwalk_hidecb__add_hide_cb_during_walking(void)
129+
{
130+
git_revwalk *walk;
131+
git_oid id;
132+
int error;
133+
134+
cl_git_pass(git_revwalk_new(&walk, _repo));
135+
cl_git_pass(git_revwalk_push(walk, &_head_id));
136+
137+
/* Start walking without adding hide callback */
138+
cl_git_pass(git_revwalk_next(&id, walk));
139+
140+
/* Now add hide callback */
141+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_none_cb, NULL));
142+
143+
/* walk should be reset */
144+
error = git_revwalk_next(&id, walk);
145+
cl_assert_equal_i(error, GIT_ITEROVER);
146+
147+
git_revwalk_free(walk);
148+
}
149+
150+
void test_revwalk_hidecb__hide_some_commits(void)
151+
{
152+
git_revwalk *walk;
153+
git_oid id;
154+
int i, error;
155+
156+
cl_git_pass(git_revwalk_new(&walk, _repo));
157+
cl_git_pass(git_revwalk_push(walk, &_head_id));
158+
159+
/* Add hide callback */
160+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_commit_cb, NULL));
161+
162+
i = 0;
163+
while ((error = git_revwalk_next(&id, walk)) == 0) {
164+
cl_assert_equal_i(git_oid_cmp(&id, &commit_ids[i]), 0);
165+
i++;
166+
}
167+
168+
cl_assert_equal_i(i, 4);
169+
cl_assert_equal_i(error, GIT_ITEROVER);
170+
171+
git_revwalk_free(walk);
172+
}
173+
174+
void test_revwalk_hidecb__test_payload(void)
175+
{
176+
git_revwalk *walk;
177+
git_oid id;
178+
int i, error;
179+
180+
cl_git_pass(git_revwalk_new(&walk, _repo));
181+
cl_git_pass(git_revwalk_push(walk, &_head_id));
182+
183+
/* Add hide callback, pass id of parent of initial commit as payload data */
184+
cl_git_pass(git_revwalk_add_hide_cb(walk, hide_commit_use_payload_cb, &commit_ids[5]));
185+
186+
i = 0;
187+
while ((error = git_revwalk_next(&id, walk)) == 0) {
188+
cl_assert_equal_i(git_oid_cmp(&id, &commit_ids[i]), 0);
189+
i++;
190+
}
191+
192+
/* walker should return four commits */
193+
cl_assert_equal_i(i, 4);
194+
cl_assert_equal_i(error, GIT_ITEROVER);
195+
196+
git_revwalk_free(walk);
197+
}
198+

0 commit comments

Comments
 (0)