зеркало из https://github.com/microsoft/git.git
prep_exclude: remove the artificial PATH_MAX limit
This fixes a segfault in git-status with long paths on Windows, where PATH_MAX is only 260. This also fixes the problem of silently ignoring .gitignore if the full path exceeds PATH_MAX. Now add_excludes_from_file() will report if it gets ENAMETOOLONG. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
709359c85c
Коммит
aceb9429b3
47
dir.c
47
dir.c
|
@ -799,12 +799,12 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
|
|||
*/
|
||||
while ((stk = dir->exclude_stack) != NULL) {
|
||||
if (stk->baselen <= baselen &&
|
||||
!strncmp(dir->basebuf, base, stk->baselen))
|
||||
!strncmp(dir->basebuf.buf, base, stk->baselen))
|
||||
break;
|
||||
el = &group->el[dir->exclude_stack->exclude_ix];
|
||||
dir->exclude_stack = stk->prev;
|
||||
dir->exclude = NULL;
|
||||
free((char *)el->src); /* see strdup() below */
|
||||
free((char *)el->src); /* see strbuf_detach() below */
|
||||
clear_exclude_list(el);
|
||||
free(stk);
|
||||
group->nr--;
|
||||
|
@ -814,8 +814,17 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
|
|||
if (dir->exclude)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Lazy initialization. All call sites currently just
|
||||
* memset(dir, 0, sizeof(*dir)) before use. Changing all of
|
||||
* them seems lots of work for little benefit.
|
||||
*/
|
||||
if (!dir->basebuf.buf)
|
||||
strbuf_init(&dir->basebuf, PATH_MAX);
|
||||
|
||||
/* Read from the parent directories and push them down. */
|
||||
current = stk ? stk->baselen : -1;
|
||||
strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current);
|
||||
while (current < baselen) {
|
||||
struct exclude_stack *stk = xcalloc(1, sizeof(*stk));
|
||||
const char *cp;
|
||||
|
@ -833,48 +842,47 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
|
|||
stk->baselen = cp - base;
|
||||
stk->exclude_ix = group->nr;
|
||||
el = add_exclude_list(dir, EXC_DIRS, NULL);
|
||||
memcpy(dir->basebuf + current, base + current,
|
||||
stk->baselen - current);
|
||||
strbuf_add(&dir->basebuf, base + current, stk->baselen - current);
|
||||
assert(stk->baselen == dir->basebuf.len);
|
||||
|
||||
/* Abort if the directory is excluded */
|
||||
if (stk->baselen) {
|
||||
int dt = DT_DIR;
|
||||
dir->basebuf[stk->baselen - 1] = 0;
|
||||
dir->basebuf.buf[stk->baselen - 1] = 0;
|
||||
dir->exclude = last_exclude_matching_from_lists(dir,
|
||||
dir->basebuf, stk->baselen - 1,
|
||||
dir->basebuf + current, &dt);
|
||||
dir->basebuf[stk->baselen - 1] = '/';
|
||||
dir->basebuf.buf, stk->baselen - 1,
|
||||
dir->basebuf.buf + current, &dt);
|
||||
dir->basebuf.buf[stk->baselen - 1] = '/';
|
||||
if (dir->exclude &&
|
||||
dir->exclude->flags & EXC_FLAG_NEGATIVE)
|
||||
dir->exclude = NULL;
|
||||
if (dir->exclude) {
|
||||
dir->basebuf[stk->baselen] = 0;
|
||||
dir->exclude_stack = stk;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to read per-directory file unless path is too long */
|
||||
if (dir->exclude_per_dir &&
|
||||
stk->baselen + strlen(dir->exclude_per_dir) < PATH_MAX) {
|
||||
strcpy(dir->basebuf + stk->baselen,
|
||||
dir->exclude_per_dir);
|
||||
/* Try to read per-directory file */
|
||||
if (dir->exclude_per_dir) {
|
||||
/*
|
||||
* 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.
|
||||
* strbuf_detach() and free() here in the caller.
|
||||
*/
|
||||
el->src = strdup(dir->basebuf);
|
||||
add_excludes_from_file_to_list(dir->basebuf,
|
||||
dir->basebuf, stk->baselen, el, 1);
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
strbuf_addbuf(&sb, &dir->basebuf);
|
||||
strbuf_addstr(&sb, dir->exclude_per_dir);
|
||||
el->src = strbuf_detach(&sb, NULL);
|
||||
add_excludes_from_file_to_list(el->src, el->src,
|
||||
stk->baselen, el, 1);
|
||||
}
|
||||
dir->exclude_stack = stk;
|
||||
current = stk->baselen;
|
||||
}
|
||||
dir->basebuf[baselen] = '\0';
|
||||
strbuf_setlen(&dir->basebuf, baselen);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1671,4 +1679,5 @@ void clear_directory(struct dir_struct *dir)
|
|||
free(stk);
|
||||
stk = prev;
|
||||
}
|
||||
strbuf_release(&dir->basebuf);
|
||||
}
|
||||
|
|
2
dir.h
2
dir.h
|
@ -119,7 +119,7 @@ struct dir_struct {
|
|||
*/
|
||||
struct exclude_stack *exclude_stack;
|
||||
struct exclude *exclude;
|
||||
char basebuf[PATH_MAX];
|
||||
struct strbuf basebuf;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче