Skip to content

Commit 4d676f6

Browse files
author
Vicent Marti
committed
Merge pull request #464 from adelcambre/tree-count-recursive
Add Tree#count_recursive
2 parents bf0cf3c + 501f69d commit 4d676f6

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

ext/rugged/rugged_tree.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,69 @@ static VALUE rb_git_tree_entrycount(VALUE self)
9393
return INT2FIX(git_tree_entrycount(tree));
9494
}
9595

96+
struct rugged_treecount_cb_payload
97+
{
98+
int count;
99+
int limit;
100+
};
101+
102+
static int rugged__treecount_cb(const char *root, const git_tree_entry *entry, void *data)
103+
{
104+
struct rugged_treecount_cb_payload *payload = data;
105+
106+
if (payload->limit >= 0 && payload->count >= payload->limit) {
107+
return -1;
108+
} else if(git_tree_entry_type(entry) == GIT_OBJ_TREE) {
109+
return 0;
110+
} else {
111+
++(payload->count);
112+
return 1;
113+
}
114+
}
115+
116+
/*
117+
* call-seq:
118+
* tree.count_recursive(limit=nil) -> count
119+
*
120+
* `limit` - The maximum number of blobs to the count in the repository.
121+
* Rugged will stop walking the tree after `limit` items to avoid long
122+
* execution times.
123+
*
124+
* Return the number of blobs (up to the limit) contained in the tree and
125+
* all subtrees.
126+
*/
127+
static VALUE rb_git_tree_entrycount_recursive(int argc, VALUE* argv, VALUE self)
128+
{
129+
git_tree *tree;
130+
int error;
131+
struct rugged_treecount_cb_payload payload;
132+
VALUE rb_limit;
133+
134+
Data_Get_Struct(self, git_tree, tree);
135+
136+
rb_scan_args(argc, argv, "01", &rb_limit);
137+
138+
payload.limit = -1;
139+
payload.count = 0;
140+
141+
if (!NIL_P(rb_limit)) {
142+
Check_Type(rb_limit, T_FIXNUM);
143+
payload.limit = FIX2INT(rb_limit);
144+
}
145+
146+
147+
error = git_tree_walk(tree, GIT_TREEWALK_PRE, &rugged__treecount_cb, (void *)&payload);
148+
149+
if (error && giterr_last()->klass == GITERR_CALLBACK) {
150+
giterr_clear();
151+
error = 0;
152+
}
153+
154+
rugged_exception_check(error);
155+
156+
return INT2FIX(payload.count);
157+
}
158+
96159
/*
97160
* call-seq:
98161
* tree[e] -> entry
@@ -813,6 +876,7 @@ void Init_rugged_tree(void)
813876
*/
814877
rb_cRuggedTree = rb_define_class_under(rb_mRugged, "Tree", rb_cRuggedObject);
815878
rb_define_method(rb_cRuggedTree, "count", rb_git_tree_entrycount, 0);
879+
rb_define_method(rb_cRuggedTree, "count_recursive", rb_git_tree_entrycount_recursive, -1);
816880
rb_define_method(rb_cRuggedTree, "length", rb_git_tree_entrycount, 0);
817881
rb_define_method(rb_cRuggedTree, "get_entry", rb_git_tree_get_entry, 1);
818882
rb_define_method(rb_cRuggedTree, "get_entry_by_oid", rb_git_tree_get_entry_by_oid, 1);

test/tree_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ def test_read_tree_data
4747
assert_equal @oid, @tree.oid
4848
assert_equal :tree, @tree.type
4949
assert_equal 3, @tree.count
50+
assert_equal 6, @tree.count_recursive
51+
assert_equal 5, @tree.count_recursive(5)
52+
assert_equal 6, @tree.count_recursive(10)
53+
assert_raises(TypeError) do
54+
@tree.count_recursive("NaN")
55+
end
5056
assert_equal "1385f264afb75a56a5bec74243be9b367ba4ca08", @tree[0][:oid]
5157
assert_equal "fa49b077972391ad58037050f2a75f74e3671e92", @tree[1][:oid]
5258
end

0 commit comments

Comments
 (0)