X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=dir.c;h=32b57f0125d1b9e95345eb23a9a32fbf8444b1b8;hb=c4431d380c20b4c05c373980c600798fc02e79b0;hp=16401d8017c5d96dc17ac9d52ab77eabbc4e9270;hpb=e035ce939d7e26afee4936ed32f1db9428ac026e;p=git.git diff --git a/dir.c b/dir.c index 16401d801..32b57f012 100644 --- a/dir.c +++ b/dir.c @@ -40,6 +40,18 @@ int common_prefix(const char **pathspec) return prefix; } +/* + * Does 'match' matches the given name? + * A match is found if + * + * (1) the 'match' string is leading directory of 'name', or + * (2) the 'match' string is a wildcard and matches 'name', or + * (3) the 'match' string is exactly the same as 'name'. + * + * and the return value tells which case it was. + * + * It returns 0 when there is no match. + */ static int match_one(const char *match, const char *name, int namelen) { int matchlen; @@ -47,27 +59,30 @@ static int match_one(const char *match, const char *name, int namelen) /* If the match was just the prefix, we matched */ matchlen = strlen(match); if (!matchlen) - return 1; + return MATCHED_RECURSIVELY; /* * If we don't match the matchstring exactly, * we need to match by fnmatch */ if (strncmp(match, name, matchlen)) - return !fnmatch(match, name, 0); + return !fnmatch(match, name, 0) ? MATCHED_FNMATCH : 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]; + if (!name[matchlen]) + return MATCHED_EXACTLY; + if (match[matchlen-1] == '/' || name[matchlen] == '/') + return MATCHED_RECURSIVELY; + return 0; } +/* + * Given a name and a list of pathspecs, see if the name matches + * any of the pathspecs. The caller is also interested in seeing + * all pathspec matches some names it calls this function with + * (otherwise the user could have mistyped the unmatched pathspec), + * and a mark is left in seen[] array for pathspec element that + * actually matched anything. + */ int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen) { int retval; @@ -77,12 +92,16 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre namelen -= prefix; for (retval = 0; (match = *pathspec++) != NULL; seen++) { - if (retval & *seen) + int how; + if (retval && *seen == MATCHED_EXACTLY) continue; match += prefix; - if (match_one(match, name, namelen)) { - retval = 1; - *seen = 1; + how = match_one(match, name, namelen); + if (how) { + if (retval < how) + retval = how; + if (*seen < how) + *seen = how; } } return retval; @@ -123,7 +142,7 @@ static int add_excludes_from_file_1(const char *fname, return 0; } buf = xmalloc(size+1); - if (read(fd, buf, size) != size) + if (read_in_full(fd, buf, size) != size) goto err; close(fd); @@ -241,12 +260,12 @@ int excluded(struct dir_struct *dir, const char *pathname) return 0; } -static void add_name(struct dir_struct *dir, const char *pathname, int len) +struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len) { struct dir_entry *ent; if (cache_name_pos(pathname, len) >= 0) - return; + return NULL; if (dir->nr == dir->alloc) { int alloc = alloc_nr(dir->alloc); @@ -254,10 +273,12 @@ static void add_name(struct dir_struct *dir, const char *pathname, int len) dir->entries = xrealloc(dir->entries, alloc*sizeof(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; dir->entries[dir->nr++] = ent; + return ent; } static int dir_exists(const char *dirname, int len) @@ -345,7 +366,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co if (check_only) goto exit_early; else - add_name(dir, fullname, baselen + len); + dir_add_name(dir, fullname, baselen + len); } exit_early: closedir(fdir);