зеркало из https://github.com/microsoft/git.git
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:
Родитель
22705334b9
Коммит
ad6f2157f9
73
dir.c
73
dir.c
|
@ -41,7 +41,8 @@ struct cached_dir {
|
|||
int nr_files;
|
||||
int nr_dirs;
|
||||
|
||||
struct dirent *de;
|
||||
const char *d_name;
|
||||
int d_type;
|
||||
const char *file;
|
||||
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 untracked_cache_dir *untracked,
|
||||
int check_only, int stop_at_first_file, const struct pathspec *pathspec);
|
||||
static int get_dtype(struct dirent *de, struct index_state *istate,
|
||||
const char *path, int len);
|
||||
static int resolve_dtype(int dtype, struct index_state *istate,
|
||||
const char *path, int len);
|
||||
|
||||
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;
|
||||
|
||||
if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
|
||||
if (*dtype == DT_UNKNOWN)
|
||||
*dtype = get_dtype(NULL, istate, pathname, pathlen);
|
||||
*dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
|
||||
if (*dtype != DT_DIR)
|
||||
continue;
|
||||
}
|
||||
|
@ -1842,10 +1842,9 @@ static int get_index_dtype(struct index_state *istate,
|
|||
return DT_UNKNOWN;
|
||||
}
|
||||
|
||||
static int get_dtype(struct dirent *de, struct index_state *istate,
|
||||
const char *path, int len)
|
||||
static int resolve_dtype(int dtype, struct index_state *istate,
|
||||
const char *path, int len)
|
||||
{
|
||||
int dtype = de ? DTYPE(de) : DT_UNKNOWN;
|
||||
struct stat st;
|
||||
|
||||
if (dtype != DT_UNKNOWN)
|
||||
|
@ -1870,14 +1869,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
|||
struct strbuf *path,
|
||||
int baselen,
|
||||
const struct pathspec *pathspec,
|
||||
int dtype, struct dirent *de)
|
||||
int dtype)
|
||||
{
|
||||
int exclude;
|
||||
int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
|
||||
enum path_treatment path_treatment;
|
||||
|
||||
if (dtype == DT_UNKNOWN)
|
||||
dtype = get_dtype(de, istate, path->buf, path->len);
|
||||
dtype = resolve_dtype(dtype, istate, path->buf, path->len);
|
||||
|
||||
/* Always exclude indexed files */
|
||||
if (dtype != DT_DIR && has_path_in_index)
|
||||
|
@ -1985,21 +1983,18 @@ static enum path_treatment treat_path(struct dir_struct *dir,
|
|||
int baselen,
|
||||
const struct pathspec *pathspec)
|
||||
{
|
||||
int dtype;
|
||||
struct dirent *de = cdir->de;
|
||||
|
||||
if (!de)
|
||||
if (!cdir->d_name)
|
||||
return treat_path_fast(dir, untracked, cdir, istate, path,
|
||||
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;
|
||||
strbuf_setlen(path, baselen);
|
||||
strbuf_addstr(path, de->d_name);
|
||||
strbuf_addstr(path, cdir->d_name);
|
||||
if (simplify_away(path->buf, path->len, pathspec))
|
||||
return path_none;
|
||||
|
||||
dtype = DTYPE(de);
|
||||
return treat_one_path(dir, untracked, istate, path, baselen, pathspec, dtype, de);
|
||||
return treat_one_path(dir, untracked, istate, path, baselen, pathspec,
|
||||
cdir->d_type);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct dirent *de;
|
||||
|
||||
if (cdir->fdir) {
|
||||
cdir->de = readdir(cdir->fdir);
|
||||
if (!cdir->de)
|
||||
de = readdir(cdir->fdir);
|
||||
if (!de) {
|
||||
cdir->d_name = NULL;
|
||||
cdir->d_type = DT_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
cdir->d_name = de->d_name;
|
||||
cdir->d_type = DTYPE(de);
|
||||
return 0;
|
||||
}
|
||||
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 */
|
||||
if ((state == path_recurse) ||
|
||||
((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) ||
|
||||
(pathspec &&
|
||||
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 subdir = STRBUF_INIT;
|
||||
int prevlen, baselen;
|
||||
const char *cp;
|
||||
struct cached_dir cdir;
|
||||
struct dirent *de;
|
||||
enum path_treatment state = path_none;
|
||||
|
||||
/*
|
||||
|
@ -2342,22 +2344,8 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||
if (!len)
|
||||
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));
|
||||
cdir.de = de;
|
||||
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
|
||||
de->d_type = DT_DIR;
|
||||
#endif
|
||||
cdir.d_type = DT_DIR;
|
||||
baselen = 0;
|
||||
prevlen = 0;
|
||||
while (1) {
|
||||
|
@ -2374,12 +2362,13 @@ static int treat_leading_path(struct dir_struct *dir,
|
|||
break;
|
||||
strbuf_reset(&sb);
|
||||
strbuf_add(&sb, path, prevlen);
|
||||
memcpy(de->d_name, path+prevlen, baselen-prevlen);
|
||||
de->d_name[baselen-prevlen] = '\0';
|
||||
strbuf_reset(&subdir);
|
||||
strbuf_add(&subdir, path+prevlen, baselen-prevlen);
|
||||
cdir.d_name = subdir.buf;
|
||||
state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
|
||||
pathspec);
|
||||
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 ||
|
||||
do_match_pathspec(istate, pathspec, sb.buf, sb.len,
|
||||
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,
|
||||
state);
|
||||
|
||||
free(de);
|
||||
strbuf_release(&subdir);
|
||||
strbuf_release(&sb);
|
||||
return state == path_recurse;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче