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

[PATCH 40/45] parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Jun 9, 2013, 06:26 UTC
Message-ID
<1370759178-1709-41-git-send-email-pclouds@gmail.com>
In-Reply-To
<1370759178-1709-1-git-send-email-pclouds@gmail.com>

The prefix length is passed from one command to another via the new magic 'prefix'. The magic is for parse_pathspec's internal use only, not visible to parse_pathspec's callers.

Prefix length is not preserved across commands when --literal-pathspecs is specified (no magic is allowed, including 'prefix'). That's OK because we know all paths are literal. No magic, no special treatment regarding prefix. (This may be no longer true if we make :(glob) default)

Other options to preserve the prefix include saving it to env variable or quoting. Env var way (at least _one_ env var) is not suitable because the prefix is not the same for all pathspecs. Pathspecs starting with "../" will eat into the prefix part.

We could also preserve 'prefix' across commands by quoting the prefix part, then dequoting on receiving. But it may not be 100% accurate, we may dequote longer than the original prefix part, for example. That may be good or not, but it's not the purpose.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 pathspec.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/pathspec.c b/pathspec.c
index e2ee268..2bd400a 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -92,9 +92,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
 				const char *elt)
 {
 	unsigned magic = 0, short_magic = 0;
-	const char *copyfrom = elt;
+	const char *copyfrom = elt, *long_magic_end = NULL;
 	char *match;
-	int i;
+	int i, pathspec_prefix = -1;
 
 	if (elt[0] != ':') {
 		; /* nothing to do */
@@ -112,18 +112,29 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
 				nextat = copyfrom + len;
 			if (!len)
 				continue;
-			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
+			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
 				if (strlen(pathspec_magic[i].name) == len &&
 				    !strncmp(pathspec_magic[i].name, copyfrom, len)) {
 					magic |= pathspec_magic[i].bit;
 					break;
 				}
+				if (!prefixcmp(copyfrom, "prefix:")) {
+					char *endptr;
+					pathspec_prefix = strtol(copyfrom + 7,
+								 &endptr, 10);
+					if (endptr - copyfrom != len)
+						die(_("invalid parameter for pathspec magic 'prefix'"));
+					/* "i" would be wrong, but it does not matter */
+					break;
+				}
+			}
 			if (ARRAY_SIZE(pathspec_magic) <= i)
 				die(_("Invalid pathspec magic '%.*s' in '%s'"),
 				    (int) len, copyfrom, elt);
 		}
 		if (*copyfrom != ')')
 			die(_("Missing ')' at the end of pathspec magic in '%s'"), elt);
+		long_magic_end = copyfrom;
 		copyfrom++;
 	} else {
 		/* shorthand */
@@ -150,7 +161,14 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
 	magic |= short_magic;
 	*p_short_magic = short_magic;
 
-	if (magic & PATHSPEC_FROMTOP) {
+	if (pathspec_prefix >= 0 &&
+	    (prefixlen || (prefix && *prefix)))
+		die("BUG: 'prefix' magic is supposed to be used at worktree's root");
+
+	if (pathspec_prefix >= 0) {
+		match = xstrdup(copyfrom);
+		prefixlen = pathspec_prefix;
+	} else if (magic & PATHSPEC_FROMTOP) {
 		match = xstrdup(copyfrom);
 		prefixlen = 0;
 	} else {
@@ -165,7 +183,20 @@ static unsigned prefix_pathspec(struct pathspec_item *item,
 	 */
 	if (flags & PATHSPEC_PREFIX_ORIGIN) {
 		struct strbuf sb = STRBUF_INIT;
-		strbuf_add(&sb, elt, copyfrom - elt);
+		const char *start = elt;
+		if (prefixlen && !limit_pathspec_to_literal()) {
+			/* Preserve the actual prefix length of each pattern */
+			if (long_magic_end) {
+				strbuf_add(&sb, start, long_magic_end - start);
+				strbuf_addf(&sb, ",prefix:%d", prefixlen);
+				start = long_magic_end;
+			} else {
+				if (*start == ':')
+					start++;
+				strbuf_addf(&sb, ":(prefix:%d)", prefixlen);
+			}
+		}
+		strbuf_add(&sb, start, copyfrom - start);
 		strbuf_addstr(&sb, match);
 		item->original = strbuf_detach(&sb, NULL);
 	} else
-- 
1.8.2.83.gc99314b
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 49 of 54 in “"struct pathspec" conversion and :(glob)”
  1. 00/45 "struct pathspec" conversion and :(glob)Nguyễn Thái Ngọc Duy, Jun 9, 2013
  2. 01/45 clean: remove unused variable "seen"Nguyễn Thái Ngọc Duy, Jun 9, 2013
  3. 02/45 Move struct pathspec and related functions to pathspec.[ch]Nguyễn Thái Ngọc Duy, Jun 9, 2013
  4. 03/45 pathspec: i18n-ize error strings in pathspec parsing codeNguyễn Thái Ngọc Duy, Jun 9, 2013
  5. 04/45 pathspec: add copy_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  6. Eric SunshineJun 9, 2013
  7. Junio C HamanoJun 12, 2013
  8. 05/45 Add parse_pathspec() that converts cmdline args to struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  9. Eric SunshineJun 10, 2013
  10. 06/45 parse_pathspec: save original pathspec for reportingNguyễn Thái Ngọc Duy, Jun 9, 2013
  11. 07/45 parse_pathspec: add PATHSPEC_PREFER_{CWD,FULL}Nguyễn Thái Ngọc Duy, Jun 9, 2013
  12. Eric SunshineJun 10, 2013
  13. 08/45 Convert some get_pathspec() calls to parse_pathspec()Nguyễn Thái Ngọc Duy, Jun 9, 2013
  14. 09/45 parse_pathspec: a special flag for max_depth featureNguyễn Thái Ngọc Duy, Jun 9, 2013
  15. Eric SunshineJun 10, 2013
  16. 10/45 parse_pathspec: support stripping submodule trailing slashesNguyễn Thái Ngọc Duy, Jun 9, 2013
  17. Eric SunshineJun 10, 2013
  18. 11/45 parse_pathspec: support stripping/checking submodule pathsNguyễn Thái Ngọc Duy, Jun 9, 2013
  19. 12/45 parse_pathspec: support prefixing original patternsNguyễn Thái Ngọc Duy, Jun 9, 2013
  20. Eric SunshineJun 10, 2013
  21. 13/45 Guard against new pathspec magic in pathspec matching codeNguyễn Thái Ngọc Duy, Jun 9, 2013
  22. Eric SunshineJun 10, 2013
  23. 14/45 clean: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  24. 15/45 commit: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  25. 16/45 status: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  26. 17/45 rerere: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  27. 18/45 checkout: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  28. 19/45 rm: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  29. 20/45 ls-files: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  30. 21/45 archive: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  31. 22/45 check-ignore: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  32. 23/45 add: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  33. 24/45 reset: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  34. 25/45 line-log: convert to use parse_pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  35. 26/45 Convert read_cache_preload() to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  36. 27/45 Convert run_add_interactive to use struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  37. 28/45 Convert unmerge_cache to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  38. 29/45 checkout: convert read_tree_some to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  39. 30/45 Convert report_path_error to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  40. 31/45 Convert refresh_index to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  41. 32/45 Convert {read,fill}_directory to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  42. 33/45 Convert add_files_to_cache to take struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  43. 34/45 Convert common_prefix() to use struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  44. 35/45 Remove diff_tree_{setup,release}_pathsNguyễn Thái Ngọc Duy, Jun 9, 2013
  45. 36/45 Remove init_pathspec() in favor of parse_pathspec()Nguyễn Thái Ngọc Duy, Jun 9, 2013
  46. 37/45 Remove match_pathspec() in favor of match_pathspec_depth()Nguyễn Thái Ngọc Duy, Jun 9, 2013
  47. 38/45 tree-diff: remove the use of pathspec's raw[] in follow-rename codepathNguyễn Thái Ngọc Duy, Jun 9, 2013
  48. 39/45 parse_pathspec: make sure the prefix part is wildcard-freeNguyễn Thái Ngọc Duy, Jun 9, 2013
  49. 40/45 parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGINNguyễn Thái Ngọc Duy, Jun 9, 2013
  50. 41/45 Kill limit_pathspec_to_literal() as it's only used by parse_pathspec()Nguyễn Thái Ngọc Duy, Jun 9, 2013
  51. 42/45 pathspec: support :(literal) syntax for noglob pathspecNguyễn Thái Ngọc Duy, Jun 9, 2013
  52. 43/45 pathspec: make --literal-pathspecs disable pathspec magicNguyễn Thái Ngọc Duy, Jun 9, 2013
  53. 44/45 pathspec: support :(glob) syntaxNguyễn Thái Ngọc Duy, Jun 9, 2013
  54. 45/45 Rename field "raw" to "_raw" in struct pathspecNguyễn Thái Ngọc Duy, Jun 9, 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.