From: Junio C Hamano Date: Wed, 24 Mar 2010 23:24:03 +0000 (-0700) Subject: Merge branch 'jk/maint-add-ignored-dir' into maint X-Git-Tag: v1.7.0.4~17 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/bcbbe4f9d9afa025024f18a474d11bfec32e3207?ds=inline;hp=-c Merge branch 'jk/maint-add-ignored-dir' into maint * jk/maint-add-ignored-dir: tests for "git add ignored-dir/file" without -f dir: fix COLLECT_IGNORED on excluded prefixes t0050: mark non-working test as such --- bcbbe4f9d9afa025024f18a474d11bfec32e3207 diff --combined dir.c index 133c333df6,14ac91a7bb..cb83332a26 --- a/dir.c +++ b/dir.c @@@ -200,35 -200,11 +200,35 @@@ void add_exclude(const char *string, co which->excludes[which->nr++] = x; } -static int add_excludes_from_file_1(const char *fname, - const char *base, - int baselen, - char **buf_p, - struct exclude_list *which) +static void *read_skip_worktree_file_from_index(const char *path, size_t *size) +{ + int pos, len; + unsigned long sz; + enum object_type type; + void *data; + struct index_state *istate = &the_index; + + len = strlen(path); + pos = index_name_pos(istate, path, len); + if (pos < 0) + return NULL; + if (!ce_skip_worktree(istate->cache[pos])) + return NULL; + data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz); + if (!data || type != OBJ_BLOB) { + free(data); + return NULL; + } + *size = xsize_t(sz); + return data; +} + +int add_excludes_from_file_to_list(const char *fname, + const char *base, + int baselen, + char **buf_p, + struct exclude_list *which, + int check_index) { struct stat st; int fd, i; @@@ -236,39 -212,24 +236,39 @@@ char *buf, *entry; fd = open(fname, O_RDONLY); - if (fd < 0 || fstat(fd, &st) < 0) - goto err; - size = xsize_t(st.st_size); - if (size == 0) { - close(fd); - return 0; + if (fd < 0 || fstat(fd, &st) < 0) { + if (0 <= fd) + close(fd); + if (!check_index || + (buf = read_skip_worktree_file_from_index(fname, &size)) == NULL) + return -1; + if (size == 0) { + free(buf); + return 0; + } + if (buf[size-1] != '\n') { + buf = xrealloc(buf, size+1); + buf[size++] = '\n'; + } } - buf = xmalloc(size+1); - if (read_in_full(fd, buf, size) != size) - { - free(buf); - goto err; + else { + size = xsize_t(st.st_size); + if (size == 0) { + close(fd); + return 0; + } + buf = xmalloc(size+1); + if (read_in_full(fd, buf, size) != size) { + free(buf); + close(fd); + return -1; + } + buf[size++] = '\n'; + close(fd); } - close(fd); if (buf_p) *buf_p = buf; - buf[size++] = '\n'; entry = buf; for (i = 0; i < size; i++) { if (buf[i] == '\n') { @@@ -280,12 -241,17 +280,12 @@@ } } return 0; - - err: - if (0 <= fd) - close(fd); - return -1; } void add_excludes_from_file(struct dir_struct *dir, const char *fname) { - if (add_excludes_from_file_1(fname, "", 0, NULL, - &dir->exclude_list[EXC_FILE]) < 0) + if (add_excludes_from_file_to_list(fname, "", 0, NULL, + &dir->exclude_list[EXC_FILE], 0) < 0) die("cannot use %s as an exclude file", fname); } @@@ -334,9 -300,9 +334,9 @@@ static void prep_exclude(struct dir_str memcpy(dir->basebuf + current, base + current, stk->baselen - current); strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir); - add_excludes_from_file_1(dir->basebuf, - dir->basebuf, stk->baselen, - &stk->filebuf, el); + add_excludes_from_file_to_list(dir->basebuf, + dir->basebuf, stk->baselen, + &stk->filebuf, el, 1); dir->exclude_stack = stk; current = stk->baselen; } @@@ -346,9 -312,9 +346,9 @@@ /* Scan the list and let the last match determine the fate. * Return 1 for exclude, 0 for include and -1 for undecided. */ -static int excluded_1(const char *pathname, - int pathlen, const char *basename, int *dtype, - struct exclude_list *el) +int excluded_from_list(const char *pathname, + int pathlen, const char *basename, int *dtype, + struct exclude_list *el) { int i; @@@ -359,12 -325,6 +359,12 @@@ int to_exclude = x->to_exclude; if (x->flags & EXC_FLAG_MUSTBEDIR) { + if (!dtype) { + if (!prefixcmp(pathname, exclude)) + return to_exclude; + else + continue; + } if (*dtype == DT_UNKNOWN) *dtype = get_dtype(NULL, pathname, pathlen); if (*dtype != DT_DIR) @@@ -422,8 -382,8 +422,8 @@@ int excluded(struct dir_struct *dir, co prep_exclude(dir, pathname, basename-pathname); for (st = EXC_CMDL; st <= EXC_FILE; st++) { - switch (excluded_1(pathname, pathlen, basename, - dtype_p, &dir->exclude_list[st])) { + switch (excluded_from_list(pathname, pathlen, basename, + dtype_p, &dir->exclude_list[st])) { case 0: return 0; case 1: @@@ -594,13 -554,29 +594,29 @@@ static int simplify_away(const char *pa return 0; } - static int in_pathspec(const char *path, int len, const struct path_simplify *simplify) + /* + * This function tells us whether an excluded path matches a + * list of "interesting" pathspecs. That is, whether a path matched + * by any of the pathspecs could possibly be ignored by excluding + * the specified path. This can happen if: + * + * 1. the path is mentioned explicitly in the pathspec + * + * 2. the path is a directory prefix of some element in the + * pathspec + */ + static int exclude_matches_pathspec(const char *path, int len, + const struct path_simplify *simplify) { if (simplify) { for (; simplify->path; simplify++) { if (len == simplify->len && !memcmp(path, simplify->path, len)) return 1; + if (len < simplify->len + && simplify->path[len] == '/' + && !memcmp(path, simplify->path, len)) + return 1; } } return 0; @@@ -678,7 -654,7 +694,7 @@@ static enum path_treatment treat_one_pa { int exclude = excluded(dir, path, &dtype); if (exclude && (dir->flags & DIR_COLLECT_IGNORED) - && in_pathspec(path, *len, simplify)) + && exclude_matches_pathspec(path, *len, simplify)) dir_add_ignored(dir, path, *len); /* @@@ -1044,7 -1020,7 +1060,7 @@@ int remove_path(const char *name slash = dirs + (slash - name); do { *slash = '\0'; - } while (rmdir(dirs) && (slash = strrchr(dirs, '/'))); + } while (rmdir(dirs) == 0 && (slash = strrchr(dirs, '/'))); free(dirs); } return 0;