@@ -22,6 +22,7 @@ struct type_and_oid_list
22
22
{
23
23
enum object_type type ;
24
24
struct oid_array oids ;
25
+ int maybe_interesting ;
25
26
};
26
27
27
28
#define TYPE_AND_OID_LIST_INIT { \
@@ -124,6 +125,8 @@ static int add_children(struct path_walk_context *ctx,
124
125
strmap_put (& ctx -> paths_to_lists , path .buf , list );
125
126
string_list_append (& ctx -> path_stack , path .buf );
126
127
}
128
+ if (!(o -> flags & UNINTERESTING ))
129
+ list -> maybe_interesting = 1 ;
127
130
oid_array_append (& list -> oids , & entry .oid );
128
131
}
129
132
@@ -145,6 +148,40 @@ static int walk_path(struct path_walk_context *ctx,
145
148
146
149
list = strmap_get (& ctx -> paths_to_lists , path );
147
150
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
+
148
185
/* Evaluate function pointer on this data, if requested. */
149
186
if ((list -> type == OBJ_TREE && ctx -> info -> trees ) ||
150
187
(list -> type == OBJ_BLOB && ctx -> info -> blobs ))
@@ -187,7 +224,7 @@ static void clear_strmap(struct strmap *map)
187
224
int walk_objects_by_path (struct path_walk_info * info )
188
225
{
189
226
const char * root_path = "" ;
190
- int ret = 0 ;
227
+ int ret = 0 , has_uninteresting = 0 ;
191
228
size_t commits_nr = 0 , paths_nr = 0 ;
192
229
struct commit * c ;
193
230
struct type_and_oid_list * root_tree_list ;
@@ -199,6 +236,7 @@ int walk_objects_by_path(struct path_walk_info *info)
199
236
.path_stack = STRING_LIST_INIT_DUP ,
200
237
.paths_to_lists = STRMAP_INIT
201
238
};
239
+ struct oidset root_tree_set = OIDSET_INIT ;
202
240
203
241
trace2_region_enter ("path-walk" , "commit-walk" , info -> revs -> repo );
204
242
@@ -211,6 +249,7 @@ int walk_objects_by_path(struct path_walk_info *info)
211
249
/* Insert a single list for the root tree into the paths. */
212
250
CALLOC_ARRAY (root_tree_list , 1 );
213
251
root_tree_list -> type = OBJ_TREE ;
252
+ root_tree_list -> maybe_interesting = 1 ;
214
253
strmap_put (& ctx .paths_to_lists , root_path , root_tree_list );
215
254
216
255
/*
@@ -301,10 +340,17 @@ int walk_objects_by_path(struct path_walk_info *info)
301
340
oid = get_commit_tree_oid (c );
302
341
t = lookup_tree (info -> revs -> repo , oid );
303
342
304
- if (t )
343
+ if (t ) {
344
+ oidset_insert (& root_tree_set , oid );
305
345
oid_array_append (& root_tree_list -> oids , oid );
306
- else
346
+ } else {
307
347
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
+ }
308
354
}
309
355
310
356
trace2_data_intmax ("path-walk" , ctx .repo , "commits" , commits_nr );
@@ -317,6 +363,21 @@ int walk_objects_by_path(struct path_walk_info *info)
317
363
oid_array_clear (& commit_list -> oids );
318
364
free (commit_list );
319
365
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
+
320
381
string_list_append (& ctx .path_stack , root_path );
321
382
322
383
trace2_region_enter ("path-walk" , "path-walk" , info -> revs -> repo );
0 commit comments