dir: remove struct path_simplify

Teach simplify_away() and exclude_matches_pathspec() to handle struct
pathspec directly, eliminating the need for the struct path_simplify.

Also renamed the len parameter to pathlen in exclude_matches_pathspec()
to match the parameter names used in simplify_away().

Signed-off-by: Brandon Williams <bmwill@google.com>
Reviewed-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Brandon Williams 2017-01-04 10:03:57 -08:00 committed by Junio C Hamano
parent 2ec87741b2
commit e1b8c7bdc0

177
dir.c
View File

@ -16,11 +16,6 @@
#include "varint.h" #include "varint.h"
#include "ewah/ewok.h" #include "ewah/ewok.h"
struct path_simplify {
int len;
const char *path;
};
/* /*
* Tells read_directory_recursive how a file or directory should be treated. * Tells read_directory_recursive how a file or directory should be treated.
* Values are ordered by significance, e.g. if a directory contains both * Values are ordered by significance, e.g. if a directory contains both
@ -50,7 +45,7 @@ struct cached_dir {
static enum path_treatment read_directory_recursive(struct dir_struct *dir, static enum path_treatment read_directory_recursive(struct dir_struct *dir,
const char *path, int len, struct untracked_cache_dir *untracked, const char *path, int len, struct untracked_cache_dir *untracked,
int check_only, const struct path_simplify *simplify); int check_only, const struct pathspec *pathspec);
static int get_dtype(struct dirent *de, const char *path, int len); static int get_dtype(struct dirent *de, const char *path, int len);
int fspathcmp(const char *a, const char *b) int fspathcmp(const char *a, const char *b)
@ -1312,7 +1307,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
static enum path_treatment treat_directory(struct dir_struct *dir, static enum path_treatment treat_directory(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
const char *dirname, int len, int baselen, int exclude, const char *dirname, int len, int baselen, int exclude,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
/* The "len-1" is to strip the final '/' */ /* The "len-1" is to strip the final '/' */
switch (directory_exists_in_index(dirname, len-1)) { switch (directory_exists_in_index(dirname, len-1)) {
@ -1341,7 +1336,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
untracked = lookup_untracked(dir->untracked, untracked, untracked = lookup_untracked(dir->untracked, untracked,
dirname + baselen, len - baselen); dirname + baselen, len - baselen);
return read_directory_recursive(dir, dirname, len, return read_directory_recursive(dir, dirname, len,
untracked, 1, simplify); untracked, 1, pathspec);
} }
/* /*
@ -1349,24 +1344,33 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
* reading - if the path cannot possibly be in the pathspec, * reading - if the path cannot possibly be in the pathspec,
* return true, and we'll skip it early. * return true, and we'll skip it early.
*/ */
static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify) static int simplify_away(const char *path, int pathlen,
const struct pathspec *pathspec)
{ {
if (simplify) { int i;
for (;;) {
const char *match = simplify->path;
int len = simplify->len;
if (!match) if (!pathspec || !pathspec->nr)
break; return 0;
if (len > pathlen)
len = pathlen; GUARD_PATHSPEC(pathspec,
if (!memcmp(path, match, len)) PATHSPEC_FROMTOP |
return 0; PATHSPEC_MAXDEPTH |
simplify++; PATHSPEC_LITERAL |
} PATHSPEC_GLOB |
return 1; PATHSPEC_ICASE |
PATHSPEC_EXCLUDE);
for (i = 0; i < pathspec->nr; i++) {
const struct pathspec_item *item = &pathspec->items[i];
int len = item->nowildcard_len;
if (len > pathlen)
len = pathlen;
if (!ps_strncmp(item, item->match, path, len))
return 0;
} }
return 0;
return 1;
} }
/* /*
@ -1380,19 +1384,33 @@ static int simplify_away(const char *path, int pathlen, const struct path_simpli
* 2. the path is a directory prefix of some element in the * 2. the path is a directory prefix of some element in the
* pathspec * pathspec
*/ */
static int exclude_matches_pathspec(const char *path, int len, static int exclude_matches_pathspec(const char *path, int pathlen,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
if (simplify) { int i;
for (; simplify->path; simplify++) {
if (len == simplify->len if (!pathspec || !pathspec->nr)
&& !memcmp(path, simplify->path, len)) return 0;
return 1;
if (len < simplify->len GUARD_PATHSPEC(pathspec,
&& simplify->path[len] == '/' PATHSPEC_FROMTOP |
&& !memcmp(path, simplify->path, len)) PATHSPEC_MAXDEPTH |
return 1; PATHSPEC_LITERAL |
} PATHSPEC_GLOB |
PATHSPEC_ICASE |
PATHSPEC_EXCLUDE);
for (i = 0; i < pathspec->nr; i++) {
const struct pathspec_item *item = &pathspec->items[i];
int len = item->nowildcard_len;
if (len == pathlen &&
!ps_strncmp(item, item->match, path, pathlen))
return 1;
if (len > pathlen &&
item->match[pathlen] == '/' &&
!ps_strncmp(item, item->match, path, pathlen))
return 1;
} }
return 0; return 0;
} }
@ -1460,7 +1478,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct strbuf *path, struct strbuf *path,
int baselen, int baselen,
const struct path_simplify *simplify, const struct pathspec *pathspec,
int dtype, struct dirent *de) int dtype, struct dirent *de)
{ {
int exclude; int exclude;
@ -1512,7 +1530,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
case DT_DIR: case DT_DIR:
strbuf_addch(path, '/'); strbuf_addch(path, '/');
return treat_directory(dir, untracked, path->buf, path->len, return treat_directory(dir, untracked, path->buf, path->len,
baselen, exclude, simplify); baselen, exclude, pathspec);
case DT_REG: case DT_REG:
case DT_LNK: case DT_LNK:
return exclude ? path_excluded : path_untracked; return exclude ? path_excluded : path_untracked;
@ -1524,7 +1542,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
struct cached_dir *cdir, struct cached_dir *cdir,
struct strbuf *path, struct strbuf *path,
int baselen, int baselen,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
strbuf_setlen(path, baselen); strbuf_setlen(path, baselen);
if (!cdir->ucd) { if (!cdir->ucd) {
@ -1541,7 +1559,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
* with check_only set. * with check_only set.
*/ */
return read_directory_recursive(dir, path->buf, path->len, return read_directory_recursive(dir, path->buf, path->len,
cdir->ucd, 1, simplify); cdir->ucd, 1, pathspec);
/* /*
* We get path_recurse in the first run when * We get path_recurse in the first run when
* directory_exists_in_index() returns index_nonexistent. We * directory_exists_in_index() returns index_nonexistent. We
@ -1556,23 +1574,23 @@ static enum path_treatment treat_path(struct dir_struct *dir,
struct cached_dir *cdir, struct cached_dir *cdir,
struct strbuf *path, struct strbuf *path,
int baselen, int baselen,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
int dtype; int dtype;
struct dirent *de = cdir->de; struct dirent *de = cdir->de;
if (!de) if (!de)
return treat_path_fast(dir, untracked, cdir, path, return treat_path_fast(dir, untracked, cdir, path,
baselen, simplify); baselen, pathspec);
if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git")) if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
return path_none; return path_none;
strbuf_setlen(path, baselen); strbuf_setlen(path, baselen);
strbuf_addstr(path, de->d_name); strbuf_addstr(path, de->d_name);
if (simplify_away(path->buf, path->len, simplify)) if (simplify_away(path->buf, path->len, pathspec))
return path_none; return path_none;
dtype = DTYPE(de); dtype = DTYPE(de);
return treat_one_path(dir, untracked, path, baselen, simplify, dtype, de); return treat_one_path(dir, untracked, path, baselen, pathspec, dtype, de);
} }
static void add_untracked(struct untracked_cache_dir *dir, const char *name) static void add_untracked(struct untracked_cache_dir *dir, const char *name)
@ -1703,7 +1721,7 @@ static void close_cached_dir(struct cached_dir *cdir)
static enum path_treatment read_directory_recursive(struct dir_struct *dir, static enum path_treatment read_directory_recursive(struct dir_struct *dir,
const char *base, int baselen, const char *base, int baselen,
struct untracked_cache_dir *untracked, int check_only, struct untracked_cache_dir *untracked, int check_only,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
struct cached_dir cdir; struct cached_dir cdir;
enum path_treatment state, subdir_state, dir_state = path_none; enum path_treatment state, subdir_state, dir_state = path_none;
@ -1719,7 +1737,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
while (!read_cached_dir(&cdir)) { while (!read_cached_dir(&cdir)) {
/* check how the file or directory should be treated */ /* check how the file or directory should be treated */
state = treat_path(dir, untracked, &cdir, &path, baselen, simplify); state = treat_path(dir, untracked, &cdir, &path,
baselen, pathspec);
if (state > dir_state) if (state > dir_state)
dir_state = state; dir_state = state;
@ -1731,8 +1750,9 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
path.buf + baselen, path.buf + baselen,
path.len - baselen); path.len - baselen);
subdir_state = subdir_state =
read_directory_recursive(dir, path.buf, path.len, read_directory_recursive(dir, path.buf,
ud, check_only, simplify); path.len, ud,
check_only, pathspec);
if (subdir_state > dir_state) if (subdir_state > dir_state)
dir_state = subdir_state; dir_state = subdir_state;
} }
@ -1756,7 +1776,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
else if ((dir->flags & DIR_SHOW_IGNORED_TOO) || else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||
((dir->flags & DIR_COLLECT_IGNORED) && ((dir->flags & DIR_COLLECT_IGNORED) &&
exclude_matches_pathspec(path.buf, path.len, exclude_matches_pathspec(path.buf, path.len,
simplify))) pathspec)))
dir_add_ignored(dir, path.buf, path.len); dir_add_ignored(dir, path.buf, path.len);
break; break;
@ -1787,36 +1807,9 @@ static int cmp_name(const void *p1, const void *p2)
return name_compare(e1->name, e1->len, e2->name, e2->len); return name_compare(e1->name, e1->len, e2->name, e2->len);
} }
static struct path_simplify *create_simplify(const char **pathspec)
{
int nr, alloc = 0;
struct path_simplify *simplify = NULL;
if (!pathspec)
return NULL;
for (nr = 0 ; ; nr++) {
const char *match;
ALLOC_GROW(simplify, nr + 1, alloc);
match = *pathspec++;
if (!match)
break;
simplify[nr].path = match;
simplify[nr].len = simple_length(match);
}
simplify[nr].path = NULL;
simplify[nr].len = 0;
return simplify;
}
static void free_simplify(struct path_simplify *simplify)
{
free(simplify);
}
static int treat_leading_path(struct dir_struct *dir, static int treat_leading_path(struct dir_struct *dir,
const char *path, int len, const char *path, int len,
const struct path_simplify *simplify) const struct pathspec *pathspec)
{ {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int baselen, rc = 0; int baselen, rc = 0;
@ -1840,9 +1833,9 @@ static int treat_leading_path(struct dir_struct *dir,
strbuf_add(&sb, path, baselen); strbuf_add(&sb, path, baselen);
if (!is_directory(sb.buf)) if (!is_directory(sb.buf))
break; break;
if (simplify_away(sb.buf, sb.len, simplify)) if (simplify_away(sb.buf, sb.len, pathspec))
break; break;
if (treat_one_path(dir, NULL, &sb, baselen, simplify, if (treat_one_path(dir, NULL, &sb, baselen, pathspec,
DT_DIR, NULL) == path_none) DT_DIR, NULL) == path_none)
break; /* do not recurse into it */ break; /* do not recurse into it */
if (len <= baselen) { if (len <= baselen) {
@ -2010,33 +2003,14 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
return root; return root;
} }
int read_directory(struct dir_struct *dir, const char *path, int len, const struct pathspec *pathspec) int read_directory(struct dir_struct *dir, const char *path,
int len, const struct pathspec *pathspec)
{ {
struct path_simplify *simplify;
struct untracked_cache_dir *untracked; struct untracked_cache_dir *untracked;
/*
* Check out create_simplify()
*/
if (pathspec)
GUARD_PATHSPEC(pathspec,
PATHSPEC_FROMTOP |
PATHSPEC_MAXDEPTH |
PATHSPEC_LITERAL |
PATHSPEC_GLOB |
PATHSPEC_ICASE |
PATHSPEC_EXCLUDE);
if (has_symlink_leading_path(path, len)) if (has_symlink_leading_path(path, len))
return dir->nr; return dir->nr;
/*
* exclude patterns are treated like positive ones in
* create_simplify. Usually exclude patterns should be a
* subset of positive ones, which has no impacts on
* create_simplify().
*/
simplify = create_simplify(pathspec ? pathspec->_raw : NULL);
untracked = validate_untracked_cache(dir, len, pathspec); untracked = validate_untracked_cache(dir, len, pathspec);
if (!untracked) if (!untracked)
/* /*
@ -2044,9 +2018,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru
* e.g. prep_exclude() * e.g. prep_exclude()
*/ */
dir->untracked = NULL; dir->untracked = NULL;
if (!len || treat_leading_path(dir, path, len, simplify)) if (!len || treat_leading_path(dir, path, len, pathspec))
read_directory_recursive(dir, path, len, untracked, 0, simplify); read_directory_recursive(dir, path, len, untracked, 0, pathspec);
free_simplify(simplify);
QSORT(dir->entries, dir->nr, cmp_name); QSORT(dir->entries, dir->nr, cmp_name);
QSORT(dir->ignored, dir->ignored_nr, cmp_name); QSORT(dir->ignored, dir->ignored_nr, cmp_name);
if (dir->untracked) { if (dir->untracked) {