Skip to content

Commit

Permalink
unpack-trees: fix nested sparse-dir search
Browse files Browse the repository at this point in the history
The iterated search in find_cache_entry() was recently modified to
include a loop that searches backwards for a sparse directory entry that
matches the given traverse_info and name_entry. However, the string
comparison failed to actually concatenate those two strings, so this
failed to find a sparse directory when it was not a top-level directory.

This caused some errors in rare cases where a 'git checkout' spanned a
diff that modified files within the sparse directory entry, but we could
not correctly find the entry.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
  • Loading branch information
derrickstolee committed Jul 6, 2021
1 parent 4ad0348 commit 2d3b5b4
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions unpack-trees.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,10 @@ static int sparse_dir_matches_path(const struct cache_entry *ce,
static struct cache_entry *find_cache_entry(struct traverse_info *info,
const struct name_entry *p)
{
struct cache_entry *ce;
struct cache_entry *ce = NULL;
int pos = find_cache_pos(info, p->path, p->pathlen);
struct unpack_trees_options *o = info->data;
struct strbuf full_path = STRBUF_INIT;

if (0 <= pos)
return o->src_index->cache[pos];
Expand All @@ -1304,6 +1305,10 @@ static struct cache_entry *find_cache_entry(struct traverse_info *info,
if (pos < 0 || pos >= o->src_index->cache_nr)
return NULL;

strbuf_addstr(&full_path, info->traverse_path);
strbuf_add(&full_path, p->path, p->pathlen);
strbuf_addch(&full_path, '/');

/*
* We might have multiple entries between 'pos' and
* the actual sparse-directory entry, so start walking
Expand All @@ -1315,17 +1320,20 @@ static struct cache_entry *find_cache_entry(struct traverse_info *info,
/*
* Have we walked too far?
*/
if (strncmp(ce->name, p->path, p->pathlen))
return NULL;
if (strncmp(ce->name, full_path.buf, full_path.len)) {
ce = NULL;
break;
}

if (S_ISSPARSEDIR(ce->ce_mode) &&
sparse_dir_matches_path(ce, info, p))
return ce;
break;

pos--;
}

return NULL;
strbuf_release(&full_path);
return ce;
}

static void debug_path(struct traverse_info *info)
Expand Down

0 comments on commit 2d3b5b4

Please sign in to comment.