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

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

 



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@xxxxxxxxx>
---
 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

--
To unsubscribe from this list: 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]