mirror of
https://github.com/git/git.git
synced 2026-02-19 06:12:03 +00:00
Merge branch 'jc/ls-files-i-dir' into next
"git ls-files --exclude=t -i" did not consider anything under t/ as excluded, as it did not pay attention to exclusion of leading paths while walking the index. * jc/ls-files-i-dir: ls-files -i: micro-optimize path_excluded() ls-files -i: pay attention to exclusion of leading paths
This commit is contained in:
@@ -203,6 +203,10 @@ static void show_ru_info(void)
|
||||
static void show_files(struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
struct path_exclude_check check;
|
||||
|
||||
if ((dir->flags & DIR_SHOW_IGNORED))
|
||||
path_exclude_check_init(&check, dir);
|
||||
|
||||
/* For cached/deleted files we don't need to even do the readdir */
|
||||
if (show_others || show_killed) {
|
||||
@@ -215,9 +219,8 @@ static void show_files(struct dir_struct *dir)
|
||||
if (show_cached | show_stage) {
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
int dtype = ce_to_dtype(ce);
|
||||
if (dir->flags & DIR_SHOW_IGNORED &&
|
||||
!excluded(dir, ce->name, &dtype))
|
||||
if ((dir->flags & DIR_SHOW_IGNORED) &&
|
||||
!path_excluded(&check, ce))
|
||||
continue;
|
||||
if (show_unmerged && !ce_stage(ce))
|
||||
continue;
|
||||
@@ -232,9 +235,8 @@ static void show_files(struct dir_struct *dir)
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
struct stat st;
|
||||
int err;
|
||||
int dtype = ce_to_dtype(ce);
|
||||
if (dir->flags & DIR_SHOW_IGNORED &&
|
||||
!excluded(dir, ce->name, &dtype))
|
||||
if ((dir->flags & DIR_SHOW_IGNORED) &&
|
||||
!path_excluded(&check, ce))
|
||||
continue;
|
||||
if (ce->ce_flags & CE_UPDATE)
|
||||
continue;
|
||||
@@ -247,6 +249,9 @@ static void show_files(struct dir_struct *dir)
|
||||
show_ce_entry(tag_modified, ce);
|
||||
}
|
||||
}
|
||||
|
||||
if ((dir->flags & DIR_SHOW_IGNORED))
|
||||
path_exclude_check_clear(&check);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
50
dir.c
50
dir.c
@@ -573,6 +573,56 @@ int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void path_exclude_check_init(struct path_exclude_check *check,
|
||||
struct dir_struct *dir)
|
||||
{
|
||||
check->dir = dir;
|
||||
strbuf_init(&check->path, 256);
|
||||
}
|
||||
|
||||
void path_exclude_check_clear(struct path_exclude_check *check)
|
||||
{
|
||||
strbuf_release(&check->path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the ce->name excluded? This is for a caller like show_files() that
|
||||
* do not honor directory hierarchy and iterate through paths that are
|
||||
* possibly in an ignored directory.
|
||||
*
|
||||
* A path to a directory known to be excluded is left in check->path to
|
||||
* optimize for repeated checks for files in the same excluded directory.
|
||||
*/
|
||||
int path_excluded(struct path_exclude_check *check, struct cache_entry *ce)
|
||||
{
|
||||
int i, dtype;
|
||||
struct strbuf *path = &check->path;
|
||||
|
||||
if (path->len &&
|
||||
path->len <= ce_namelen(ce) &&
|
||||
!memcmp(ce->name, path->buf, path->len) &&
|
||||
(!ce->name[path->len] || ce->name[path->len] == '/'))
|
||||
return 1;
|
||||
|
||||
strbuf_setlen(path, 0);
|
||||
for (i = 0; ce->name[i]; i++) {
|
||||
int ch = ce->name[i];
|
||||
|
||||
if (ch == '/') {
|
||||
dtype = DT_DIR;
|
||||
if (excluded(check->dir, path->buf, &dtype))
|
||||
return 1;
|
||||
}
|
||||
strbuf_addch(path, ch);
|
||||
}
|
||||
|
||||
/* An entry in the index; cannot be a directory with subentries */
|
||||
strbuf_setlen(path, 0);
|
||||
|
||||
dtype = ce_to_dtype(ce);
|
||||
return excluded(check->dir, ce->name, &dtype);
|
||||
}
|
||||
|
||||
static struct dir_entry *dir_entry_new(const char *pathname, int len)
|
||||
{
|
||||
struct dir_entry *ent;
|
||||
|
||||
16
dir.h
16
dir.h
@@ -1,6 +1,8 @@
|
||||
#ifndef DIR_H
|
||||
#define DIR_H
|
||||
|
||||
#include "strbuf.h"
|
||||
|
||||
struct dir_entry {
|
||||
unsigned int len;
|
||||
char name[FLEX_ARRAY]; /* more */
|
||||
@@ -78,6 +80,20 @@ extern int excluded_from_list(const char *pathname, int pathlen, const char *bas
|
||||
int *dtype, struct exclude_list *el);
|
||||
extern int excluded(struct dir_struct *, const char *, int *);
|
||||
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
|
||||
|
||||
/*
|
||||
* The excluded() API is meant for callers that check each level of leading
|
||||
* directory hierarchies with excluded() to avoid recursing into excluded
|
||||
* directories. Callers that do not do so should use this API instead.
|
||||
*/
|
||||
struct path_exclude_check {
|
||||
struct dir_struct *dir;
|
||||
struct strbuf path;
|
||||
};
|
||||
extern void path_exclude_check_init(struct path_exclude_check *, struct dir_struct *);
|
||||
extern void path_exclude_check_clear(struct path_exclude_check *);
|
||||
extern int path_excluded(struct path_exclude_check *, struct cache_entry *);
|
||||
|
||||
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
|
||||
char **buf_p, struct exclude_list *which, int check_index);
|
||||
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
|
||||
|
||||
Reference in New Issue
Block a user