зеркало из https://github.com/microsoft/git.git
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
This commit is contained in:
Коммит
a4fdd79f13
46
attr.c
46
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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
1
cache.h
1
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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
3
config.c
3
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче