Merge branch 'bw/dir-c-stops-relying-on-the-index'

API update.

* bw/dir-c-stops-relying-on-the-index:
  dir: convert fill_directory to take an index
  dir: convert read_directory to take an index
  dir: convert read_directory_recursive to take an index
  dir: convert open_cached_dir to take an index
  dir: convert is_excluded to take an index
  dir: convert prep_exclude to take an index
  dir: convert add_excludes to take an index
  dir: convert is_excluded_from_list to take an index
  dir: convert last_exclude_matching_from_list to take an index
  dir: convert dir_add* to take an index
  dir: convert get_dtype to take index
  dir: convert directory_exists_in_index to take index
  dir: convert read_skip_worktree_file_from_index to take an index
  dir: stop using the index compatibility macros
This commit is contained in:
Junio C Hamano 2017-05-29 12:34:41 +09:00
commit 4eeed27e16
9 changed files with 150 additions and 107 deletions

View File

@ -400,7 +400,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
} }
/* This picks up the paths that are not tracked */ /* This picks up the paths that are not tracked */
baselen = fill_directory(&dir, &pathspec); baselen = fill_directory(&dir, &the_index, &pathspec);
if (pathspec.nr) if (pathspec.nr)
seen = prune_directory(&dir, &pathspec, baselen); seen = prune_directory(&dir, &pathspec, baselen);
} }
@ -436,8 +436,9 @@ int cmd_add(int argc, const char **argv, const char *prefix)
!file_exists(path))) { !file_exists(path))) {
if (ignore_missing) { if (ignore_missing) {
int dtype = DT_UNKNOWN; int dtype = DT_UNKNOWN;
if (is_excluded(&dir, path, &dtype)) if (is_excluded(&dir, &the_index, path, &dtype))
dir_add_ignored(&dir, path, pathspec.items[i].len); dir_add_ignored(&dir, &the_index,
path, pathspec.items[i].len);
} else } else
die(_("pathspec '%s' did not match any files"), die(_("pathspec '%s' did not match any files"),
pathspec.items[i].original); pathspec.items[i].original);

View File

@ -101,7 +101,8 @@ static int check_ignore(struct dir_struct *dir,
full_path = pathspec.items[i].match; full_path = pathspec.items[i].match;
exclude = NULL; exclude = NULL;
if (!seen[i]) { if (!seen[i]) {
exclude = last_exclude_matching(dir, full_path, &dtype); exclude = last_exclude_matching(dir, &the_index,
full_path, &dtype);
} }
if (!quiet && (exclude || show_non_matching)) if (!quiet && (exclude || show_non_matching))
output_exclude(pathspec.items[i].original, exclude); output_exclude(pathspec.items[i].original, exclude);

View File

@ -683,7 +683,7 @@ static int filter_by_patterns_cmd(void)
for_each_string_list_item(item, &del_list) { for_each_string_list_item(item, &del_list) {
int dtype = DT_UNKNOWN; int dtype = DT_UNKNOWN;
if (is_excluded(&dir, item->string, &dtype)) { if (is_excluded(&dir, &the_index, item->string, &dtype)) {
*item->string = '\0'; *item->string = '\0';
changed++; changed++;
} }
@ -930,7 +930,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
PATHSPEC_PREFER_CWD, PATHSPEC_PREFER_CWD,
prefix, argv); prefix, argv);
fill_directory(&dir, &pathspec); fill_directory(&dir, &the_index, &pathspec);
for (i = 0; i < dir.nr; i++) { for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i]; struct dir_entry *ent = dir.entries[i];

View File

@ -866,7 +866,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
if (exc_std) if (exc_std)
setup_standard_excludes(&dir); setup_standard_excludes(&dir);
fill_directory(&dir, pathspec); fill_directory(&dir, &the_index, pathspec);
for (i = 0; i < dir.nr; i++) { for (i = 0; i < dir.nr; i++) {
if (!dir_path_match(dir.entries[i], pathspec, 0, NULL)) if (!dir_path_match(dir.entries[i], pathspec, 0, NULL))
continue; continue;

View File

@ -322,7 +322,7 @@ static void show_ru_info(void)
static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce) static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
{ {
int dtype = ce_to_dtype(ce); int dtype = ce_to_dtype(ce);
return is_excluded(dir, ce->name, &dtype); return is_excluded(dir, &the_index, ce->name, &dtype);
} }
static void show_files(struct dir_struct *dir) static void show_files(struct dir_struct *dir)
@ -333,7 +333,7 @@ static void show_files(struct dir_struct *dir)
if (show_others || show_killed) { if (show_others || show_killed) {
if (!show_others) if (!show_others)
dir->flags |= DIR_COLLECT_KILLED_ONLY; dir->flags |= DIR_COLLECT_KILLED_ONLY;
fill_directory(dir, &pathspec); fill_directory(dir, &the_index, &pathspec);
if (show_others) if (show_others)
show_other_files(dir); show_other_files(dir);
if (show_killed) if (show_killed)

200
dir.c
View File

@ -7,6 +7,7 @@
* Copyright (C) Linus Torvalds, 2005-2006 * Copyright (C) Linus Torvalds, 2005-2006
* Junio Hamano, 2005-2006 * Junio Hamano, 2005-2006
*/ */
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h" #include "cache.h"
#include "dir.h" #include "dir.h"
#include "attr.h" #include "attr.h"
@ -45,9 +46,11 @@ 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, struct index_state *istate, const char *path, int len,
struct untracked_cache_dir *untracked,
int check_only, const struct pathspec *pathspec); 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, struct index_state *istate,
const char *path, int len);
int fspathcmp(const char *a, const char *b) int fspathcmp(const char *a, const char *b)
{ {
@ -174,7 +177,9 @@ char *common_prefix(const struct pathspec *pathspec)
return len ? xmemdupz(pathspec->items[0].match, len) : NULL; return len ? xmemdupz(pathspec->items[0].match, len) : NULL;
} }
int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec) int fill_directory(struct dir_struct *dir,
struct index_state *istate,
const struct pathspec *pathspec)
{ {
const char *prefix; const char *prefix;
size_t prefix_len; size_t prefix_len;
@ -187,7 +192,7 @@ int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec)
prefix = prefix_len ? pathspec->items[0].match : ""; prefix = prefix_len ? pathspec->items[0].match : "";
/* Read the directory and prune it */ /* Read the directory and prune it */
read_directory(dir, prefix, prefix_len, pathspec); read_directory(dir, istate, prefix, prefix_len, pathspec);
return prefix_len; return prefix_len;
} }
@ -587,7 +592,8 @@ void add_exclude(const char *string, const char *base,
x->el = el; x->el = el;
} }
static void *read_skip_worktree_file_from_index(const char *path, size_t *size, static void *read_skip_worktree_file_from_index(const struct index_state *istate,
const char *path, size_t *size,
struct sha1_stat *sha1_stat) struct sha1_stat *sha1_stat)
{ {
int pos, len; int pos, len;
@ -596,12 +602,12 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size,
void *data; void *data;
len = strlen(path); len = strlen(path);
pos = cache_name_pos(path, len); pos = index_name_pos(istate, path, len);
if (pos < 0) if (pos < 0)
return NULL; return NULL;
if (!ce_skip_worktree(active_cache[pos])) if (!ce_skip_worktree(istate->cache[pos]))
return NULL; return NULL;
data = read_sha1_file(active_cache[pos]->oid.hash, &type, &sz); data = read_sha1_file(istate->cache[pos]->oid.hash, &type, &sz);
if (!data || type != OBJ_BLOB) { if (!data || type != OBJ_BLOB) {
free(data); free(data);
return NULL; return NULL;
@ -609,7 +615,7 @@ static void *read_skip_worktree_file_from_index(const char *path, size_t *size,
*size = xsize_t(sz); *size = xsize_t(sz);
if (sha1_stat) { if (sha1_stat) {
memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat)); memset(&sha1_stat->stat, 0, sizeof(sha1_stat->stat));
hashcpy(sha1_stat->sha1, active_cache[pos]->oid.hash); hashcpy(sha1_stat->sha1, istate->cache[pos]->oid.hash);
} }
return data; return data;
} }
@ -727,7 +733,7 @@ static void invalidate_directory(struct untracked_cache *uc,
/* /*
* Given a file with name "fname", read it (either from disk, or from * Given a file with name "fname", read it (either from disk, or from
* the index if "check_index" is non-zero), parse it and store the * an index if 'istate' is non-null), parse it and store the
* exclude rules in "el". * exclude rules in "el".
* *
* If "ss" is not NULL, compute SHA-1 of the exclude file and fill * If "ss" is not NULL, compute SHA-1 of the exclude file and fill
@ -735,7 +741,8 @@ static void invalidate_directory(struct untracked_cache *uc,
* ss_valid is non-zero, "ss" must contain good value as input. * ss_valid is non-zero, "ss" must contain good value as input.
*/ */
static int add_excludes(const char *fname, const char *base, int baselen, static int add_excludes(const char *fname, const char *base, int baselen,
struct exclude_list *el, int check_index, struct exclude_list *el,
struct index_state *istate,
struct sha1_stat *sha1_stat) struct sha1_stat *sha1_stat)
{ {
struct stat st; struct stat st;
@ -749,8 +756,8 @@ static int add_excludes(const char *fname, const char *base, int baselen,
warn_on_inaccessible(fname); warn_on_inaccessible(fname);
if (0 <= fd) if (0 <= fd)
close(fd); close(fd);
if (!check_index || if (!istate ||
(buf = read_skip_worktree_file_from_index(fname, &size, sha1_stat)) == NULL) (buf = read_skip_worktree_file_from_index(istate, fname, &size, sha1_stat)) == NULL)
return -1; return -1;
if (size == 0) { if (size == 0) {
free(buf); free(buf);
@ -782,15 +789,15 @@ static int add_excludes(const char *fname, const char *base, int baselen,
if (sha1_stat) { if (sha1_stat) {
int pos; int pos;
if (sha1_stat->valid && if (sha1_stat->valid &&
!match_stat_data_racy(&the_index, &sha1_stat->stat, &st)) !match_stat_data_racy(istate, &sha1_stat->stat, &st))
; /* no content change, ss->sha1 still good */ ; /* no content change, ss->sha1 still good */
else if (check_index && else if (istate &&
(pos = cache_name_pos(fname, strlen(fname))) >= 0 && (pos = index_name_pos(istate, fname, strlen(fname))) >= 0 &&
!ce_stage(active_cache[pos]) && !ce_stage(istate->cache[pos]) &&
ce_uptodate(active_cache[pos]) && ce_uptodate(istate->cache[pos]) &&
!would_convert_to_git(fname)) !would_convert_to_git(fname))
hashcpy(sha1_stat->sha1, hashcpy(sha1_stat->sha1,
active_cache[pos]->oid.hash); istate->cache[pos]->oid.hash);
else else
hash_sha1_file(buf, size, "blob", sha1_stat->sha1); hash_sha1_file(buf, size, "blob", sha1_stat->sha1);
fill_stat_data(&sha1_stat->stat, &st); fill_stat_data(&sha1_stat->stat, &st);
@ -821,9 +828,9 @@ static int add_excludes(const char *fname, const char *base, int baselen,
int add_excludes_from_file_to_list(const char *fname, const char *base, int add_excludes_from_file_to_list(const char *fname, const char *base,
int baselen, struct exclude_list *el, int baselen, struct exclude_list *el,
int check_index) struct index_state *istate)
{ {
return add_excludes(fname, base, baselen, el, check_index, NULL); return add_excludes(fname, base, baselen, el, istate, NULL);
} }
struct exclude_list *add_exclude_list(struct dir_struct *dir, struct exclude_list *add_exclude_list(struct dir_struct *dir,
@ -855,7 +862,7 @@ static void add_excludes_from_file_1(struct dir_struct *dir, const char *fname,
if (!dir->untracked) if (!dir->untracked)
dir->unmanaged_exclude_files++; dir->unmanaged_exclude_files++;
el = add_exclude_list(dir, EXC_FILE, fname); el = add_exclude_list(dir, EXC_FILE, fname);
if (add_excludes(fname, "", 0, el, 0, sha1_stat) < 0) if (add_excludes(fname, "", 0, el, NULL, sha1_stat) < 0)
die("cannot use %s as an exclude file", fname); die("cannot use %s as an exclude file", fname);
} }
@ -958,7 +965,8 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
int pathlen, int pathlen,
const char *basename, const char *basename,
int *dtype, int *dtype,
struct exclude_list *el) struct exclude_list *el,
struct index_state *istate)
{ {
struct exclude *exc = NULL; /* undecided */ struct exclude *exc = NULL; /* undecided */
int i; int i;
@ -973,7 +981,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
if (x->flags & EXC_FLAG_MUSTBEDIR) { if (x->flags & EXC_FLAG_MUSTBEDIR) {
if (*dtype == DT_UNKNOWN) if (*dtype == DT_UNKNOWN)
*dtype = get_dtype(NULL, pathname, pathlen); *dtype = get_dtype(NULL, istate, pathname, pathlen);
if (*dtype != DT_DIR) if (*dtype != DT_DIR)
continue; continue;
} }
@ -1006,16 +1014,18 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
*/ */
int is_excluded_from_list(const char *pathname, int is_excluded_from_list(const char *pathname,
int pathlen, const char *basename, int *dtype, int pathlen, const char *basename, int *dtype,
struct exclude_list *el) struct exclude_list *el, struct index_state *istate)
{ {
struct exclude *exclude; struct exclude *exclude;
exclude = last_exclude_matching_from_list(pathname, pathlen, basename, dtype, el); exclude = last_exclude_matching_from_list(pathname, pathlen, basename,
dtype, el, istate);
if (exclude) if (exclude)
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1; return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
return -1; /* undecided */ return -1; /* undecided */
} }
static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir, static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir,
struct index_state *istate,
const char *pathname, int pathlen, const char *basename, const char *pathname, int pathlen, const char *basename,
int *dtype_p) int *dtype_p)
{ {
@ -1027,7 +1037,7 @@ static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir,
for (j = group->nr - 1; j >= 0; j--) { for (j = group->nr - 1; j >= 0; j--) {
exclude = last_exclude_matching_from_list( exclude = last_exclude_matching_from_list(
pathname, pathlen, basename, dtype_p, pathname, pathlen, basename, dtype_p,
&group->el[j]); &group->el[j], istate);
if (exclude) if (exclude)
return exclude; return exclude;
} }
@ -1039,7 +1049,9 @@ static struct exclude *last_exclude_matching_from_lists(struct dir_struct *dir,
* Loads the per-directory exclude list for the substring of base * Loads the per-directory exclude list for the substring of base
* which has a char length of baselen. * which has a char length of baselen.
*/ */
static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) static void prep_exclude(struct dir_struct *dir,
struct index_state *istate,
const char *base, int baselen)
{ {
struct exclude_list_group *group; struct exclude_list_group *group;
struct exclude_list *el; struct exclude_list *el;
@ -1118,6 +1130,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
int dt = DT_DIR; int dt = DT_DIR;
dir->basebuf.buf[stk->baselen - 1] = 0; dir->basebuf.buf[stk->baselen - 1] = 0;
dir->exclude = last_exclude_matching_from_lists(dir, dir->exclude = last_exclude_matching_from_lists(dir,
istate,
dir->basebuf.buf, stk->baselen - 1, dir->basebuf.buf, stk->baselen - 1,
dir->basebuf.buf + current, &dt); dir->basebuf.buf + current, &dt);
dir->basebuf.buf[stk->baselen - 1] = '/'; dir->basebuf.buf[stk->baselen - 1] = '/';
@ -1159,7 +1172,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
strbuf_addbuf(&sb, &dir->basebuf); strbuf_addbuf(&sb, &dir->basebuf);
strbuf_addstr(&sb, dir->exclude_per_dir); strbuf_addstr(&sb, dir->exclude_per_dir);
el->src = strbuf_detach(&sb, NULL); el->src = strbuf_detach(&sb, NULL);
add_excludes(el->src, el->src, stk->baselen, el, 1, add_excludes(el->src, el->src, stk->baselen, el, istate,
untracked ? &sha1_stat : NULL); untracked ? &sha1_stat : NULL);
} }
/* /*
@ -1194,19 +1207,20 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
* undecided. * undecided.
*/ */
struct exclude *last_exclude_matching(struct dir_struct *dir, struct exclude *last_exclude_matching(struct dir_struct *dir,
const char *pathname, struct index_state *istate,
int *dtype_p) const char *pathname,
int *dtype_p)
{ {
int pathlen = strlen(pathname); int pathlen = strlen(pathname);
const char *basename = strrchr(pathname, '/'); const char *basename = strrchr(pathname, '/');
basename = (basename) ? basename+1 : pathname; basename = (basename) ? basename+1 : pathname;
prep_exclude(dir, pathname, basename-pathname); prep_exclude(dir, istate, pathname, basename-pathname);
if (dir->exclude) if (dir->exclude)
return dir->exclude; return dir->exclude;
return last_exclude_matching_from_lists(dir, pathname, pathlen, return last_exclude_matching_from_lists(dir, istate, pathname, pathlen,
basename, dtype_p); basename, dtype_p);
} }
@ -1215,10 +1229,11 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,
* scans all exclude lists to determine whether pathname is excluded. * scans all exclude lists to determine whether pathname is excluded.
* Returns 1 if true, otherwise 0. * Returns 1 if true, otherwise 0.
*/ */
int is_excluded(struct dir_struct *dir, const char *pathname, int *dtype_p) int is_excluded(struct dir_struct *dir, struct index_state *istate,
const char *pathname, int *dtype_p)
{ {
struct exclude *exclude = struct exclude *exclude =
last_exclude_matching(dir, pathname, dtype_p); last_exclude_matching(dir, istate, pathname, dtype_p);
if (exclude) if (exclude)
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1; return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
return 0; return 0;
@ -1233,18 +1248,22 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
return ent; return ent;
} }
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len) static struct dir_entry *dir_add_name(struct dir_struct *dir,
struct index_state *istate,
const char *pathname, int len)
{ {
if (cache_file_exists(pathname, len, ignore_case)) if (index_file_exists(istate, pathname, len, ignore_case))
return NULL; return NULL;
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc); ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
return dir->entries[dir->nr++] = dir_entry_new(pathname, len); return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
} }
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) struct dir_entry *dir_add_ignored(struct dir_struct *dir,
struct index_state *istate,
const char *pathname, int len)
{ {
if (!cache_name_is_other(pathname, len)) if (!index_name_is_other(istate, pathname, len))
return NULL; return NULL;
ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc); ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
@ -1262,14 +1281,15 @@ enum exist_status {
* the directory name; instead, use the case insensitive * the directory name; instead, use the case insensitive
* directory hash. * directory hash.
*/ */
static enum exist_status directory_exists_in_index_icase(const char *dirname, int len) static enum exist_status directory_exists_in_index_icase(struct index_state *istate,
const char *dirname, int len)
{ {
struct cache_entry *ce; struct cache_entry *ce;
if (cache_dir_exists(dirname, len)) if (index_dir_exists(istate, dirname, len))
return index_directory; return index_directory;
ce = cache_file_exists(dirname, len, ignore_case); ce = index_file_exists(istate, dirname, len, ignore_case);
if (ce && S_ISGITLINK(ce->ce_mode)) if (ce && S_ISGITLINK(ce->ce_mode))
return index_gitdir; return index_gitdir;
@ -1283,18 +1303,19 @@ static enum exist_status directory_exists_in_index_icase(const char *dirname, in
* the files it contains) will sort with the '/' at the * the files it contains) will sort with the '/' at the
* end. * end.
*/ */
static enum exist_status directory_exists_in_index(const char *dirname, int len) static enum exist_status directory_exists_in_index(struct index_state *istate,
const char *dirname, int len)
{ {
int pos; int pos;
if (ignore_case) if (ignore_case)
return directory_exists_in_index_icase(dirname, len); return directory_exists_in_index_icase(istate, dirname, len);
pos = cache_name_pos(dirname, len); pos = index_name_pos(istate, dirname, len);
if (pos < 0) if (pos < 0)
pos = -pos-1; pos = -pos-1;
while (pos < active_nr) { while (pos < istate->cache_nr) {
const struct cache_entry *ce = active_cache[pos++]; const struct cache_entry *ce = istate->cache[pos++];
unsigned char endchar; unsigned char endchar;
if (strncmp(ce->name, dirname, len)) if (strncmp(ce->name, dirname, len))
@ -1344,12 +1365,13 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
* (c) otherwise, we recurse into it. * (c) otherwise, we recurse into it.
*/ */
static enum path_treatment treat_directory(struct dir_struct *dir, static enum path_treatment treat_directory(struct dir_struct *dir,
struct index_state *istate,
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 pathspec *pathspec) 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(istate, dirname, len-1)) {
case index_directory: case index_directory:
return path_recurse; return path_recurse;
@ -1374,7 +1396,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, istate, dirname, len,
untracked, 1, pathspec); untracked, 1, pathspec);
} }
@ -1455,12 +1477,13 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
return 0; return 0;
} }
static int get_index_dtype(const char *path, int len) static int get_index_dtype(struct index_state *istate,
const char *path, int len)
{ {
int pos; int pos;
const struct cache_entry *ce; const struct cache_entry *ce;
ce = cache_file_exists(path, len, 0); ce = index_file_exists(istate, path, len, 0);
if (ce) { if (ce) {
if (!ce_uptodate(ce)) if (!ce_uptodate(ce))
return DT_UNKNOWN; return DT_UNKNOWN;
@ -1474,12 +1497,12 @@ static int get_index_dtype(const char *path, int len)
} }
/* Try to look it up as a directory */ /* Try to look it up as a directory */
pos = cache_name_pos(path, len); pos = index_name_pos(istate, path, len);
if (pos >= 0) if (pos >= 0)
return DT_UNKNOWN; return DT_UNKNOWN;
pos = -pos-1; pos = -pos-1;
while (pos < active_nr) { while (pos < istate->cache_nr) {
ce = active_cache[pos++]; ce = istate->cache[pos++];
if (strncmp(ce->name, path, len)) if (strncmp(ce->name, path, len))
break; break;
if (ce->name[len] > '/') if (ce->name[len] > '/')
@ -1493,14 +1516,15 @@ static int get_index_dtype(const char *path, int len)
return DT_UNKNOWN; return DT_UNKNOWN;
} }
static int get_dtype(struct dirent *de, const char *path, int len) static int get_dtype(struct dirent *de, struct index_state *istate,
const char *path, int len)
{ {
int dtype = de ? DTYPE(de) : DT_UNKNOWN; int dtype = de ? DTYPE(de) : DT_UNKNOWN;
struct stat st; struct stat st;
if (dtype != DT_UNKNOWN) if (dtype != DT_UNKNOWN)
return dtype; return dtype;
dtype = get_index_dtype(path, len); dtype = get_index_dtype(istate, path, len);
if (dtype != DT_UNKNOWN) if (dtype != DT_UNKNOWN)
return dtype; return dtype;
if (lstat(path, &st)) if (lstat(path, &st))
@ -1516,16 +1540,17 @@ static int get_dtype(struct dirent *de, const char *path, int len)
static enum path_treatment treat_one_path(struct dir_struct *dir, static enum path_treatment treat_one_path(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct index_state *istate,
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, struct dirent *de)
{ {
int exclude; int exclude;
int has_path_in_index = !!cache_file_exists(path->buf, path->len, ignore_case); int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
if (dtype == DT_UNKNOWN) if (dtype == DT_UNKNOWN)
dtype = get_dtype(de, 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)
@ -1552,10 +1577,10 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
if ((dir->flags & DIR_COLLECT_KILLED_ONLY) && if ((dir->flags & DIR_COLLECT_KILLED_ONLY) &&
(dtype == DT_DIR) && (dtype == DT_DIR) &&
!has_path_in_index && !has_path_in_index &&
(directory_exists_in_index(path->buf, path->len) == index_nonexistent)) (directory_exists_in_index(istate, path->buf, path->len) == index_nonexistent))
return path_none; return path_none;
exclude = is_excluded(dir, path->buf, &dtype); exclude = is_excluded(dir, istate, path->buf, &dtype);
/* /*
* Excluded? If we don't explicitly want to show * Excluded? If we don't explicitly want to show
@ -1569,7 +1594,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
return path_none; return path_none;
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, istate, untracked, path->buf, path->len,
baselen, exclude, pathspec); baselen, exclude, pathspec);
case DT_REG: case DT_REG:
case DT_LNK: case DT_LNK:
@ -1580,6 +1605,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
static enum path_treatment treat_path_fast(struct dir_struct *dir, static enum path_treatment treat_path_fast(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct cached_dir *cdir, struct cached_dir *cdir,
struct index_state *istate,
struct strbuf *path, struct strbuf *path,
int baselen, int baselen,
const struct pathspec *pathspec) const struct pathspec *pathspec)
@ -1598,7 +1624,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
* to its bottom. Verify again the same set of directories * to its bottom. Verify again the same set of directories
* with check_only set. * with check_only set.
*/ */
return read_directory_recursive(dir, path->buf, path->len, return read_directory_recursive(dir, istate, path->buf, path->len,
cdir->ucd, 1, pathspec); cdir->ucd, 1, pathspec);
/* /*
* We get path_recurse in the first run when * We get path_recurse in the first run when
@ -1612,6 +1638,7 @@ static enum path_treatment treat_path_fast(struct dir_struct *dir,
static enum path_treatment treat_path(struct dir_struct *dir, static enum path_treatment treat_path(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct cached_dir *cdir, struct cached_dir *cdir,
struct index_state *istate,
struct strbuf *path, struct strbuf *path,
int baselen, int baselen,
const struct pathspec *pathspec) const struct pathspec *pathspec)
@ -1620,7 +1647,7 @@ static enum path_treatment treat_path(struct dir_struct *dir,
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, istate, path,
baselen, pathspec); 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;
@ -1630,7 +1657,7 @@ static enum path_treatment treat_path(struct dir_struct *dir,
return path_none; return path_none;
dtype = DTYPE(de); dtype = DTYPE(de);
return treat_one_path(dir, untracked, path, baselen, pathspec, dtype, de); return treat_one_path(dir, untracked, istate, 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)
@ -1644,6 +1671,7 @@ static void add_untracked(struct untracked_cache_dir *dir, const char *name)
static int valid_cached_dir(struct dir_struct *dir, static int valid_cached_dir(struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct index_state *istate,
struct strbuf *path, struct strbuf *path,
int check_only) int check_only)
{ {
@ -1658,7 +1686,7 @@ static int valid_cached_dir(struct dir_struct *dir,
return 0; return 0;
} }
if (!untracked->valid || if (!untracked->valid ||
match_stat_data_racy(&the_index, &untracked->stat_data, &st)) { match_stat_data_racy(istate, &untracked->stat_data, &st)) {
if (untracked->valid) if (untracked->valid)
invalidate_directory(dir->untracked, untracked); invalidate_directory(dir->untracked, untracked);
fill_stat_data(&untracked->stat_data, &st); fill_stat_data(&untracked->stat_data, &st);
@ -1679,10 +1707,10 @@ static int valid_cached_dir(struct dir_struct *dir,
*/ */
if (path->len && path->buf[path->len - 1] != '/') { if (path->len && path->buf[path->len - 1] != '/') {
strbuf_addch(path, '/'); strbuf_addch(path, '/');
prep_exclude(dir, path->buf, path->len); prep_exclude(dir, istate, path->buf, path->len);
strbuf_setlen(path, path->len - 1); strbuf_setlen(path, path->len - 1);
} else } else
prep_exclude(dir, path->buf, path->len); prep_exclude(dir, istate, path->buf, path->len);
/* hopefully prep_exclude() haven't invalidated this entry... */ /* hopefully prep_exclude() haven't invalidated this entry... */
return untracked->valid; return untracked->valid;
@ -1691,12 +1719,13 @@ static int valid_cached_dir(struct dir_struct *dir,
static int open_cached_dir(struct cached_dir *cdir, static int open_cached_dir(struct cached_dir *cdir,
struct dir_struct *dir, struct dir_struct *dir,
struct untracked_cache_dir *untracked, struct untracked_cache_dir *untracked,
struct index_state *istate,
struct strbuf *path, struct strbuf *path,
int check_only) int check_only)
{ {
memset(cdir, 0, sizeof(*cdir)); memset(cdir, 0, sizeof(*cdir));
cdir->untracked = untracked; cdir->untracked = untracked;
if (valid_cached_dir(dir, untracked, path, check_only)) if (valid_cached_dir(dir, untracked, istate, path, check_only))
return 0; return 0;
cdir->fdir = opendir(path->len ? path->buf : "."); cdir->fdir = opendir(path->len ? path->buf : ".");
if (dir->untracked) if (dir->untracked)
@ -1759,9 +1788,9 @@ static void close_cached_dir(struct cached_dir *cdir)
* Returns the most significant path_treatment value encountered in the scan. * Returns the most significant path_treatment value encountered in the scan.
*/ */
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, struct index_state *istate, const char *base, int baselen,
struct untracked_cache_dir *untracked, int check_only, struct untracked_cache_dir *untracked, int check_only,
const struct pathspec *pathspec) 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;
@ -1769,7 +1798,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
strbuf_add(&path, base, baselen); strbuf_add(&path, base, baselen);
if (open_cached_dir(&cdir, dir, untracked, &path, check_only)) if (open_cached_dir(&cdir, dir, untracked, istate, &path, check_only))
goto out; goto out;
if (untracked) if (untracked)
@ -1777,7 +1806,7 @@ 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, state = treat_path(dir, untracked, &cdir, istate, &path,
baselen, pathspec); baselen, pathspec);
if (state > dir_state) if (state > dir_state)
@ -1790,7 +1819,7 @@ 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, read_directory_recursive(dir, istate, path.buf,
path.len, ud, path.len, ud,
check_only, pathspec); check_only, pathspec);
if (subdir_state > dir_state) if (subdir_state > dir_state)
@ -1812,18 +1841,18 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
switch (state) { switch (state) {
case path_excluded: case path_excluded:
if (dir->flags & DIR_SHOW_IGNORED) if (dir->flags & DIR_SHOW_IGNORED)
dir_add_name(dir, path.buf, path.len); dir_add_name(dir, istate, path.buf, path.len);
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,
pathspec))) pathspec)))
dir_add_ignored(dir, path.buf, path.len); dir_add_ignored(dir, istate, path.buf, path.len);
break; break;
case path_untracked: case path_untracked:
if (dir->flags & DIR_SHOW_IGNORED) if (dir->flags & DIR_SHOW_IGNORED)
break; break;
dir_add_name(dir, path.buf, path.len); dir_add_name(dir, istate, path.buf, path.len);
if (cdir.fdir) if (cdir.fdir)
add_untracked(untracked, path.buf + baselen); add_untracked(untracked, path.buf + baselen);
break; break;
@ -1848,6 +1877,7 @@ static int cmp_name(const void *p1, const void *p2)
} }
static int treat_leading_path(struct dir_struct *dir, static int treat_leading_path(struct dir_struct *dir,
struct index_state *istate,
const char *path, int len, const char *path, int len,
const struct pathspec *pathspec) const struct pathspec *pathspec)
{ {
@ -1875,7 +1905,7 @@ static int treat_leading_path(struct dir_struct *dir,
break; break;
if (simplify_away(sb.buf, sb.len, pathspec)) if (simplify_away(sb.buf, sb.len, pathspec))
break; break;
if (treat_one_path(dir, NULL, &sb, baselen, pathspec, if (treat_one_path(dir, NULL, istate, &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) {
@ -2043,8 +2073,8 @@ 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 read_directory(struct dir_struct *dir, struct index_state *istate,
int len, const struct pathspec *pathspec) const char *path, int len, const struct pathspec *pathspec)
{ {
struct untracked_cache_dir *untracked; struct untracked_cache_dir *untracked;
@ -2058,8 +2088,8 @@ int read_directory(struct dir_struct *dir, const char *path,
* e.g. prep_exclude() * e.g. prep_exclude()
*/ */
dir->untracked = NULL; dir->untracked = NULL;
if (!len || treat_leading_path(dir, path, len, pathspec)) if (!len || treat_leading_path(dir, istate, path, len, pathspec))
read_directory_recursive(dir, path, len, untracked, 0, pathspec); read_directory_recursive(dir, istate, path, len, untracked, 0, pathspec);
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) {
@ -2073,12 +2103,12 @@ int read_directory(struct dir_struct *dir, const char *path,
dir->untracked->gitignore_invalidated, dir->untracked->gitignore_invalidated,
dir->untracked->dir_invalidated, dir->untracked->dir_invalidated,
dir->untracked->dir_opened); dir->untracked->dir_opened);
if (dir->untracked == the_index.untracked && if (dir->untracked == istate->untracked &&
(dir->untracked->dir_opened || (dir->untracked->dir_opened ||
dir->untracked->gitignore_invalidated || dir->untracked->gitignore_invalidated ||
dir->untracked->dir_invalidated)) dir->untracked->dir_invalidated))
the_index.cache_changed |= UNTRACKED_CHANGED; istate->cache_changed |= UNTRACKED_CHANGED;
if (dir->untracked != the_index.untracked) { if (dir->untracked != istate->untracked) {
free(dir->untracked); free(dir->untracked);
dir->untracked = NULL; dir->untracked = NULL;
} }

25
dir.h
View File

@ -214,12 +214,20 @@ extern int match_pathspec(const struct pathspec *pathspec,
extern int report_path_error(const char *ps_matched, const struct pathspec *pathspec, const char *prefix); extern int report_path_error(const char *ps_matched, const struct pathspec *pathspec, const char *prefix);
extern int within_depth(const char *name, int namelen, int depth, int max_depth); extern int within_depth(const char *name, int namelen, int depth, int max_depth);
extern int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec); extern int fill_directory(struct dir_struct *dir,
extern int read_directory(struct dir_struct *, const char *path, int len, const struct pathspec *pathspec); struct index_state *istate,
const struct pathspec *pathspec);
extern int read_directory(struct dir_struct *, struct index_state *istate,
const char *path, int len,
const struct pathspec *pathspec);
extern int is_excluded_from_list(const char *pathname, int pathlen, const char *basename, extern int is_excluded_from_list(const char *pathname, int pathlen,
int *dtype, struct exclude_list *el); const char *basename, int *dtype,
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len); struct exclude_list *el,
struct index_state *istate);
struct dir_entry *dir_add_ignored(struct dir_struct *dir,
struct index_state *istate,
const char *pathname, int len);
/* /*
* these implement the matching logic for dir.c:excluded_from_list and * these implement the matching logic for dir.c:excluded_from_list and
@ -232,14 +240,17 @@ extern int match_pathname(const char *, int,
const char *, int, int, unsigned); const char *, int, int, unsigned);
extern struct exclude *last_exclude_matching(struct dir_struct *dir, extern struct exclude *last_exclude_matching(struct dir_struct *dir,
struct index_state *istate,
const char *name, int *dtype); const char *name, int *dtype);
extern int is_excluded(struct dir_struct *dir, const char *name, int *dtype); extern int is_excluded(struct dir_struct *dir,
struct index_state *istate,
const char *name, int *dtype);
extern struct exclude_list *add_exclude_list(struct dir_struct *dir, extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
int group_type, const char *src); int group_type, const char *src);
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen, extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
struct exclude_list *el, int check_index); struct exclude_list *el, struct index_state *istate);
extern void add_excludes_from_file(struct dir_struct *, const char *fname); extern void add_excludes_from_file(struct dir_struct *, const char *fname);
extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen); extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
extern void add_exclude(const char *string, const char *base, extern void add_exclude(const char *string, const char *base,

View File

@ -1073,7 +1073,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
struct cache_entry **cache_end; struct cache_entry **cache_end;
int dtype = DT_DIR; int dtype = DT_DIR;
int ret = is_excluded_from_list(prefix->buf, prefix->len, int ret = is_excluded_from_list(prefix->buf, prefix->len,
basename, &dtype, el); basename, &dtype, el, &the_index);
int rc; int rc;
strbuf_addch(prefix, '/'); strbuf_addch(prefix, '/');
@ -1176,7 +1176,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
/* Non-directory */ /* Non-directory */
dtype = ce_to_dtype(ce); dtype = ce_to_dtype(ce);
ret = is_excluded_from_list(ce->name, ce_namelen(ce), ret = is_excluded_from_list(ce->name, ce_namelen(ce),
name, &dtype, el); name, &dtype, el, &the_index);
if (ret < 0) if (ret < 0)
ret = defval; ret = defval;
if (ret > 0) if (ret > 0)
@ -1256,7 +1256,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
o->skip_sparse_checkout = 1; o->skip_sparse_checkout = 1;
if (!o->skip_sparse_checkout) { if (!o->skip_sparse_checkout) {
char *sparse = git_pathdup("info/sparse-checkout"); char *sparse = git_pathdup("info/sparse-checkout");
if (add_excludes_from_file_to_list(sparse, "", 0, &el, 0) < 0) if (add_excludes_from_file_to_list(sparse, "", 0, &el, NULL) < 0)
o->skip_sparse_checkout = 1; o->skip_sparse_checkout = 1;
else else
o->el = &el; o->el = &el;
@ -1597,7 +1597,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
memset(&d, 0, sizeof(d)); memset(&d, 0, sizeof(d));
if (o->dir) if (o->dir)
d.exclude_per_dir = o->dir->exclude_per_dir; d.exclude_per_dir = o->dir->exclude_per_dir;
i = read_directory(&d, pathbuf, namelen+1, NULL); i = read_directory(&d, &the_index, pathbuf, namelen+1, NULL);
if (i) if (i)
return o->gently ? -1 : return o->gently ? -1 :
add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name); add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
@ -1639,7 +1639,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
return 0; return 0;
if (o->dir && if (o->dir &&
is_excluded(o->dir, name, &dtype)) is_excluded(o->dir, &the_index, name, &dtype))
/* /*
* ce->name is explicitly excluded, so it is Ok to * ce->name is explicitly excluded, so it is Ok to
* overwrite it. * overwrite it.

View File

@ -665,7 +665,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
dir.untracked = the_index.untracked; dir.untracked = the_index.untracked;
setup_standard_excludes(&dir); setup_standard_excludes(&dir);
fill_directory(&dir, &s->pathspec); fill_directory(&dir, &the_index, &s->pathspec);
for (i = 0; i < dir.nr; i++) { for (i = 0; i < dir.nr; i++) {
struct dir_entry *ent = dir.entries[i]; struct dir_entry *ent = dir.entries[i];