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

[PATCH v2 23/46] add: convert to use parse_pathspec

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Jul 14, 2013, 08:35 UTC
Message-ID
<1373790969-13000-24-git-send-email-pclouds@gmail.com>
In-Reply-To
<1373790969-13000-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/add.c | 103 +++++++++++++++++++++++++---------------------------------
 pathspec.c    |  43 ------------------------
 2 files changed, 45 insertions(+), 101 deletions(-)
diff --git a/builtin/add.c b/builtin/add.c
index f45d9d4..9a7235e 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -226,21 +226,6 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
 	return seen;
 }
 
-/*
- * Checks the index to see whether any path in pathspec refers to
- * something inside a submodule.  If so, dies with an error message.
- */
-static void treat_gitlinks(const char **pathspec)
-{
-	int i;
-
-	if (!pathspec || !*pathspec)
-		return;
-
-	for (i = 0; pathspec[i]; i++)
-		pathspec[i] = check_path_for_gitlink(pathspec[i]);
-}
-
 static void refresh(int verbose, const char **pathspec)
 {
 	char *seen;
@@ -258,25 +243,6 @@ static void refresh(int verbose, const char **pathspec)
         free(seen);
 }
 
-/*
- * Normalizes argv relative to prefix, via get_pathspec(), and then
- * runs die_if_path_beyond_symlink() on each path in the normalized
- * list.
- */
-static const char **validate_pathspec(const char **argv, const char *prefix)
-{
-	const char **pathspec = get_pathspec(prefix, argv);
-
-	if (pathspec) {
-		const char **p;
-		for (p = pathspec; *p; p++) {
-			die_if_path_beyond_symlink(*p, prefix);
-		}
-	}
-
-	return pathspec;
-}
-
 int run_add_interactive(const char *revision, const char *patch_mode,
 			const char **pathspec)
 {
@@ -308,17 +274,23 @@ int run_add_interactive(const char *revision, const char *patch_mode,
 
 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
 {
-	const char **pathspec = NULL;
+	struct pathspec pathspec;
 
-	if (argc) {
-		pathspec = validate_pathspec(argv, prefix);
-		if (!pathspec)
-			return -1;
-	}
+	/*
+	 * git-add--interactive itself does not parse pathspec. It
+	 * simply passes the pathspec to other builtin commands. Let's
+	 * hope all of them support all magic, or we'll need to limit
+	 * the magic here. There is still a problem with prefix. But
+	 * that'll be worked on later on.
+	 */
+	parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_SYMLINK_LEADING_PATH,
+		       prefix, argv);
 
 	return run_add_interactive(NULL,
 				   patch ? "--patch" : NULL,
-				   pathspec);
+				   pathspec.raw);
 }
 
 static int edit_patch(int argc, const char **argv, const char *prefix)
@@ -445,7 +417,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 {
 	int exit_status = 0;
 	int newfd;
-	const char **pathspec;
+	struct pathspec pathspec;
 	struct dir_struct dir;
 	int flags;
 	int add_new_files;
@@ -526,11 +498,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
 		return 0;
 	}
-	pathspec = validate_pathspec(argv, prefix);
 
 	if (read_cache() < 0)
 		die(_("index file corrupt"));
-	treat_gitlinks(pathspec);
+
+	/*
+	 * Check the "pathspec '%s' did not match any files" block
+	 * below before enabling new magic.
+	 */
+	parse_pathspec(&pathspec, 0,
+		       PATHSPEC_PREFER_FULL |
+		       PATHSPEC_SYMLINK_LEADING_PATH |
+		       PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
+		       prefix, argv);
 
 	if (add_new_files) {
 		int baselen;
@@ -543,34 +523,40 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		}
 
 		/* This picks up the paths that are not tracked */
-		baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
-		if (pathspec)
-			seen = prune_directory(&dir, pathspec, baselen,
+		baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec.raw);
+		if (pathspec.nr)
+			seen = prune_directory(&dir, pathspec.raw, baselen,
 					implicit_dot ? WARN_IMPLICIT_DOT : 0);
 	}
 
 	if (refresh_only) {
-		refresh(verbose, pathspec);
+		refresh(verbose, pathspec.raw);
 		goto finish;
 	}
 	if (implicit_dot && prefix)
 		refresh_cache(REFRESH_QUIET);
 
-	if (pathspec) {
+	if (pathspec.nr) {
 		int i;
 
 		if (!seen)
-			seen = find_pathspecs_matching_against_index(pathspec);
-		for (i = 0; pathspec[i]; i++) {
-			if (!seen[i] && pathspec[i][0]
-			    && !file_exists(pathspec[i])) {
+			seen = find_pathspecs_matching_against_index(pathspec.raw);
+
+		/*
+		 * file_exists() assumes exact match
+		 */
+		GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
+
+		for (i = 0; pathspec.raw[i]; i++) {
+			if (!seen[i] && pathspec.raw[i][0]
+			    && !file_exists(pathspec.raw[i])) {
 				if (ignore_missing) {
 					int dtype = DT_UNKNOWN;
-					if (is_excluded(&dir, pathspec[i], &dtype))
-						dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
+					if (is_excluded(&dir, pathspec.raw[i], &dtype))
+						dir_add_ignored(&dir, pathspec.raw[i], strlen(pathspec.raw[i]));
 				} else
 					die(_("pathspec '%s' did not match any files"),
-					    pathspec[i]);
+					    pathspec.raw[i]);
 			}
 		}
 		free(seen);
@@ -586,10 +572,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		 */
 		update_data.implicit_dot = prefix;
 		update_data.implicit_dot_len = strlen(prefix);
-		pathspec = NULL;
+		free_pathspec(&pathspec);
+		memset(&pathspec, 0, sizeof(pathspec));
 	}
 	update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
-	update_files_in_cache(prefix, pathspec, &update_data);
+	update_files_in_cache(prefix, pathspec.raw, &update_data);
 
 	exit_status |= !!update_data.add_errors;
 	if (add_new_files)
diff --git a/pathspec.c b/pathspec.c
index 5c9631a..2774bda 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -58,49 +58,6 @@ char *find_pathspecs_matching_against_index(const char **pathspec)
 }
 
 /*
- * Check the index to see whether path refers to a submodule, or
- * something inside a submodule.  If the former, returns the path with
- * any trailing slash stripped.  If the latter, dies with an error
- * message.
- */
-const char *check_path_for_gitlink(const char *path)
-{
-	int i, path_len = strlen(path);
-	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
-		if (S_ISGITLINK(ce->ce_mode)) {
-			int ce_len = ce_namelen(ce);
-			if (path_len <= ce_len || path[ce_len] != '/' ||
-			    memcmp(ce->name, path, ce_len))
-				/* path does not refer to this
-				 * submodule or anything inside it */
-				continue;
-			if (path_len == ce_len + 1) {
-				/* path refers to submodule;
-				 * strip trailing slash */
-				return xstrndup(ce->name, ce_len);
-			} else {
-				die (_("Path '%s' is in submodule '%.*s'"),
-				     path, ce_len, ce->name);
-			}
-		}
-	}
-	return path;
-}
-
-/*
- * Dies if the given path refers to a file inside a symlinked
- * directory in the index.
- */
-void die_if_path_beyond_symlink(const char *path, const char *prefix)
-{
-	if (has_symlink_leading_path(path, strlen(path))) {
-		int len = prefix ? strlen(prefix) : 0;
-		die(_("'%s' is beyond a symbolic link"), path + len);
-	}
-}
-
-/*
  * Magic pathspec
  *
  * Possible future magic semantics include stuff like:
-- 
1.8.2.83.gc99314b
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 24 of 52 in “"struct pathspec" conversion and :(glob) and :(icase)”
  1. 00/46 "struct pathspec" conversion and :(glob) and :(icase)Nguyễn Thái Ngọc Duy, Jul 14, 2013
  2. 01/46 clean: remove unused variable "seen"Nguyễn Thái Ngọc Duy, Jul 14, 2013
  3. 02/46 Move struct pathspec and related functions to pathspec.[ch]Nguyễn Thái Ngọc Duy, Jul 14, 2013
  4. 03/46 pathspec: i18n-ize error strings in pathspec parsing codeNguyễn Thái Ngọc Duy, Jul 14, 2013
  5. 04/46 pathspec: add copy_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  6. 05/46 Add parse_pathspec() that converts cmdline args to struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  7. 06/46 parse_pathspec: save original pathspec for reportingNguyễn Thái Ngọc Duy, Jul 14, 2013
  8. 07/46 parse_pathspec: add PATHSPEC_PREFER_{CWD,FULL}Nguyễn Thái Ngọc Duy, Jul 14, 2013
  9. 08/46 Convert some get_pathspec() calls to parse_pathspec()Nguyễn Thái Ngọc Duy, Jul 14, 2013
  10. 09/46 parse_pathspec: add special flag for max_depth featureNguyễn Thái Ngọc Duy, Jul 14, 2013
  11. 10/46 parse_pathspec: support stripping submodule trailing slashesNguyễn Thái Ngọc Duy, Jul 14, 2013
  12. 11/46 parse_pathspec: support stripping/checking submodule pathsNguyễn Thái Ngọc Duy, Jul 14, 2013
  13. 12/46 parse_pathspec: support prefixing original patternsNguyễn Thái Ngọc Duy, Jul 14, 2013
  14. 13/46 Guard against new pathspec magic in pathspec matching codeNguyễn Thái Ngọc Duy, Jul 14, 2013
  15. 14/46 clean: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  16. 15/46 commit: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  17. 16/46 status: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  18. 17/46 rerere: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  19. 18/46 checkout: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  20. 19/46 rm: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  21. 20/46 ls-files: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  22. 21/46 archive: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  23. 22/46 check-ignore: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  24. 23/46 add: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  25. 24/46 reset: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  26. 25/46 line-log: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  27. 26/46 Convert read_cache_preload() to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  28. 27/46 Convert run_add_interactive to use struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  29. 28/46 Convert unmerge_cache to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  30. 29/46 checkout: convert read_tree_some to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  31. 30/46 Convert report_path_error to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  32. 31/46 Convert refresh_index to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  33. 32/46 Convert {read,fill}_directory to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  34. 33/46 Convert add_files_to_cache to take struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  35. 34/46 Convert common_prefix() to use struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  36. 35/46 Remove diff_tree_{setup,release}_pathsNguyễn Thái Ngọc Duy, Jul 14, 2013
  37. 36/46 Remove init_pathspec() in favor of parse_pathspec()Nguyễn Thái Ngọc Duy, Jul 14, 2013
  38. 37/46 Remove match_pathspec() in favor of match_pathspec_depth()Nguyễn Thái Ngọc Duy, Jul 14, 2013
  39. 38/46 tree-diff: remove the use of pathspec's raw[] in follow-rename codepathNguyễn Thái Ngọc Duy, Jul 14, 2013
  40. 39/46 Rename field "raw" to "_raw" in struct pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  41. 40/46 parse_pathspec: make sure the prefix part is wildcard-freeNguyễn Thái Ngọc Duy, Jul 14, 2013
  42. 41/46 parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGINNguyễn Thái Ngọc Duy, Jul 14, 2013
  43. 42/46 Kill limit_pathspec_to_literal() as it's only used by parse_pathspec()Nguyễn Thái Ngọc Duy, Jul 14, 2013
  44. 43/46 pathspec: support :(literal) syntax for noglob pathspecNguyễn Thái Ngọc Duy, Jul 14, 2013
  45. 44/46 pathspec: make --literal-pathspecs disable pathspec magicNguyễn Thái Ngọc Duy, Jul 14, 2013
  46. 45/46 pathspec: support :(glob) syntaxNguyễn Thái Ngọc Duy, Jul 14, 2013
  47. 46/46 parse_pathspec: accept :(icase)path syntaxNguyễn Thái Ngọc Duy, Jul 14, 2013
  48. Eric SunshineJul 14, 2013
  49. Junio C HamanoJul 15, 2013
  50. Junio C HamanoJul 15, 2013
  51. "git fmt-merge-msg" usage (was [PATCH v2 00/46] "struct pathspec" conversion and :(glob) and :(icase))Michael Haggerty, Aug 16, 2013
  52. Junio C HamanoAug 18, 2013

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.