33#include "builtin.h"
44#include "environment.h"
55#include "parse-options.h"
6+ #include "path-walk.h"
67#include "quote.h"
78#include "ref-filter.h"
89#include "refs.h"
10+ #include "revision.h"
911#include "strbuf.h"
1012#include "string-list.h"
1113#include "shallow.h"
@@ -167,6 +169,18 @@ struct ref_stats {
167169 size_t others ;
168170};
169171
172+ struct object_stats {
173+ size_t tags ;
174+ size_t commits ;
175+ size_t trees ;
176+ size_t blobs ;
177+ };
178+
179+ struct repo_structure {
180+ struct ref_stats refs ;
181+ struct object_stats objects ;
182+ };
183+
170184struct stats_table {
171185 struct string_list rows ;
172186
@@ -234,9 +248,17 @@ static inline size_t get_total_reference_count(struct ref_stats *stats)
234248 return stats -> branches + stats -> remotes + stats -> tags + stats -> others ;
235249}
236250
251+ static inline size_t get_total_object_count (struct object_stats * stats )
252+ {
253+ return stats -> tags + stats -> commits + stats -> trees + stats -> blobs ;
254+ }
255+
237256static void stats_table_setup_structure (struct stats_table * table ,
238- struct ref_stats * refs )
257+ struct repo_structure * stats )
239258{
259+ struct object_stats * objects = & stats -> objects ;
260+ struct ref_stats * refs = & stats -> refs ;
261+ size_t object_total ;
240262 size_t ref_total ;
241263
242264 ref_total = get_total_reference_count (refs );
@@ -246,6 +268,15 @@ static void stats_table_setup_structure(struct stats_table *table,
246268 stats_table_count_addf (table , refs -> tags , " * %s" , _ ("Tags" ));
247269 stats_table_count_addf (table , refs -> remotes , " * %s" , _ ("Remotes" ));
248270 stats_table_count_addf (table , refs -> others , " * %s" , _ ("Others" ));
271+
272+ object_total = get_total_object_count (objects );
273+ stats_table_addf (table , "" );
274+ stats_table_addf (table , "* %s" , _ ("Reachable objects" ));
275+ stats_table_count_addf (table , object_total , " * %s" , _ ("Count" ));
276+ stats_table_count_addf (table , objects -> commits , " * %s" , _ ("Commits" ));
277+ stats_table_count_addf (table , objects -> trees , " * %s" , _ ("Trees" ));
278+ stats_table_count_addf (table , objects -> blobs , " * %s" , _ ("Blobs" ));
279+ stats_table_count_addf (table , objects -> tags , " * %s" , _ ("Tags" ));
249280}
250281
251282static void stats_table_print_structure (const struct stats_table * table )
@@ -299,12 +330,18 @@ static void stats_table_clear(struct stats_table *table)
299330 string_list_clear (& table -> rows , 1 );
300331}
301332
333+ struct count_references_data {
334+ struct ref_stats * stats ;
335+ struct rev_info * revs ;
336+ };
337+
302338static int count_references (const char * refname ,
303339 const char * referent UNUSED ,
304- const struct object_id * oid UNUSED ,
340+ const struct object_id * oid ,
305341 int flags UNUSED , void * cb_data )
306342{
307- struct ref_stats * stats = cb_data ;
343+ struct count_references_data * data = cb_data ;
344+ struct ref_stats * stats = data -> stats ;
308345
309346 switch (ref_kind_from_refname (refname )) {
310347 case FILTER_REFS_BRANCHES :
@@ -323,13 +360,64 @@ static int count_references(const char *refname,
323360 BUG ("unexpected reference type" );
324361 }
325362
363+ /*
364+ * While iterating through references for counting, also add OIDs in
365+ * preparation for the path walk.
366+ */
367+ add_pending_oid (data -> revs , NULL , oid , 0 );
368+
326369 return 0 ;
327370}
328371
329372static void structure_count_references (struct ref_stats * stats ,
373+ struct rev_info * revs ,
330374 struct repository * repo )
331375{
332- refs_for_each_ref (get_main_ref_store (repo ), count_references , & stats );
376+ struct count_references_data data = {
377+ .stats = stats ,
378+ .revs = revs ,
379+ };
380+
381+ refs_for_each_ref (get_main_ref_store (repo ), count_references , & data );
382+ }
383+
384+
385+ static int count_objects (const char * path UNUSED , struct oid_array * oids ,
386+ enum object_type type , void * cb_data )
387+ {
388+ struct object_stats * stats = cb_data ;
389+
390+ switch (type ) {
391+ case OBJ_TAG :
392+ stats -> tags += oids -> nr ;
393+ break ;
394+ case OBJ_COMMIT :
395+ stats -> commits += oids -> nr ;
396+ break ;
397+ case OBJ_TREE :
398+ stats -> trees += oids -> nr ;
399+ break ;
400+ case OBJ_BLOB :
401+ stats -> blobs += oids -> nr ;
402+ break ;
403+ default :
404+ BUG ("invalid object type" );
405+ }
406+
407+ return 0 ;
408+ }
409+
410+ static void structure_count_objects (struct object_stats * stats ,
411+ struct rev_info * revs )
412+ {
413+ struct path_walk_info info = PATH_WALK_INFO_INIT ;
414+
415+ info .revs = revs ;
416+ info .path_fn = count_objects ;
417+ info .path_fn_data = stats ;
418+
419+ walk_objects_by_path (& info );
420+ path_walk_info_clear (& info );
333421}
334422
335423static int cmd_repo_structure (int argc , const char * * argv , const char * prefix ,
@@ -338,19 +426,24 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
338426 struct stats_table table = {
339427 .rows = STRING_LIST_INIT_DUP ,
340428 };
341- struct ref_stats stats = { 0 };
429+ struct repo_structure stats = { 0 };
430+ struct rev_info revs ;
342431 struct option options [] = { 0 };
343432
344433 argc = parse_options (argc , argv , prefix , options , repo_usage , 0 );
345434 if (argc )
346435 usage (_ ("too many arguments" ));
347436
348- structure_count_references (& stats , repo );
437+ repo_init_revisions (repo , & revs , prefix );
438+
439+ structure_count_references (& stats .refs , & revs , repo );
440+ structure_count_objects (& stats .objects , & revs );
349441
350442 stats_table_setup_structure (& table , & stats );
351443 stats_table_print_structure (& table );
352444
353445 stats_table_clear (& table );
446+ release_revisions (& revs );
354447
355448 return 0 ;
356449}
0 commit comments