diff options
-rw-r--r-- | builtin-add.c | 69 | ||||
-rw-r--r-- | dir.c | 26 | ||||
-rw-r--r-- | dir.h | 9 |
3 files changed, 51 insertions, 53 deletions
diff --git a/builtin-add.c b/builtin-add.c index 159117106a..734547994f 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -40,42 +40,29 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p dir->nr = dst - dir->entries; for (i = 0; i < specs; i++) { - struct stat st; - const char *match; - if (seen[i]) - continue; - - match = pathspec[i]; - if (!match[0]) - continue; - - /* Existing file? We must have ignored it */ - if (!lstat(match, &st)) { - struct dir_entry *ent; - - ent = dir_add_name(dir, match, strlen(match)); - ent->ignored = 1; - if (S_ISDIR(st.st_mode)) - ent->ignored_dir = 1; - continue; - } - die("pathspec '%s' did not match any files", match); + if (!seen[i] && !file_exists(pathspec[i])) + die("pathspec '%s' did not match any files", + pathspec[i]); } } -static void fill_directory(struct dir_struct *dir, const char **pathspec) +static void fill_directory(struct dir_struct *dir, const char **pathspec, + int ignored_too) { const char *path, *base; int baselen; /* Set up the default git porcelain excludes */ memset(dir, 0, sizeof(*dir)); - dir->exclude_per_dir = ".gitignore"; - path = git_path("info/exclude"); - if (!access(path, R_OK)) - add_excludes_from_file(dir, path); - if (!access(excludes_file, R_OK)) - add_excludes_from_file(dir, excludes_file); + if (!ignored_too) { + dir->collect_ignored = 1; + dir->exclude_per_dir = ".gitignore"; + path = git_path("info/exclude"); + if (!access(path, R_OK)) + add_excludes_from_file(dir, path); + if (!access(excludes_file, R_OK)) + add_excludes_from_file(dir, excludes_file); + } /* * Calculate common prefix for the pathspec, and @@ -219,13 +206,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) } pathspec = get_pathspec(prefix, argv + i); - fill_directory(&dir, pathspec); + fill_directory(&dir, pathspec, ignored_too); if (show_only) { const char *sep = "", *eof = ""; for (i = 0; i < dir.nr; i++) { - if (!ignored_too && dir.entries[i]->ignored) - continue; printf("%s%s", sep, dir.entries[i]->name); sep = " "; eof = "\n"; @@ -237,25 +222,13 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (read_cache() < 0) die("index file corrupt"); - if (!ignored_too) { - int has_ignored = 0; - for (i = 0; i < dir.nr; i++) - if (dir.entries[i]->ignored) - has_ignored = 1; - if (has_ignored) { - fprintf(stderr, ignore_warning); - for (i = 0; i < dir.nr; i++) { - if (!dir.entries[i]->ignored) - continue; - fprintf(stderr, "%s", dir.entries[i]->name); - if (dir.entries[i]->ignored_dir) - fprintf(stderr, " (directory)"); - fputc('\n', stderr); - } - fprintf(stderr, - "Use -f if you really want to add them.\n"); - exit(1); + if (dir.ignored_nr) { + fprintf(stderr, ignore_warning); + for (i = 0; i < dir.ignored_nr; i++) { + fprintf(stderr, "%s\n", dir.ignored[i]->name); } + fprintf(stderr, "Use -f if you really want to add them.\n"); + exit(1); } for (i = 0; i < dir.nr; i++) @@ -275,7 +275,6 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len) { struct dir_entry *ent; ent = xmalloc(sizeof(*ent) + len + 1); - ent->ignored = ent->ignored_dir = 0; ent->len = len; memcpy(ent->name, pathname, len); ent->name[len] = 0; @@ -291,6 +290,15 @@ struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int return dir->entries[dir->nr++] = dir_entry_new(pathname, len); } +struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) +{ + if (cache_name_pos(pathname, len) >= 0) + return NULL; + + ALLOC_GROW(dir->ignored, dir->ignored_nr, dir->ignored_alloc); + return dir->ignored[dir->ignored_nr++] = dir_entry_new(pathname, len); +} + enum exist_status { index_nonexistent = 0, index_directory, @@ -423,6 +431,18 @@ static int simplify_away(const char *path, int pathlen, const struct path_simpli return 0; } +static int in_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; + } + } + return 0; +} + /* * Read a directory tree. We currently ignore anything but * directories, regular files and symlinks. That's because git @@ -463,6 +483,9 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co continue; exclude = excluded(dir, fullname); + if (exclude && dir->collect_ignored + && in_pathspec(fullname, baselen + len, simplify)) + dir_add_ignored(dir, fullname, baselen + len); if (exclude != dir->show_ignored) { if (!dir->show_ignored || DTYPE(de) != DT_DIR) { continue; @@ -609,6 +632,7 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i read_directory_recursive(dir, path, base, baselen, 0, simplify); free_simplify(simplify); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); + qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; } @@ -13,9 +13,7 @@ struct dir_entry { - unsigned int ignored : 1; - unsigned int ignored_dir : 1; - unsigned int len : 30; + unsigned int len; char name[FLEX_ARRAY]; /* more */ }; @@ -31,11 +29,14 @@ struct exclude_list { struct dir_struct { int nr, alloc; + int ignored_nr, ignored_alloc; unsigned int show_ignored:1, show_other_directories:1, hide_empty_directories:1, - no_gitlinks:1; + no_gitlinks:1, + collect_ignored:1; struct dir_entry **entries; + struct dir_entry **ignored; /* Exclude info */ const char *exclude_per_dir; |