Browse Source

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 <peff@peff.net>
Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Jeff King 18 years ago committed by Junio C Hamano
parent
commit
e96980ef81
  1. 69
      builtin-add.c
  2. 16
      dir.c
  3. 4
      dir.h

69
builtin-add.c

@ -40,42 +40,29 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p @@ -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) @@ -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) @@ -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++)

16
dir.c

@ -275,7 +275,6 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len) { @@ -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 @@ -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 @@ -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) {

4
dir.h

@ -13,9 +13,7 @@ @@ -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 */
};


Loading…
Cancel
Save