зеркало из https://github.com/microsoft/git.git
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>
This commit is contained in:
Родитель
2abd31b078
Коммит
e96980ef81
|
@ -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++)
|
||||
|
|
16
dir.c
16
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) {
|
||||
|
|
4
dir.h
4
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 */
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче