Skip to content

Commit

Permalink
Merge branch 'en/fill-directory-exponential'
Browse files Browse the repository at this point in the history
The directory traversal code had redundant recursive calls which
made its performance characteristics exponential with respect to
the depth of the tree, which was corrected.

* en/fill-directory-exponential:
  completion: fix 'git add' on paths under an untracked directory
  Fix error-prone fill_directory() API; make it only return matches
  dir: replace double pathspec matching with single in treat_directory()
  dir: include DIR_KEEP_UNTRACKED_CONTENTS handling in treat_directory()
  dir: replace exponential algorithm with a linear one
  dir: refactor treat_directory to clarify control flow
  dir: fix confusion based on variable tense
  dir: fix broken comment
  dir: consolidate treat_path() and treat_one_path()
  dir: fix simple typo in comment
  t3000: add more testcases testing a variety of ls-files issues
  t7063: more thorough status checking
  • Loading branch information
gitster committed Apr 29, 2020
2 parents 48eee46 + c0af173 commit 6eacc39
Show file tree
Hide file tree
Showing 10 changed files with 437 additions and 201 deletions.
6 changes: 0 additions & 6 deletions builtin/clean.c
Expand Up @@ -983,12 +983,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (!cache_name_is_other(ent->name, ent->len))
continue;

if (pathspec.nr)
matches = dir_path_match(&the_index, ent, &pathspec, 0, NULL);

if (pathspec.nr && !matches)
continue;

if (lstat(ent->name, &st))
die_errno("Cannot lstat '%s'", ent->name);

Expand Down
2 changes: 0 additions & 2 deletions builtin/grep.c
Expand Up @@ -701,8 +701,6 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,

fill_directory(&dir, opt->repo->index, pathspec);
for (i = 0; i < dir.nr; i++) {
if (!dir_path_match(opt->repo->index, dir.entries[i], pathspec, 0, NULL))
continue;
hit |= grep_file(opt, dir.entries[i]->name);
if (hit && opt->status_only)
break;
Expand Down
5 changes: 3 additions & 2 deletions builtin/ls-files.c
Expand Up @@ -128,8 +128,9 @@ static void show_dir_entry(const struct index_state *istate,
if (len > ent->len)
die("git ls-files: internal error - directory entry not superset of prefix");

if (!dir_path_match(istate, ent, &pathspec, len, ps_matched))
return;
/* If ps_matches is non-NULL, figure out which pathspec(s) match. */
if (ps_matched)
dir_path_match(istate, ent, &pathspec, len, ps_matched);

fputs(tag, stdout);
write_eolinfo(istate, NULL, ent->name);
Expand Down
17 changes: 5 additions & 12 deletions builtin/stash.c
Expand Up @@ -861,30 +861,23 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked,
struct strbuf *untracked_files)
{
int i;
int max_len;
int found = 0;
char *seen;
struct dir_struct dir;

memset(&dir, 0, sizeof(dir));
if (include_untracked != INCLUDE_ALL_FILES)
setup_standard_excludes(&dir);

seen = xcalloc(ps->nr, 1);

max_len = fill_directory(&dir, the_repository->index, ps);
fill_directory(&dir, the_repository->index, ps);
for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i];
if (dir_path_match(&the_index, ent, ps, max_len, seen)) {
found++;
strbuf_addstr(untracked_files, ent->name);
/* NUL-terminate: will be fed to update-index -z */
strbuf_addch(untracked_files, '\0');
}
found++;
strbuf_addstr(untracked_files, ent->name);
/* NUL-terminate: will be fed to update-index -z */
strbuf_addch(untracked_files, '\0');
free(ent);
}

free(seen);
free(dir.entries);
free(dir.ignored);
clear_directory(&dir);
Expand Down
2 changes: 1 addition & 1 deletion contrib/completion/git-completion.bash
Expand Up @@ -504,7 +504,7 @@ __git_index_files ()
{
local root="$2" match="$3"

__git_ls_files_helper "$root" "$1" "$match" |
__git_ls_files_helper "$root" "$1" "${match:-?}" |
awk -F / -v pfx="${2//\\/\\\\}" '{
paths[$1] = 1
}
Expand Down

0 comments on commit 6eacc39

Please sign in to comment.