Coverage Report

Created: 2026-03-31 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/sparse-index.c
Line
Count
Source
1
#define USE_THE_REPOSITORY_VARIABLE
2
#define DISABLE_SIGN_COMPARE_WARNINGS
3
4
#include "git-compat-util.h"
5
#include "environment.h"
6
#include "ewah/ewok.h"
7
#include "gettext.h"
8
#include "name-hash.h"
9
#include "read-cache-ll.h"
10
#include "repository.h"
11
#include "sparse-index.h"
12
#include "tree.h"
13
#include "pathspec.h"
14
#include "trace2.h"
15
#include "cache-tree.h"
16
#include "config.h"
17
#include "dir.h"
18
#include "fsmonitor-ll.h"
19
#include "advice.h"
20
21
/**
22
 * This global is used by expand_index() to determine if we should give the
23
 * advice for advice.sparseIndexExpanded when expanding a sparse index to a full
24
 * one. However, this is sometimes done on purpose, such as in the sparse-checkout
25
 * builtin, even when index.sparse=false. This may be disabled in
26
 * convert_to_sparse() or by commands that know they will lead to a full
27
 * expansion, but this message is not actionable.
28
 */
29
int give_advice_on_expansion = 1;
30
#define ADVICE_MSG \
31
0
  "The sparse index is expanding to a full index, a slow operation.\n"   \
32
0
  "Your working directory likely has contents that are outside of\n"     \
33
0
  "your sparse-checkout patterns. Use 'git sparse-checkout list' to\n"   \
34
0
  "see your sparse-checkout definition and compare it to your working\n" \
35
0
  "directory contents. Cleaning up any merge conflicts or staged\n"      \
36
0
  "changes before running 'git sparse-checkout clean' or 'git\n"         \
37
0
  "sparse-checkout reapply' may assist in this cleanup."
38
39
struct modify_index_context {
40
  struct index_state *write;
41
  struct pattern_list *pl;
42
};
43
44
static struct cache_entry *construct_sparse_dir_entry(
45
        struct index_state *istate,
46
        const char *sparse_dir,
47
        struct cache_tree *tree)
48
0
{
49
0
  struct cache_entry *de;
50
51
0
  de = make_cache_entry(istate, S_IFDIR, &tree->oid, sparse_dir, 0, 0);
52
53
0
  de->ce_flags |= CE_SKIP_WORKTREE;
54
0
  return de;
55
0
}
56
57
/*
58
 * Returns the number of entries "inserted" into the index.
59
 */
60
static int convert_to_sparse_rec(struct index_state *istate,
61
         int num_converted,
62
         int start, int end,
63
         const char *ct_path, size_t ct_pathlen,
64
         struct cache_tree *ct)
65
0
{
66
0
  int i, can_convert = 1;
67
0
  int start_converted = num_converted;
68
0
  struct strbuf child_path = STRBUF_INIT;
69
70
  /*
71
   * Is the current path outside of the sparse cone?
72
   * Then check if the region can be replaced by a sparse
73
   * directory entry (everything is sparse and merged).
74
   */
75
0
  if (path_in_sparse_checkout(ct_path, istate))
76
0
    can_convert = 0;
77
78
0
  for (i = start; can_convert && i < end; i++) {
79
0
    struct cache_entry *ce = istate->cache[i];
80
81
0
    if (ce_stage(ce) ||
82
0
        S_ISGITLINK(ce->ce_mode) ||
83
0
        !(ce->ce_flags & CE_SKIP_WORKTREE))
84
0
      can_convert = 0;
85
0
  }
86
87
0
  if (can_convert) {
88
0
    struct cache_entry *se;
89
0
    se = construct_sparse_dir_entry(istate, ct_path, ct);
90
91
0
    istate->cache[num_converted++] = se;
92
0
    return 1;
93
0
  }
94
95
0
  for (i = start; i < end; ) {
96
0
    int count, span, pos = -1;
97
0
    const char *base, *slash;
98
0
    struct cache_entry *ce = istate->cache[i];
99
100
    /*
101
     * Detect if this is a normal entry outside of any subtree
102
     * entry.
103
     */
104
0
    base = ce->name + ct_pathlen;
105
0
    slash = strchr(base, '/');
106
107
0
    if (slash)
108
0
      pos = cache_tree_subtree_pos(ct, base, slash - base);
109
110
0
    if (pos < 0) {
111
0
      istate->cache[num_converted++] = ce;
112
0
      i++;
113
0
      continue;
114
0
    }
115
116
0
    strbuf_setlen(&child_path, 0);
117
0
    strbuf_add(&child_path, ce->name, slash - ce->name + 1);
118
119
0
    span = ct->down[pos]->cache_tree->entry_count;
120
0
    count = convert_to_sparse_rec(istate,
121
0
                num_converted, i, i + span,
122
0
                child_path.buf, child_path.len,
123
0
                ct->down[pos]->cache_tree);
124
0
    num_converted += count;
125
0
    i += span;
126
0
  }
127
128
0
  strbuf_release(&child_path);
129
0
  return num_converted - start_converted;
130
0
}
131
132
int set_sparse_index_config(struct repository *repo, int enable)
133
0
{
134
0
  int res = repo_config_set_worktree_gently(repo,
135
0
              "index.sparse",
136
0
              enable ? "true" : "false");
137
0
  prepare_repo_settings(repo);
138
0
  repo->settings.sparse_index = enable;
139
0
  return res;
140
0
}
141
142
static int index_has_unmerged_entries(struct index_state *istate)
143
0
{
144
0
  int i;
145
0
  for (i = 0; i < istate->cache_nr; i++) {
146
0
    if (ce_stage(istate->cache[i]))
147
0
      return 1;
148
0
  }
149
150
0
  return 0;
151
0
}
152
153
int is_sparse_index_allowed(struct index_state *istate, int flags)
154
0
{
155
0
  struct repo_config_values *cfg = repo_config_values(the_repository);
156
157
0
  if (!cfg->apply_sparse_checkout || !core_sparse_checkout_cone)
158
0
    return 0;
159
160
0
  if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
161
0
    int test_env;
162
163
    /*
164
     * The sparse index is not (yet) integrated with a split index.
165
     */
166
0
    if (istate->split_index || git_env_bool("GIT_TEST_SPLIT_INDEX", 0))
167
0
      return 0;
168
    /*
169
     * The GIT_TEST_SPARSE_INDEX environment variable triggers the
170
     * index.sparse config variable to be on.
171
     */
172
0
    test_env = git_env_bool("GIT_TEST_SPARSE_INDEX", -1);
173
0
    if (test_env >= 0)
174
0
      set_sparse_index_config(istate->repo, test_env);
175
176
    /*
177
     * Only convert to sparse if index.sparse is set.
178
     */
179
0
    prepare_repo_settings(istate->repo);
180
0
    if (!istate->repo->settings.sparse_index)
181
0
      return 0;
182
0
  }
183
184
0
  if (init_sparse_checkout_patterns(istate))
185
0
    return 0;
186
187
  /*
188
   * We need cone-mode patterns to use sparse-index. If a user edits
189
   * their sparse-checkout file manually, then we can detect during
190
   * parsing that they are not actually using cone-mode patterns and
191
   * hence we need to abort this conversion _without error_. Warnings
192
   * already exist in the pattern parsing to inform the user of their
193
   * bad patterns.
194
   */
195
0
  if (!istate->sparse_checkout_patterns->use_cone_patterns)
196
0
    return 0;
197
198
0
  return 1;
199
0
}
200
201
int convert_to_sparse(struct index_state *istate, int flags)
202
0
{
203
  /*
204
   * If the index is already sparse, empty, or otherwise
205
   * cannot be converted to sparse, do not convert.
206
   */
207
0
  if (istate->sparse_index == INDEX_COLLAPSED || !istate->cache_nr ||
208
0
      !is_sparse_index_allowed(istate, flags))
209
0
    return 0;
210
211
  /*
212
   * If we are purposefully collapsing a full index, then don't give
213
   * advice when it is expanded later.
214
   */
215
0
  give_advice_on_expansion = 0;
216
217
  /*
218
   * NEEDSWORK: If we have unmerged entries, then stay full.
219
   * Unmerged entries prevent the cache-tree extension from working.
220
   */
221
0
  if (index_has_unmerged_entries(istate))
222
0
    return 0;
223
224
0
  if (!cache_tree_fully_valid(istate->cache_tree)) {
225
    /* Clear and recompute the cache-tree */
226
0
    cache_tree_free(&istate->cache_tree);
227
228
    /*
229
     * Silently return if there is a problem with the cache tree update,
230
     * which might just be due to a conflict state in some entry.
231
     *
232
     * This might create new tree objects, so be sure to use
233
     * WRITE_TREE_MISSING_OK.
234
     */
235
0
    if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
236
0
      return 0;
237
0
  }
238
239
0
  remove_fsmonitor(istate);
240
241
0
  trace2_region_enter("index", "convert_to_sparse", istate->repo);
242
0
  istate->cache_nr = convert_to_sparse_rec(istate,
243
0
             0, 0, istate->cache_nr,
244
0
             "", 0, istate->cache_tree);
245
246
  /* Clear and recompute the cache-tree */
247
0
  cache_tree_free(&istate->cache_tree);
248
0
  cache_tree_update(istate, 0);
249
250
0
  istate->fsmonitor_has_run_once = 0;
251
0
  ewah_free(istate->fsmonitor_dirty);
252
0
  istate->fsmonitor_dirty = NULL;
253
0
  FREE_AND_NULL(istate->fsmonitor_last_update);
254
255
0
  istate->sparse_index = INDEX_COLLAPSED;
256
0
  trace2_region_leave("index", "convert_to_sparse", istate->repo);
257
0
  return 0;
258
0
}
259
260
static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
261
0
{
262
0
  ALLOC_GROW(istate->cache, nr + 1, istate->cache_alloc);
263
264
0
  istate->cache[nr] = ce;
265
0
  add_name_hash(istate, ce);
266
0
}
267
268
static int add_path_to_index(const struct object_id *oid,
269
           struct strbuf *base, const char *path,
270
           unsigned int mode, void *context)
271
0
{
272
0
  struct modify_index_context *ctx = (struct modify_index_context *)context;
273
0
  struct cache_entry *ce;
274
0
  size_t len = base->len;
275
276
0
  if (S_ISDIR(mode)) {
277
0
    int dtype;
278
0
    size_t baselen = base->len;
279
0
    if (!ctx->pl)
280
0
      return READ_TREE_RECURSIVE;
281
282
    /*
283
     * Have we expanded to a point outside of the sparse-checkout?
284
     *
285
     * Artificially pad the path name with a slash "/" to
286
     * indicate it as a directory, and add an arbitrary file
287
     * name ("-") so we can consider base->buf as a file name
288
     * to match against the cone-mode patterns.
289
     *
290
     * If we compared just "path", then we would expand more
291
     * than we should. Since every file at root is always
292
     * included, we would expand every directory at root at
293
     * least one level deep instead of using sparse directory
294
     * entries.
295
     */
296
0
    strbuf_addstr(base, path);
297
0
    strbuf_add(base, "/-", 2);
298
299
0
    if (path_matches_pattern_list(base->buf, base->len,
300
0
                NULL, &dtype,
301
0
                ctx->pl, ctx->write)) {
302
0
      strbuf_setlen(base, baselen);
303
0
      return READ_TREE_RECURSIVE;
304
0
    }
305
306
    /*
307
     * The path "{base}{path}/" is a sparse directory. Create the correct
308
     * name for inserting the entry into the index.
309
     */
310
0
    strbuf_setlen(base, base->len - 1);
311
0
  } else {
312
0
    strbuf_addstr(base, path);
313
0
  }
314
315
0
  ce = make_cache_entry(ctx->write, mode, oid, base->buf, 0, 0);
316
0
  ce->ce_flags |= CE_SKIP_WORKTREE | CE_EXTENDED;
317
0
  set_index_entry(ctx->write, ctx->write->cache_nr++, ce);
318
319
0
  strbuf_setlen(base, len);
320
0
  return 0;
321
0
}
322
323
void expand_index(struct index_state *istate, struct pattern_list *pl)
324
0
{
325
0
  int i;
326
0
  struct index_state *full;
327
0
  struct strbuf base = STRBUF_INIT;
328
0
  const char *tr_region;
329
0
  struct modify_index_context ctx;
330
331
  /*
332
   * If the index is already full, then keep it full. We will convert
333
   * it to a sparse index on write, if possible.
334
   */
335
0
  if (istate->sparse_index == INDEX_EXPANDED)
336
0
    return;
337
338
  /*
339
   * If our index is sparse, but our new pattern set does not use
340
   * cone mode patterns, then we need to expand the index before we
341
   * continue. A NULL pattern set indicates a full expansion to a
342
   * full index.
343
   */
344
0
  if (pl && !pl->use_cone_patterns) {
345
0
    pl = NULL;
346
0
  } else {
347
    /*
348
     * We might contract file entries into sparse-directory
349
     * entries, and for that we will need the cache tree to
350
     * be recomputed.
351
     */
352
0
    cache_tree_free(&istate->cache_tree);
353
354
    /*
355
     * If there is a problem creating the cache tree, then we
356
     * need to expand to a full index since we cannot satisfy
357
     * the current request as a sparse index.
358
     */
359
0
    if (cache_tree_update(istate, 0))
360
0
      pl = NULL;
361
0
  }
362
363
0
  if (!pl && give_advice_on_expansion) {
364
0
    give_advice_on_expansion = 0;
365
0
    advise_if_enabled(ADVICE_SPARSE_INDEX_EXPANDED,
366
0
          _(ADVICE_MSG));
367
0
  }
368
369
  /*
370
   * A NULL pattern set indicates we are expanding a full index, so
371
   * we use a special region name that indicates the full expansion.
372
   * This is used by test cases, but also helps to differentiate the
373
   * two cases.
374
   */
375
0
  tr_region = pl ? "expand_index" : "ensure_full_index";
376
0
  trace2_region_enter("index", tr_region, istate->repo);
377
378
  /* initialize basics of new index */
379
0
  full = xcalloc(1, sizeof(struct index_state));
380
0
  memcpy(full, istate, sizeof(struct index_state));
381
382
  /*
383
   * This slightly-misnamed 'full' index might still be sparse if we
384
   * are only modifying the list of sparse directories. This hinges
385
   * on whether we have a non-NULL pattern list.
386
   */
387
0
  full->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
388
389
  /* then change the necessary things */
390
0
  full->cache_alloc = (3 * istate->cache_alloc) / 2;
391
0
  full->cache_nr = 0;
392
0
  ALLOC_ARRAY(full->cache, full->cache_alloc);
393
394
0
  ctx.write = full;
395
0
  ctx.pl = pl;
396
397
0
  for (i = 0; i < istate->cache_nr; i++) {
398
0
    struct cache_entry *ce = istate->cache[i];
399
0
    struct tree *tree;
400
0
    struct pathspec ps;
401
0
    int dtype;
402
403
0
    if (!S_ISSPARSEDIR(ce->ce_mode)) {
404
0
      set_index_entry(full, full->cache_nr++, ce);
405
0
      continue;
406
0
    }
407
408
    /* We now have a sparse directory entry. Should we expand? */
409
0
    if (pl &&
410
0
        path_matches_pattern_list(ce->name, ce->ce_namelen,
411
0
                NULL, &dtype,
412
0
                pl, istate) == NOT_MATCHED) {
413
0
      set_index_entry(full, full->cache_nr++, ce);
414
0
      continue;
415
0
    }
416
417
0
    if (!(ce->ce_flags & CE_SKIP_WORKTREE))
418
0
      warning(_("index entry is a directory, but not sparse (%08x)"),
419
0
        ce->ce_flags);
420
421
    /* recursively walk into cd->name */
422
0
    tree = lookup_tree(istate->repo, &ce->oid);
423
424
0
    memset(&ps, 0, sizeof(ps));
425
0
    ps.recursive = 1;
426
0
    ps.has_wildcard = 1;
427
0
    ps.max_depth = -1;
428
429
0
    strbuf_setlen(&base, 0);
430
0
    strbuf_add(&base, ce->name, strlen(ce->name));
431
432
0
    read_tree_at(istate->repo, tree, &base, 0, &ps,
433
0
           add_path_to_index, &ctx);
434
435
    /* free directory entries. full entries are re-used */
436
0
    discard_cache_entry(ce);
437
0
  }
438
439
  /* Copy back into original index. */
440
0
  memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash));
441
0
  memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash));
442
0
  istate->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
443
0
  free(istate->cache);
444
0
  istate->cache = full->cache;
445
0
  istate->cache_nr = full->cache_nr;
446
0
  istate->cache_alloc = full->cache_alloc;
447
0
  istate->fsmonitor_has_run_once = 0;
448
0
  ewah_free(istate->fsmonitor_dirty);
449
0
  istate->fsmonitor_dirty = NULL;
450
0
  FREE_AND_NULL(istate->fsmonitor_last_update);
451
452
0
  strbuf_release(&base);
453
0
  free(full);
454
455
  /* Clear and recompute the cache-tree */
456
0
  cache_tree_free(&istate->cache_tree);
457
0
  cache_tree_update(istate, 0);
458
459
0
  trace2_region_leave("index", tr_region, istate->repo);
460
0
}
461
462
void ensure_full_index(struct index_state *istate)
463
0
{
464
0
  if (!istate)
465
0
    BUG("ensure_full_index() must get an index!");
466
0
  expand_index(istate, NULL);
467
0
}
468
469
void ensure_correct_sparsity(struct index_state *istate)
470
0
{
471
  /*
472
   * If the index can be sparse, make it sparse. Otherwise,
473
   * ensure the index is full.
474
   */
475
0
  if (is_sparse_index_allowed(istate, 0))
476
0
    convert_to_sparse(istate, 0);
477
0
  else
478
0
    ensure_full_index(istate);
479
0
}
480
481
struct path_found_data {
482
  /**
483
   * The path stored in 'dir', if non-empty, corresponds to the most-
484
   * recent path that we checked where:
485
   *
486
   *   1. The path should be a directory, according to the index.
487
   *   2. The path does not exist.
488
   *   3. The parent path _does_ exist. (This may be the root of the
489
   *      working directory.)
490
   */
491
  struct strbuf dir;
492
  size_t lstat_count;
493
};
494
495
0
#define PATH_FOUND_DATA_INIT { \
496
0
  .dir = STRBUF_INIT \
497
0
}
498
499
static void clear_path_found_data(struct path_found_data *data)
500
0
{
501
0
  strbuf_release(&data->dir);
502
0
}
503
504
/**
505
 * Return the length of the longest common substring that ends in a
506
 * slash ('/') to indicate the longest common parent directory. Returns
507
 * zero if no common directory exists.
508
 */
509
static size_t max_common_dir_prefix(const char *path1, const char *path2)
510
0
{
511
0
  size_t common_prefix = 0;
512
0
  for (size_t i = 0; path1[i] && path2[i]; i++) {
513
0
    if (path1[i] != path2[i])
514
0
      break;
515
516
    /*
517
     * If they agree at a directory separator, then add one
518
     * to make sure it is included in the common prefix string.
519
     */
520
0
    if (path1[i] == '/')
521
0
      common_prefix = i + 1;
522
0
  }
523
524
0
  return common_prefix;
525
0
}
526
527
static int path_found(const char *path, struct path_found_data *data)
528
0
{
529
0
  struct stat st;
530
0
  size_t common_prefix;
531
532
  /*
533
   * If data->dir is non-empty, then it contains a path that doesn't
534
   * exist, including an ending slash ('/'). If it is a prefix of 'path',
535
   * then we can return 0.
536
   */
537
0
  if (data->dir.len && !memcmp(path, data->dir.buf, data->dir.len))
538
0
    return 0;
539
540
  /*
541
   * Otherwise, we must check if the current path exists. If it does, then
542
   * return 1. The cached directory will be skipped until we come across
543
   * a missing path again.
544
   */
545
0
  data->lstat_count++;
546
0
  if (!lstat(path, &st))
547
0
    return 1;
548
549
  /*
550
   * At this point, we know that 'path' doesn't exist, and we know that
551
   * the parent directory of 'data->dir' does exist. Let's set 'data->dir'
552
   * to be the top-most non-existing directory of 'path'. If the first
553
   * parent of 'path' exists, then we will act as though 'path'
554
   * corresponds to a directory (by adding a slash).
555
   */
556
0
  common_prefix = max_common_dir_prefix(path, data->dir.buf);
557
558
  /*
559
   * At this point, 'path' and 'data->dir' have a common existing parent
560
   * directory given by path[0..common_prefix] (which could have length 0).
561
   * We "grow" the data->dir buffer by checking for existing directories
562
   * along 'path'.
563
   */
564
565
0
  strbuf_setlen(&data->dir, common_prefix);
566
0
  while (1) {
567
    /* Find the next directory in 'path'. */
568
0
    const char *rest = path + data->dir.len;
569
0
    const char *next_slash = strchr(rest, '/');
570
571
    /*
572
     * If there are no more slashes, then 'path' doesn't contain a
573
     * non-existent _parent_ directory. Set 'data->dir' to be equal
574
     * to 'path' plus an additional slash, so it can be used for
575
     * caching in the future. The filename of 'path' is considered
576
     * a non-existent directory.
577
     *
578
     * Note: if "{path}/" exists as a directory, then it will never
579
     * appear as a prefix of other callers to this method, assuming
580
     * the context from the clear_skip_worktree... methods. If this
581
     * method is reused, then this must be reconsidered.
582
     */
583
0
    if (!next_slash) {
584
0
      strbuf_addstr(&data->dir, rest);
585
0
      strbuf_addch(&data->dir, '/');
586
0
      break;
587
0
    }
588
589
    /*
590
     * Now that we have a slash, let's grow 'data->dir' to include
591
     * this slash, then test if we should stop.
592
     */
593
0
    strbuf_add(&data->dir, rest, next_slash - rest + 1);
594
595
    /* If the parent dir doesn't exist, then stop here. */
596
0
    data->lstat_count++;
597
0
    if (lstat(data->dir.buf, &st))
598
0
      return 0;
599
0
  }
600
601
  /*
602
   * At this point, 'data->dir' is equal to 'path' plus a slash character,
603
   * and the parent directory of 'path' definitely exists. Moreover, we
604
   * know that 'path' doesn't exist, or we would have returned 1 earlier.
605
   */
606
0
  return 0;
607
0
}
608
609
static int clear_skip_worktree_from_present_files_sparse(struct index_state *istate)
610
0
{
611
0
  struct path_found_data data = PATH_FOUND_DATA_INIT;
612
613
0
  int path_count = 0;
614
0
  int to_restart = 0;
615
616
0
  trace2_region_enter("index", "clear_skip_worktree_from_present_files_sparse",
617
0
          istate->repo);
618
0
  for (int i = 0; i < istate->cache_nr; i++) {
619
0
    struct cache_entry *ce = istate->cache[i];
620
621
0
    if (ce_skip_worktree(ce)) {
622
0
      path_count++;
623
0
      if (path_found(ce->name, &data)) {
624
0
        if (S_ISSPARSEDIR(ce->ce_mode)) {
625
0
          to_restart = 1;
626
0
          break;
627
0
        }
628
0
        ce->ce_flags &= ~CE_SKIP_WORKTREE;
629
0
      }
630
0
    }
631
0
  }
632
633
0
  trace2_data_intmax("index", istate->repo,
634
0
         "sparse_path_count", path_count);
635
0
  trace2_data_intmax("index", istate->repo,
636
0
         "sparse_lstat_count", data.lstat_count);
637
0
  trace2_region_leave("index", "clear_skip_worktree_from_present_files_sparse",
638
0
          istate->repo);
639
0
  clear_path_found_data(&data);
640
0
  return to_restart;
641
0
}
642
643
static void clear_skip_worktree_from_present_files_full(struct index_state *istate)
644
0
{
645
0
  struct path_found_data data = PATH_FOUND_DATA_INIT;
646
647
0
  int path_count = 0;
648
649
0
  trace2_region_enter("index", "clear_skip_worktree_from_present_files_full",
650
0
          istate->repo);
651
0
  for (int i = 0; i < istate->cache_nr; i++) {
652
0
    struct cache_entry *ce = istate->cache[i];
653
654
0
    if (S_ISSPARSEDIR(ce->ce_mode))
655
0
      BUG("ensure-full-index did not fully flatten?");
656
657
0
    if (ce_skip_worktree(ce)) {
658
0
      path_count++;
659
0
      if (path_found(ce->name, &data))
660
0
        ce->ce_flags &= ~CE_SKIP_WORKTREE;
661
0
    }
662
0
  }
663
664
0
  trace2_data_intmax("index", istate->repo,
665
0
         "full_path_count", path_count);
666
0
  trace2_data_intmax("index", istate->repo,
667
0
         "full_lstat_count", data.lstat_count);
668
0
  trace2_region_leave("index", "clear_skip_worktree_from_present_files_full",
669
0
          istate->repo);
670
0
  clear_path_found_data(&data);
671
0
}
672
673
void clear_skip_worktree_from_present_files(struct index_state *istate)
674
0
{
675
0
  struct repo_config_values *cfg = repo_config_values(the_repository);
676
677
0
  if (!cfg->apply_sparse_checkout ||
678
0
      sparse_expect_files_outside_of_patterns)
679
0
    return;
680
681
0
  if (clear_skip_worktree_from_present_files_sparse(istate)) {
682
0
    ensure_full_index(istate);
683
0
    clear_skip_worktree_from_present_files_full(istate);
684
0
  }
685
0
}
686
687
/*
688
 * This static global helps avoid infinite recursion between
689
 * expand_to_path() and index_file_exists().
690
 */
691
static int in_expand_to_path = 0;
692
693
void expand_to_path(struct index_state *istate,
694
        const char *path, size_t pathlen, int icase)
695
0
{
696
0
  struct strbuf path_mutable = STRBUF_INIT;
697
0
  size_t substr_len;
698
699
  /* prevent extra recursion */
700
0
  if (in_expand_to_path)
701
0
    return;
702
703
0
  if (!istate->sparse_index)
704
0
    return;
705
706
0
  in_expand_to_path = 1;
707
708
  /*
709
   * We only need to actually expand a region if the
710
   * following are both true:
711
   *
712
   * 1. 'path' is not already in the index.
713
   * 2. Some parent directory of 'path' is a sparse directory.
714
   */
715
716
0
  if (index_file_exists(istate, path, pathlen, icase))
717
0
    goto cleanup;
718
719
0
  strbuf_add(&path_mutable, path, pathlen);
720
0
  strbuf_addch(&path_mutable, '/');
721
722
  /* Check the name hash for all parent directories */
723
0
  substr_len = 0;
724
0
  while (substr_len < pathlen) {
725
0
    char temp;
726
0
    char *replace = strchr(path_mutable.buf + substr_len, '/');
727
728
0
    if (!replace)
729
0
      break;
730
731
    /* replace the character _after_ the slash */
732
0
    replace++;
733
0
    temp = *replace;
734
0
    *replace = '\0';
735
0
    substr_len = replace - path_mutable.buf;
736
0
    if (index_file_exists(istate, path_mutable.buf,
737
0
              substr_len, icase)) {
738
      /*
739
       * We found a parent directory in the name-hash
740
       * hashtable, because only sparse directory entries
741
       * have a trailing '/' character.  Since "path" wasn't
742
       * in the index, perhaps it exists within this
743
       * sparse-directory.  Expand accordingly.
744
       */
745
0
      ensure_full_index(istate);
746
0
      break;
747
0
    }
748
749
0
    *replace = temp;
750
0
  }
751
752
0
cleanup:
753
0
  strbuf_release(&path_mutable);
754
0
  in_expand_to_path = 0;
755
0
}