Skip to content

Commit

Permalink
builtin-add: simplify (and increase accuracy of) exclude handling
Browse files Browse the repository at this point in the history
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 <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
peff authored and gitster committed Jun 13, 2007
1 parent 2abd31b commit e96980e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 53 deletions.
69 changes: 21 additions & 48 deletions builtin-add.c
Expand Up @@ -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
Expand Down Expand Up @@ -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";
Expand All @@ -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++)
Expand Down
16 changes: 14 additions & 2 deletions dir.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 1 addition & 3 deletions dir.h
Expand Up @@ -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 */
};

Expand Down

0 comments on commit e96980e

Please sign in to comment.