Browse Source

ls-files: prevent prune_cache from overeagerly pruning submodules

Since (ae8d08242 pathspec: pass directory indicator to
match_pathspec_item()) the path matching logic has been able to cope
with submodules without needing to strip off a trailing slash if a path
refers to a submodule.

ls-files is the only caller of 'parse_pathspec()' which relies on the
behavior of the PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP flag because it
uses the result to construct a common prefix of all provided pathspecs
which is then used to prune the index of all entries which don't have
that prefix.  Since submodules entries in the index don't have a
trailing slash 'prune_cache()' will be overeager and prune a submodule
'sub' if the common prefix is 'sub/'.  To correct this behavior, only
prune entries which don't match up to, but not including, a trailing
slash of the common prefix.

This is in preparation to remove the
PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP flag in a later patch.

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Brandon Williams 8 years ago committed by Junio C Hamano
parent
commit
cbca060e10
  1. 31
      builtin/ls-files.c

31
builtin/ls-files.c

@ -97,7 +97,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
{ {
int len = max_prefix_len; int len = max_prefix_len;


if (len >= ent->len) if (len > ent->len)
die("git ls-files: internal error - directory entry not superset of prefix"); die("git ls-files: internal error - directory entry not superset of prefix");


if (!dir_path_match(ent, &pathspec, len, ps_matched)) if (!dir_path_match(ent, &pathspec, len, ps_matched))
@ -238,7 +238,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
strbuf_addstr(&name, super_prefix); strbuf_addstr(&name, super_prefix);
strbuf_addstr(&name, ce->name); strbuf_addstr(&name, ce->name);


if (len >= ce_namelen(ce)) if (len > ce_namelen(ce))
die("git ls-files: internal error - cache entry not superset of prefix"); die("git ls-files: internal error - cache entry not superset of prefix");


if (recurse_submodules && S_ISGITLINK(ce->ce_mode) && if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
@ -403,6 +403,25 @@ static void prune_cache(const char *prefix, size_t prefixlen)
active_nr = last - pos; active_nr = last - pos;
} }


static int get_common_prefix_len(const char *common_prefix)
{
int common_prefix_len;

if (!common_prefix)
return 0;

common_prefix_len = strlen(common_prefix);

/*
* If the prefix has a trailing slash, strip it so that submodules wont
* be pruned from the index.
*/
if (common_prefix[common_prefix_len - 1] == '/')
common_prefix_len--;

return common_prefix_len;
}

/* /*
* Read the tree specified with --with-tree option * Read the tree specified with --with-tree option
* (typically, HEAD) into stage #1 and then * (typically, HEAD) into stage #1 and then
@ -624,8 +643,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
"--error-unmatch"); "--error-unmatch");


parse_pathspec(&pathspec, 0, parse_pathspec(&pathspec, 0,
PATHSPEC_PREFER_CWD | PATHSPEC_PREFER_CWD,
PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
prefix, argv); prefix, argv);


/* /*
@ -637,7 +655,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
max_prefix = NULL; max_prefix = NULL;
else else
max_prefix = common_prefix(&pathspec); max_prefix = common_prefix(&pathspec);
max_prefix_len = max_prefix ? strlen(max_prefix) : 0; max_prefix_len = get_common_prefix_len(max_prefix);

prune_cache(max_prefix, max_prefix_len);


/* Treat unmatching pathspec elements as errors */ /* Treat unmatching pathspec elements as errors */
if (pathspec.nr && error_unmatch) if (pathspec.nr && error_unmatch)
@ -651,7 +671,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
show_killed || show_modified || show_resolve_undo)) show_killed || show_modified || show_resolve_undo))
show_cached = 1; show_cached = 1;


prune_cache(max_prefix, max_prefix_len);
if (with_tree) { if (with_tree) {
/* /*
* Basic sanity check; show-stages and show-unmerged * Basic sanity check; show-stages and show-unmerged

Loading…
Cancel
Save