diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2014-07-14 11:50:22 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-07-14 15:24:34 -0700 |
commit | aceb9429b37a4a36e91f9eeb60e7ba488f73604b (patch) | |
tree | 16b0e9ab9bffa98114425a5bd1934d174fe5f694 /dir.c | |
parent | 709359c85cf366df68a1cabf9d68978c05c541c5 (diff) | |
download | git-aceb9429b37a4a36e91f9eeb60e7ba488f73604b.tar.gz |
prep_exclude: remove the artificial PATH_MAX limitnd/path-max-must-go
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>
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 47 |
1 files changed, 28 insertions, 19 deletions
@@ -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); } |