From cde151815eb409d8dd457e7aaa3ded2e53796343 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:11 +0200 Subject: [PATCH 01/29] doc: Add a link from gitattributes(5) to git-check-attr(1) Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 412c55b549..3d8643437e 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -952,6 +952,9 @@ frotz unspecified ---------------------------------------------------------------- +SEE ALSO +-------- +linkgit:git-check-attr[1]. GIT --- From 650cfc512e189c1af347c9eeaebc0377e0dcb88d Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:12 +0200 Subject: [PATCH 02/29] doc: Correct git_attr() calls in example code Commit 7fb0eaa2 (2010-01-17) changed git_attr() to take a string instead of a string and a length. Update the documentation accordingly. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/technical/api-gitattributes.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt index 9d97eaa9de..916720f7ac 100644 --- a/Documentation/technical/api-gitattributes.txt +++ b/Documentation/technical/api-gitattributes.txt @@ -11,9 +11,9 @@ Data Structure `struct git_attr`:: An attribute is an opaque object that is identified by its name. - Pass the name and its length to `git_attr()` function to obtain - the object of this type. The internal representation of this - structure is of no interest to the calling programs. + Pass the name to `git_attr()` function to obtain the object of + this type. The internal representation of this structure is + of no interest to the calling programs. `struct git_attr_check`:: @@ -72,8 +72,8 @@ static void setup_check(void) { if (check[0].attr) return; /* already done */ - check[0].attr = git_attr("crlf", 4); - check[1].attr = git_attr("ident", 5); + check[0].attr = git_attr("crlf"); + check[1].attr = git_attr("ident"); } ------------ From d42453ab1a482df0fdb428c20de1189a21a2bee1 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:13 +0200 Subject: [PATCH 03/29] Remove anachronism from comment Setting attributes to arbitrary values ("attribute=value") is now supported, so it is no longer necessary for this comment to justify prohibiting '=' in an attribute name. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/attr.c b/attr.c index f6b3f7e850..4a1244f9a9 100644 --- a/attr.c +++ b/attr.c @@ -50,10 +50,8 @@ static unsigned hash_name(const char *name, int namelen) static int invalid_attr_name(const char *name, int namelen) { /* - * Attribute name cannot begin with '-' and from - * [-A-Za-z0-9_.]. We'd specifically exclude '=' for now, - * as we might later want to allow non-binary value for - * attributes, e.g. "*.svg merge=special-merge-program-for-svg" + * Attribute name cannot begin with '-' and must consist of + * characters from [-A-Za-z0-9_.]. */ if (*name == '-') return -1; From c0b13b21b8daa4bfb222e9c4d335c8b340c511a0 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:14 +0200 Subject: [PATCH 04/29] Disallow the empty string as an attribute name Previously, it was possible to have a line like "file.txt =foo" in a .gitattribute file, after which an invocation like "git check-attr '' -- file.txt" would succeed. This patch disallows both constructs. Please note that any existing .gitattributes file that tries to set an empty attribute will now trigger the error message "error: : not a valid attribute name" whereas previously the nonsense was allowed through. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 2 +- t/t0003-attributes.sh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/attr.c b/attr.c index 4a1244f9a9..b1d1d6d791 100644 --- a/attr.c +++ b/attr.c @@ -53,7 +53,7 @@ static int invalid_attr_name(const char *name, int namelen) * Attribute name cannot begin with '-' and must consist of * characters from [-A-Za-z0-9_.]. */ - if (*name == '-') + if (namelen <= 0 || *name == '-') return -1; while (namelen--) { char ch = *name++; diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index ebbc7554a7..8c76b79bb0 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -42,6 +42,12 @@ test_expect_success 'setup' ' ' +test_expect_success 'command line checks' ' + + test_must_fail git check-attr "" -- f + +' + test_expect_success 'attribute test' ' attr_check f f && From dcc04366a4658763500724888d9e74cae317c861 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:15 +0200 Subject: [PATCH 05/29] git-check-attr: Add missing "&&" Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 8c76b79bb0..dae76b39b8 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -35,7 +35,7 @@ test_expect_success 'setup' ' echo "h test=a/b/h" && echo "d/* test=a/b/d/*" echo "d/yes notest" - ) >a/b/.gitattributes + ) >a/b/.gitattributes && ( echo "global test=global" ) >"$HOME"/global-gitattributes From 09d7dd7ad62fef60fc223fa74eb04c8dc783c2f6 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:16 +0200 Subject: [PATCH 06/29] git-check-attr: Add tests of command-line parsing Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index dae76b39b8..f1debeb7ad 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -44,6 +44,13 @@ test_expect_success 'setup' ' test_expect_success 'command line checks' ' + test_must_fail git check-attr && + test_must_fail git check-attr -- && + test_must_fail git check-attr -- f && + echo "f" | test_must_fail git check-attr --stdin && + echo "f" | test_must_fail git check-attr --stdin -- f && + echo "f" | test_must_fail git check-attr --stdin test -- f && + echo "f" | test_must_fail git check-attr --stdin test f && test_must_fail git check-attr "" -- f ' From 352404ac4ccab144cd866b1f24c90b8f29ca33c2 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:17 +0200 Subject: [PATCH 07/29] Provide access to the name attribute of git_attr It will be present in any likely future reimplementation, and its availability simplifies other code. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/technical/api-gitattributes.txt | 3 ++- attr.c | 5 +++++ attr.h | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt index 916720f7ac..ab3a84d2f7 100644 --- a/Documentation/technical/api-gitattributes.txt +++ b/Documentation/technical/api-gitattributes.txt @@ -13,7 +13,8 @@ Data Structure An attribute is an opaque object that is identified by its name. Pass the name to `git_attr()` function to obtain the object of this type. The internal representation of this structure is - of no interest to the calling programs. + of no interest to the calling programs. The name of the + attribute can be retrieved by calling `git_attr_name()`. `struct git_attr_check`:: diff --git a/attr.c b/attr.c index b1d1d6d791..bfa1f43793 100644 --- a/attr.c +++ b/attr.c @@ -36,6 +36,11 @@ static int attr_nr; static struct git_attr_check *check_all_attr; static struct git_attr *(git_attr_hash[HASHSIZE]); +char *git_attr_name(struct git_attr *attr) +{ + return attr->name; +} + static unsigned hash_name(const char *name, int namelen) { unsigned val = 0, c; diff --git a/attr.h b/attr.h index 8b3f19be67..d4f875a3d5 100644 --- a/attr.h +++ b/attr.h @@ -29,6 +29,13 @@ struct git_attr_check { const char *value; }; +/* + * Return the name of the attribute represented by the argument. The + * return value is a pointer to a null-delimited string that is part + * of the internal data structure; it should not be modified or freed. + */ +char *git_attr_name(struct git_attr *); + int git_checkattr(const char *path, int, struct git_attr_check *); enum git_attr_direction { From 66a1fb30335191b5ebdbcc331832e8903eb3cd0e Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:18 +0200 Subject: [PATCH 08/29] git-check-attr: Use git_attr_name() Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 3016d29caa..5f04126d4d 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -21,7 +21,7 @@ static const struct option check_attr_options[] = { }; static void check_attr(int cnt, struct git_attr_check *check, - const char** name, const char *file) + const char *file) { int j; if (git_checkattr(file, cnt, check)) @@ -37,12 +37,11 @@ static void check_attr(int cnt, struct git_attr_check *check, value = "unspecified"; quote_c_style(file, NULL, stdout, 0); - printf(": %s: %s\n", name[j], value); + printf(": %s: %s\n", git_attr_name(check[j].attr), value); } } -static void check_attr_stdin_paths(int cnt, struct git_attr_check *check, - const char** name) +static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) { struct strbuf buf, nbuf; int line_termination = null_term_line ? 0 : '\n'; @@ -56,7 +55,7 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check, die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } - check_attr(cnt, check, name, buf.buf); + check_attr(cnt, check, buf.buf); maybe_flush_or_die(stdout, "attribute to stdout"); } strbuf_release(&buf); @@ -113,10 +112,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) } if (stdin_paths) - check_attr_stdin_paths(cnt, check, argv); + check_attr_stdin_paths(cnt, check); else { for (i = doubledash; i < argc; i++) - check_attr(cnt, check, argv, argv[i]); + check_attr(cnt, check, argv[i]); maybe_flush_or_die(stdout, "attribute to stdout"); } return 0; From a872701755347efe22be998d1e39f454fc422ff2 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:19 +0200 Subject: [PATCH 09/29] Teach prepare_attr_stack() to figure out dirlen itself Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/attr.c b/attr.c index bfa1f43793..7f0f390d52 100644 --- a/attr.c +++ b/attr.c @@ -535,11 +535,18 @@ static void bootstrap_attr_stack(void) } } -static void prepare_attr_stack(const char *path, int dirlen) +static void prepare_attr_stack(const char *path) { struct attr_stack *elem, *info; - int len; + int dirlen, len; struct strbuf pathbuf; + const char *cp; + + cp = strrchr(path, '/'); + if (!cp) + dirlen = 0; + else + dirlen = cp - path; strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE)); @@ -709,20 +716,14 @@ static int macroexpand_one(int attr_nr, int rem) int git_checkattr(const char *path, int num, struct git_attr_check *check) { struct attr_stack *stk; - const char *cp; - int dirlen, pathlen, i, rem; + int pathlen, i, rem; bootstrap_attr_stack(); for (i = 0; i < attr_nr; i++) check_all_attr[i].value = ATTR__UNKNOWN; pathlen = strlen(path); - cp = strrchr(path, '/'); - if (!cp) - dirlen = 0; - else - dirlen = cp - path; - prepare_attr_stack(path, dirlen); + prepare_attr_stack(path); rem = attr_nr; for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) rem = fill(path, pathlen, stk, rem); From 2d72174492b926dffd15d5fd8f4239060fb12247 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:20 +0200 Subject: [PATCH 10/29] Extract a function collect_all_attrs() Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/attr.c b/attr.c index 7f0f390d52..bc589f0b78 100644 --- a/attr.c +++ b/attr.c @@ -713,20 +713,31 @@ static int macroexpand_one(int attr_nr, int rem) return rem; } -int git_checkattr(const char *path, int num, struct git_attr_check *check) +/* + * Collect all attributes for path into the array pointed to by + * check_all_attr. + */ +static void collect_all_attrs(const char *path) { struct attr_stack *stk; - int pathlen, i, rem; + int i, pathlen, rem; bootstrap_attr_stack(); + prepare_attr_stack(path); for (i = 0; i < attr_nr; i++) check_all_attr[i].value = ATTR__UNKNOWN; pathlen = strlen(path); - prepare_attr_stack(path); rem = attr_nr; for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) rem = fill(path, pathlen, stk, rem); +} + +int git_checkattr(const char *path, int num, struct git_attr_check *check) +{ + int i; + + collect_all_attrs(path); for (i = 0; i < num; i++) { const char *value = check_all_attr[check[i].attr->attr_nr].value; From cd93bffb91630d8c695e1ac59239aa75cc2ebf92 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:21 +0200 Subject: [PATCH 11/29] Remove redundant call to bootstrap_attr_stack() prepare_attr_stack() does the same thing. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/attr.c b/attr.c index bc589f0b78..b8ce1586c8 100644 --- a/attr.c +++ b/attr.c @@ -722,7 +722,6 @@ static void collect_all_attrs(const char *path) struct attr_stack *stk; int i, pathlen, rem; - bootstrap_attr_stack(); prepare_attr_stack(path); for (i = 0; i < attr_nr; i++) check_all_attr[i].value = ATTR__UNKNOWN; From 7373eab48e284a808cde766831172d3447f9e320 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:22 +0200 Subject: [PATCH 12/29] Remove redundant check bootstrap_attr_stack() also checks whether attr_stack is already set. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- attr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/attr.c b/attr.c index b8ce1586c8..ab30c81b41 100644 --- a/attr.c +++ b/attr.c @@ -565,8 +565,7 @@ static void prepare_attr_stack(const char *path) * .gitattributes in deeper directories to shallower ones, * and finally use the built-in set as the default. */ - if (!attr_stack) - bootstrap_attr_stack(); + bootstrap_attr_stack(); /* * Pop the "info" one that is always at the top of the stack. From ee548df3005d976d4e6a78b3b4454fed812ea28c Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:23 +0200 Subject: [PATCH 13/29] Allow querying all attributes on a file Add a function, git_all_attrs(), that reports on all attributes that are set on a path. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/technical/api-gitattributes.txt | 44 +++++++++++++------ attr.c | 28 ++++++++++++ attr.h | 9 ++++ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt index ab3a84d2f7..16ccb1cdc3 100644 --- a/Documentation/technical/api-gitattributes.txt +++ b/Documentation/technical/api-gitattributes.txt @@ -22,19 +22,6 @@ Data Structure to `git_checkattr()` function, and receives the results. -Calling Sequence ----------------- - -* Prepare an array of `struct git_attr_check` to define the list of - attributes you would want to check. To populate this array, you would - need to define necessary attributes by calling `git_attr()` function. - -* Call git_checkattr() to check the attributes for the path. - -* Inspect `git_attr_check` structure to see how each of the attribute in - the array is defined for the path. - - Attribute Values ---------------- @@ -58,6 +45,19 @@ If none of the above returns true, `.value` member points at a string value of the attribute for the path. +Querying Specific Attributes +---------------------------- + +* Prepare an array of `struct git_attr_check` to define the list of + attributes you would want to check. To populate this array, you would + need to define necessary attributes by calling `git_attr()` function. + +* Call `git_checkattr()` to check the attributes for the path. + +* Inspect `git_attr_check` structure to see how each of the attribute in + the array is defined for the path. + + Example ------- @@ -109,4 +109,20 @@ static void setup_check(void) } ------------ -(JC) + +Querying All Attributes +----------------------- + +To get the values of all attributes associated with a file: + +* Call `git_all_attrs()`, which returns an array of `git_attr_check` + structures. + +* Iterate over the `git_attr_check` array to examine the attribute + names and values. The name of the attribute described by a + `git_attr_check` object can be retrieved via + `git_attr_name(check[i].attr)`. (Please note that no items will be + returned for unset attributes, so `ATTR_UNSET()` will return false + for all returned `git_array_check` objects.) + +* Free the `git_array_check` array. diff --git a/attr.c b/attr.c index ab30c81b41..658112eeb6 100644 --- a/attr.c +++ b/attr.c @@ -747,6 +747,34 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) return 0; } +int git_all_attrs(const char *path, int *num, struct git_attr_check **check) +{ + int i, count, j; + + collect_all_attrs(path); + + /* Count the number of attributes that are set. */ + count = 0; + for (i = 0; i < attr_nr; i++) { + const char *value = check_all_attr[i].value; + if (value != ATTR__UNSET && value != ATTR__UNKNOWN) + ++count; + } + *num = count; + *check = xmalloc(sizeof(**check) * count); + j = 0; + for (i = 0; i < attr_nr; i++) { + const char *value = check_all_attr[i].value; + if (value != ATTR__UNSET && value != ATTR__UNKNOWN) { + (*check)[j].attr = check_all_attr[i].attr; + (*check)[j].value = value; + ++j; + } + } + + return 0; +} + void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate) { enum git_attr_direction old = direction; diff --git a/attr.h b/attr.h index d4f875a3d5..9e228933a5 100644 --- a/attr.h +++ b/attr.h @@ -38,6 +38,15 @@ char *git_attr_name(struct git_attr *); int git_checkattr(const char *path, int, struct git_attr_check *); +/* + * Retrieve all attributes that apply to the specified path. *num + * will be set the the number of attributes on the path; **check will + * be set to point at a newly-allocated array of git_attr_check + * objects describing the attributes and their values. *check must be + * free()ed by the caller. + */ +int git_all_attrs(const char *path, int *num, struct git_attr_check **check); + enum git_attr_direction { GIT_ATTR_CHECKIN, GIT_ATTR_CHECKOUT, From 46f96a6d8ed70ecac7c1532d7f9775320409917b Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:24 +0200 Subject: [PATCH 14/29] git-check-attr: Extract a function output_attr() Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 5f04126d4d..384c5a6171 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -20,12 +20,10 @@ static const struct option check_attr_options[] = { OPT_END() }; -static void check_attr(int cnt, struct git_attr_check *check, +static void output_attr(int cnt, struct git_attr_check *check, const char *file) { int j; - if (git_checkattr(file, cnt, check)) - die("git_checkattr died"); for (j = 0; j < cnt; j++) { const char *value = check[j].value; @@ -41,6 +39,14 @@ static void check_attr(int cnt, struct git_attr_check *check, } } +static void check_attr(int cnt, struct git_attr_check *check, + const char *file) +{ + if (git_checkattr(file, cnt, check)) + die("git_checkattr died"); + output_attr(cnt, check, file); +} + static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) { struct strbuf buf, nbuf; From d6541bb1ac753a3cc0b92021cf82b07cf459cb28 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:25 +0200 Subject: [PATCH 15/29] git-check-attr: Introduce a new variable Avoid reusing variable "doubledash" to mean something other than the expected "position of a double-dash, if any". Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 384c5a6171..c5270786d4 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -71,7 +71,7 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) int cmd_check_attr(int argc, const char **argv, const char *prefix) { struct git_attr_check *check; - int cnt, i, doubledash; + int cnt, i, doubledash, filei; const char *errstr = NULL; argc = parse_options(argc, argv, prefix, check_attr_options, @@ -92,14 +92,15 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) /* If there is no double dash, we handle only one attribute */ if (doubledash < 0) { cnt = 1; - doubledash = 0; - } else + filei = 1; + } else { cnt = doubledash; - doubledash++; + filei = doubledash + 1; + } if (cnt <= 0) errstr = "No attribute specified"; - else if (stdin_paths && doubledash < argc) + else if (stdin_paths && filei < argc) errstr = "Can't specify files with --stdin"; if (errstr) { error("%s", errstr); @@ -120,7 +121,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) if (stdin_paths) check_attr_stdin_paths(cnt, check); else { - for (i = doubledash; i < argc; i++) + for (i = filei; i < argc; i++) check_attr(cnt, check, argv[i]); maybe_flush_or_die(stdout, "attribute to stdout"); } From 9e37a7e126c98513789ce60c4bec67d7940dbf4b Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:26 +0200 Subject: [PATCH 16/29] git-check-attr: Extract a function error_with_usage() Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index c5270786d4..d0042227c2 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -68,6 +68,12 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) strbuf_release(&nbuf); } +static NORETURN void error_with_usage(const char *msg) +{ + error("%s", msg); + usage_with_options(check_attr_usage, check_attr_options); +} + int cmd_check_attr(int argc, const char **argv, const char *prefix) { struct git_attr_check *check; @@ -103,8 +109,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) else if (stdin_paths && filei < argc) errstr = "Can't specify files with --stdin"; if (errstr) { - error("%s", errstr); - usage_with_options(check_attr_usage, check_attr_options); + error_with_usage(errstr); } check = xcalloc(cnt, sizeof(*check)); From 27937447efdf2b50e6294e94bde22f07c526b2de Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:27 +0200 Subject: [PATCH 17/29] git-check-attr: Handle each error separately This will make the code easier to refactor. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index d0042227c2..de3fef7348 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -78,7 +78,6 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) { struct git_attr_check *check; int cnt, i, doubledash, filei; - const char *errstr = NULL; argc = parse_options(argc, argv, prefix, check_attr_options, check_attr_usage, PARSE_OPT_KEEP_DASHDASH); @@ -105,12 +104,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) } if (cnt <= 0) - errstr = "No attribute specified"; - else if (stdin_paths && filei < argc) - errstr = "Can't specify files with --stdin"; - if (errstr) { - error_with_usage(errstr); - } + error_with_usage("No attribute specified"); + + if (stdin_paths && filei < argc) + error_with_usage("Can't specify files with --stdin"); check = xcalloc(cnt, sizeof(*check)); for (i = 0; i < cnt; i++) { From 72541040c3ed00084344de5bf75cbc5a514504bb Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:28 +0200 Subject: [PATCH 18/29] git-check-attr: Process command-line args more systematically Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index de3fef7348..e9b827ffb5 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -81,8 +81,6 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, check_attr_options, check_attr_usage, PARSE_OPT_KEEP_DASHDASH); - if (!argc) - usage_with_options(check_attr_usage, check_attr_options); if (read_cache() < 0) { die("invalid cache"); @@ -94,8 +92,17 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) doubledash = i; } - /* If there is no double dash, we handle only one attribute */ - if (doubledash < 0) { + /* Check attribute argument(s): */ + if (doubledash == 0) { + error_with_usage("No attribute specified"); + } else if (doubledash < 0) { + /* + * There is no double dash; treat the first + * argument as an attribute. + */ + if (!argc) + error_with_usage("No attribute specified"); + cnt = 1; filei = 1; } else { @@ -103,9 +110,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) filei = doubledash + 1; } - if (cnt <= 0) - error_with_usage("No attribute specified"); - + /* Check file argument(s): */ if (stdin_paths && filei < argc) error_with_usage("Can't specify files with --stdin"); From fdf6be8259fc59fc251b325f66e86df0fe905e79 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:29 +0200 Subject: [PATCH 19/29] git-check-attr: Error out if no pathnames are specified If no pathnames are passed as command-line arguments and the --stdin option is not specified, fail with the error message "No file specified". Add tests of this behavior. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 9 +++++++-- t/t0003-attributes.sh | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index e9b827ffb5..6cf6421399 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -111,8 +111,13 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) } /* Check file argument(s): */ - if (stdin_paths && filei < argc) - error_with_usage("Can't specify files with --stdin"); + if (stdin_paths) { + if (filei < argc) + error_with_usage("Can't specify files with --stdin"); + } else { + if (filei >= argc) + error_with_usage("No file specified"); + } check = xcalloc(cnt, sizeof(*check)); for (i = 0; i < cnt; i++) { diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index f1debeb7ad..22540051d8 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -46,6 +46,8 @@ test_expect_success 'command line checks' ' test_must_fail git check-attr && test_must_fail git check-attr -- && + test_must_fail git check-attr test && + test_must_fail git check-attr test -- && test_must_fail git check-attr -- f && echo "f" | test_must_fail git check-attr --stdin && echo "f" | test_must_fail git check-attr --stdin -- f && From 4ca0f188f6ece3098b60b6ba732e1e8551466f60 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:30 +0200 Subject: [PATCH 20/29] git-check-attr: Add an --all option to show all attributes Add new usage patterns git check-attr [-a | --all] [--] pathname... git check-attr --stdin [-a | --all] < which display all attributes associated with the specified file(s). Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/git-check-attr.txt | 16 ++++++++-- builtin/check-attr.c | 52 ++++++++++++++++++++++---------- t/t0003-attributes.sh | 24 +++++++++++++++ 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt index 30eca6cee6..798e5d5b4f 100644 --- a/Documentation/git-check-attr.txt +++ b/Documentation/git-check-attr.txt @@ -9,8 +9,8 @@ git-check-attr - Display gitattributes information SYNOPSIS -------- [verse] -'git check-attr' attr... [--] pathname... -'git check-attr' --stdin [-z] attr... < +'git check-attr' [-a | --all | attr...] [--] pathname... +'git check-attr' --stdin [-z] [-a | --all | attr...] < DESCRIPTION ----------- @@ -19,6 +19,11 @@ For every pathname, this command will list if each attribute is 'unspecified', OPTIONS ------- +-a, --all:: + List all attributes that are associated with the specified + paths. If this option is used, then 'unspecified' attributes + will not be included in the output. + --stdin:: Read file names from stdin instead of from the command-line. @@ -69,6 +74,13 @@ org/example/MyClass.java: diff: java org/example/MyClass.java: myAttr: set --------------- +* Listing all attributes for a file: +--------------- +$ git check-attr --all -- org/example/MyClass.java +org/example/MyClass.java: diff: java +org/example/MyClass.java: myAttr: set +--------------- + * Listing an attribute for multiple files: --------------- $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 6cf6421399..b0d2ebc3dc 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -4,16 +4,18 @@ #include "quote.h" #include "parse-options.h" +static int all_attrs; static int stdin_paths; static const char * const check_attr_usage[] = { -"git check-attr attr... [--] pathname...", -"git check-attr --stdin attr... < ", +"git check-attr [-a | --all | attr...] [--] pathname...", +"git check-attr --stdin [-a | --all | attr...] < ", NULL }; static int null_term_line; static const struct option check_attr_options[] = { + OPT_BOOLEAN('a', "all", &all_attrs, "report all attributes set on file"), OPT_BOOLEAN(0 , "stdin", &stdin_paths, "read file names from stdin"), OPT_BOOLEAN('z', NULL, &null_term_line, "input paths are terminated by a null character"), @@ -42,9 +44,16 @@ static void output_attr(int cnt, struct git_attr_check *check, static void check_attr(int cnt, struct git_attr_check *check, const char *file) { - if (git_checkattr(file, cnt, check)) - die("git_checkattr died"); - output_attr(cnt, check, file); + if (check != NULL) { + if (git_checkattr(file, cnt, check)) + die("git_checkattr died"); + output_attr(cnt, check, file); + } else { + if (git_all_attrs(file, &cnt, &check)) + die("git_all_attrs died"); + output_attr(cnt, check, file); + free(check); + } } static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) @@ -92,8 +101,14 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) doubledash = i; } - /* Check attribute argument(s): */ - if (doubledash == 0) { + /* Process --all and/or attribute arguments: */ + if (all_attrs) { + if (doubledash >= 1) + error_with_usage("Attributes and --all both specified"); + + cnt = 0; + filei = doubledash + 1; + } else if (doubledash == 0) { error_with_usage("No attribute specified"); } else if (doubledash < 0) { /* @@ -119,15 +134,20 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) error_with_usage("No file specified"); } - check = xcalloc(cnt, sizeof(*check)); - for (i = 0; i < cnt; i++) { - const char *name; - struct git_attr *a; - name = argv[i]; - a = git_attr(name); - if (!a) - return error("%s: not a valid attribute name", name); - check[i].attr = a; + if (all_attrs) { + check = NULL; + } else { + check = xcalloc(cnt, sizeof(*check)); + for (i = 0; i < cnt; i++) { + const char *name; + struct git_attr *a; + name = argv[i]; + a = git_attr(name); + if (!a) + return error("%s: not a valid attribute name", + name); + check[i].attr = a; + } } if (stdin_paths) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 22540051d8..8892ba3bb2 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -107,6 +107,30 @@ EOF test_cmp expect actual ' +test_expect_success 'attribute test: --all option' ' + + cat < all && +f: test: f +a/f: test: f +a/c/f: test: f +a/g: test: a/g +a/b/g: test: a/b/g +b/g: test: unspecified +a/b/h: test: a/b/h +a/b/d/g: test: a/b/d/* +onoff: test: unset +offon: test: set +no: notest: set +a/b/d/no: test: a/b/d/* +a/b/d/no: notest: set +a/b/d/yes: notest: set +EOF + + grep -v unspecified < all | sort > expect && + sed -e "s/:.*//" < all | uniq | git check-attr --stdin --all | sort > actual && + test_cmp expect actual +' + test_expect_success 'root subdir attribute test' ' attr_check a/i a/i && From c9d8f0ac3b9029d825c7d1c049953aacbc489e1c Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:31 +0200 Subject: [PATCH 21/29] git-check-attr: Drive two tests using the same raw data Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 59 +++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 8892ba3bb2..a49f8a9813 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -38,7 +38,25 @@ test_expect_success 'setup' ' ) >a/b/.gitattributes && ( echo "global test=global" - ) >"$HOME"/global-gitattributes + ) >"$HOME"/global-gitattributes && + cat <expect-all +f: test: f +a/f: test: f +a/c/f: test: f +a/g: test: a/g +a/b/g: test: a/b/g +b/g: test: unspecified +a/b/h: test: a/b/h +a/b/d/g: test: a/b/d/* +onoff: test: unset +offon: test: set +no: notest: set +no: test: unspecified +a/b/d/no: notest: set +a/b/d/no: test: a/b/d/* +a/b/d/yes: notest: set +a/b/d/yes: test: unspecified +EOF ' @@ -87,47 +105,16 @@ test_expect_success 'core.attributesfile' ' test_expect_success 'attribute test: read paths from stdin' ' - cat < expect && -f: test: f -a/f: test: f -a/c/f: test: f -a/g: test: a/g -a/b/g: test: a/b/g -b/g: test: unspecified -a/b/h: test: a/b/h -a/b/d/g: test: a/b/d/* -onoff: test: unset -offon: test: set -no: test: unspecified -a/b/d/no: test: a/b/d/* -a/b/d/yes: test: unspecified -EOF - + grep -v notest < expect-all > expect && sed -e "s/:.*//" < expect | git check-attr --stdin test > actual && test_cmp expect actual ' test_expect_success 'attribute test: --all option' ' - cat < all && -f: test: f -a/f: test: f -a/c/f: test: f -a/g: test: a/g -a/b/g: test: a/b/g -b/g: test: unspecified -a/b/h: test: a/b/h -a/b/d/g: test: a/b/d/* -onoff: test: unset -offon: test: set -no: notest: set -a/b/d/no: test: a/b/d/* -a/b/d/no: notest: set -a/b/d/yes: notest: set -EOF - - grep -v unspecified < all | sort > expect && - sed -e "s/:.*//" < all | uniq | git check-attr --stdin --all | sort > actual && + grep -v unspecified < expect-all | sort > expect && + sed -e "s/:.*//" < expect-all | uniq | + git check-attr --stdin --all | sort > actual && test_cmp expect actual ' From ca64d061e0ddf7fa1496a15c75eb5e730c4360e0 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:32 +0200 Subject: [PATCH 22/29] git-check-attr: Fix command-line handling to match docs According to the git-check-attr synopsis, if the '--stdin' option is used then no pathnames are expected on the command line. Change the behavior to match this description; namely, if '--stdin' is used but not '--', then treat all command-line arguments as attribute names. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/git-check-attr.txt | 7 +++++-- builtin/check-attr.c | 15 +++++++++------ t/t0003-attributes.sh | 1 - 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt index 798e5d5b4f..1f7312a189 100644 --- a/Documentation/git-check-attr.txt +++ b/Documentation/git-check-attr.txt @@ -33,8 +33,11 @@ OPTIONS \--:: Interpret all preceding arguments as attributes and all following - arguments as path names. If not supplied, only the first argument will - be treated as an attribute. + arguments as path names. + +If none of `--stdin`, `--all`, or `--` is used, the first argument +will be treated as an attribute and the rest of the arguments as +pathnames. OUTPUT ------ diff --git a/builtin/check-attr.c b/builtin/check-attr.c index b0d2ebc3dc..f20772ad6e 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -111,15 +111,18 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) } else if (doubledash == 0) { error_with_usage("No attribute specified"); } else if (doubledash < 0) { - /* - * There is no double dash; treat the first - * argument as an attribute. - */ if (!argc) error_with_usage("No attribute specified"); - cnt = 1; - filei = 1; + if (stdin_paths) { + /* Treat all arguments as attribute names. */ + cnt = argc; + filei = argc; + } else { + /* Treat exactly one argument as an attribute name. */ + cnt = 1; + filei = 1; + } } else { cnt = doubledash; filei = doubledash + 1; diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index a49f8a9813..5acb2d5bbd 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -70,7 +70,6 @@ test_expect_success 'command line checks' ' echo "f" | test_must_fail git check-attr --stdin && echo "f" | test_must_fail git check-attr --stdin -- f && echo "f" | test_must_fail git check-attr --stdin test -- f && - echo "f" | test_must_fail git check-attr --stdin test f && test_must_fail git check-attr "" -- f ' From d932f4eb9fc88e93040635d291f6c195ea2e4ee3 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:36:33 +0200 Subject: [PATCH 23/29] Rename git_checkattr() to git_check_attr() Suggested by: Junio Hamano Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- Documentation/technical/api-gitattributes.txt | 8 ++++---- archive.c | 2 +- attr.c | 2 +- attr.h | 4 ++-- builtin/check-attr.c | 4 ++-- builtin/pack-objects.c | 2 +- convert.c | 2 +- ll-merge.c | 4 ++-- userdiff.c | 2 +- ws.c | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Documentation/technical/api-gitattributes.txt b/Documentation/technical/api-gitattributes.txt index 16ccb1cdc3..ce363b6305 100644 --- a/Documentation/technical/api-gitattributes.txt +++ b/Documentation/technical/api-gitattributes.txt @@ -19,7 +19,7 @@ Data Structure `struct git_attr_check`:: This structure represents a set of attributes to check in a call - to `git_checkattr()` function, and receives the results. + to `git_check_attr()` function, and receives the results. Attribute Values @@ -52,7 +52,7 @@ Querying Specific Attributes attributes you would want to check. To populate this array, you would need to define necessary attributes by calling `git_attr()` function. -* Call `git_checkattr()` to check the attributes for the path. +* Call `git_check_attr()` to check the attributes for the path. * Inspect `git_attr_check` structure to see how each of the attribute in the array is defined for the path. @@ -78,13 +78,13 @@ static void setup_check(void) } ------------ -. Call `git_checkattr()` with the prepared array of `struct git_attr_check`: +. Call `git_check_attr()` with the prepared array of `struct git_attr_check`: ------------ const char *path; setup_check(); - git_checkattr(path, ARRAY_SIZE(check), check); + git_check_attr(path, ARRAY_SIZE(check), check); ------------ . Act on `.value` member of the result, left in `check[]`: diff --git a/archive.c b/archive.c index 2a7a28e3ed..3fd7f475f1 100644 --- a/archive.c +++ b/archive.c @@ -123,7 +123,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base, path_without_prefix = path.buf + args->baselen; setup_archive_check(check); - if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) { + if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) { if (ATTR_TRUE(check[0].value)) return 0; convert = ATTR_TRUE(check[1].value); diff --git a/attr.c b/attr.c index 658112eeb6..da29c8eb45 100644 --- a/attr.c +++ b/attr.c @@ -731,7 +731,7 @@ static void collect_all_attrs(const char *path) rem = fill(path, pathlen, stk, rem); } -int git_checkattr(const char *path, int num, struct git_attr_check *check) +int git_check_attr(const char *path, int num, struct git_attr_check *check) { int i; diff --git a/attr.h b/attr.h index 9e228933a5..eb8ca0d7c0 100644 --- a/attr.h +++ b/attr.h @@ -20,7 +20,7 @@ extern const char git_attr__false[]; #define ATTR_UNSET(v) ((v) == NULL) /* - * Send one or more git_attr_check to git_checkattr(), and + * Send one or more git_attr_check to git_check_attr(), and * each 'value' member tells what its value is. * Unset one is returned as NULL. */ @@ -36,7 +36,7 @@ struct git_attr_check { */ char *git_attr_name(struct git_attr *); -int git_checkattr(const char *path, int, struct git_attr_check *); +int git_check_attr(const char *path, int, struct git_attr_check *); /* * Retrieve all attributes that apply to the specified path. *num diff --git a/builtin/check-attr.c b/builtin/check-attr.c index f20772ad6e..6b163687b6 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -45,8 +45,8 @@ static void check_attr(int cnt, struct git_attr_check *check, const char *file) { if (check != NULL) { - if (git_checkattr(file, cnt, check)) - die("git_checkattr died"); + if (git_check_attr(file, cnt, check)) + die("git_check_attr died"); output_attr(cnt, check, file); } else { if (git_all_attrs(file, &cnt, &check)) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 84e6dafb12..ac8bed8aa1 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -634,7 +634,7 @@ static int no_try_delta(const char *path) struct git_attr_check check[1]; setup_delta_attr_check(check); - if (git_checkattr(path, ARRAY_SIZE(check), check)) + if (git_check_attr(path, ARRAY_SIZE(check), check)) return 0; if (ATTR_FALSE(check->value)) return 1; diff --git a/convert.c b/convert.c index 85939c29be..416bf83c75 100644 --- a/convert.c +++ b/convert.c @@ -727,7 +727,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path) git_config(read_convert_config, NULL); } - if (!git_checkattr(path, NUM_CONV_ATTRS, ccheck)) { + if (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) { ca->crlf_action = git_path_check_crlf(path, ccheck + 4); if (ca->crlf_action == CRLF_GUESS) ca->crlf_action = git_path_check_crlf(path, ccheck + 0); diff --git a/ll-merge.c b/ll-merge.c index 6ce512efc4..da59738c9b 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -330,7 +330,7 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2] check[0].attr = git_attr("merge"); check[1].attr = git_attr("conflict-marker-size"); } - return git_checkattr(path, 2, check); + return git_check_attr(path, 2, check); } static void normalize_file(mmfile_t *mm, const char *path) @@ -387,7 +387,7 @@ int ll_merge_marker_size(const char *path) if (!check.attr) check.attr = git_attr("conflict-marker-size"); - if (!git_checkattr(path, 1, &check) && check.value) { + if (!git_check_attr(path, 1, &check) && check.value) { marker_size = atoi(check.value); if (marker_size <= 0) marker_size = DEFAULT_CONFLICT_MARKER_SIZE; diff --git a/userdiff.c b/userdiff.c index 01d3a8b81e..bf553ad91b 100644 --- a/userdiff.c +++ b/userdiff.c @@ -270,7 +270,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path) if (!path) return NULL; - if (git_checkattr(path, 1, &check)) + if (git_check_attr(path, 1, &check)) return NULL; if (ATTR_TRUE(check.value)) diff --git a/ws.c b/ws.c index 9fb9b14760..b498d7599d 100644 --- a/ws.c +++ b/ws.c @@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname) struct git_attr_check attr_whitespace_rule; setup_whitespace_attr_check(&attr_whitespace_rule); - if (!git_checkattr(pathname, 1, &attr_whitespace_rule)) { + if (!git_check_attr(pathname, 1, &attr_whitespace_rule)) { const char *value; value = attr_whitespace_rule.value; From fa92f3233c65251c3311f0834526ce96a1963554 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:43 +0200 Subject: [PATCH 24/29] git-check-attr: test that no output is written to stderr Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 5acb2d5bbd..4f2fbc0781 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -9,9 +9,10 @@ attr_check () { path="$1" expect="$2" - git check-attr test -- "$path" >actual && + git check-attr test -- "$path" >actual 2>err && echo "$path: test: $2" >expect && - test_cmp expect actual + test_cmp expect actual && + test_line_count = 0 err } From d4d4f8df14c3c19d445a8a79dca56bd33812ee04 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:44 +0200 Subject: [PATCH 25/29] git-check-attr: Demonstrate problems with unnormalized paths Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 4f2fbc0781..43957eae68 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -93,6 +93,15 @@ test_expect_success 'attribute test' ' ' +test_expect_failure 'unnormalized paths' ' + + attr_check ./f f && + attr_check ./a/g a/g && + attr_check a/./g a/g && + attr_check a/c/../b/g a/b/g + +' + test_expect_success 'core.attributesfile' ' attr_check global unspecified && git config core.attributesfile "$HOME/global-gitattributes" && From 0216af8356ef562147251c40fef72be25b8b9b07 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:45 +0200 Subject: [PATCH 26/29] git-check-attr: Demonstrate problems with relative paths Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- t/t0003-attributes.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 43957eae68..f6cf77d125 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -19,7 +19,7 @@ attr_check () { test_expect_success 'setup' ' - mkdir -p a/b/d a/c && + mkdir -p a/b/d a/c b && ( echo "[attr]notest !test" echo "f test=f" @@ -102,6 +102,19 @@ test_expect_failure 'unnormalized paths' ' ' +test_expect_failure 'relative paths' ' + + (cd a && attr_check ../f f) && + (cd a && attr_check f f) && + (cd a && attr_check i a/i) && + (cd a && attr_check g a/g) && + (cd a && attr_check b/g a/b/g) && + (cd b && attr_check ../a/f f) && + (cd b && attr_check ../a/g a/g) && + (cd b && attr_check ../a/b/g a/b/g) + +' + test_expect_success 'core.attributesfile' ' attr_check global unspecified && git config core.attributesfile "$HOME/global-gitattributes" && From f5114a40c0d0276ce6ff215a3dc51eb19da5b420 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:46 +0200 Subject: [PATCH 27/29] git-check-attr: Normalize paths Normalize the path arguments (relative to the working tree root, if applicable) before looking up their attributes. This requires passing the prefix down the call chain. This fixes two test cases for different reasons: * "unnormalized paths" is fixed because the .gitattribute-file-seeking code is not confused into reading the top-level file twice. * "relative paths" is fixed because the canonical pathnames are passed to get_check_attr() or get_all_attrs(), allowing them to match the pathname patterns as expected. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- builtin/check-attr.c | 20 ++++++++++++-------- t/t0003-attributes.sh | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 6b163687b6..708988a0e1 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -41,22 +41,26 @@ static void output_attr(int cnt, struct git_attr_check *check, } } -static void check_attr(int cnt, struct git_attr_check *check, - const char *file) +static void check_attr(const char *prefix, int cnt, + struct git_attr_check *check, const char *file) { + char *full_path = + prefix_path(prefix, prefix ? strlen(prefix) : 0, file); if (check != NULL) { - if (git_check_attr(file, cnt, check)) + if (git_check_attr(full_path, cnt, check)) die("git_check_attr died"); output_attr(cnt, check, file); } else { - if (git_all_attrs(file, &cnt, &check)) + if (git_all_attrs(full_path, &cnt, &check)) die("git_all_attrs died"); output_attr(cnt, check, file); free(check); } + free(full_path); } -static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) +static void check_attr_stdin_paths(const char *prefix, int cnt, + struct git_attr_check *check) { struct strbuf buf, nbuf; int line_termination = null_term_line ? 0 : '\n'; @@ -70,7 +74,7 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check) die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } - check_attr(cnt, check, buf.buf); + check_attr(prefix, cnt, check, buf.buf); maybe_flush_or_die(stdout, "attribute to stdout"); } strbuf_release(&buf); @@ -154,10 +158,10 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) } if (stdin_paths) - check_attr_stdin_paths(cnt, check); + check_attr_stdin_paths(prefix, cnt, check); else { for (i = filei; i < argc; i++) - check_attr(cnt, check, argv[i]); + check_attr(prefix, cnt, check, argv[i]); maybe_flush_or_die(stdout, "attribute to stdout"); } return 0; diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index f6cf77d125..ae2f1da28f 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -93,7 +93,7 @@ test_expect_success 'attribute test' ' ' -test_expect_failure 'unnormalized paths' ' +test_expect_success 'unnormalized paths' ' attr_check ./f f && attr_check ./a/g a/g && @@ -102,7 +102,7 @@ test_expect_failure 'unnormalized paths' ' ' -test_expect_failure 'relative paths' ' +test_expect_success 'relative paths' ' (cd a && attr_check ../f f) && (cd a && attr_check f f) && From 87a246e1b562544c25af66f4712cd81bc64f2d44 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:47 +0200 Subject: [PATCH 28/29] test-path-utils: Add subcommand "absolute_path" Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- test-path-utils.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test-path-utils.c b/test-path-utils.c index e7671593df..a410e3026f 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -20,6 +20,15 @@ int main(int argc, char **argv) return 0; } + if (argc >= 2 && !strcmp(argv[1], "absolute_path")) { + while (argc > 2) { + puts(absolute_path(argv[2])); + argc--; + argv++; + } + return 0; + } + if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) { int len = longest_ancestor_length(argv[2], argv[3]); printf("%d\n", len); From 9e8137238d1b7f558dd61c8737883e73c8368e4b Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Thu, 4 Aug 2011 06:47:48 +0200 Subject: [PATCH 29/29] test-path-utils: Add subcommand "prefix_path" Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- test-path-utils.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test-path-utils.c b/test-path-utils.c index a410e3026f..3bc20e91da 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -35,6 +35,19 @@ int main(int argc, char **argv) return 0; } + if (argc >= 4 && !strcmp(argv[1], "prefix_path")) { + char *prefix = argv[2]; + int prefix_len = strlen(prefix); + int nongit_ok; + setup_git_directory_gently(&nongit_ok); + while (argc > 3) { + puts(prefix_path(prefix, prefix_len, argv[3])); + argc--; + argv++; + } + return 0; + } + if (argc == 4 && !strcmp(argv[1], "strip_path_suffix")) { char *prefix = strip_path_suffix(argv[2], argv[3]); printf("%s\n", prefix ? prefix : "(null)");