diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 26 |
1 files changed, 20 insertions, 6 deletions
@@ -349,7 +349,7 @@ void parse_exclude_pattern(const char **pattern, } 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; @@ -373,8 +373,10 @@ void add_exclude(const char *string, const char *base, 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) @@ -425,7 +427,7 @@ int add_excludes_from_file_to_list(const char *fname, int check_index) { struct stat st; - int fd, i; + int fd, i, lineno = 1; size_t size = 0; char *buf, *entry; @@ -467,15 +469,17 @@ int add_excludes_from_file_to_list(const char *fname, 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; @@ -484,6 +488,7 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type) ALLOC_GROW(group->el, group->nr + 1, group->alloc); el = &group->el[group->nr++]; memset(el, 0, sizeof(*el)); + el->src = src; return el; } @@ -493,7 +498,7 @@ struct exclude_list *add_exclude_list(struct dir_struct *dir, int group_type) 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); } @@ -524,6 +529,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) 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--; @@ -550,7 +556,15 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) 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, |