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

[PATCH] attr: support quoting pathname patterns in C style

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Nov 4, 2010, 13:55 UTC
Message-ID
<1288878944-14066-1-git-send-email-pclouds@gmail.com>
In-Reply-To
<AANLkTinNctmWpshBeSTzZRm6+EJ=Cjdpoaj4Aon+52_b@mail.gmail.com>

Full pattern must be quoted. So 'pat"t"ern attr' will give exactly 'pat"t"ern', not 'pattern'. Also clarify that leading whitespaces are not part of the pattern and document comment syntax.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Obvious regression: patterns that begin with double quote will
 now work differently.
 Documentation/gitattributes.txt |    8 +++++---
 attr.c                          |   25 +++++++++++++++++++++----
 t/t0003-attributes.sh           |   25 ++++++++++++++++++++++++-
 3 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index c80ca5d..bc6c65c 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -21,9 +21,11 @@ Each line in `gitattributes` file is of form:
 	pattern	attr1 attr2 ...
 
 That is, a pattern followed by an attributes list,
-separated by whitespaces.  When the pattern matches the
-path in question, the attributes listed on the line are given to
-the path.
+separated by whitespaces. Leading and trailing whitespaces are
+ignored. Lines that begin with '#' are ignored. Patterns
+that begin with a double quote are quoted in C style.
+When the pattern matches the path in question, the attributes
+listed on the line are given to the path.
 
 Each attribute can be in one of these states for a given path:
 
diff --git a/attr.c b/attr.c
index 6aff695..f3063d8 100644
--- a/attr.c
+++ b/attr.c
@@ -2,6 +2,7 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "attr.h"
+#include "quote.h"
 
 const char git_attr__true[] = "(builtin)true";
 const char git_attr__false[] = "\0(builtin)false";
@@ -181,21 +182,33 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 {
 	int namelen;
 	int num_attr;
-	const char *cp, *name;
+	const char *cp, *name, *ep;
 	struct match_attr *res = NULL;
 	int pass;
 	int is_macro;
+	struct strbuf pattern = STRBUF_INIT;
 
 	cp = line + strspn(line, blank);
 	if (!*cp || *cp == '#')
 		return NULL;
 	name = cp;
-	namelen = strcspn(name, blank);
+	if (*cp == '"') {
+		if (unquote_c_style(&pattern, name, &ep))
+			die("Broken attribute line: %s", line);
+		namelen = ep - name;
+		name = pattern.buf;
+	}
+	else {
+		namelen = strcspn(name, blank);
+		ep = name + namelen;
+	}
+
 	if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
 	    !prefixcmp(name, ATTRIBUTE_MACRO_PREFIX)) {
 		if (!macro_ok) {
 			fprintf(stderr, "%s not allowed: %s:%d\n",
 				name, src, lineno);
+			strbuf_release(&pattern);
 			return NULL;
 		}
 		is_macro = 1;
@@ -206,6 +219,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 			fprintf(stderr,
 				"%.*s is not a valid attribute name: %s:%d\n",
 				namelen, name, src, lineno);
+			strbuf_release(&pattern);
 			return NULL;
 		}
 	}
@@ -215,12 +229,14 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 	for (pass = 0; pass < 2; pass++) {
 		/* pass 0 counts and allocates, pass 1 fills */
 		num_attr = 0;
-		cp = name + namelen;
+		cp = ep;
 		cp = cp + strspn(cp, blank);
 		while (*cp) {
 			cp = parse_attr(src, lineno, cp, &num_attr, res);
-			if (!cp)
+			if (!cp) {
+				strbuf_release(&pattern);
 				return NULL;
+			}
 		}
 		if (pass)
 			break;
@@ -238,6 +254,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 		res->is_macro = is_macro;
 		res->num_attr = num_attr;
 	}
+	strbuf_release(&pattern);
 	return res;
 }
 
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 25205ac..a57f358 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -10,17 +10,37 @@ attr_check () {
 	expect="$2"
 
 	git check-attr test -- "$path" >actual &&
-	echo "$path: test: $2" >expect &&
+	echo "$path: test: $expect" >expect &&
 	test_cmp expect actual
 
 }
 
+attr_check_quote () {
+
+	path="$1"
+	quoted_path="$2"
+	expect="$3"
+
+	git check-attr test -- "$path" >actual &&
+	echo "\"$quoted_path\": test: $expect" >expect &&
+	test_cmp expect actual
+
+}
+
+test_expect_success 'open-quoted pathname' '
+	echo "\"a test=a" >.gitattributes &&
+	test_must_fail attr_check a a
+'
+
 
 test_expect_success 'setup' '
 
 	mkdir -p a/b/d a/c &&
 	(
 		echo "[attr]notest !test"
+		echo "\" d \"	test=d"
+		echo " e	test=e"
+		echo " e\"	test=e"
 		echo "f	test=f"
 		echo "a/i test=a/i"
 		echo "onoff test -test"
@@ -44,6 +64,9 @@ test_expect_success 'setup' '
 
 test_expect_success 'attribute test' '
 
+	attr_check " d " d &&
+	attr_check e e &&
+	attr_check_quote e\" e\\\" e &&
 	attr_check f f &&
 	attr_check a/f f &&
 	attr_check a/c/f f &&
-- 
1.7.3.2.210.g045198
Previous: Kevin BallardNext: Sverre Rabbelier
Message 5 of 18 in “.gitattributes escape character?”
  1. Marc StrapetzNov 3, 2010
  2. Nguyen Thai Ngoc DuyNov 3, 2010
  3. Marc StrapetzNov 3, 2010
  4. Kevin BallardNov 3, 2010
  5. attr: support quoting pathname patterns in C styleNguyễn Thái Ngọc Duy, Nov 4, 2010
  6. Sverre RabbelierNov 4, 2010
  7. Eric SunshineNov 4, 2010
  8. Nguyen Thai Ngoc DuyNov 5, 2010
  9. Junio C HamanoNov 5, 2010
  10. Kevin BallardNov 5, 2010
  11. Junio C HamanoNov 8, 2010
  12. Kevin BallardNov 8, 2010
  13. Johannes SixtNov 9, 2010
  14. Kevin BallardNov 9, 2010
  15. Junio C HamanoNov 10, 2010
  16. Kevin BallardNov 10, 2010
  17. Marc StrapetzNov 6, 2010
  18. attr: support quoting pathname patterns in C styleNguyễn Thái Ngọc Duy, Nov 7, 2010

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.