git

Форк
0
/
sparse-index.c 
742 строки · 20.0 Кб
1
#include "git-compat-util.h"
2
#include "environment.h"
3
#include "gettext.h"
4
#include "name-hash.h"
5
#include "read-cache-ll.h"
6
#include "repository.h"
7
#include "sparse-index.h"
8
#include "tree.h"
9
#include "pathspec.h"
10
#include "trace2.h"
11
#include "cache-tree.h"
12
#include "config.h"
13
#include "dir.h"
14
#include "fsmonitor-ll.h"
15
#include "advice.h"
16

17
/**
18
 * This global is used by expand_index() to determine if we should give the
19
 * advice for advice.sparseIndexExpanded when expanding a sparse index to a full
20
 * one. However, this is sometimes done on purpose, such as in the sparse-checkout
21
 * builtin, even when index.sparse=false. This may be disabled in
22
 * convert_to_sparse().
23
 */
24
static int give_advice_on_expansion = 1;
25
#define ADVICE_MSG \
26
	"The sparse index is expanding to a full index, a slow operation.\n"   \
27
	"Your working directory likely has contents that are outside of\n"     \
28
	"your sparse-checkout patterns. Use 'git sparse-checkout list' to\n"   \
29
	"see your sparse-checkout definition and compare it to your working\n" \
30
	"directory contents. Running 'git clean' may assist in this cleanup."
31

32
struct modify_index_context {
33
	struct index_state *write;
34
	struct pattern_list *pl;
35
};
36

37
static struct cache_entry *construct_sparse_dir_entry(
38
				struct index_state *istate,
39
				const char *sparse_dir,
40
				struct cache_tree *tree)
41
{
42
	struct cache_entry *de;
43

44
	de = make_cache_entry(istate, S_IFDIR, &tree->oid, sparse_dir, 0, 0);
45

46
	de->ce_flags |= CE_SKIP_WORKTREE;
47
	return de;
48
}
49

50
/*
51
 * Returns the number of entries "inserted" into the index.
52
 */
53
static int convert_to_sparse_rec(struct index_state *istate,
54
				 int num_converted,
55
				 int start, int end,
56
				 const char *ct_path, size_t ct_pathlen,
57
				 struct cache_tree *ct)
58
{
59
	int i, can_convert = 1;
60
	int start_converted = num_converted;
61
	struct strbuf child_path = STRBUF_INIT;
62

63
	/*
64
	 * Is the current path outside of the sparse cone?
65
	 * Then check if the region can be replaced by a sparse
66
	 * directory entry (everything is sparse and merged).
67
	 */
68
	if (path_in_sparse_checkout(ct_path, istate))
69
		can_convert = 0;
70

71
	for (i = start; can_convert && i < end; i++) {
72
		struct cache_entry *ce = istate->cache[i];
73

74
		if (ce_stage(ce) ||
75
		    S_ISGITLINK(ce->ce_mode) ||
76
		    !(ce->ce_flags & CE_SKIP_WORKTREE))
77
			can_convert = 0;
78
	}
79

80
	if (can_convert) {
81
		struct cache_entry *se;
82
		se = construct_sparse_dir_entry(istate, ct_path, ct);
83

84
		istate->cache[num_converted++] = se;
85
		return 1;
86
	}
87

88
	for (i = start; i < end; ) {
89
		int count, span, pos = -1;
90
		const char *base, *slash;
91
		struct cache_entry *ce = istate->cache[i];
92

93
		/*
94
		 * Detect if this is a normal entry outside of any subtree
95
		 * entry.
96
		 */
97
		base = ce->name + ct_pathlen;
98
		slash = strchr(base, '/');
99

100
		if (slash)
101
			pos = cache_tree_subtree_pos(ct, base, slash - base);
102

103
		if (pos < 0) {
104
			istate->cache[num_converted++] = ce;
105
			i++;
106
			continue;
107
		}
108

109
		strbuf_setlen(&child_path, 0);
110
		strbuf_add(&child_path, ce->name, slash - ce->name + 1);
111

112
		span = ct->down[pos]->cache_tree->entry_count;
113
		count = convert_to_sparse_rec(istate,
114
					      num_converted, i, i + span,
115
					      child_path.buf, child_path.len,
116
					      ct->down[pos]->cache_tree);
117
		num_converted += count;
118
		i += span;
119
	}
120

121
	strbuf_release(&child_path);
122
	return num_converted - start_converted;
123
}
124

125
int set_sparse_index_config(struct repository *repo, int enable)
126
{
127
	int res = repo_config_set_worktree_gently(repo,
128
						  "index.sparse",
129
						  enable ? "true" : "false");
130
	prepare_repo_settings(repo);
131
	repo->settings.sparse_index = enable;
132
	return res;
133
}
134

135
static int index_has_unmerged_entries(struct index_state *istate)
136
{
137
	int i;
138
	for (i = 0; i < istate->cache_nr; i++) {
139
		if (ce_stage(istate->cache[i]))
140
			return 1;
141
	}
142

143
	return 0;
144
}
145

146
int is_sparse_index_allowed(struct index_state *istate, int flags)
147
{
148
	if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
149
		return 0;
150

151
	if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
152
		int test_env;
153

154
		/*
155
		 * The sparse index is not (yet) integrated with a split index.
156
		 */
157
		if (istate->split_index || git_env_bool("GIT_TEST_SPLIT_INDEX", 0))
158
			return 0;
159
		/*
160
		 * The GIT_TEST_SPARSE_INDEX environment variable triggers the
161
		 * index.sparse config variable to be on.
162
		 */
163
		test_env = git_env_bool("GIT_TEST_SPARSE_INDEX", -1);
164
		if (test_env >= 0)
165
			set_sparse_index_config(istate->repo, test_env);
166

167
		/*
168
		 * Only convert to sparse if index.sparse is set.
169
		 */
170
		prepare_repo_settings(istate->repo);
171
		if (!istate->repo->settings.sparse_index)
172
			return 0;
173
	}
174

175
	if (init_sparse_checkout_patterns(istate))
176
		return 0;
177

178
	/*
179
	 * We need cone-mode patterns to use sparse-index. If a user edits
180
	 * their sparse-checkout file manually, then we can detect during
181
	 * parsing that they are not actually using cone-mode patterns and
182
	 * hence we need to abort this conversion _without error_. Warnings
183
	 * already exist in the pattern parsing to inform the user of their
184
	 * bad patterns.
185
	 */
186
	if (!istate->sparse_checkout_patterns->use_cone_patterns)
187
		return 0;
188

189
	return 1;
190
}
191

192
int convert_to_sparse(struct index_state *istate, int flags)
193
{
194
	/*
195
	 * If the index is already sparse, empty, or otherwise
196
	 * cannot be converted to sparse, do not convert.
197
	 */
198
	if (istate->sparse_index == INDEX_COLLAPSED || !istate->cache_nr ||
199
	    !is_sparse_index_allowed(istate, flags))
200
		return 0;
201

202
	/*
203
	 * If we are purposefully collapsing a full index, then don't give
204
	 * advice when it is expanded later.
205
	 */
206
	give_advice_on_expansion = 0;
207

208
	/*
209
	 * NEEDSWORK: If we have unmerged entries, then stay full.
210
	 * Unmerged entries prevent the cache-tree extension from working.
211
	 */
212
	if (index_has_unmerged_entries(istate))
213
		return 0;
214

215
	if (!cache_tree_fully_valid(istate->cache_tree)) {
216
		/* Clear and recompute the cache-tree */
217
		cache_tree_free(&istate->cache_tree);
218

219
		/*
220
		 * Silently return if there is a problem with the cache tree update,
221
		 * which might just be due to a conflict state in some entry.
222
		 *
223
		 * This might create new tree objects, so be sure to use
224
		 * WRITE_TREE_MISSING_OK.
225
		 */
226
		if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
227
			return 0;
228
	}
229

230
	remove_fsmonitor(istate);
231

232
	trace2_region_enter("index", "convert_to_sparse", istate->repo);
233
	istate->cache_nr = convert_to_sparse_rec(istate,
234
						 0, 0, istate->cache_nr,
235
						 "", 0, istate->cache_tree);
236

237
	/* Clear and recompute the cache-tree */
238
	cache_tree_free(&istate->cache_tree);
239
	cache_tree_update(istate, 0);
240

241
	istate->fsmonitor_has_run_once = 0;
242
	FREE_AND_NULL(istate->fsmonitor_dirty);
243
	FREE_AND_NULL(istate->fsmonitor_last_update);
244

245
	istate->sparse_index = INDEX_COLLAPSED;
246
	trace2_region_leave("index", "convert_to_sparse", istate->repo);
247
	return 0;
248
}
249

250
static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
251
{
252
	ALLOC_GROW(istate->cache, nr + 1, istate->cache_alloc);
253

254
	istate->cache[nr] = ce;
255
	add_name_hash(istate, ce);
256
}
257

258
static int add_path_to_index(const struct object_id *oid,
259
			     struct strbuf *base, const char *path,
260
			     unsigned int mode, void *context)
261
{
262
	struct modify_index_context *ctx = (struct modify_index_context *)context;
263
	struct cache_entry *ce;
264
	size_t len = base->len;
265

266
	if (S_ISDIR(mode)) {
267
		int dtype;
268
		size_t baselen = base->len;
269
		if (!ctx->pl)
270
			return READ_TREE_RECURSIVE;
271

272
		/*
273
		 * Have we expanded to a point outside of the sparse-checkout?
274
		 *
275
		 * Artificially pad the path name with a slash "/" to
276
		 * indicate it as a directory, and add an arbitrary file
277
		 * name ("-") so we can consider base->buf as a file name
278
		 * to match against the cone-mode patterns.
279
		 *
280
		 * If we compared just "path", then we would expand more
281
		 * than we should. Since every file at root is always
282
		 * included, we would expand every directory at root at
283
		 * least one level deep instead of using sparse directory
284
		 * entries.
285
		 */
286
		strbuf_addstr(base, path);
287
		strbuf_add(base, "/-", 2);
288

289
		if (path_matches_pattern_list(base->buf, base->len,
290
					      NULL, &dtype,
291
					      ctx->pl, ctx->write)) {
292
			strbuf_setlen(base, baselen);
293
			return READ_TREE_RECURSIVE;
294
		}
295

296
		/*
297
		 * The path "{base}{path}/" is a sparse directory. Create the correct
298
		 * name for inserting the entry into the index.
299
		 */
300
		strbuf_setlen(base, base->len - 1);
301
	} else {
302
		strbuf_addstr(base, path);
303
	}
304

305
	ce = make_cache_entry(ctx->write, mode, oid, base->buf, 0, 0);
306
	ce->ce_flags |= CE_SKIP_WORKTREE | CE_EXTENDED;
307
	set_index_entry(ctx->write, ctx->write->cache_nr++, ce);
308

309
	strbuf_setlen(base, len);
310
	return 0;
311
}
312

313
void expand_index(struct index_state *istate, struct pattern_list *pl)
314
{
315
	int i;
316
	struct index_state *full;
317
	struct strbuf base = STRBUF_INIT;
318
	const char *tr_region;
319
	struct modify_index_context ctx;
320

321
	/*
322
	 * If the index is already full, then keep it full. We will convert
323
	 * it to a sparse index on write, if possible.
324
	 */
325
	if (istate->sparse_index == INDEX_EXPANDED)
326
		return;
327

328
	/*
329
	 * If our index is sparse, but our new pattern set does not use
330
	 * cone mode patterns, then we need to expand the index before we
331
	 * continue. A NULL pattern set indicates a full expansion to a
332
	 * full index.
333
	 */
334
	if (pl && !pl->use_cone_patterns) {
335
		pl = NULL;
336
	} else {
337
		/*
338
		 * We might contract file entries into sparse-directory
339
		 * entries, and for that we will need the cache tree to
340
		 * be recomputed.
341
		 */
342
		cache_tree_free(&istate->cache_tree);
343

344
		/*
345
		 * If there is a problem creating the cache tree, then we
346
		 * need to expand to a full index since we cannot satisfy
347
		 * the current request as a sparse index.
348
		 */
349
		if (cache_tree_update(istate, 0))
350
			pl = NULL;
351
	}
352

353
	if (!pl && give_advice_on_expansion) {
354
		give_advice_on_expansion = 0;
355
		advise_if_enabled(ADVICE_SPARSE_INDEX_EXPANDED,
356
				  _(ADVICE_MSG));
357
	}
358

359
	/*
360
	 * A NULL pattern set indicates we are expanding a full index, so
361
	 * we use a special region name that indicates the full expansion.
362
	 * This is used by test cases, but also helps to differentiate the
363
	 * two cases.
364
	 */
365
	tr_region = pl ? "expand_index" : "ensure_full_index";
366
	trace2_region_enter("index", tr_region, istate->repo);
367

368
	/* initialize basics of new index */
369
	full = xcalloc(1, sizeof(struct index_state));
370
	memcpy(full, istate, sizeof(struct index_state));
371

372
	/*
373
	 * This slightly-misnamed 'full' index might still be sparse if we
374
	 * are only modifying the list of sparse directories. This hinges
375
	 * on whether we have a non-NULL pattern list.
376
	 */
377
	full->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
378

379
	/* then change the necessary things */
380
	full->cache_alloc = (3 * istate->cache_alloc) / 2;
381
	full->cache_nr = 0;
382
	ALLOC_ARRAY(full->cache, full->cache_alloc);
383

384
	ctx.write = full;
385
	ctx.pl = pl;
386

387
	for (i = 0; i < istate->cache_nr; i++) {
388
		struct cache_entry *ce = istate->cache[i];
389
		struct tree *tree;
390
		struct pathspec ps;
391
		int dtype;
392

393
		if (!S_ISSPARSEDIR(ce->ce_mode)) {
394
			set_index_entry(full, full->cache_nr++, ce);
395
			continue;
396
		}
397

398
		/* We now have a sparse directory entry. Should we expand? */
399
		if (pl &&
400
		    path_matches_pattern_list(ce->name, ce->ce_namelen,
401
					      NULL, &dtype,
402
					      pl, istate) == NOT_MATCHED) {
403
			set_index_entry(full, full->cache_nr++, ce);
404
			continue;
405
		}
406

407
		if (!(ce->ce_flags & CE_SKIP_WORKTREE))
408
			warning(_("index entry is a directory, but not sparse (%08x)"),
409
				ce->ce_flags);
410

411
		/* recursively walk into cd->name */
412
		tree = lookup_tree(istate->repo, &ce->oid);
413

414
		memset(&ps, 0, sizeof(ps));
415
		ps.recursive = 1;
416
		ps.has_wildcard = 1;
417
		ps.max_depth = -1;
418

419
		strbuf_setlen(&base, 0);
420
		strbuf_add(&base, ce->name, strlen(ce->name));
421

422
		read_tree_at(istate->repo, tree, &base, 0, &ps,
423
			     add_path_to_index, &ctx);
424

425
		/* free directory entries. full entries are re-used */
426
		discard_cache_entry(ce);
427
	}
428

429
	/* Copy back into original index. */
430
	memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash));
431
	memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash));
432
	istate->sparse_index = pl ? INDEX_PARTIALLY_SPARSE : INDEX_EXPANDED;
433
	free(istate->cache);
434
	istate->cache = full->cache;
435
	istate->cache_nr = full->cache_nr;
436
	istate->cache_alloc = full->cache_alloc;
437
	istate->fsmonitor_has_run_once = 0;
438
	FREE_AND_NULL(istate->fsmonitor_dirty);
439
	FREE_AND_NULL(istate->fsmonitor_last_update);
440

441
	strbuf_release(&base);
442
	free(full);
443

444
	/* Clear and recompute the cache-tree */
445
	cache_tree_free(&istate->cache_tree);
446
	cache_tree_update(istate, 0);
447

448
	trace2_region_leave("index", tr_region, istate->repo);
449
}
450

451
void ensure_full_index(struct index_state *istate)
452
{
453
	if (!istate)
454
		BUG("ensure_full_index() must get an index!");
455
	expand_index(istate, NULL);
456
}
457

458
void ensure_correct_sparsity(struct index_state *istate)
459
{
460
	/*
461
	 * If the index can be sparse, make it sparse. Otherwise,
462
	 * ensure the index is full.
463
	 */
464
	if (is_sparse_index_allowed(istate, 0))
465
		convert_to_sparse(istate, 0);
466
	else
467
		ensure_full_index(istate);
468
}
469

470
struct path_found_data {
471
	/**
472
	 * The path stored in 'dir', if non-empty, corresponds to the most-
473
	 * recent path that we checked where:
474
	 *
475
	 *   1. The path should be a directory, according to the index.
476
	 *   2. The path does not exist.
477
	 *   3. The parent path _does_ exist. (This may be the root of the
478
	 *      working directory.)
479
	 */
480
	struct strbuf dir;
481
	size_t lstat_count;
482
};
483

484
#define PATH_FOUND_DATA_INIT { \
485
	.dir = STRBUF_INIT \
486
}
487

488
static void clear_path_found_data(struct path_found_data *data)
489
{
490
	strbuf_release(&data->dir);
491
}
492

493
/**
494
 * Return the length of the longest common substring that ends in a
495
 * slash ('/') to indicate the longest common parent directory. Returns
496
 * zero if no common directory exists.
497
 */
498
static size_t max_common_dir_prefix(const char *path1, const char *path2)
499
{
500
	size_t common_prefix = 0;
501
	for (size_t i = 0; path1[i] && path2[i]; i++) {
502
		if (path1[i] != path2[i])
503
			break;
504

505
		/*
506
		 * If they agree at a directory separator, then add one
507
		 * to make sure it is included in the common prefix string.
508
		 */
509
		if (path1[i] == '/')
510
			common_prefix = i + 1;
511
	}
512

513
	return common_prefix;
514
}
515

516
static int path_found(const char *path, struct path_found_data *data)
517
{
518
	struct stat st;
519
	size_t common_prefix;
520

521
	/*
522
	 * If data->dir is non-empty, then it contains a path that doesn't
523
	 * exist, including an ending slash ('/'). If it is a prefix of 'path',
524
	 * then we can return 0.
525
	 */
526
	if (data->dir.len && !memcmp(path, data->dir.buf, data->dir.len))
527
		return 0;
528

529
	/*
530
	 * Otherwise, we must check if the current path exists. If it does, then
531
	 * return 1. The cached directory will be skipped until we come across
532
	 * a missing path again.
533
	 */
534
	data->lstat_count++;
535
	if (!lstat(path, &st))
536
		return 1;
537

538
	/*
539
	 * At this point, we know that 'path' doesn't exist, and we know that
540
	 * the parent directory of 'data->dir' does exist. Let's set 'data->dir'
541
	 * to be the top-most non-existing directory of 'path'. If the first
542
	 * parent of 'path' exists, then we will act as though 'path'
543
	 * corresponds to a directory (by adding a slash).
544
	 */
545
	common_prefix = max_common_dir_prefix(path, data->dir.buf);
546

547
	/*
548
	 * At this point, 'path' and 'data->dir' have a common existing parent
549
	 * directory given by path[0..common_prefix] (which could have length 0).
550
	 * We "grow" the data->dir buffer by checking for existing directories
551
	 * along 'path'.
552
	 */
553

554
	strbuf_setlen(&data->dir, common_prefix);
555
	while (1) {
556
		/* Find the next directory in 'path'. */
557
		const char *rest = path + data->dir.len;
558
		const char *next_slash = strchr(rest, '/');
559

560
		/*
561
		 * If there are no more slashes, then 'path' doesn't contain a
562
		 * non-existent _parent_ directory. Set 'data->dir' to be equal
563
		 * to 'path' plus an additional slash, so it can be used for
564
		 * caching in the future. The filename of 'path' is considered
565
		 * a non-existent directory.
566
		 *
567
		 * Note: if "{path}/" exists as a directory, then it will never
568
		 * appear as a prefix of other callers to this method, assuming
569
		 * the context from the clear_skip_worktree... methods. If this
570
		 * method is reused, then this must be reconsidered.
571
		 */
572
		if (!next_slash) {
573
			strbuf_addstr(&data->dir, rest);
574
			strbuf_addch(&data->dir, '/');
575
			break;
576
		}
577

578
		/*
579
		 * Now that we have a slash, let's grow 'data->dir' to include
580
		 * this slash, then test if we should stop.
581
		 */
582
		strbuf_add(&data->dir, rest, next_slash - rest + 1);
583

584
		/* If the parent dir doesn't exist, then stop here. */
585
		data->lstat_count++;
586
		if (lstat(data->dir.buf, &st))
587
			return 0;
588
	}
589

590
	/*
591
	 * At this point, 'data->dir' is equal to 'path' plus a slash character,
592
	 * and the parent directory of 'path' definitely exists. Moreover, we
593
	 * know that 'path' doesn't exist, or we would have returned 1 earlier.
594
	 */
595
	return 0;
596
}
597

598
static int clear_skip_worktree_from_present_files_sparse(struct index_state *istate)
599
{
600
	struct path_found_data data = PATH_FOUND_DATA_INIT;
601

602
	int path_count = 0;
603
	int to_restart = 0;
604

605
	trace2_region_enter("index", "clear_skip_worktree_from_present_files_sparse",
606
			    istate->repo);
607
	for (int i = 0; i < istate->cache_nr; i++) {
608
		struct cache_entry *ce = istate->cache[i];
609

610
		if (ce_skip_worktree(ce)) {
611
			path_count++;
612
			if (path_found(ce->name, &data)) {
613
				if (S_ISSPARSEDIR(ce->ce_mode)) {
614
					to_restart = 1;
615
					break;
616
				}
617
				ce->ce_flags &= ~CE_SKIP_WORKTREE;
618
			}
619
		}
620
	}
621

622
	trace2_data_intmax("index", istate->repo,
623
			   "sparse_path_count", path_count);
624
	trace2_data_intmax("index", istate->repo,
625
			   "sparse_lstat_count", data.lstat_count);
626
	trace2_region_leave("index", "clear_skip_worktree_from_present_files_sparse",
627
			    istate->repo);
628
	clear_path_found_data(&data);
629
	return to_restart;
630
}
631

632
static void clear_skip_worktree_from_present_files_full(struct index_state *istate)
633
{
634
	struct path_found_data data = PATH_FOUND_DATA_INIT;
635

636
	int path_count = 0;
637

638
	trace2_region_enter("index", "clear_skip_worktree_from_present_files_full",
639
			    istate->repo);
640
	for (int i = 0; i < istate->cache_nr; i++) {
641
		struct cache_entry *ce = istate->cache[i];
642

643
		if (S_ISSPARSEDIR(ce->ce_mode))
644
			BUG("ensure-full-index did not fully flatten?");
645

646
		if (ce_skip_worktree(ce)) {
647
			path_count++;
648
			if (path_found(ce->name, &data))
649
				ce->ce_flags &= ~CE_SKIP_WORKTREE;
650
		}
651
	}
652

653
	trace2_data_intmax("index", istate->repo,
654
			   "full_path_count", path_count);
655
	trace2_data_intmax("index", istate->repo,
656
			   "full_lstat_count", data.lstat_count);
657
	trace2_region_leave("index", "clear_skip_worktree_from_present_files_full",
658
			    istate->repo);
659
	clear_path_found_data(&data);
660
}
661

662
void clear_skip_worktree_from_present_files(struct index_state *istate)
663
{
664
	if (!core_apply_sparse_checkout ||
665
	    sparse_expect_files_outside_of_patterns)
666
		return;
667

668
	if (clear_skip_worktree_from_present_files_sparse(istate)) {
669
		ensure_full_index(istate);
670
		clear_skip_worktree_from_present_files_full(istate);
671
	}
672
}
673

674
/*
675
 * This static global helps avoid infinite recursion between
676
 * expand_to_path() and index_file_exists().
677
 */
678
static int in_expand_to_path = 0;
679

680
void expand_to_path(struct index_state *istate,
681
		    const char *path, size_t pathlen, int icase)
682
{
683
	struct strbuf path_mutable = STRBUF_INIT;
684
	size_t substr_len;
685

686
	/* prevent extra recursion */
687
	if (in_expand_to_path)
688
		return;
689

690
	if (!istate->sparse_index)
691
		return;
692

693
	in_expand_to_path = 1;
694

695
	/*
696
	 * We only need to actually expand a region if the
697
	 * following are both true:
698
	 *
699
	 * 1. 'path' is not already in the index.
700
	 * 2. Some parent directory of 'path' is a sparse directory.
701
	 */
702

703
	if (index_file_exists(istate, path, pathlen, icase))
704
		goto cleanup;
705

706
	strbuf_add(&path_mutable, path, pathlen);
707
	strbuf_addch(&path_mutable, '/');
708

709
	/* Check the name hash for all parent directories */
710
	substr_len = 0;
711
	while (substr_len < pathlen) {
712
		char temp;
713
		char *replace = strchr(path_mutable.buf + substr_len, '/');
714

715
		if (!replace)
716
			break;
717

718
		/* replace the character _after_ the slash */
719
		replace++;
720
		temp = *replace;
721
		*replace = '\0';
722
		substr_len = replace - path_mutable.buf;
723
		if (index_file_exists(istate, path_mutable.buf,
724
				      substr_len, icase)) {
725
			/*
726
			 * We found a parent directory in the name-hash
727
			 * hashtable, because only sparse directory entries
728
			 * have a trailing '/' character.  Since "path" wasn't
729
			 * in the index, perhaps it exists within this
730
			 * sparse-directory.  Expand accordingly.
731
			 */
732
			ensure_full_index(istate);
733
			break;
734
		}
735

736
		*replace = temp;
737
	}
738

739
cleanup:
740
	strbuf_release(&path_mutable);
741
	in_expand_to_path = 0;
742
}
743

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.