Skip to content

Commit

Permalink
builtin-add: warn on unmatched pathspecs
Browse files Browse the repository at this point in the history
This is in the same spirit as what bba319b and 45e4812 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>
  • Loading branch information
Linus Torvalds authored and Junio C Hamano committed May 17, 2006
1 parent 0d78153 commit f259339
Showing 1 changed file with 58 additions and 19 deletions.
77 changes: 58 additions & 19 deletions builtin-add.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit f259339

Please sign in to comment.