diff options
author | Linus Torvalds <torvalds@osdl.org> | 2006-05-17 13:23:19 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2006-05-17 15:27:18 -0700 |
commit | f25933987f29070e9cd79dfddf03018010e82e80 (patch) | |
tree | 9506887ac501e31648953e168e6ccf99287384a7 /builtin-add.c | |
parent | 0d78153952e70c21e94dc6b7eefcb2ac5337a902 (diff) | |
download | git-f25933987f29070e9cd79dfddf03018010e82e80.tar.gz |
builtin-add: warn on unmatched pathspecs
This is in the same spirit as what bba319b5 and 45e48120 tried
to do to help users. A command such as "git add Documentaiton"
with misspelled pathspecs would give a friendly reminder with
this.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'builtin-add.c')
-rw-r--r-- | builtin-add.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/builtin-add.c b/builtin-add.c index d225988e53..089c7a89b3 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -44,50 +44,89 @@ static int common_prefix(const char **pathspec) return prefix; } -static int match(const char **pathspec, const char *name, int namelen, int 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; - while ((match = *pathspec++) != NULL) { - int matchlen; - + for (retval = 0; (match = *pathspec++) != NULL; seen++) { + if (retval & *seen) + continue; match += prefix; - matchlen = strlen(match); - if (!matchlen) - return 1; - if (!strncmp(match, name, matchlen)) { - if (match[matchlen-1] == '/') - return 1; - switch (name[matchlen]) { - case '/': case '\0': - return 1; - } + if (match_one(match, name, namelen)) { + retval = 1; + *seen = 1; } - if (!fnmatch(match, name, 0)) - return 1; } - return 0; + return retval; } static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) { - int i; + char *seen; + int i, specs; struct dir_entry **src, **dst; + for (specs = 0; pathspec[specs]; specs++) + /* nothing */; + seen = xmalloc(specs); + memset(seen, 0, specs); + src = dst = dir->entries; i = dir->nr; while (--i >= 0) { struct dir_entry *entry = *src++; - if (!match(pathspec, entry->name, entry->len, prefix)) { + if (!match(pathspec, entry->name, entry->len, prefix, seen)) { free(entry); continue; } *dst++ = entry; } dir->nr = dst - dir->entries; + + for (i = 0; i < specs; i++) { + struct stat st; + const char *match; + if (seen[i]) + continue; + + /* Existing file? We must have ignored it */ + match = pathspec[i]; + if (!lstat(match, &st)) + continue; + die("pathspec '%s' did not match any files", match); + } } static void fill_directory(struct dir_struct *dir, const char **pathspec) |