9
9
#include "dir.h"
10
10
#include "fsmonitor.h"
11
11
12
+ struct modify_index_context {
13
+ struct index_state * write ;
14
+ struct pattern_list * pl ;
15
+ };
16
+
12
17
static struct cache_entry * construct_sparse_dir_entry (
13
18
struct index_state * istate ,
14
19
const char * sparse_dir ,
@@ -173,7 +178,7 @@ int convert_to_sparse(struct index_state *istate, int flags)
173
178
* If the index is already sparse, empty, or otherwise
174
179
* cannot be converted to sparse, do not convert.
175
180
*/
176
- if (istate -> sparse_index || !istate -> cache_nr ||
181
+ if (istate -> sparse_index == INDEX_COLLAPSED || !istate -> cache_nr ||
177
182
!is_sparse_index_allowed (istate , flags ))
178
183
return 0 ;
179
184
@@ -214,7 +219,7 @@ int convert_to_sparse(struct index_state *istate, int flags)
214
219
FREE_AND_NULL (istate -> fsmonitor_dirty );
215
220
FREE_AND_NULL (istate -> fsmonitor_last_update );
216
221
217
- istate -> sparse_index = 1 ;
222
+ istate -> sparse_index = INDEX_COLLAPSED ;
218
223
trace2_region_leave ("index" , "convert_to_sparse" , istate -> repo );
219
224
return 0 ;
220
225
}
@@ -231,56 +236,148 @@ static int add_path_to_index(const struct object_id *oid,
231
236
struct strbuf * base , const char * path ,
232
237
unsigned int mode , void * context )
233
238
{
234
- struct index_state * istate = (struct index_state * )context ;
239
+ struct modify_index_context * ctx = (struct modify_index_context * )context ;
235
240
struct cache_entry * ce ;
236
241
size_t len = base -> len ;
237
242
238
- if (S_ISDIR (mode ))
239
- return READ_TREE_RECURSIVE ;
243
+ if (S_ISDIR (mode )) {
244
+ int dtype ;
245
+ size_t baselen = base -> len ;
246
+ if (!ctx -> pl )
247
+ return READ_TREE_RECURSIVE ;
248
+
249
+ /*
250
+ * Have we expanded to a point outside of the sparse-checkout?
251
+ *
252
+ * Artificially pad the path name with a slash "/" to
253
+ * indicate it as a directory, and add an arbitrary file
254
+ * name ("-") so we can consider base->buf as a file name
255
+ * to match against the cone-mode patterns.
256
+ *
257
+ * If we compared just "path", then we would expand more
258
+ * than we should. Since every file at root is always
259
+ * included, we would expand every directory at root at
260
+ * least one level deep instead of using sparse directory
261
+ * entries.
262
+ */
263
+ strbuf_addstr (base , path );
264
+ strbuf_add (base , "/-" , 2 );
265
+
266
+ if (path_matches_pattern_list (base -> buf , base -> len ,
267
+ NULL , & dtype ,
268
+ ctx -> pl , ctx -> write )) {
269
+ strbuf_setlen (base , baselen );
270
+ return READ_TREE_RECURSIVE ;
271
+ }
240
272
241
- strbuf_addstr (base , path );
273
+ /*
274
+ * The path "{base}{path}/" is a sparse directory. Create the correct
275
+ * name for inserting the entry into the index.
276
+ */
277
+ strbuf_setlen (base , base -> len - 1 );
278
+ } else {
279
+ strbuf_addstr (base , path );
280
+ }
242
281
243
- ce = make_cache_entry (istate , mode , oid , base -> buf , 0 , 0 );
282
+ ce = make_cache_entry (ctx -> write , mode , oid , base -> buf , 0 , 0 );
244
283
ce -> ce_flags |= CE_SKIP_WORKTREE | CE_EXTENDED ;
245
- set_index_entry (istate , istate -> cache_nr ++ , ce );
284
+ set_index_entry (ctx -> write , ctx -> write -> cache_nr ++ , ce );
246
285
247
286
strbuf_setlen (base , len );
248
287
return 0 ;
249
288
}
250
289
251
- void ensure_full_index (struct index_state * istate )
290
+ void expand_index (struct index_state * istate , struct pattern_list * pl )
252
291
{
253
292
int i ;
254
293
struct index_state * full ;
255
294
struct strbuf base = STRBUF_INIT ;
295
+ const char * tr_region ;
296
+ struct modify_index_context ctx ;
256
297
257
- if (!istate || !istate -> sparse_index )
298
+ /*
299
+ * If the index is already full, then keep it full. We will convert
300
+ * it to a sparse index on write, if possible.
301
+ */
302
+ if (!istate || istate -> sparse_index == INDEX_EXPANDED )
258
303
return ;
259
304
305
+ /*
306
+ * If our index is sparse, but our new pattern set does not use
307
+ * cone mode patterns, then we need to expand the index before we
308
+ * continue. A NULL pattern set indicates a full expansion to a
309
+ * full index.
310
+ */
311
+ if (pl && !pl -> use_cone_patterns ) {
312
+ pl = NULL ;
313
+ } else {
314
+ /*
315
+ * We might contract file entries into sparse-directory
316
+ * entries, and for that we will need the cache tree to
317
+ * be recomputed.
318
+ */
319
+ cache_tree_free (& istate -> cache_tree );
320
+
321
+ /*
322
+ * If there is a problem creating the cache tree, then we
323
+ * need to expand to a full index since we cannot satisfy
324
+ * the current request as a sparse index.
325
+ */
326
+ if (cache_tree_update (istate , 0 ))
327
+ pl = NULL ;
328
+ }
329
+
260
330
if (!istate -> repo )
261
331
istate -> repo = the_repository ;
262
332
263
- trace2_region_enter ("index" , "ensure_full_index" , istate -> repo );
333
+ /*
334
+ * A NULL pattern set indicates we are expanding a full index, so
335
+ * we use a special region name that indicates the full expansion.
336
+ * This is used by test cases, but also helps to differentiate the
337
+ * two cases.
338
+ */
339
+ tr_region = pl ? "expand_index" : "ensure_full_index" ;
340
+ trace2_region_enter ("index" , tr_region , istate -> repo );
264
341
265
342
/* initialize basics of new index */
266
343
full = xcalloc (1 , sizeof (struct index_state ));
267
344
memcpy (full , istate , sizeof (struct index_state ));
268
345
346
+ /*
347
+ * This slightly-misnamed 'full' index might still be sparse if we
348
+ * are only modifying the list of sparse directories. This hinges
349
+ * on whether we have a non-NULL pattern list.
350
+ */
351
+ full -> sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED ;
352
+
269
353
/* then change the necessary things */
270
- full -> sparse_index = 0 ;
271
354
full -> cache_alloc = (3 * istate -> cache_alloc ) / 2 ;
272
355
full -> cache_nr = 0 ;
273
356
ALLOC_ARRAY (full -> cache , full -> cache_alloc );
274
357
358
+ ctx .write = full ;
359
+ ctx .pl = pl ;
360
+
275
361
for (i = 0 ; i < istate -> cache_nr ; i ++ ) {
276
362
struct cache_entry * ce = istate -> cache [i ];
277
363
struct tree * tree ;
278
364
struct pathspec ps ;
365
+ int dtype ;
279
366
280
367
if (!S_ISSPARSEDIR (ce -> ce_mode )) {
281
368
set_index_entry (full , full -> cache_nr ++ , ce );
282
369
continue ;
283
370
}
371
+
372
+ /* We now have a sparse directory entry. Should we expand? */
373
+ if (pl &&
374
+ path_matches_pattern_list (ce -> name , ce -> ce_namelen ,
375
+ NULL , & dtype ,
376
+ pl , istate ) == NOT_MATCHED ) {
377
+ set_index_entry (full , full -> cache_nr ++ , ce );
378
+ continue ;
379
+ }
380
+
284
381
if (!(ce -> ce_flags & CE_SKIP_WORKTREE ))
285
382
warning (_ ("index entry is a directory, but not sparse (%08x)" ),
286
383
ce -> ce_flags );
@@ -297,7 +394,7 @@ void ensure_full_index(struct index_state *istate)
297
394
strbuf_add (& base , ce -> name , strlen (ce -> name ));
298
395
299
396
read_tree_at (istate -> repo , tree , & base , & ps ,
300
- add_path_to_index , full );
397
+ add_path_to_index , & ctx );
301
398
302
399
/* free directory entries. full entries are re-used */
303
400
discard_cache_entry (ce );
@@ -306,7 +403,7 @@ void ensure_full_index(struct index_state *istate)
306
403
/* Copy back into original index. */
307
404
memcpy (& istate -> name_hash , & full -> name_hash , sizeof (full -> name_hash ));
308
405
memcpy (& istate -> dir_hash , & full -> dir_hash , sizeof (full -> dir_hash ));
309
- istate -> sparse_index = 0 ;
406
+ istate -> sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED ;
310
407
free (istate -> cache );
311
408
istate -> cache = full -> cache ;
312
409
istate -> cache_nr = full -> cache_nr ;
@@ -322,7 +419,12 @@ void ensure_full_index(struct index_state *istate)
322
419
cache_tree_free (& istate -> cache_tree );
323
420
cache_tree_update (istate , 0 );
324
421
325
- trace2_region_leave ("index" , "ensure_full_index" , istate -> repo );
422
+ trace2_region_leave ("index" , tr_region , istate -> repo );
423
+ }
424
+
425
+ void ensure_full_index (struct index_state * istate )
426
+ {
427
+ expand_index (istate , NULL );
326
428
}
327
429
328
430
void ensure_correct_sparsity (struct index_state * istate )
0 commit comments