1313#include "ref-filter.h"
1414#include "refs.h"
1515#include "revision.h"
16+ #include "run-command.h"
1617#include "strbuf.h"
1718#include "strvec.h"
1819#include "trace2.h"
@@ -171,6 +172,12 @@ struct large_item {
171172 * order).
172173 */
173174 struct object_id containing_commit_oid ;
175+
176+ /*
177+ * Lookup `containing_commit_oid` using `git name-rev`.
178+ * Lazy allocate this post-treewalk.
179+ */
180+ struct strbuf name_rev ;
174181};
175182
176183struct large_item_vec {
@@ -207,8 +214,10 @@ static void free_large_item_vec(struct large_item_vec *vec)
207214 if (!vec )
208215 return ;
209216
210- for (size_t k = 0 ; k < vec -> nr_items ; k ++ )
217+ for (size_t k = 0 ; k < vec -> nr_items ; k ++ ) {
211218 strbuf_release (& vec -> items [k ].name );
219+ strbuf_release (& vec -> items [k ].name_rev );
220+ }
212221
213222 free (vec -> dimension_label );
214223 free (vec -> item_label );
@@ -243,6 +252,9 @@ static void maybe_insert_large_item(struct large_item_vec *vec,
243252 * The last large_item in the vector is about to be
244253 * overwritten by the previous one during the shift.
245254 * Steal its allocated strbuf and reuse it.
255+ *
256+ * We can ignore .name_rev because it will not be
257+ * allocated until after the treewalk.
246258 */
247259 strbuf_release (& vec -> items [vec -> nr_items - 1 ].name );
248260
@@ -764,7 +776,7 @@ static void survey_report_largest_vec(struct large_item_vec *vec)
764776 return ;
765777
766778 table .table_name = vec -> dimension_label ;
767- strvec_pushl (& table .header , "Size" , "OID" , "Name" , "Commit" , NULL );
779+ strvec_pushl (& table .header , "Size" , "OID" , "Name" , "Commit" , "Name-Rev" , NULL );
768780
769781 for (size_t k = 0 ; k < vec -> nr_items ; k ++ ) {
770782 struct large_item * pk = & vec -> items [k ];
@@ -775,6 +787,7 @@ static void survey_report_largest_vec(struct large_item_vec *vec)
775787 insert_table_rowv (& table , size .buf , oid_to_hex (& pk -> oid ), pk -> name .buf ,
776788 is_null_oid (& pk -> containing_commit_oid ) ?
777789 "" : oid_to_hex (& pk -> containing_commit_oid ),
790+ pk -> name_rev .len ? pk -> name_rev .buf : "" ,
778791 NULL );
779792 }
780793 }
@@ -1125,6 +1138,73 @@ static void do_load_refs(struct survey_context *ctx,
11251138 ref_sorting_release (sorting );
11261139}
11271140
1141+ /*
1142+ * Try to run `git name-rev` on each of the containing-commit-oid's
1143+ * in this large-item-vec to get a pretty name for each OID. Silently
1144+ * ignore errors if it fails because this info is nice to have but not
1145+ * essential.
1146+ */
1147+ static void large_item_vec_lookup_name_rev (struct survey_context * ctx ,
1148+ struct large_item_vec * vec )
1149+ {
1150+ struct child_process cp = CHILD_PROCESS_INIT ;
1151+ struct strbuf in = STRBUF_INIT ;
1152+ struct strbuf out = STRBUF_INIT ;
1153+ const char * line ;
1154+ size_t k ;
1155+
1156+ if (!vec || !vec -> nr_items )
1157+ return ;
1158+
1159+ ctx -> progress_total += vec -> nr_items ;
1160+ display_progress (ctx -> progress , ctx -> progress_total );
1161+
1162+ for (k = 0 ; k < vec -> nr_items ; k ++ )
1163+ strbuf_addf (& in , "%s\n" , oid_to_hex (& vec -> items [k ].containing_commit_oid ));
1164+
1165+ cp .git_cmd = 1 ;
1166+ strvec_pushl (& cp .args , "name-rev" , "--name-only" , "--annotate-stdin" , NULL );
1167+ if (pipe_command (& cp , in .buf , in .len , & out , 0 , NULL , 0 )) {
1168+ strbuf_release (& in );
1169+ strbuf_release (& out );
1170+ return ;
1171+ }
1172+
1173+ line = out .buf ;
1174+ k = 0 ;
1175+ while (* line ) {
1176+ const char * eol = strchrnul (line , '\n' );
1177+
1178+ strbuf_init (& vec -> items [k ].name_rev , 0 );
1179+ strbuf_add (& vec -> items [k ].name_rev , line , (eol - line ));
1180+
1181+ line = eol + 1 ;
1182+ k ++ ;
1183+ }
1184+
1185+ strbuf_release (& in );
1186+ strbuf_release (& out );
1187+ }
1188+
1189+ static void do_lookup_name_rev (struct survey_context * ctx )
1190+ {
1191+ if (ctx -> opts .show_progress ) {
1192+ ctx -> progress_total = 0 ;
1193+ ctx -> progress = start_progress (_ ("Resolving name-revs..." ), 0 );
1194+ }
1195+
1196+ large_item_vec_lookup_name_rev (ctx , ctx -> report .reachable_objects .commits .vec_largest_by_nr_parents );
1197+ large_item_vec_lookup_name_rev (ctx , ctx -> report .reachable_objects .commits .vec_largest_by_size_bytes );
1198+
1199+ large_item_vec_lookup_name_rev (ctx , ctx -> report .reachable_objects .trees .vec_largest_by_nr_entries );
1200+ large_item_vec_lookup_name_rev (ctx , ctx -> report .reachable_objects .trees .vec_largest_by_size_bytes );
1201+
1202+ large_item_vec_lookup_name_rev (ctx , ctx -> report .reachable_objects .blobs .vec_largest_by_size_bytes );
1203+
1204+ if (ctx -> opts .show_progress )
1205+ stop_progress (& ctx -> progress );
1206+ }
1207+
11281208/*
11291209 * The REFS phase:
11301210 *
@@ -1478,7 +1558,10 @@ static void survey_phase_objects(struct survey_context *ctx)
14781558
14791559 release_revisions (& revs );
14801560 trace2_region_leave ("survey" , "phase/objects" , ctx -> repo );
1481- }
1561+
1562+ trace2_region_enter ("survey" , "phase/namerev" , the_repository );
1563+ do_lookup_name_rev (ctx );
1564+ trace2_region_enter ("survey" , "phase/namerev" , the_repository );}
14821565
14831566int cmd_survey (int argc , const char * * argv , const char * prefix , struct repository * repo )
14841567{
0 commit comments