dir.c: keep track of where patterns came from
For exclude patterns read in from files, the filename is stored in the exclude list, and the originating line number is stored in the individual exclude (counting starting at 1). For exclude patterns provided on the command line, a string describing the source of the patterns is stored in the exclude list, and the sequence number assigned to each exclude pattern is negative, with counting starting at -1. So for example the 2nd pattern provided via --exclude would be numbered -2. This allows any future consumers of that data to easily distinguish between exclude patterns from files vs. from the CLI. Signed-off-by: Adam Spiers <git@adamspiers.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Adam Spiers committed
Jan 6, 2013 at 16:58 UTC
c04318e46aae79b8b8df059e2118519d83dfee12
4 files changed
+44
-12
builtin/clean.c
+2
-2
@@ -97,10 +97,10 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
97
if (!ignored)
98
setup_standard_excludes(&dir);
99
100
- add_exclude_list(&dir, EXC_CMDL);
100
+ add_exclude_list(&dir, EXC_CMDL, "--exclude option");
101
for (i = 0; i < exclude_list.nr; i++)
102
add_exclude(exclude_list.items[i].string, "", 0,
103
- &dir.exclude_list_group[EXC_CMDL].el[0]);
103
+ &dir.exclude_list_group[EXC_CMDL].el[0], -(i+1));
104
105
pathspec = get_pathspec(prefix, argv);
106
builtin/ls-files.c
+3
-2
@@ -35,6 +35,7 @@ static int error_unmatch;
35
static char *ps_matched;
36
static const char *with_tree;
37
static int exc_given;
38
+static int exclude_args;
39
40
static const char *tag_cached = "";
41
static const char *tag_unmerged = "";
@@ -423,7 +424,7 @@ static int option_parse_exclude(const struct option *opt,
424
struct exclude_list_group *group = opt->value;
425
426
exc_given = 1;
426
- add_exclude(arg, "", 0, &group->el[0]);
427
+ add_exclude(arg, "", 0, &group->el[0], --exclude_args);
428
429
return 0;
430
}
@@ -524,7 +525,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
525
if (read_cache() < 0)
526
die("index file corrupt");
527
527
- add_exclude_list(&dir, EXC_CMDL);
528
+ add_exclude_list(&dir, EXC_CMDL, "--exclude option");
529
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
530
ls_files_usage, 0);
531
if (show_tag || show_valid_bit) {
dir.c
+20
-6
@@ -349,7 +349,7 @@ void parse_exclude_pattern(const char **pattern,
349
}
350
351
void add_exclude(const char *string, const char *base,
352
- int baselen, struct exclude_list *el)
352
+ int baselen, struct exclude_list *el, int srcpos)
353
{
354
struct exclude *x;
355
int patternlen;
@@ -373,8 +373,10 @@ void add_exclude(const char *string, const char *base,
373
x->base = base;
374
x->baselen = baselen;
375
x->flags = flags;
376
+ x->srcpos = srcpos;
377
ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
378
el->excludes[el->nr++] = x;
379
+ x->el = el;
380
}
381
382
static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
@@ -425,7 +427,7 @@ int add_excludes_from_file_to_list(const char *fname,
427
int check_index)
428
{
429
struct stat st;
428
- int fd, i;
430
+ int fd, i, lineno = 1;
431
size_t size = 0;
432
char *buf, *entry;
433
@@ -467,15 +469,17 @@ int add_excludes_from_file_to_list(const char *fname,
469
if (buf[i] == '\n') {
470
if (entry != buf + i && entry[0] != '#') {
471
buf[i - (i && buf[i-1] == '\r')] = 0;
470
- add_exclude(entry, base, baselen, el);
472
+ add_exclude(entry, base, baselen, el, lineno);
473
}
474
+ lineno++;
475
entry = buf + i + 1;
476
}
477
}
478
return 0;
479
}
480
478
-struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type)
481
+struct exclude_list *add_exclude_list(struct dir_struct *dir,
482
+ int group_type, const char *src)
483
{
484
struct exclude_list *el;
485
struct exclude_list_group *group;
@@ -484,6 +488,7 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type)
488
ALLOC_GROW(group->el, group->nr + 1, group->alloc);
489
el = &group->el[group->nr++];
490
memset(el, 0, sizeof(*el));
491
+ el->src = src;
492
return el;
493
}
494
@@ -493,7 +498,7 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type)
498
void add_excludes_from_file(struct dir_struct *dir, const char *fname)
499
{
500
struct exclude_list *el;
496
- el = add_exclude_list(dir, EXC_FILE);
501
+ el = add_exclude_list(dir, EXC_FILE, fname);
502
if (add_excludes_from_file_to_list(fname, "", 0, el, 0) < 0)
503
die("cannot use %s as an exclude file", fname);
504
}
@@ -524,6 +529,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
529
break;
530
el = &group->el[dir->exclude_stack->exclude_ix];
531
dir->exclude_stack = stk->prev;
532
+ free((char *)el->src); /* see strdup() below */
533
clear_exclude_list(el);
534
free(stk);
535
group->nr--;
@@ -550,7 +556,15 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
556
memcpy(dir->basebuf + current, base + current,
557
stk->baselen - current);
558
strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
553
- el = add_exclude_list(dir, EXC_DIRS);
559
+ /*
560
+ * dir->basebuf gets reused by the traversal, but we
561
+ * need fname to remain unchanged to ensure the src
562
+ * member of each struct exclude correctly
563
+ * back-references its source file. Other invocations
564
+ * of add_exclude_list provide stable strings, so we
565
+ * strdup() and free() here in the caller.
566
+ */
567
+ el = add_exclude_list(dir, EXC_DIRS, strdup(dir->basebuf));
568
stk->exclude_ix = group->nr - 1;
569
add_excludes_from_file_to_list(dir->basebuf,
570
dir->basebuf, stk->baselen,
dir.h
+19
-2
@@ -25,16 +25,32 @@ struct dir_entry {
25
struct exclude_list {
26
int nr;
27
int alloc;
28
+
29
/* remember pointer to exclude file contents so we can free() */
30
char *filebuf;
31
32
+ /* origin of list, e.g. path to filename, or descriptive string */
33
+ const char *src;
34
+
35
struct exclude {
36
+ /*
37
+ * This allows callers of last_exclude_matching() etc.
38
+ * to determine the origin of the matching pattern.
39
+ */
40
+ struct exclude_list *el;
41
+
42
const char *pattern;
43
int patternlen;
44
int nowildcardlen;
45
const char *base;
46
int baselen;
47
int flags;
48
+
49
+ /*
50
+ * Counting starts from 1 for line numbers in ignore files,
51
+ * and from -1 decrementing for patterns from CLI args.
52
+ */
53
+ int srcpos;
54
} **excludes;
55
};
56
@@ -144,13 +160,14 @@ extern struct exclude *last_exclude_matching_path(struct path_exclude_check *, c
160
extern int is_path_excluded(struct path_exclude_check *, const char *, int namelen, int *dtype);
161
162
147
-extern struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type);
163
+extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
164
+ int group_type, const char *src);
165
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
166
struct exclude_list *el, int check_index);
167
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
168
extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen);
169
extern void add_exclude(const char *string, const char *base,
153
- int baselen, struct exclude_list *el);
170
+ int baselen, struct exclude_list *el, int srcpos);
171
extern void clear_exclude_list(struct exclude_list *el);
172
extern int file_exists(const char *);
173