From 2abd31b07864049f0352d86c0c90413123f40945 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 11 Jun 2007 09:39:50 -0400 Subject: dir_struct: add collect_ignored option When set, this option will cause read_directory to keep track of which entries were ignored. While this shouldn't effect functionality in most cases, it can make warning messages to the user much more useful. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/dir.c b/dir.c index 5ba6030..6ed9eda 100644 --- a/dir.c +++ b/dir.c @@ -291,6 +291,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, @@ -463,6 +472,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co continue; exclude = excluded(dir, fullname); + if (exclude && dir->collect_ignored) + dir_add_ignored(dir, fullname, baselen + len); if (exclude != dir->show_ignored) { if (!dir->show_ignored || DTYPE(de) != DT_DIR) { continue; @@ -609,6 +620,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; } diff --git a/dir.h b/dir.h index 172147f..c94f3cb 100644 --- a/dir.h +++ b/dir.h @@ -31,11 +31,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; -- cgit v0.10.2-6-g49f6 From e96980ef8164f266308ea5fec536863a629866dc Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 12 Jun 2007 23:42:14 +0200 Subject: builtin-add: simplify (and increase accuracy of) exclude handling Previously, the code would always set up the excludes, and then manually pick through the pathspec we were given, assuming that non-added but existing paths were just ignored. This was mostly correct, but would erroneously mark a totally empty directory as 'ignored'. Instead, we now use the collect_ignored option of dir_struct, which unambiguously tells us whether a path was ignored. This simplifies the code, and means empty directories are now just not mentioned at all. Furthermore, we now conditionally ask dir_struct to respect excludes, depending on whether the '-f' flag has been set. This means we don't have to pick through the result, checking for an 'ignored' flag; ignored entries were either added or not in the first place. We can safely get rid of the special 'ignored' flags to dir_entry, which were not used anywhere else. Signed-off-by: Jeff King Signed-off-by: Jonas Fonseca Signed-off-by: Junio C Hamano diff --git a/builtin-add.c b/builtin-add.c index 1591171..7345479 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++) diff --git a/dir.c b/dir.c index 6ed9eda..98e24ad 100644 --- a/dir.c +++ b/dir.c @@ -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; @@ -432,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 @@ -472,7 +483,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co continue; exclude = excluded(dir, fullname); - if (exclude && dir->collect_ignored) + 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) { diff --git a/dir.h b/dir.h index c94f3cb..ec0e8ab 100644 --- a/dir.h +++ b/dir.h @@ -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 */ }; -- cgit v0.10.2-6-g49f6