@@ -22,6 +22,7 @@ struct type_and_oid_list
2222{
2323 enum object_type type ;
2424 struct oid_array oids ;
25+ int maybe_interesting ;
2526};
2627
2728#define TYPE_AND_OID_LIST_INIT { \
@@ -124,6 +125,8 @@ static int add_children(struct path_walk_context *ctx,
124125 strmap_put (& ctx -> paths_to_lists , path .buf , list );
125126 string_list_append (& ctx -> path_stack , path .buf );
126127 }
128+ if (!(o -> flags & UNINTERESTING ))
129+ list -> maybe_interesting = 1 ;
127130 oid_array_append (& list -> oids , & entry .oid );
128131 }
129132
@@ -145,6 +148,40 @@ static int walk_path(struct path_walk_context *ctx,
145148
146149 list = strmap_get (& ctx -> paths_to_lists , path );
147150
151+ if (ctx -> info -> prune_all_uninteresting ) {
152+ /*
153+ * This is true if all objects were UNINTERESTING
154+ * when added to the list.
155+ */
156+ if (!list -> maybe_interesting )
157+ return 0 ;
158+
159+ /*
160+ * But it's still possible that the objects were set
161+ * as UNINTERESTING after being added. Do a quick check.
162+ */
163+ list -> maybe_interesting = 0 ;
164+ for (size_t i = 0 ;
165+ !list -> maybe_interesting && i < list -> oids .nr ;
166+ i ++ ) {
167+ if (list -> type == OBJ_TREE ) {
168+ struct tree * t = lookup_tree (ctx -> repo ,
169+ & list -> oids .oid [i ]);
170+ if (t && !(t -> object .flags & UNINTERESTING ))
171+ list -> maybe_interesting = 1 ;
172+ } else {
173+ struct blob * b = lookup_blob (ctx -> repo ,
174+ & list -> oids .oid [i ]);
175+ if (b && !(b -> object .flags & UNINTERESTING ))
176+ list -> maybe_interesting = 1 ;
177+ }
178+ }
179+
180+ /* We have confirmed that all objects are UNINTERESTING. */
181+ if (!list -> maybe_interesting )
182+ return 0 ;
183+ }
184+
148185 /* Evaluate function pointer on this data, if requested. */
149186 if ((list -> type == OBJ_TREE && ctx -> info -> trees ) ||
150187 (list -> type == OBJ_BLOB && ctx -> info -> blobs ))
@@ -187,7 +224,7 @@ static void clear_strmap(struct strmap *map)
187224int walk_objects_by_path (struct path_walk_info * info )
188225{
189226 const char * root_path = "" ;
190- int ret = 0 ;
227+ int ret = 0 , has_uninteresting = 0 ;
191228 size_t commits_nr = 0 , paths_nr = 0 ;
192229 struct commit * c ;
193230 struct type_and_oid_list * root_tree_list ;
@@ -199,6 +236,7 @@ int walk_objects_by_path(struct path_walk_info *info)
199236 .path_stack = STRING_LIST_INIT_DUP ,
200237 .paths_to_lists = STRMAP_INIT
201238 };
239+ struct oidset root_tree_set = OIDSET_INIT ;
202240
203241 trace2_region_enter ("path-walk" , "commit-walk" , info -> revs -> repo );
204242
@@ -211,6 +249,7 @@ int walk_objects_by_path(struct path_walk_info *info)
211249 /* Insert a single list for the root tree into the paths. */
212250 CALLOC_ARRAY (root_tree_list , 1 );
213251 root_tree_list -> type = OBJ_TREE ;
252+ root_tree_list -> maybe_interesting = 1 ;
214253 strmap_put (& ctx .paths_to_lists , root_path , root_tree_list );
215254
216255 /*
@@ -301,10 +340,17 @@ int walk_objects_by_path(struct path_walk_info *info)
301340 oid = get_commit_tree_oid (c );
302341 t = lookup_tree (info -> revs -> repo , oid );
303342
304- if (t )
343+ if (t ) {
344+ oidset_insert (& root_tree_set , oid );
305345 oid_array_append (& root_tree_list -> oids , oid );
306- else
346+ } else {
307347 warning ("could not find tree %s" , oid_to_hex (oid ));
348+ }
349+
350+ if (t && (c -> object .flags & UNINTERESTING )) {
351+ t -> object .flags |= UNINTERESTING ;
352+ has_uninteresting = 1 ;
353+ }
308354 }
309355
310356 trace2_data_intmax ("path-walk" , ctx .repo , "commits" , commits_nr );
@@ -317,6 +363,21 @@ int walk_objects_by_path(struct path_walk_info *info)
317363 oid_array_clear (& commit_list -> oids );
318364 free (commit_list );
319365
366+ /*
367+ * Before performing a DFS of our paths and emitting them as interesting,
368+ * do a full walk of the trees to distribute the UNINTERESTING bit. Use
369+ * the sparse algorithm if prune_all_uninteresting was set.
370+ */
371+ if (has_uninteresting ) {
372+ trace2_region_enter ("path-walk" , "uninteresting-walk" , info -> revs -> repo );
373+ if (info -> prune_all_uninteresting )
374+ mark_trees_uninteresting_sparse (ctx .repo , & root_tree_set );
375+ else
376+ mark_trees_uninteresting_dense (ctx .repo , & root_tree_set );
377+ trace2_region_leave ("path-walk" , "uninteresting-walk" , info -> revs -> repo );
378+ }
379+ oidset_clear (& root_tree_set );
380+
320381 string_list_append (& ctx .path_stack , root_path );
321382
322383 trace2_region_enter ("path-walk" , "path-walk" , info -> revs -> repo );
0 commit comments