Skip to content

Commit cd807a5

Browse files
derrickstoleegitster
authored andcommitted
unpack-trees: compare sparse directories correctly
As we further integrate the sparse-index into unpack-trees, we need to ensure that we compare sparse directory entries correctly with other entries. This affects searching for an exact path as well as sorting index entries. Sparse directory entries contain the trailing directory separator. This is important for the sorting, in particular. Thus, within do_compare_entry() we stop using S_IFREG in all cases, since sparse directories should use S_IFDIR to indicate that the comparison should treat the entry name as a dirctory. Within compare_entry(), it first calls do_compare_entry() to check the leading portion of the name. When the input path is a directory name, we could match exactly already. Thus, we should return 0 if we have an exact string match on a sparse directory entry. The final check is a length comparison between the strings. Reviewed-by: Elijah Newren <[email protected]> Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 17a1bb5 commit cd807a5

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

unpack-trees.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ static int do_compare_entry(const struct cache_entry *ce,
983983
int pathlen, ce_len;
984984
const char *ce_name;
985985
int cmp;
986+
unsigned ce_mode;
986987

987988
/*
988989
* If we have not precomputed the traverse path, it is quicker
@@ -1005,7 +1006,8 @@ static int do_compare_entry(const struct cache_entry *ce,
10051006
ce_len -= pathlen;
10061007
ce_name = ce->name + pathlen;
10071008

1008-
return df_name_compare(ce_name, ce_len, S_IFREG, name, namelen, mode);
1009+
ce_mode = S_ISSPARSEDIR(ce->ce_mode) ? S_IFDIR : S_IFREG;
1010+
return df_name_compare(ce_name, ce_len, ce_mode, name, namelen, mode);
10091011
}
10101012

10111013
static int compare_entry(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
@@ -1014,6 +1016,16 @@ static int compare_entry(const struct cache_entry *ce, const struct traverse_inf
10141016
if (cmp)
10151017
return cmp;
10161018

1019+
/*
1020+
* At this point, we know that we have a prefix match. If ce
1021+
* is a sparse directory, then allow an exact match. This only
1022+
* works when the input name is a directory, since ce->name
1023+
* ends in a directory separator.
1024+
*/
1025+
if (S_ISSPARSEDIR(ce->ce_mode) &&
1026+
ce->ce_namelen == traverse_path_len(info, tree_entry_len(n)) + 1)
1027+
return 0;
1028+
10171029
/*
10181030
* Even if the beginning compared identically, the ce should
10191031
* compare as bigger than a directory leading up to it!

0 commit comments

Comments
 (0)