diff --git a/attr.c b/attr.c index 33cb4e4d113cbb..76b079f0f530e1 100644 --- a/attr.c +++ b/attr.c @@ -11,6 +11,7 @@ #include "cache.h" #include "exec_cmd.h" #include "attr.h" +#include "dir.h" const char git_attr__true[] = "(builtin)true"; const char git_attr__false[] = "\0(builtin)false"; @@ -20,8 +21,6 @@ static const char git_attr__unknown[] = "(builtin)unknown"; #define ATTR__UNSET NULL #define ATTR__UNKNOWN git_attr__unknown -static const char *attributes_file; - /* This is a randomly chosen prime. */ #define HASHSIZE 257 @@ -494,14 +493,6 @@ static int git_attr_system(void) return !git_env_bool("GIT_ATTR_NOSYSTEM", 0); } -static int git_attr_config(const char *var, const char *value, void *dummy) -{ - if (!strcmp(var, "core.attributesfile")) - return git_config_pathname(&attributes_file, var, value); - - return 0; -} - static void bootstrap_attr_stack(void) { if (!attr_stack) { @@ -521,9 +512,8 @@ static void bootstrap_attr_stack(void) } } - git_config(git_attr_config, NULL); - if (attributes_file) { - elem = read_attr_from_file(attributes_file, 1); + if (git_attributes_file) { + elem = read_attr_from_file(git_attributes_file, 1); if (elem) { elem->origin = NULL; elem->prev = attr_stack; @@ -533,7 +523,7 @@ static void bootstrap_attr_stack(void) if (!is_bare_repository() || direction == GIT_ATTR_INDEX) { elem = read_attr(GITATTRIBUTES_FILE, 1); - elem->origin = strdup(""); + elem->origin = xstrdup(""); elem->prev = attr_stack; attr_stack = elem; debug_push(elem); @@ -552,7 +542,6 @@ static void prepare_attr_stack(const char *path) { struct attr_stack *elem, *info; int dirlen, len; - struct strbuf pathbuf; const char *cp; cp = strrchr(path, '/'); @@ -561,8 +550,6 @@ static void prepare_attr_stack(const char *path) else dirlen = cp - path; - strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE)); - /* * At the bottom of the attribute stack is the built-in * set of attribute definitions, followed by the contents @@ -607,27 +594,28 @@ static void prepare_attr_stack(const char *path) * Read from parent directories and push them down */ if (!is_bare_repository() || direction == GIT_ATTR_INDEX) { - while (1) { - char *cp; + struct strbuf pathbuf = STRBUF_INIT; + while (1) { len = strlen(attr_stack->origin); if (dirlen <= len) break; - strbuf_reset(&pathbuf); - strbuf_add(&pathbuf, path, dirlen); + cp = memchr(path + len + 1, '/', dirlen - len - 1); + if (!cp) + cp = path + dirlen; + strbuf_add(&pathbuf, path, cp - path); strbuf_addch(&pathbuf, '/'); - cp = strchr(pathbuf.buf + len + 1, '/'); - strcpy(cp + 1, GITATTRIBUTES_FILE); + strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE); elem = read_attr(pathbuf.buf, 0); - *cp = '\0'; - elem->origin = strdup(pathbuf.buf); + strbuf_setlen(&pathbuf, cp - path); + elem->origin = strbuf_detach(&pathbuf, NULL); elem->prev = attr_stack; attr_stack = elem; debug_push(elem); } - } - strbuf_release(&pathbuf); + strbuf_release(&pathbuf); + } /* * Finally push the "info" one at the top of the stack. @@ -644,7 +632,7 @@ static int path_matches(const char *pathname, int pathlen, /* match basename */ const char *basename = strrchr(pathname, '/'); basename = basename ? basename + 1 : pathname; - return (fnmatch(pattern, basename, 0) == 0); + return (fnmatch_icase(pattern, basename, 0) == 0); } /* * match with FNM_PATHNAME; the pattern has base implicitly @@ -658,7 +646,7 @@ static int path_matches(const char *pathname, int pathlen, return 0; if (baselen != 0) baselen++; - return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0; + return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0; } static int macroexpand_one(int attr_nr, int rem); diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 708988a0e1a318..abb11650fdd936 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -92,6 +92,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) struct git_attr_check *check; int cnt, i, doubledash, filei; + git_config(git_default_config, NULL); + argc = parse_options(argc, argv, prefix, check_attr_options, check_attr_usage, PARSE_OPT_KEEP_DASHDASH); diff --git a/builtin/mv.c b/builtin/mv.c index 40f33ca4d0e6d0..5efe6c5760c43d 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -29,7 +29,11 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec, to_copy--; if (to_copy != length || base_name) { char *it = xmemdupz(result[i], to_copy); - result[i] = base_name ? strdup(basename(it)) : it; + if (base_name) { + result[i] = xstrdup(basename(it)); + free(it); + } else + result[i] = it; } } return get_pathspec(prefix, result); diff --git a/cache.h b/cache.h index 607c2ea612889c..8d95fb25a2505a 100644 --- a/cache.h +++ b/cache.h @@ -589,6 +589,7 @@ extern int warn_ambiguous_refs; extern int shared_repository; extern const char *apply_default_whitespace; extern const char *apply_default_ignorewhitespace; +extern const char *git_attributes_file; extern int zlib_compression_level; extern int core_compression_level; extern int core_compression_seen; diff --git a/compat/mingw.c b/compat/mingw.c index 6ef0cc4f99becd..8947418ce78faa 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1183,7 +1183,7 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service, } ai->ai_addrlen = sizeof(struct sockaddr_in); if (hints && (hints->ai_flags & AI_CANONNAME)) - ai->ai_canonname = h ? strdup(h->h_name) : NULL; + ai->ai_canonname = h ? xstrdup(h->h_name) : NULL; else ai->ai_canonname = NULL; diff --git a/compat/qsort.c b/compat/qsort.c index d93dce2cf8fa33..9574d537bd38d3 100644 --- a/compat/qsort.c +++ b/compat/qsort.c @@ -55,7 +55,7 @@ void git_qsort(void *b, size_t n, size_t s, msort_with_tmp(b, n, s, cmp, buf); } else { /* It's somewhat large, so malloc it. */ - char *tmp = malloc(size); + char *tmp = xmalloc(size); msort_with_tmp(b, n, s, cmp, tmp); free(tmp); } diff --git a/config.c b/config.c index 4183f80262ea9f..d3bcaa023d1f23 100644 --- a/config.c +++ b/config.c @@ -491,6 +491,9 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.attributesfile")) + return git_config_pathname(&git_attributes_file, var, value); + if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; diff --git a/environment.c b/environment.c index e96edcfebc4174..d60b73f6a5a886 100644 --- a/environment.c +++ b/environment.c @@ -29,6 +29,7 @@ const char *git_log_output_encoding; int shared_repository = PERM_UMASK; const char *apply_default_whitespace; const char *apply_default_ignorewhitespace; +const char *git_attributes_file; int zlib_compression_level = Z_BEST_SPEED; int core_compression_level; int core_compression_seen; diff --git a/show-index.c b/show-index.c index 4c0ac138aff7b5..63f9da53237d42 100644 --- a/show-index.c +++ b/show-index.c @@ -48,7 +48,7 @@ int main(int argc, char **argv) unsigned char sha1[20]; uint32_t crc; uint32_t off; - } *entries = malloc(nr * sizeof(entries[0])); + } *entries = xmalloc(nr * sizeof(entries[0])); for (i = 0; i < nr; i++) if (fread(entries[i].sha1, 20, 1, stdin) != 1) die("unable to read sha1 %u/%u", i, nr); diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index ae2f1da28fa55b..6946c4b82f9291 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -9,7 +9,7 @@ attr_check () { path="$1" expect="$2" - git check-attr test -- "$path" >actual 2>err && + git $3 check-attr test -- "$path" >actual 2>err && echo "$path: test: $2" >expect && test_cmp expect actual && test_line_count = 0 err @@ -27,6 +27,7 @@ test_expect_success 'setup' ' echo "onoff test -test" echo "offon -test test" echo "no notest" + echo "A/e/F test=A/e/F" ) >.gitattributes && ( echo "g test=a/g" && @@ -93,6 +94,62 @@ test_expect_success 'attribute test' ' ' +test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' ' + + test_must_fail attr_check F f "-c core.ignorecase=0" && + test_must_fail attr_check a/F f "-c core.ignorecase=0" && + test_must_fail attr_check a/c/F f "-c core.ignorecase=0" && + test_must_fail attr_check a/G a/g "-c core.ignorecase=0" && + test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" && + test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" && + test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" && + test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" && + test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" && + test_must_fail attr_check oFfOn set "-c core.ignorecase=0" && + attr_check NO unspecified "-c core.ignorecase=0" && + test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" && + test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0" + +' + +test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' ' + + attr_check F f "-c core.ignorecase=1" && + attr_check a/F f "-c core.ignorecase=1" && + attr_check a/c/F f "-c core.ignorecase=1" && + attr_check a/G a/g "-c core.ignorecase=1" && + attr_check a/B/g a/b/g "-c core.ignorecase=1" && + attr_check a/b/G a/b/g "-c core.ignorecase=1" && + attr_check a/b/H a/b/h "-c core.ignorecase=1" && + attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" && + attr_check oNoFf unset "-c core.ignorecase=1" && + attr_check oFfOn set "-c core.ignorecase=1" && + attr_check NO unspecified "-c core.ignorecase=1" && + attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" && + attr_check a/b/d/YES unspecified "-c core.ignorecase=1" && + attr_check a/E/f "A/e/F" "-c core.ignorecase=1" + +' + +test_expect_success 'check whether FS is case-insensitive' ' + mkdir junk && + echo good >junk/CamelCase && + echo bad >junk/camelcase && + if test "$(cat junk/CamelCase)" != good + then + test_set_prereq CASE_INSENSITIVE_FS + fi +' + +test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' ' + test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" && + test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check A/b/h a/b/h "-c core.ignorecase=1" && + attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" && + attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1" +' + test_expect_success 'unnormalized paths' ' attr_check ./f f && diff --git a/transport-helper.c b/transport-helper.c index 4eab844d4abfa2..07131261fefeab 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -183,7 +183,7 @@ static struct child_process *get_helper(struct transport *transport) ALLOC_GROW(refspecs, refspec_nr + 1, refspec_alloc); - refspecs[refspec_nr++] = strdup(capname + strlen("refspec ")); + refspecs[refspec_nr++] = xstrdup(capname + strlen("refspec ")); } else if (!strcmp(capname, "connect")) { data->connect = 1; } else if (!prefixcmp(capname, "export-marks ")) { @@ -445,7 +445,7 @@ static int fetch_with_import(struct transport *transport, if (data->refspecs) private = apply_refspecs(data->refspecs, data->refspec_nr, posn->name); else - private = strdup(posn->name); + private = xstrdup(posn->name); read_ref(private, posn->old_sha1); free(private); }