Skip to content

Commit 2aabbd5

Browse files
committed
fixup! sparse-index: make non-mixed reset sparse-aware
Fix an edge case where the cache tree is constructed improperly because invalid cone-mode patterns are manually set in the sparse definition. Also fix test bug (would not report error without `|| return 1`). Signed-off-by: Victoria Dye <[email protected]>
1 parent 8bd47db commit 2aabbd5

File tree

4 files changed

+49
-24
lines changed

4 files changed

+49
-24
lines changed

cache-tree.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,17 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
800800
return ret;
801801
}
802802

803+
static void prime_cache_tree_sparse_dir(struct repository *r,
804+
struct cache_tree *it,
805+
struct tree *tree,
806+
struct strbuf *tree_path)
807+
{
808+
809+
oidcpy(&it->oid, &tree->object.oid);
810+
it->entry_count = 1;
811+
return;
812+
}
813+
803814
static void prime_cache_tree_rec(struct repository *r,
804815
struct cache_tree *it,
805816
struct tree *tree,
@@ -812,21 +823,6 @@ static void prime_cache_tree_rec(struct repository *r,
812823

813824
oidcpy(&it->oid, &tree->object.oid);
814825

815-
/*
816-
* If this entry is outside the sparse-checkout cone, then it might be
817-
* a sparse directory entry. Check the index to ensure it is by looking
818-
* for an entry with the exact same name as the tree. If no matching sparse
819-
* entry is found, a staged or conflicted entry is preventing this
820-
* directory from collapsing to a sparse directory entry, so the cache
821-
* tree expansion should continue.
822-
*/
823-
if (r->index->sparse_index &&
824-
!path_in_cone_modesparse_checkout(tree_path->buf, r->index) &&
825-
index_name_pos(r->index, tree_path->buf, tree_path->len) >= 0) {
826-
it->entry_count = 1;
827-
return;
828-
}
829-
830826
init_tree_desc(&desc, tree->buffer, tree->size);
831827
cnt = 0;
832828
while (tree_entry(&desc, &entry)) {
@@ -846,7 +842,18 @@ static void prime_cache_tree_rec(struct repository *r,
846842
strbuf_add(&subtree_path, entry.path, entry.pathlen);
847843
strbuf_addch(&subtree_path, '/');
848844

849-
prime_cache_tree_rec(r, sub->cache_tree, subtree, &subtree_path);
845+
/*
846+
* If a sparse index is in use, the directory being processed may be
847+
* sparse. To confirm that, we can check whether an entry with that
848+
* exact name exists in the index. If it does, the created subtree
849+
* should be sparse. Otherwise, cache tree expansion should continue
850+
* as normal.
851+
*/
852+
if (r->index->sparse_index &&
853+
index_entry_exists(r->index, subtree_path.buf, subtree_path.len))
854+
prime_cache_tree_sparse_dir(r, sub->cache_tree, subtree, &subtree_path);
855+
else
856+
prime_cache_tree_rec(r, sub->cache_tree, subtree, &subtree_path);
850857
cnt += sub->cache_tree->entry_count;
851858
}
852859
}

cache.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,16 @@ struct cache_entry *index_file_next_match(struct index_state *istate, struct cac
833833
*/
834834
int index_name_pos(struct index_state *, const char *name, int namelen);
835835

836+
/*
837+
* Determines whether an entry with the given name exists within the
838+
* given index. The return value is 1 if an exact match is found, otherwise
839+
* it is 0. Note that, unlike index_name_pos, this function does not expand
840+
* the index if it is sparse. If an item exists within the full index but it
841+
* is contained within a sparse directory (and not in the sparse index), 0 is
842+
* returned.
843+
*/
844+
int index_entry_exists(struct index_state *, const char *name, int namelen);
845+
836846
/*
837847
* Some functions return the negative complement of an insert position when a
838848
* precise match was not found but a position was found where the entry would

read-cache.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,10 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char
564564
return 0;
565565
}
566566

567-
static int index_name_stage_pos(struct index_state *istate, const char *name, int namelen, int stage)
567+
static int index_name_stage_pos(struct index_state *istate,
568+
const char *name, int namelen,
569+
int stage,
570+
int search_sparse)
568571
{
569572
int first, last;
570573

@@ -583,7 +586,7 @@ static int index_name_stage_pos(struct index_state *istate, const char *name, in
583586
first = next+1;
584587
}
585588

586-
if (istate->sparse_index &&
589+
if (search_sparse && istate->sparse_index &&
587590
first > 0) {
588591
/* Note: first <= istate->cache_nr */
589592
struct cache_entry *ce = istate->cache[first - 1];
@@ -599,7 +602,7 @@ static int index_name_stage_pos(struct index_state *istate, const char *name, in
599602
ce_namelen(ce) < namelen &&
600603
!strncmp(name, ce->name, ce_namelen(ce))) {
601604
ensure_full_index(istate);
602-
return index_name_stage_pos(istate, name, namelen, stage);
605+
return index_name_stage_pos(istate, name, namelen, stage, search_sparse);
603606
}
604607
}
605608

@@ -608,7 +611,12 @@ static int index_name_stage_pos(struct index_state *istate, const char *name, in
608611

609612
int index_name_pos(struct index_state *istate, const char *name, int namelen)
610613
{
611-
return index_name_stage_pos(istate, name, namelen, 0);
614+
return index_name_stage_pos(istate, name, namelen, 0, 1);
615+
}
616+
617+
int index_entry_exists(struct index_state *istate, const char *name, int namelen)
618+
{
619+
return index_name_stage_pos(istate, name, namelen, 0, 0) >= 0;
612620
}
613621

614622
int remove_index_entry_at(struct index_state *istate, int pos)
@@ -1235,7 +1243,7 @@ static int has_dir_name(struct index_state *istate,
12351243
*/
12361244
}
12371245

1238-
pos = index_name_stage_pos(istate, name, len, stage);
1246+
pos = index_name_stage_pos(istate, name, len, stage, 1);
12391247
if (pos >= 0) {
12401248
/*
12411249
* Found one, but not so fast. This could
@@ -1332,7 +1340,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
13321340
strcmp(ce->name, istate->cache[istate->cache_nr - 1]->name) > 0)
13331341
pos = index_pos_to_insert_pos(istate->cache_nr);
13341342
else
1335-
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
1343+
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce), 1);
13361344

13371345
/*
13381346
* Cache tree path should be invalidated only after index_name_stage_pos,
@@ -1374,7 +1382,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
13741382
if (!ok_to_replace)
13751383
return error(_("'%s' appears as both a file and as a directory"),
13761384
ce->name);
1377-
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
1385+
pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce), 1);
13781386
pos = -pos-1;
13791387
}
13801388
return pos + 1;

t/t1092-sparse-checkout-compatibility.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ test_expect_success 'sparse-index is not expanded' '
10501050
do
10511051
echo >>sparse-index/README.md &&
10521052
ensure_not_expanded reset --mixed $ref
1053-
ensure_not_expanded reset --hard $ref
1053+
ensure_not_expanded reset --hard $ref || return 1
10541054
done &&
10551055
10561056
ensure_not_expanded reset --hard update-deep &&

0 commit comments

Comments
 (0)