2222#include "progress.h"
2323#include "reflog-walk.h"
2424#include "oidset.h"
25+ #include "oidmap.h"
2526#include "packfile.h"
27+ #include "quote.h"
28+ #include "strbuf.h"
2629
2730static const char rev_list_usage [] =
2831"git rev-list [<options>] <commit>... [--] [<path>...]\n"
@@ -73,11 +76,17 @@ static unsigned progress_counter;
7376static struct oidset omitted_objects ;
7477static int arg_print_omitted ; /* print objects omitted by filter */
7578
76- static struct oidset missing_objects ;
79+ struct missing_objects_map_entry {
80+ struct oidmap_entry entry ;
81+ const char * path ;
82+ unsigned type ;
83+ };
84+ static struct oidmap missing_objects ;
7785enum missing_action {
7886 MA_ERROR = 0 , /* fail if any missing objects are encountered */
7987 MA_ALLOW_ANY , /* silently allow ALL missing objects */
8088 MA_PRINT , /* print ALL missing objects in special section */
89+ MA_PRINT_INFO , /* same as MA_PRINT but also prints missing object info */
8190 MA_ALLOW_PROMISOR , /* silently allow all missing PROMISOR objects */
8291};
8392static enum missing_action arg_missing_action ;
@@ -101,7 +110,49 @@ static off_t get_object_disk_usage(struct object *obj)
101110 return size ;
102111}
103112
104- static inline void finish_object__ma (struct object * obj )
113+ static void add_missing_object_entry (struct object_id * oid , const char * path ,
114+ unsigned type )
115+ {
116+ struct missing_objects_map_entry * entry ;
117+
118+ if (oidmap_get (& missing_objects , oid ))
119+ return ;
120+
121+ CALLOC_ARRAY (entry , 1 );
122+ entry -> entry .oid = * oid ;
123+ entry -> type = type ;
124+ if (path )
125+ entry -> path = xstrdup (path );
126+ oidmap_put (& missing_objects , entry );
127+ }
128+
129+ static void print_missing_object (struct missing_objects_map_entry * entry ,
130+ int print_missing_info )
131+ {
132+ struct strbuf sb = STRBUF_INIT ;
133+
134+ if (!print_missing_info ) {
135+ printf ("?%s\n" , oid_to_hex (& entry -> entry .oid ));
136+ return ;
137+ }
138+
139+ if (entry -> path && * entry -> path ) {
140+ struct strbuf path = STRBUF_INIT ;
141+
142+ strbuf_addstr (& sb , " path=" );
143+ quote_path (entry -> path , NULL , & path , QUOTE_PATH_QUOTE_SP );
144+ strbuf_addbuf (& sb , & path );
145+
146+ strbuf_release (& path );
147+ }
148+ if (entry -> type )
149+ strbuf_addf (& sb , " type=%s" , type_name (entry -> type ));
150+
151+ printf ("?%s%s\n" , oid_to_hex (& entry -> entry .oid ), sb .buf );
152+ strbuf_release (& sb );
153+ }
154+
155+ static inline void finish_object__ma (struct object * obj , const char * name )
105156{
106157 /*
107158 * Whether or not we try to dynamically fetch missing objects
@@ -119,7 +170,8 @@ static inline void finish_object__ma(struct object *obj)
119170 return ;
120171
121172 case MA_PRINT :
122- oidset_insert (& missing_objects , & obj -> oid );
173+ case MA_PRINT_INFO :
174+ add_missing_object_entry (& obj -> oid , name , obj -> type );
123175 return ;
124176
125177 case MA_ALLOW_PROMISOR :
@@ -152,7 +204,7 @@ static void show_commit(struct commit *commit, void *data)
152204
153205 if (revs -> do_not_die_on_missing_objects &&
154206 oidset_contains (& revs -> missing_commits , & commit -> object .oid )) {
155- finish_object__ma (& commit -> object );
207+ finish_object__ma (& commit -> object , NULL );
156208 return ;
157209 }
158210
@@ -268,12 +320,11 @@ static void show_commit(struct commit *commit, void *data)
268320 finish_commit (commit );
269321}
270322
271- static int finish_object (struct object * obj , const char * name UNUSED ,
272- void * cb_data )
323+ static int finish_object (struct object * obj , const char * name , void * cb_data )
273324{
274325 struct rev_list_info * info = cb_data ;
275326 if (oid_object_info_extended (the_repository , & obj -> oid , NULL , 0 ) < 0 ) {
276- finish_object__ma (obj );
327+ finish_object__ma (obj , name );
277328 return 1 ;
278329 }
279330 if (info -> revs -> verify_objects && !obj -> parsed && obj -> type != OBJ_COMMIT )
@@ -414,6 +465,12 @@ static inline int parse_missing_action_value(const char *value)
414465 return 1 ;
415466 }
416467
468+ if (!strcmp (value , "print-info" )) {
469+ arg_missing_action = MA_PRINT_INFO ;
470+ fetch_if_missing = 0 ;
471+ return 1 ;
472+ }
473+
417474 if (!strcmp (value , "allow-promisor" )) {
418475 arg_missing_action = MA_ALLOW_PROMISOR ;
419476 fetch_if_missing = 0 ;
@@ -781,10 +838,18 @@ int cmd_rev_list(int argc,
781838
782839 if (arg_print_omitted )
783840 oidset_init (& omitted_objects , DEFAULT_OIDSET_SIZE );
784- if (arg_missing_action == MA_PRINT ) {
785- oidset_init (& missing_objects , DEFAULT_OIDSET_SIZE );
841+ if (arg_missing_action == MA_PRINT ||
842+ arg_missing_action == MA_PRINT_INFO ) {
843+ struct oidset_iter iter ;
844+ struct object_id * oid ;
845+
846+ oidmap_init (& missing_objects , DEFAULT_OIDSET_SIZE );
847+ oidset_iter_init (& revs .missing_commits , & iter );
848+
786849 /* Add missing tips */
787- oidset_insert_from_set (& missing_objects , & revs .missing_commits );
850+ while ((oid = oidset_iter_next (& iter )))
851+ add_missing_object_entry (oid , NULL , 0 );
852+
788853 oidset_clear (& revs .missing_commits );
789854 }
790855
@@ -800,13 +865,20 @@ int cmd_rev_list(int argc,
800865 printf ("~%s\n" , oid_to_hex (oid ));
801866 oidset_clear (& omitted_objects );
802867 }
803- if (arg_missing_action == MA_PRINT ) {
804- struct oidset_iter iter ;
805- struct object_id * oid ;
806- oidset_iter_init (& missing_objects , & iter );
807- while ((oid = oidset_iter_next (& iter )))
808- printf ("?%s\n" , oid_to_hex (oid ));
809- oidset_clear (& missing_objects );
868+ if (arg_missing_action == MA_PRINT ||
869+ arg_missing_action == MA_PRINT_INFO ) {
870+ struct missing_objects_map_entry * entry ;
871+ struct oidmap_iter iter ;
872+
873+ oidmap_iter_init (& missing_objects , & iter );
874+
875+ while ((entry = oidmap_iter_next (& iter ))) {
876+ print_missing_object (entry , arg_missing_action ==
877+ MA_PRINT_INFO );
878+ free ((void * )entry -> path );
879+ }
880+
881+ oidmap_free (& missing_objects , true);
810882 }
811883
812884 stop_progress (& progress );
0 commit comments