Skip to content

Commit

Permalink
dir.c: refactor is_path_excluded()
Browse files Browse the repository at this point in the history
In a similar way to the previous commit, this extracts a new helper
function last_exclude_matching_path() which return the last
exclude_list element which matched, or NULL if no match was found.
is_path_excluded() becomes a wrapper around this, and just returns 0
or 1 depending on whether any matching exclude_list element was found.

This allows callers to find out _why_ a given path was excluded,
rather than just whether it was or not, paving the way for a new git
sub-command which allows users to test their exclude lists from the
command line.

Signed-off-by: Adam Spiers <[email protected]>
Signed-off-by: Junio C Hamano <[email protected]>
  • Loading branch information
aspiers authored and gitster committed Dec 28, 2012
1 parent f4cd69a commit a35341a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
47 changes: 38 additions & 9 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ void path_exclude_check_init(struct path_exclude_check *check,
struct dir_struct *dir)
{
check->dir = dir;
check->exclude = NULL;
strbuf_init(&check->path, 256);
}

Expand All @@ -718,18 +719,21 @@ void path_exclude_check_clear(struct path_exclude_check *check)
}

/*
* Is this 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.
* For each subdirectory in name, starting with the top-most, checks
* to see if that subdirectory is excluded, and if so, returns the
* corresponding exclude structure. Otherwise, checks whether name
* itself (which is presumably a file) is excluded.
*
* 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 is_path_excluded(struct path_exclude_check *check,
const char *name, int namelen, int *dtype)
struct exclude *last_exclude_matching_path(struct path_exclude_check *check,
const char *name, int namelen,
int *dtype)
{
int i;
struct strbuf *path = &check->path;
struct exclude *exclude;

/*
* we allow the caller to pass namelen as an optimization; it
Expand All @@ -739,28 +743,53 @@ int is_path_excluded(struct path_exclude_check *check,
if (namelen < 0)
namelen = strlen(name);

/*
* If path is non-empty, and name is equal to path or a
* subdirectory of path, name should be excluded, because
* it's inside a directory which is already known to be
* excluded and was previously left in check->path.
*/
if (path->len &&
path->len <= namelen &&
!memcmp(name, path->buf, path->len) &&
(!name[path->len] || name[path->len] == '/'))
return 1;
return check->exclude;

strbuf_setlen(path, 0);
for (i = 0; name[i]; i++) {
int ch = name[i];

if (ch == '/') {
int dt = DT_DIR;
if (is_excluded(check->dir, path->buf, &dt))
return 1;
exclude = last_exclude_matching(check->dir,
path->buf, &dt);
if (exclude) {
check->exclude = exclude;
return exclude;
}
}
strbuf_addch(path, ch);
}

/* An entry in the index; cannot be a directory with subentries */
strbuf_setlen(path, 0);

return is_excluded(check->dir, name, dtype);
return last_exclude_matching(check->dir, name, dtype);
}

/*
* Is this 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.
*/
int is_path_excluded(struct path_exclude_check *check,
const char *name, int namelen, int *dtype)
{
struct exclude *exclude =
last_exclude_matching_path(check, name, namelen, dtype);
if (exclude)
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
return 0;
}

static struct dir_entry *dir_entry_new(const char *pathname, int len)
Expand Down
3 changes: 3 additions & 0 deletions dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,13 @@ extern int match_pathname(const char *, int,
*/
struct path_exclude_check {
struct dir_struct *dir;
struct exclude *exclude;
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 struct exclude *last_exclude_matching_path(struct path_exclude_check *, const char *,
int namelen, int *dtype);
extern int is_path_excluded(struct path_exclude_check *, const char *, int namelen, int *dtype);


Expand Down

0 comments on commit a35341a

Please sign in to comment.