X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=dir.c;h=5a40d8ff8c99c80bf8f0484425db6022c6f7d8e9;hb=2886bdb118699fbc343e3c0b4f93f06fbeae1061;hp=d40b62e1c19c342dfddeb157b295d8188f9a1f20;hpb=ae12e59a8c895e48d4ef52ac6936674ac7be6370;p=git.git diff --git a/dir.c b/dir.c index d40b62e1c..5a40d8ff8 100644 --- a/dir.c +++ b/dir.c @@ -11,6 +11,86 @@ #include "cache.h" #include "dir.h" +int common_prefix(const char **pathspec) +{ + const char *path, *slash, *next; + int prefix; + + if (!pathspec) + return 0; + + path = *pathspec; + slash = strrchr(path, '/'); + if (!slash) + return 0; + + prefix = slash - path + 1; + while ((next = *++pathspec) != NULL) { + int len = strlen(next); + if (len >= prefix && !memcmp(path, next, len)) + continue; + for (;;) { + if (!len) + return 0; + if (next[--len] != '/') + continue; + if (memcmp(path, next, len+1)) + continue; + prefix = len + 1; + break; + } + } + return prefix; +} + +static int match_one(const char *match, const char *name, int namelen) +{ + int matchlen; + + /* If the match was just the prefix, we matched */ + matchlen = strlen(match); + if (!matchlen) + return 1; + + /* + * If we don't match the matchstring exactly, + * we need to match by fnmatch + */ + if (strncmp(match, name, matchlen)) + return !fnmatch(match, name, 0); + + /* + * If we did match the string exactly, we still + * need to make sure that it happened on a path + * component boundary (ie either the last character + * of the match was '/', or the next character of + * the name was '/' or the terminating NUL. + */ + return match[matchlen-1] == '/' || + name[matchlen] == '/' || + !name[matchlen]; +} + +int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen) +{ + int retval; + const char *match; + + name += prefix; + namelen -= prefix; + + for (retval = 0; (match = *pathspec++) != NULL; seen++) { + if (retval & *seen) + continue; + match += prefix; + if (match_one(match, name, namelen)) { + retval = 1; + *seen = 1; + } + } + return retval; +} + void add_exclude(const char *string, const char *base, int baselen, struct exclude_list *which) { @@ -21,8 +101,8 @@ void add_exclude(const char *string, const char *base, x->baselen = baselen; if (which->nr == which->alloc) { which->alloc = alloc_nr(which->alloc); - which->excludes = realloc(which->excludes, - which->alloc * sizeof(x)); + which->excludes = xrealloc(which->excludes, + which->alloc * sizeof(x)); } which->excludes[which->nr++] = x; } @@ -32,17 +112,15 @@ static int add_excludes_from_file_1(const char *fname, int baselen, struct exclude_list *which) { + struct stat st; int fd, i; long size; char *buf, *entry; fd = open(fname, O_RDONLY); - if (fd < 0) - goto err; - size = lseek(fd, 0, SEEK_END); - if (size < 0) + if (fd < 0 || fstat(fd, &st) < 0) goto err; - lseek(fd, 0, SEEK_SET); + size = st.st_size; if (size == 0) { close(fd); return 0; @@ -213,7 +291,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co if (fdir) { int exclude_stk; struct dirent *de; - char fullname[MAXPATHLEN + 1]; + char fullname[PATH_MAX + 1]; memcpy(fullname, base, baselen); exclude_stk = push_exclude_per_directory(dir, base, baselen); @@ -256,7 +334,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co if (dir->show_other_directories && (subdir || !dir->hide_empty_directories) && !dir_exists(fullname, baselen + len)) { - // Rewind the read subdirectory + /* Rewind the read subdirectory */ while (dir->nr > rewind_base) free(dir->entries[--dir->nr]); break;