From: Linus Torvalds Date: Fri, 19 May 2006 23:07:51 +0000 (-0700) Subject: Move pathspec matching from builtin-add.c into dir.c X-Git-Tag: v1.4.0-rc1~79^2~1 X-Git-Url: https://git.octo.it/?p=git.git;a=commitdiff_plain;h=3c6a370b0ee78114a656acba04fddf306252b9d5 Move pathspec matching from builtin-add.c into dir.c I'll use it for builtin-rm.c too. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff --git a/builtin-add.c b/builtin-add.c index 37243f8c..6166f66b 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -12,86 +12,6 @@ static const char builtin_add_usage[] = "git-add [-n] [-v] ..."; -static 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]; -} - -static int match(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; -} - static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) { char *seen; @@ -107,7 +27,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p i = dir->nr; while (--i >= 0) { struct dir_entry *entry = *src++; - if (!match(pathspec, entry->name, entry->len, prefix, seen)) { + if (!match_pathspec(pathspec, entry->name, entry->len, prefix, seen)) { free(entry); continue; } diff --git a/dir.c b/dir.c index d40b62e1..d778ecd8 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) { diff --git a/dir.h b/dir.h index 4f65f570..56a1b7fc 100644 --- a/dir.h +++ b/dir.h @@ -39,6 +39,9 @@ struct dir_struct { struct exclude_list exclude_list[3]; }; +extern int common_prefix(const char **pathspec); +extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen); + extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen); extern int excluded(struct dir_struct *, const char *); extern void add_excludes_from_file(struct dir_struct *, const char *fname);