dir: restructure in a way to avoid passing around a struct dirent
Restructure the code slightly to avoid passing around a struct dirent anywhere, which also enables us to avoid trying to manufacture one. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
22705334b9
commit
ad6f2157f9
73
dir.c
73
dir.c
@ -41,7 +41,8 @@ struct cached_dir {
|
|||||||
int nr_files;
|
int nr_files;
|
||||||
int nr_dirs;
|
int nr_dirs;
|
||||||
|
|
||||||
struct dirent *de;
|
const char *d_name;
|
||||||
|
int d_type;
|
||||||
const char *file;
|
const char *file;
|
||||||
struct untracked_cache_dir *ucd;
|
struct untracked_cache_dir *ucd;
|
||||||
};
|
};
|
||||||
@ -50,8 +51,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
|||||||
struct index_state *istate, const char *path, int len,
|
struct index_state *istate, const char *path, int len,
|
||||||
struct untracked_cache_dir *untracked,
|
struct untracked_cache_dir *untracked,
|
||||||
int check_only, int stop_at_first_file, const struct pathspec *pathspec);
|
int check_only, int stop_at_first_file, const struct pathspec *pathspec);
|
||||||
static int get_dtype(struct dirent *de, struct index_state *istate,
|
static int resolve_dtype(int dtype, struct index_state *istate,
|
||||||
const char *path, int len);
|
const char *path, int len);
|
||||||
|
|
||||||
int count_slashes(const char *s)
|
int count_slashes(const char *s)
|
||||||
{
|
{
|
||||||
@ -1215,8 +1216,7 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
|
|||||||
int prefix = pattern->nowildcardlen;
|
int prefix = pattern->nowildcardlen;
|
||||||
|
|
||||||
if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
|
if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
|
||||||
if (*dtype == DT_UNKNOWN)
|
*dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
|
||||||
*dtype = get_dtype(NULL, istate, pathname, pathlen);
|
|
||||||
if (*dtype != DT_DIR)
|
if (*dtype != DT_DIR)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1842,10 +1842,9 @@ static int get_index_dtype(struct index_state *istate,
|
|||||||
return DT_UNKNOWN;
|
return DT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dtype(struct dirent *de, struct index_state *istate,
|
static int resolve_dtype(int dtype, struct index_state *istate,
|
||||||
const char *path, int len)
|
const char *path, int len)
|
||||||
{
|
{
|
||||||
int dtype = de ? DTYPE(de) : DT_UNKNOWN;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (dtype != DT_UNKNOWN)
|
if (dtype != DT_UNKNOWN)
|
||||||
@ -1870,14 +1869,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
|||||||
struct strbuf *path,
|
struct strbuf *path,
|
||||||
int baselen,
|
int baselen,
|
||||||
const struct pathspec *pathspec,
|
const struct pathspec *pathspec,
|
||||||
int dtype, struct dirent *de)
|
int dtype)
|
||||||
{
|
{
|
||||||
int exclude;
|
int exclude;
|
||||||
int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
|
int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
|
||||||
enum path_treatment path_treatment;
|
enum path_treatment path_treatment;
|
||||||
|
|
||||||
if (dtype == DT_UNKNOWN)
|
dtype = resolve_dtype(dtype, istate, path->buf, path->len);
|
||||||
dtype = get_dtype(de, istate, path->buf, path->len);
|
|
||||||
|
|
||||||
/* Always exclude indexed files */
|
/* Always exclude indexed files */
|
||||||
if (dtype != DT_DIR && has_path_in_index)
|
if (dtype != DT_DIR && has_path_in_index)
|
||||||
@ -1985,21 +1983,18 @@ static enum path_treatment treat_path(struct dir_struct *dir,
|
|||||||
int baselen,
|
int baselen,
|
||||||
const struct pathspec *pathspec)
|
const struct pathspec *pathspec)
|
||||||
{
|
{
|
||||||
int dtype;
|
if (!cdir->d_name)
|
||||||
struct dirent *de = cdir->de;
|
|
||||||
|
|
||||||
if (!de)
|
|
||||||
return treat_path_fast(dir, untracked, cdir, istate, path,
|
return treat_path_fast(dir, untracked, cdir, istate, path,
|
||||||
baselen, pathspec);
|
baselen, pathspec);
|
||||||
if (is_dot_or_dotdot(de->d_name) || !fspathcmp(de->d_name, ".git"))
|
if (is_dot_or_dotdot(cdir->d_name) || !fspathcmp(cdir->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, cdir->d_name);
|
||||||
if (simplify_away(path->buf, path->len, pathspec))
|
if (simplify_away(path->buf, path->len, pathspec))
|
||||||
return path_none;
|
return path_none;
|
||||||
|
|
||||||
dtype = DTYPE(de);
|
return treat_one_path(dir, untracked, istate, path, baselen, pathspec,
|
||||||
return treat_one_path(dir, untracked, istate, path, baselen, pathspec, dtype, de);
|
cdir->d_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_untracked(struct untracked_cache_dir *dir, const char *name)
|
static void add_untracked(struct untracked_cache_dir *dir, const char *name)
|
||||||
@ -2087,10 +2082,17 @@ static int open_cached_dir(struct cached_dir *cdir,
|
|||||||
|
|
||||||
static int read_cached_dir(struct cached_dir *cdir)
|
static int read_cached_dir(struct cached_dir *cdir)
|
||||||
{
|
{
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
if (cdir->fdir) {
|
if (cdir->fdir) {
|
||||||
cdir->de = readdir(cdir->fdir);
|
de = readdir(cdir->fdir);
|
||||||
if (!cdir->de)
|
if (!de) {
|
||||||
|
cdir->d_name = NULL;
|
||||||
|
cdir->d_type = DT_UNKNOWN;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
cdir->d_name = de->d_name;
|
||||||
|
cdir->d_type = DTYPE(de);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (cdir->nr_dirs < cdir->untracked->dirs_nr) {
|
while (cdir->nr_dirs < cdir->untracked->dirs_nr) {
|
||||||
@ -2216,7 +2218,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
|
|||||||
/* recurse into subdir if instructed by treat_path */
|
/* recurse into subdir if instructed by treat_path */
|
||||||
if ((state == path_recurse) ||
|
if ((state == path_recurse) ||
|
||||||
((state == path_untracked) &&
|
((state == path_untracked) &&
|
||||||
(get_dtype(cdir.de, istate, path.buf, path.len) == DT_DIR) &&
|
(resolve_dtype(cdir.d_type, istate, path.buf, path.len) == DT_DIR) &&
|
||||||
((dir->flags & DIR_SHOW_IGNORED_TOO) ||
|
((dir->flags & DIR_SHOW_IGNORED_TOO) ||
|
||||||
(pathspec &&
|
(pathspec &&
|
||||||
do_match_pathspec(istate, pathspec, path.buf, path.len,
|
do_match_pathspec(istate, pathspec, path.buf, path.len,
|
||||||
@ -2314,10 +2316,10 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
|
struct strbuf subdir = STRBUF_INIT;
|
||||||
int prevlen, baselen;
|
int prevlen, baselen;
|
||||||
const char *cp;
|
const char *cp;
|
||||||
struct cached_dir cdir;
|
struct cached_dir cdir;
|
||||||
struct dirent *de;
|
|
||||||
enum path_treatment state = path_none;
|
enum path_treatment state = path_none;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2342,22 +2344,8 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||||||
if (!len)
|
if (!len)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/*
|
|
||||||
* We need a manufactured dirent with sufficient space to store a
|
|
||||||
* leading directory component of path in its d_name. Here, we
|
|
||||||
* assume that the dirent's d_name is either declared as
|
|
||||||
* char d_name[BIG_ENOUGH]
|
|
||||||
* or that it is declared at the end of the struct as
|
|
||||||
* char d_name[]
|
|
||||||
* For either case, padding with len+1 bytes at the end will ensure
|
|
||||||
* sufficient storage space.
|
|
||||||
*/
|
|
||||||
de = xcalloc(1, st_add3(sizeof(struct dirent), len, 1));
|
|
||||||
memset(&cdir, 0, sizeof(cdir));
|
memset(&cdir, 0, sizeof(cdir));
|
||||||
cdir.de = de;
|
cdir.d_type = DT_DIR;
|
||||||
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
|
|
||||||
de->d_type = DT_DIR;
|
|
||||||
#endif
|
|
||||||
baselen = 0;
|
baselen = 0;
|
||||||
prevlen = 0;
|
prevlen = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -2374,12 +2362,13 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||||||
break;
|
break;
|
||||||
strbuf_reset(&sb);
|
strbuf_reset(&sb);
|
||||||
strbuf_add(&sb, path, prevlen);
|
strbuf_add(&sb, path, prevlen);
|
||||||
memcpy(de->d_name, path+prevlen, baselen-prevlen);
|
strbuf_reset(&subdir);
|
||||||
de->d_name[baselen-prevlen] = '\0';
|
strbuf_add(&subdir, path+prevlen, baselen-prevlen);
|
||||||
|
cdir.d_name = subdir.buf;
|
||||||
state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
|
state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
|
||||||
pathspec);
|
pathspec);
|
||||||
if (state == path_untracked &&
|
if (state == path_untracked &&
|
||||||
get_dtype(cdir.de, istate, sb.buf, sb.len) == DT_DIR &&
|
resolve_dtype(cdir.d_type, istate, sb.buf, sb.len) == DT_DIR &&
|
||||||
(dir->flags & DIR_SHOW_IGNORED_TOO ||
|
(dir->flags & DIR_SHOW_IGNORED_TOO ||
|
||||||
do_match_pathspec(istate, pathspec, sb.buf, sb.len,
|
do_match_pathspec(istate, pathspec, sb.buf, sb.len,
|
||||||
baselen, NULL, DO_MATCH_LEADING_PATHSPEC) == MATCHED_RECURSIVELY_LEADING_PATHSPEC)) {
|
baselen, NULL, DO_MATCH_LEADING_PATHSPEC) == MATCHED_RECURSIVELY_LEADING_PATHSPEC)) {
|
||||||
@ -2403,7 +2392,7 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||||||
&sb, baselen, pathspec,
|
&sb, baselen, pathspec,
|
||||||
state);
|
state);
|
||||||
|
|
||||||
free(de);
|
strbuf_release(&subdir);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
return state == path_recurse;
|
return state == path_recurse;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user