git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Do "git add" as a builtin

From
Linus Torvalds <torvalds@osdl.org>
Date
May 17, 2006, 20:23 UTC
Message-ID
<Pine.LNX.4.64.0605171321020.10823@g5.osdl.org>
In-Reply-To
<7vhd3ocvyy.fsf@assigned-by-dhcp.cox.net>
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)
Previous: Junio C HamanoNext: Junio C Hamano
Message 3 of 13 in “Do "git add" as a builtin”
  1. Linus TorvaldsMay 17, 2006
  2. Junio C HamanoMay 17, 2006
  3. Linus TorvaldsMay 17, 2006
  4. Junio C HamanoMay 18, 2006
  5. Junio C HamanoMay 18, 2006
  6. [WARNING] Please be careful when using "git add" from "next" branchJunio C Hamano, May 18, 2006
  7. FIXED: [WARNING] Please be careful when using "git add" from "next" branchJunio C Hamano, May 19, 2006
  8. Linus TorvaldsMay 18, 2006
  9. Linus TorvaldsMay 18, 2006
  10. Linus TorvaldsMay 18, 2006
  11. Junio C HamanoMay 18, 2006
  12. Linus TorvaldsMay 18, 2006
  13. Linus TorvaldsMay 18, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.