Skip to content

Commit a4fdd79

Browse files
committed
Merge branch 'bc/attr-ignore-case' into maint
* bc/attr-ignore-case: attr.c: respect core.ignorecase when matching attribute patterns attr: read core.attributesfile from git_default_core_config builtin/mv.c: plug miniscule memory leak cleanup: use internal memory allocation wrapper functions everywhere attr.c: avoid inappropriate access to strbuf "buf" member Conflicts: remote.c
2 parents ffa4c36 + 6eba621 commit a4fdd79

File tree

11 files changed

+92
-36
lines changed

11 files changed

+92
-36
lines changed

attr.c

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "cache.h"
1212
#include "exec_cmd.h"
1313
#include "attr.h"
14+
#include "dir.h"
1415

1516
const char git_attr__true[] = "(builtin)true";
1617
const char git_attr__false[] = "\0(builtin)false";
@@ -20,8 +21,6 @@ static const char git_attr__unknown[] = "(builtin)unknown";
2021
#define ATTR__UNSET NULL
2122
#define ATTR__UNKNOWN git_attr__unknown
2223

23-
static const char *attributes_file;
24-
2524
/* This is a randomly chosen prime. */
2625
#define HASHSIZE 257
2726

@@ -494,14 +493,6 @@ static int git_attr_system(void)
494493
return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
495494
}
496495

497-
static int git_attr_config(const char *var, const char *value, void *dummy)
498-
{
499-
if (!strcmp(var, "core.attributesfile"))
500-
return git_config_pathname(&attributes_file, var, value);
501-
502-
return 0;
503-
}
504-
505496
static void bootstrap_attr_stack(void)
506497
{
507498
if (!attr_stack) {
@@ -521,9 +512,8 @@ static void bootstrap_attr_stack(void)
521512
}
522513
}
523514

524-
git_config(git_attr_config, NULL);
525-
if (attributes_file) {
526-
elem = read_attr_from_file(attributes_file, 1);
515+
if (git_attributes_file) {
516+
elem = read_attr_from_file(git_attributes_file, 1);
527517
if (elem) {
528518
elem->origin = NULL;
529519
elem->prev = attr_stack;
@@ -533,7 +523,7 @@ static void bootstrap_attr_stack(void)
533523

534524
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
535525
elem = read_attr(GITATTRIBUTES_FILE, 1);
536-
elem->origin = strdup("");
526+
elem->origin = xstrdup("");
537527
elem->prev = attr_stack;
538528
attr_stack = elem;
539529
debug_push(elem);
@@ -552,7 +542,6 @@ static void prepare_attr_stack(const char *path)
552542
{
553543
struct attr_stack *elem, *info;
554544
int dirlen, len;
555-
struct strbuf pathbuf;
556545
const char *cp;
557546

558547
cp = strrchr(path, '/');
@@ -561,8 +550,6 @@ static void prepare_attr_stack(const char *path)
561550
else
562551
dirlen = cp - path;
563552

564-
strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
565-
566553
/*
567554
* At the bottom of the attribute stack is the built-in
568555
* set of attribute definitions, followed by the contents
@@ -607,27 +594,28 @@ static void prepare_attr_stack(const char *path)
607594
* Read from parent directories and push them down
608595
*/
609596
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
610-
while (1) {
611-
char *cp;
597+
struct strbuf pathbuf = STRBUF_INIT;
612598

599+
while (1) {
613600
len = strlen(attr_stack->origin);
614601
if (dirlen <= len)
615602
break;
616-
strbuf_reset(&pathbuf);
617-
strbuf_add(&pathbuf, path, dirlen);
603+
cp = memchr(path + len + 1, '/', dirlen - len - 1);
604+
if (!cp)
605+
cp = path + dirlen;
606+
strbuf_add(&pathbuf, path, cp - path);
618607
strbuf_addch(&pathbuf, '/');
619-
cp = strchr(pathbuf.buf + len + 1, '/');
620-
strcpy(cp + 1, GITATTRIBUTES_FILE);
608+
strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);
621609
elem = read_attr(pathbuf.buf, 0);
622-
*cp = '\0';
623-
elem->origin = strdup(pathbuf.buf);
610+
strbuf_setlen(&pathbuf, cp - path);
611+
elem->origin = strbuf_detach(&pathbuf, NULL);
624612
elem->prev = attr_stack;
625613
attr_stack = elem;
626614
debug_push(elem);
627615
}
628-
}
629616

630-
strbuf_release(&pathbuf);
617+
strbuf_release(&pathbuf);
618+
}
631619

632620
/*
633621
* Finally push the "info" one at the top of the stack.
@@ -644,7 +632,7 @@ static int path_matches(const char *pathname, int pathlen,
644632
/* match basename */
645633
const char *basename = strrchr(pathname, '/');
646634
basename = basename ? basename + 1 : pathname;
647-
return (fnmatch(pattern, basename, 0) == 0);
635+
return (fnmatch_icase(pattern, basename, 0) == 0);
648636
}
649637
/*
650638
* match with FNM_PATHNAME; the pattern has base implicitly
@@ -658,7 +646,7 @@ static int path_matches(const char *pathname, int pathlen,
658646
return 0;
659647
if (baselen != 0)
660648
baselen++;
661-
return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
649+
return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
662650
}
663651

664652
static int macroexpand_one(int attr_nr, int rem);

builtin/check-attr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
9292
struct git_attr_check *check;
9393
int cnt, i, doubledash, filei;
9494

95+
git_config(git_default_config, NULL);
96+
9597
argc = parse_options(argc, argv, prefix, check_attr_options,
9698
check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
9799

builtin/mv.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
2929
to_copy--;
3030
if (to_copy != length || base_name) {
3131
char *it = xmemdupz(result[i], to_copy);
32-
result[i] = base_name ? strdup(basename(it)) : it;
32+
if (base_name) {
33+
result[i] = xstrdup(basename(it));
34+
free(it);
35+
} else
36+
result[i] = it;
3337
}
3438
}
3539
return get_pathspec(prefix, result);

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ extern int warn_ambiguous_refs;
589589
extern int shared_repository;
590590
extern const char *apply_default_whitespace;
591591
extern const char *apply_default_ignorewhitespace;
592+
extern const char *git_attributes_file;
592593
extern int zlib_compression_level;
593594
extern int core_compression_level;
594595
extern int core_compression_seen;

compat/mingw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
11831183
}
11841184
ai->ai_addrlen = sizeof(struct sockaddr_in);
11851185
if (hints && (hints->ai_flags & AI_CANONNAME))
1186-
ai->ai_canonname = h ? strdup(h->h_name) : NULL;
1186+
ai->ai_canonname = h ? xstrdup(h->h_name) : NULL;
11871187
else
11881188
ai->ai_canonname = NULL;
11891189

compat/qsort.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void git_qsort(void *b, size_t n, size_t s,
5555
msort_with_tmp(b, n, s, cmp, buf);
5656
} else {
5757
/* It's somewhat large, so malloc it. */
58-
char *tmp = malloc(size);
58+
char *tmp = xmalloc(size);
5959
msort_with_tmp(b, n, s, cmp, tmp);
6060
free(tmp);
6161
}

config.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ static int git_default_core_config(const char *var, const char *value)
491491
return 0;
492492
}
493493

494+
if (!strcmp(var, "core.attributesfile"))
495+
return git_config_pathname(&git_attributes_file, var, value);
496+
494497
if (!strcmp(var, "core.bare")) {
495498
is_bare_repository_cfg = git_config_bool(var, value);
496499
return 0;

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const char *git_log_output_encoding;
2929
int shared_repository = PERM_UMASK;
3030
const char *apply_default_whitespace;
3131
const char *apply_default_ignorewhitespace;
32+
const char *git_attributes_file;
3233
int zlib_compression_level = Z_BEST_SPEED;
3334
int core_compression_level;
3435
int core_compression_seen;

show-index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ int main(int argc, char **argv)
4848
unsigned char sha1[20];
4949
uint32_t crc;
5050
uint32_t off;
51-
} *entries = malloc(nr * sizeof(entries[0]));
51+
} *entries = xmalloc(nr * sizeof(entries[0]));
5252
for (i = 0; i < nr; i++)
5353
if (fread(entries[i].sha1, 20, 1, stdin) != 1)
5454
die("unable to read sha1 %u/%u", i, nr);

t/t0003-attributes.sh

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ attr_check () {
99
path="$1"
1010
expect="$2"
1111

12-
git check-attr test -- "$path" >actual 2>err &&
12+
git $3 check-attr test -- "$path" >actual 2>err &&
1313
echo "$path: test: $2" >expect &&
1414
test_cmp expect actual &&
1515
test_line_count = 0 err
@@ -27,6 +27,7 @@ test_expect_success 'setup' '
2727
echo "onoff test -test"
2828
echo "offon -test test"
2929
echo "no notest"
30+
echo "A/e/F test=A/e/F"
3031
) >.gitattributes &&
3132
(
3233
echo "g test=a/g" &&
@@ -93,6 +94,62 @@ test_expect_success 'attribute test' '
9394
9495
'
9596

97+
test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '
98+
99+
test_must_fail attr_check F f "-c core.ignorecase=0" &&
100+
test_must_fail attr_check a/F f "-c core.ignorecase=0" &&
101+
test_must_fail attr_check a/c/F f "-c core.ignorecase=0" &&
102+
test_must_fail attr_check a/G a/g "-c core.ignorecase=0" &&
103+
test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" &&
104+
test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" &&
105+
test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" &&
106+
test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" &&
107+
test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" &&
108+
test_must_fail attr_check oFfOn set "-c core.ignorecase=0" &&
109+
attr_check NO unspecified "-c core.ignorecase=0" &&
110+
test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
111+
attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&
112+
test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0"
113+
114+
'
115+
116+
test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '
117+
118+
attr_check F f "-c core.ignorecase=1" &&
119+
attr_check a/F f "-c core.ignorecase=1" &&
120+
attr_check a/c/F f "-c core.ignorecase=1" &&
121+
attr_check a/G a/g "-c core.ignorecase=1" &&
122+
attr_check a/B/g a/b/g "-c core.ignorecase=1" &&
123+
attr_check a/b/G a/b/g "-c core.ignorecase=1" &&
124+
attr_check a/b/H a/b/h "-c core.ignorecase=1" &&
125+
attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&
126+
attr_check oNoFf unset "-c core.ignorecase=1" &&
127+
attr_check oFfOn set "-c core.ignorecase=1" &&
128+
attr_check NO unspecified "-c core.ignorecase=1" &&
129+
attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&
130+
attr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&
131+
attr_check a/E/f "A/e/F" "-c core.ignorecase=1"
132+
133+
'
134+
135+
test_expect_success 'check whether FS is case-insensitive' '
136+
mkdir junk &&
137+
echo good >junk/CamelCase &&
138+
echo bad >junk/camelcase &&
139+
if test "$(cat junk/CamelCase)" != good
140+
then
141+
test_set_prereq CASE_INSENSITIVE_FS
142+
fi
143+
'
144+
145+
test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '
146+
test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" &&
147+
test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
148+
attr_check A/b/h a/b/h "-c core.ignorecase=1" &&
149+
attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&
150+
attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"
151+
'
152+
96153
test_expect_success 'unnormalized paths' '
97154
98155
attr_check ./f f &&

0 commit comments

Comments
 (0)