Re: Do "git add" as a builtin

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Wed, 17 May 2006, Junio C Hamano wrote:
> 
> By "not seeing the point", do you mean you do not agree with
> what bba319b5 and 45e48120 tried to do to help users?

Naah, I just didn't see why, and didn't bother to go exploring.

How about this patch on top of the previous one?

		Linus

----
diff --git a/builtin-add.c b/builtin-add.c
index e815b3d..82e8f44 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -44,50 +44,89 @@ static int common_prefix(const char **pa
 	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)
-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]