if (!ignored)
setup_standard_excludes(&dir);
- add_exclude_list(&dir, EXC_CMDL);
+ add_exclude_list(&dir, EXC_CMDL, "--exclude option");
for (i = 0; i < exclude_list.nr; i++)
add_exclude(exclude_list.items[i].string, "", 0,
- &dir.exclude_list_group[EXC_CMDL].el[0]);
+ &dir.exclude_list_group[EXC_CMDL].el[0], -(i+1));
pathspec = get_pathspec(prefix, argv);
static char *ps_matched;
static const char *with_tree;
static int exc_given;
+static int exclude_args;
static const char *tag_cached = "";
static const char *tag_unmerged = "";
struct exclude_list_group *group = opt->value;
exc_given = 1;
- add_exclude(arg, "", 0, &group->el[0]);
+ add_exclude(arg, "", 0, &group->el[0], --exclude_args);
return 0;
}
if (read_cache() < 0)
die("index file corrupt");
- add_exclude_list(&dir, EXC_CMDL);
+ add_exclude_list(&dir, EXC_CMDL, "--exclude option");
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
}
void add_exclude(const char *string, const char *base,
- int baselen, struct exclude_list *el)
+ int baselen, struct exclude_list *el, int srcpos)
{
struct exclude *x;
int patternlen;
x->base = base;
x->baselen = baselen;
x->flags = flags;
+ x->srcpos = srcpos;
ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
el->excludes[el->nr++] = x;
+ x->el = el;
}
static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
int check_index)
{
struct stat st;
- int fd, i;
+ int fd, i, lineno = 1;
size_t size = 0;
char *buf, *entry;
if (buf[i] == '\n') {
if (entry != buf + i && entry[0] != '#') {
buf[i - (i && buf[i-1] == '\r')] = 0;
- add_exclude(entry, base, baselen, el);
+ add_exclude(entry, base, baselen, el, lineno);
}
+ lineno++;
entry = buf + i + 1;
}
}
return 0;
}
-struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type)
+struct exclude_list *add_exclude_list(struct dir_struct *dir,
+ int group_type, const char *src)
{
struct exclude_list *el;
struct exclude_list_group *group;
ALLOC_GROW(group->el, group->nr + 1, group->alloc);
el = &group->el[group->nr++];
memset(el, 0, sizeof(*el));
+ el->src = src;
return el;
}
void add_excludes_from_file(struct dir_struct *dir, const char *fname)
{
struct exclude_list *el;
- el = add_exclude_list(dir, EXC_FILE);
+ el = add_exclude_list(dir, EXC_FILE, fname);
if (add_excludes_from_file_to_list(fname, "", 0, el, 0) < 0)
die("cannot use %s as an exclude file", fname);
}
break;
el = &group->el[dir->exclude_stack->exclude_ix];
dir->exclude_stack = stk->prev;
+ free((char *)el->src); /* see strdup() below */
clear_exclude_list(el);
free(stk);
group->nr--;
memcpy(dir->basebuf + current, base + current,
stk->baselen - current);
strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
- el = add_exclude_list(dir, EXC_DIRS);
+ /*
+ * dir->basebuf gets reused by the traversal, but we
+ * need fname to remain unchanged to ensure the src
+ * member of each struct exclude correctly
+ * back-references its source file. Other invocations
+ * of add_exclude_list provide stable strings, so we
+ * strdup() and free() here in the caller.
+ */
+ el = add_exclude_list(dir, EXC_DIRS, strdup(dir->basebuf));
stk->exclude_ix = group->nr - 1;
add_excludes_from_file_to_list(dir->basebuf,
dir->basebuf, stk->baselen,
struct exclude_list {
int nr;
int alloc;
+
/* remember pointer to exclude file contents so we can free() */
char *filebuf;
+ /* origin of list, e.g. path to filename, or descriptive string */
+ const char *src;
+
struct exclude {
+ /*
+ * This allows callers of last_exclude_matching() etc.
+ * to determine the origin of the matching pattern.
+ */
+ struct exclude_list *el;
+
const char *pattern;
int patternlen;
int nowildcardlen;
const char *base;
int baselen;
int flags;
+
+ /*
+ * Counting starts from 1 for line numbers in ignore files,
+ * and from -1 decrementing for patterns from CLI args.
+ */
+ int srcpos;
} **excludes;
};
extern int is_path_excluded(struct path_exclude_check *, const char *, int namelen, int *dtype);
-extern struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type);
+extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
+ int group_type, const char *src);
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
struct exclude_list *el, int check_index);
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen);
extern void add_exclude(const char *string, const char *base,
- int baselen, struct exclude_list *el);
+ int baselen, struct exclude_list *el, int srcpos);
extern void clear_exclude_list(struct exclude_list *el);
extern int file_exists(const char *);