@@ -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 );
0 commit comments