mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 18:03:54 +00:00
Fix handling of relative paths for attrs
Per issue #533, the handling of relative paths in attribute and ignore files was not right. Fixed this by pre-joining the relative path of the attribute/ignore file onto the match string when a full path match is required. Unfortunately, fixing this required a bit more code than I would have liked because I had to juggle things around so that the fnmatch parser would have sufficient information to prepend the relative path when it was needed.
This commit is contained in:
parent
6e03b12f57
commit
a51cd8e6f6
@ -214,7 +214,7 @@ int git_attr_cache__push_file(
|
|||||||
git_vector *stack,
|
git_vector *stack,
|
||||||
const char *base,
|
const char *base,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file **))
|
int (*loader)(git_repository *, const char *, git_attr_file *))
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
int error = GIT_SUCCESS;
|
||||||
git_attr_cache *cache = &repo->attrcache;
|
git_attr_cache *cache = &repo->attrcache;
|
||||||
@ -231,11 +231,12 @@ int git_attr_cache__push_file(
|
|||||||
/* either get attr_file from cache or read from disk */
|
/* either get attr_file from cache or read from disk */
|
||||||
file = git_hashtable_lookup(cache->files, filename);
|
file = git_hashtable_lookup(cache->files, filename);
|
||||||
if (file == NULL && git_futils_exists(filename) == GIT_SUCCESS) {
|
if (file == NULL && git_futils_exists(filename) == GIT_SUCCESS) {
|
||||||
error = (*loader)(repo, filename, &file);
|
if ((error = git_attr_file__new(&file)) == GIT_SUCCESS)
|
||||||
|
error = (*loader)(repo, filename, file);
|
||||||
add_to_cache = (error == GIT_SUCCESS);
|
add_to_cache = (error == GIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file != NULL) {
|
if (error == GIT_SUCCESS && file != NULL) {
|
||||||
/* add file to vector, if we found it */
|
/* add file to vector, if we found it */
|
||||||
error = git_vector_insert(stack, file);
|
error = git_vector_insert(stack, file);
|
||||||
|
|
||||||
|
@ -25,6 +25,6 @@ extern int git_attr_cache__push_file(
|
|||||||
git_vector *stack,
|
git_vector *stack,
|
||||||
const char *base,
|
const char *base,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file **));
|
int (*loader)(git_repository *, const char *, git_attr_file *));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
113
src/attr_file.c
113
src/attr_file.c
@ -31,21 +31,46 @@ int git_attr_file__new(git_attr_file **attrs_ptr)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_attr_file__set_path(
|
||||||
|
git_repository *repo, const char *path, git_attr_file *file)
|
||||||
|
{
|
||||||
|
if (file->path != NULL) {
|
||||||
|
git__free(file->path);
|
||||||
|
file->path = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repo == NULL)
|
||||||
|
file->path = git__strdup(path);
|
||||||
|
else {
|
||||||
|
const char *workdir = git_repository_workdir(repo);
|
||||||
|
|
||||||
|
if (workdir && git__prefixcmp(path, workdir) == 0)
|
||||||
|
file->path = git__strdup(path + strlen(workdir));
|
||||||
|
else
|
||||||
|
file->path = git__strdup(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (file->path == NULL) ? GIT_ENOMEM : GIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int git_attr_file__from_buffer(
|
int git_attr_file__from_buffer(
|
||||||
git_repository *repo, const char *buffer, git_attr_file **out)
|
git_repository *repo, const char *buffer, git_attr_file *attrs)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
int error = GIT_SUCCESS;
|
||||||
git_attr_file *attrs = NULL;
|
|
||||||
const char *scan = NULL;
|
const char *scan = NULL;
|
||||||
|
char *context = NULL;
|
||||||
git_attr_rule *rule = NULL;
|
git_attr_rule *rule = NULL;
|
||||||
|
|
||||||
*out = NULL;
|
assert(buffer && attrs);
|
||||||
|
|
||||||
if ((error = git_attr_file__new(&attrs)) < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
scan = buffer;
|
scan = buffer;
|
||||||
|
|
||||||
|
if (attrs->path && git__suffixcmp(attrs->path, GIT_ATTR_FILE) == 0) {
|
||||||
|
context = git__strndup(attrs->path,
|
||||||
|
strlen(attrs->path) - strlen(GIT_ATTR_FILE));
|
||||||
|
if (!context) error = GIT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
while (error == GIT_SUCCESS && *scan) {
|
while (error == GIT_SUCCESS && *scan) {
|
||||||
/* allocate rule if needed */
|
/* allocate rule if needed */
|
||||||
if (!rule && !(rule = git__calloc(1, sizeof(git_attr_rule)))) {
|
if (!rule && !(rule = git__calloc(1, sizeof(git_attr_rule)))) {
|
||||||
@ -54,7 +79,7 @@ int git_attr_file__from_buffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parse the next "pattern attr attr attr" line */
|
/* parse the next "pattern attr attr attr" line */
|
||||||
if (!(error = git_attr_fnmatch__parse(&rule->match, &scan)) &&
|
if (!(error = git_attr_fnmatch__parse(&rule->match, context, &scan)) &&
|
||||||
!(error = git_attr_assignment__parse(repo, &rule->assigns, &scan)))
|
!(error = git_attr_assignment__parse(repo, &rule->assigns, &scan)))
|
||||||
{
|
{
|
||||||
if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO)
|
if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO)
|
||||||
@ -76,35 +101,30 @@ int git_attr_file__from_buffer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
git_attr_rule__free(rule);
|
||||||
if (error != GIT_SUCCESS) {
|
git__free(context);
|
||||||
git_attr_rule__free(rule);
|
|
||||||
git_attr_file__free(attrs);
|
|
||||||
} else {
|
|
||||||
*out = attrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_attr_file__from_file(
|
int git_attr_file__from_file(
|
||||||
git_repository *repo, const char *path, git_attr_file **out)
|
git_repository *repo, const char *path, git_attr_file *file)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
int error = GIT_SUCCESS;
|
||||||
git_fbuffer fbuf = GIT_FBUFFER_INIT;
|
git_fbuffer fbuf = GIT_FBUFFER_INIT;
|
||||||
|
|
||||||
*out = NULL;
|
assert(path && file);
|
||||||
|
|
||||||
if ((error = git_futils_readbuffer(&fbuf, path)) < GIT_SUCCESS ||
|
if (file->path == NULL)
|
||||||
(error = git_attr_file__from_buffer(repo, fbuf.data, out)) < GIT_SUCCESS)
|
error = git_attr_file__set_path(repo, path, file);
|
||||||
{
|
|
||||||
git__rethrow(error, "Could not open attribute file '%s'", path);
|
if (error == GIT_SUCCESS &&
|
||||||
} else {
|
(error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS)
|
||||||
/* save path (okay to fail) */
|
error = git_attr_file__from_buffer(repo, fbuf.data, file);
|
||||||
(*out)->path = git__strdup(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_futils_freebuffer(&fbuf);
|
git_futils_freebuffer(&fbuf);
|
||||||
|
if (error != GIT_SUCCESS)
|
||||||
|
git__rethrow(error, "Could not open attribute file '%s'", path);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -267,6 +287,7 @@ int git_attr_path__init(
|
|||||||
*/
|
*/
|
||||||
int git_attr_fnmatch__parse(
|
int git_attr_fnmatch__parse(
|
||||||
git_attr_fnmatch *spec,
|
git_attr_fnmatch *spec,
|
||||||
|
const char *source,
|
||||||
const char **base)
|
const char **base)
|
||||||
{
|
{
|
||||||
const char *pattern, *scan;
|
const char *pattern, *scan;
|
||||||
@ -312,30 +333,38 @@ int git_attr_fnmatch__parse(
|
|||||||
*base = scan;
|
*base = scan;
|
||||||
|
|
||||||
spec->length = scan - pattern;
|
spec->length = scan - pattern;
|
||||||
spec->pattern = git__strndup(pattern, spec->length);
|
|
||||||
|
if (pattern[spec->length - 1] == '/') {
|
||||||
|
spec->length--;
|
||||||
|
spec->flags = spec->flags | GIT_ATTR_FNMATCH_DIRECTORY;
|
||||||
|
if (--slash_count <= 0)
|
||||||
|
spec->flags = spec->flags & ~GIT_ATTR_FNMATCH_FULLPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 &&
|
||||||
|
source != NULL && git_path_root(pattern) < 0)
|
||||||
|
{
|
||||||
|
size_t sourcelen = strlen(source);
|
||||||
|
/* given an unrooted fullpath match from a file inside a repo,
|
||||||
|
* prefix the pattern with the relative directory of the source file
|
||||||
|
*/
|
||||||
|
spec->pattern = git__malloc(sourcelen + spec->length + 1);
|
||||||
|
if (spec->pattern) {
|
||||||
|
memcpy(spec->pattern, source, sourcelen);
|
||||||
|
memcpy(spec->pattern + sourcelen, pattern, spec->length);
|
||||||
|
spec->length += sourcelen;
|
||||||
|
spec->pattern[spec->length] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spec->pattern = git__strndup(pattern, spec->length);
|
||||||
|
}
|
||||||
|
|
||||||
if (!spec->pattern) {
|
if (!spec->pattern) {
|
||||||
*base = git__next_line(pattern);
|
*base = git__next_line(pattern);
|
||||||
return GIT_ENOMEM;
|
return GIT_ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
/* remove '\' that might have be used for internal whitespace */
|
/* remove '\' that might have be used for internal whitespace */
|
||||||
char *from = spec->pattern, *to = spec->pattern;
|
spec->length = git__removechar(spec->pattern, '\\');
|
||||||
while (*from) {
|
|
||||||
if (*from == '\\') {
|
|
||||||
from++;
|
|
||||||
spec->length--;
|
|
||||||
}
|
|
||||||
*to++ = *from++;
|
|
||||||
}
|
|
||||||
*to = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pattern[spec->length - 1] == '/') {
|
|
||||||
spec->length--;
|
|
||||||
spec->pattern[spec->length] = '\0';
|
|
||||||
spec->flags = spec->flags | GIT_ATTR_FNMATCH_DIRECTORY;
|
|
||||||
if (--slash_count <= 0)
|
|
||||||
spec->flags = spec->flags & ~GIT_ATTR_FNMATCH_FULLPATH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
|
@ -62,14 +62,17 @@ typedef struct {
|
|||||||
* git_attr_file API
|
* git_attr_file API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int git_attr_file__from_buffer(
|
|
||||||
git_repository *repo, const char *buf, git_attr_file **out);
|
|
||||||
extern int git_attr_file__from_file(
|
|
||||||
git_repository *repo, const char *path, git_attr_file **out);
|
|
||||||
|
|
||||||
extern int git_attr_file__new(git_attr_file **attrs_ptr);
|
extern int git_attr_file__new(git_attr_file **attrs_ptr);
|
||||||
extern void git_attr_file__free(git_attr_file *file);
|
extern void git_attr_file__free(git_attr_file *file);
|
||||||
|
|
||||||
|
extern int git_attr_file__from_buffer(
|
||||||
|
git_repository *repo, const char *buf, git_attr_file *file);
|
||||||
|
extern int git_attr_file__from_file(
|
||||||
|
git_repository *repo, const char *path, git_attr_file *file);
|
||||||
|
|
||||||
|
extern int git_attr_file__set_path(
|
||||||
|
git_repository *repo, const char *path, git_attr_file *file);
|
||||||
|
|
||||||
extern int git_attr_file__lookup_one(
|
extern int git_attr_file__lookup_one(
|
||||||
git_attr_file *file,
|
git_attr_file *file,
|
||||||
const git_attr_path *path,
|
const git_attr_path *path,
|
||||||
@ -90,6 +93,7 @@ extern unsigned long git_attr_file__name_hash(const char *name);
|
|||||||
|
|
||||||
extern int git_attr_fnmatch__parse(
|
extern int git_attr_fnmatch__parse(
|
||||||
git_attr_fnmatch *spec,
|
git_attr_fnmatch *spec,
|
||||||
|
const char *source,
|
||||||
const char **base);
|
const char **base);
|
||||||
|
|
||||||
extern int git_attr_fnmatch__match(
|
extern int git_attr_fnmatch__match(
|
||||||
|
28
src/ignore.c
28
src/ignore.c
@ -8,22 +8,25 @@
|
|||||||
#define GIT_IGNORE_CONFIG "core.excludesfile"
|
#define GIT_IGNORE_CONFIG "core.excludesfile"
|
||||||
|
|
||||||
static int load_ignore_file(
|
static int load_ignore_file(
|
||||||
git_repository *GIT_UNUSED(repo), const char *path, git_attr_file **out)
|
git_repository *repo, const char *path, git_attr_file *ignores)
|
||||||
{
|
{
|
||||||
int error = GIT_SUCCESS;
|
int error = GIT_SUCCESS;
|
||||||
git_fbuffer fbuf = GIT_FBUFFER_INIT;
|
git_fbuffer fbuf = GIT_FBUFFER_INIT;
|
||||||
git_attr_file *ignores = NULL;
|
|
||||||
git_attr_fnmatch *match = NULL;
|
git_attr_fnmatch *match = NULL;
|
||||||
const char *scan = NULL;
|
const char *scan = NULL;
|
||||||
|
char *context = NULL;
|
||||||
|
|
||||||
GIT_UNUSED_ARG(repo);
|
if (ignores->path == NULL)
|
||||||
|
error = git_attr_file__set_path(repo, path, ignores);
|
||||||
|
|
||||||
*out = NULL;
|
if (git__suffixcmp(ignores->path, GIT_IGNORE_FILE) == 0) {
|
||||||
|
context = git__strndup(ignores->path,
|
||||||
|
strlen(ignores->path) - strlen(GIT_IGNORE_FILE));
|
||||||
|
if (!context) error = GIT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
if ((error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS)
|
if (error == GIT_SUCCESS)
|
||||||
error = git_attr_file__new(&ignores);
|
error = git_futils_readbuffer(&fbuf, path);
|
||||||
|
|
||||||
ignores->path = git__strdup(path);
|
|
||||||
|
|
||||||
scan = fbuf.data;
|
scan = fbuf.data;
|
||||||
|
|
||||||
@ -33,7 +36,7 @@ static int load_ignore_file(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(error = git_attr_fnmatch__parse(match, &scan))) {
|
if (!(error = git_attr_fnmatch__parse(match, context, &scan))) {
|
||||||
match->flags = match->flags | GIT_ATTR_FNMATCH_IGNORE;
|
match->flags = match->flags | GIT_ATTR_FNMATCH_IGNORE;
|
||||||
scan = git__next_line(scan);
|
scan = git__next_line(scan);
|
||||||
error = git_vector_insert(&ignores->rules, match);
|
error = git_vector_insert(&ignores->rules, match);
|
||||||
@ -52,13 +55,10 @@ static int load_ignore_file(
|
|||||||
|
|
||||||
git_futils_freebuffer(&fbuf);
|
git_futils_freebuffer(&fbuf);
|
||||||
git__free(match);
|
git__free(match);
|
||||||
|
git__free(context);
|
||||||
|
|
||||||
if (error != GIT_SUCCESS) {
|
if (error != GIT_SUCCESS)
|
||||||
git__rethrow(error, "Could not open ignore file '%s'", path);
|
git__rethrow(error, "Could not open ignore file '%s'", path);
|
||||||
git_attr_file__free(ignores);
|
|
||||||
} else {
|
|
||||||
*out = ignores;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
17
src/util.c
17
src/util.c
@ -156,6 +156,23 @@ void git__strtolower(char *str)
|
|||||||
git__strntolower(str, strlen(str));
|
git__strntolower(str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t git__removechar(char *str, char remove)
|
||||||
|
{
|
||||||
|
char *from = str, *to = str;
|
||||||
|
|
||||||
|
while (*from) {
|
||||||
|
if (*from == remove)
|
||||||
|
from++;
|
||||||
|
if (to != from)
|
||||||
|
*to = *from;
|
||||||
|
to++;
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
*to = '\0';
|
||||||
|
|
||||||
|
return (to - str);
|
||||||
|
}
|
||||||
|
|
||||||
int git__prefixcmp(const char *str, const char *prefix)
|
int git__prefixcmp(const char *str, const char *prefix)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -102,6 +102,8 @@ extern char *git__strtok(char **end, const char *sep);
|
|||||||
extern void git__strntolower(char *str, size_t len);
|
extern void git__strntolower(char *str, size_t len);
|
||||||
extern void git__strtolower(char *str);
|
extern void git__strtolower(char *str);
|
||||||
|
|
||||||
|
extern size_t git__removechar(char *str, char remove);
|
||||||
|
|
||||||
GIT_INLINE(const char *) git__next_line(const char *s)
|
GIT_INLINE(const char *) git__next_line(const char *s)
|
||||||
{
|
{
|
||||||
while (*s && *s != '\n') s++;
|
while (*s && *s != '\n') s++;
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
void test_attr_file__simple_read(void)
|
void test_attr_file__simple_read(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr0"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr0"), file->path);
|
||||||
cl_assert(file->rules.length == 1);
|
cl_assert(file->rules.length == 1);
|
||||||
|
|
||||||
@ -32,11 +33,12 @@ void test_attr_file__simple_read(void)
|
|||||||
|
|
||||||
void test_attr_file__match_variants(void)
|
void test_attr_file__match_variants(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr1"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr1"), file->path);
|
||||||
cl_assert(file->rules.length == 10);
|
cl_assert(file->rules.length == 10);
|
||||||
|
|
||||||
@ -119,11 +121,12 @@ static void check_one_assign(
|
|||||||
|
|
||||||
void test_attr_file__assign_variants(void)
|
void test_attr_file__assign_variants(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr2"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr2"), file->path);
|
||||||
cl_assert(file->rules.length == 11);
|
cl_assert(file->rules.length == 11);
|
||||||
|
|
||||||
@ -184,11 +187,12 @@ void test_attr_file__assign_variants(void)
|
|||||||
|
|
||||||
void test_attr_file__check_attr_examples(void)
|
void test_attr_file__check_attr_examples(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr3"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr3"), file->path);
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
void test_attr_lookup__simple(void)
|
void test_attr_lookup__simple(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_path path;
|
git_attr_path path;
|
||||||
const char *value = NULL;
|
const char *value = NULL;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr0"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr0"), file->path);
|
||||||
cl_assert(file->rules.length == 1);
|
cl_assert(file->rules.length == 1);
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ static void run_test_cases(git_attr_file *file, test_case *cases)
|
|||||||
|
|
||||||
void test_attr_lookup__match_variants(void)
|
void test_attr_lookup__match_variants(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
git_attr_path path;
|
git_attr_path path;
|
||||||
test_case cases[] = {
|
test_case cases[] = {
|
||||||
/* pat0 -> simple match */
|
/* pat0 -> simple match */
|
||||||
@ -132,7 +133,8 @@ void test_attr_lookup__match_variants(void)
|
|||||||
{ NULL, NULL, NULL, 0, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), file));
|
||||||
cl_assert_strequal(cl_fixture("attr/attr1"), file->path);
|
cl_assert_strequal(cl_fixture("attr/attr1"), file->path);
|
||||||
cl_assert(file->rules.length == 10);
|
cl_assert(file->rules.length == 10);
|
||||||
|
|
||||||
@ -146,7 +148,7 @@ void test_attr_lookup__match_variants(void)
|
|||||||
|
|
||||||
void test_attr_lookup__assign_variants(void)
|
void test_attr_lookup__assign_variants(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
test_case cases[] = {
|
test_case cases[] = {
|
||||||
/* pat0 -> simple assign */
|
/* pat0 -> simple assign */
|
||||||
{ "pat0", "simple", GIT_ATTR_TRUE, 0, 0 },
|
{ "pat0", "simple", GIT_ATTR_TRUE, 0, 0 },
|
||||||
@ -190,7 +192,8 @@ void test_attr_lookup__assign_variants(void)
|
|||||||
{ NULL, NULL, NULL, 0, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), file));
|
||||||
cl_assert(file->rules.length == 11);
|
cl_assert(file->rules.length == 11);
|
||||||
|
|
||||||
run_test_cases(file, cases);
|
run_test_cases(file, cases);
|
||||||
@ -200,7 +203,7 @@ void test_attr_lookup__assign_variants(void)
|
|||||||
|
|
||||||
void test_attr_lookup__check_attr_examples(void)
|
void test_attr_lookup__check_attr_examples(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
test_case cases[] = {
|
test_case cases[] = {
|
||||||
{ "foo.java", "diff", "java", 1, 0 },
|
{ "foo.java", "diff", "java", 1, 0 },
|
||||||
{ "foo.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
|
{ "foo.java", "crlf", GIT_ATTR_FALSE, 0, 0 },
|
||||||
@ -224,7 +227,8 @@ void test_attr_lookup__check_attr_examples(void)
|
|||||||
{ NULL, NULL, NULL, 0, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file));
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
run_test_cases(file, cases);
|
run_test_cases(file, cases);
|
||||||
@ -234,7 +238,7 @@ void test_attr_lookup__check_attr_examples(void)
|
|||||||
|
|
||||||
void test_attr_lookup__from_buffer(void)
|
void test_attr_lookup__from_buffer(void)
|
||||||
{
|
{
|
||||||
git_attr_file *file = NULL;
|
git_attr_file *file;
|
||||||
test_case cases[] = {
|
test_case cases[] = {
|
||||||
{ "abc", "foo", GIT_ATTR_TRUE, 0, 0 },
|
{ "abc", "foo", GIT_ATTR_TRUE, 0, 0 },
|
||||||
{ "abc", "bar", GIT_ATTR_TRUE, 0, 0 },
|
{ "abc", "bar", GIT_ATTR_TRUE, 0, 0 },
|
||||||
@ -248,7 +252,8 @@ void test_attr_lookup__from_buffer(void)
|
|||||||
{ NULL, NULL, NULL, 0, 0 }
|
{ NULL, NULL, NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__from_buffer(NULL, "a* foo\nabc bar\n* baz", &file));
|
cl_git_pass(git_attr_file__new(&file));
|
||||||
|
cl_git_pass(git_attr_file__from_buffer(NULL, "a* foo\nabc bar\n* baz", file));
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
run_test_cases(file, cases);
|
run_test_cases(file, cases);
|
||||||
|
@ -45,19 +45,24 @@ void test_attr_repo__get_one(void)
|
|||||||
{ "root_test3", "rootattr", NULL },
|
{ "root_test3", "rootattr", NULL },
|
||||||
{ "root_test3", "multiattr", "3" },
|
{ "root_test3", "multiattr", "3" },
|
||||||
{ "root_test3", "multi2", NULL },
|
{ "root_test3", "multi2", NULL },
|
||||||
{ "subdir/subdir_test1", "repoattr", GIT_ATTR_TRUE },
|
{ "sub/subdir_test1", "repoattr", GIT_ATTR_TRUE },
|
||||||
{ "subdir/subdir_test1", "rootattr", GIT_ATTR_TRUE },
|
{ "sub/subdir_test1", "rootattr", GIT_ATTR_TRUE },
|
||||||
{ "subdir/subdir_test1", "missingattr", NULL },
|
{ "sub/subdir_test1", "missingattr", NULL },
|
||||||
{ "subdir/subdir_test1", "subattr", "yes" },
|
{ "sub/subdir_test1", "subattr", "yes" },
|
||||||
{ "subdir/subdir_test1", "negattr", GIT_ATTR_FALSE },
|
{ "sub/subdir_test1", "negattr", GIT_ATTR_FALSE },
|
||||||
{ "subdir/subdir_test1", "another", NULL },
|
{ "sub/subdir_test1", "another", NULL },
|
||||||
{ "subdir/subdir_test2.txt", "repoattr", GIT_ATTR_TRUE },
|
{ "sub/subdir_test2.txt", "repoattr", GIT_ATTR_TRUE },
|
||||||
{ "subdir/subdir_test2.txt", "rootattr", GIT_ATTR_TRUE },
|
{ "sub/subdir_test2.txt", "rootattr", GIT_ATTR_TRUE },
|
||||||
{ "subdir/subdir_test2.txt", "missingattr", NULL },
|
{ "sub/subdir_test2.txt", "missingattr", NULL },
|
||||||
{ "subdir/subdir_test2.txt", "subattr", "yes" },
|
{ "sub/subdir_test2.txt", "subattr", "yes" },
|
||||||
{ "subdir/subdir_test2.txt", "negattr", GIT_ATTR_FALSE },
|
{ "sub/subdir_test2.txt", "negattr", GIT_ATTR_FALSE },
|
||||||
{ "subdir/subdir_test2.txt", "another", "one" },
|
{ "sub/subdir_test2.txt", "another", "zero" },
|
||||||
|
{ "sub/subdir_test2.txt", "reposub", GIT_ATTR_TRUE },
|
||||||
|
{ "sub/sub/subdir.txt", "another", "one" },
|
||||||
|
{ "sub/sub/subdir.txt", "reposubsub", GIT_ATTR_TRUE },
|
||||||
|
{ "sub/sub/subdir.txt", "reposub", NULL },
|
||||||
{ "does-not-exist", "foo", "yes" },
|
{ "does-not-exist", "foo", "yes" },
|
||||||
|
{ "sub/deep/file", "deepdeep", GIT_ATTR_TRUE },
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
}, *scan;
|
}, *scan;
|
||||||
|
|
||||||
@ -105,7 +110,7 @@ void test_attr_repo__get_many(void)
|
|||||||
cl_assert(values[2] == NULL);
|
cl_assert(values[2] == NULL);
|
||||||
cl_assert(values[3] == NULL);
|
cl_assert(values[3] == NULL);
|
||||||
|
|
||||||
cl_git_pass(git_attr_get_many(g_repo, "subdir/subdir_test1", 4, names, values));
|
cl_git_pass(git_attr_get_many(g_repo, "sub/subdir_test1", 4, names, values));
|
||||||
|
|
||||||
cl_assert(values[0] == GIT_ATTR_TRUE);
|
cl_assert(values[0] == GIT_ATTR_TRUE);
|
||||||
cl_assert(values[1] == GIT_ATTR_TRUE);
|
cl_assert(values[1] == GIT_ATTR_TRUE);
|
||||||
@ -136,33 +141,33 @@ void test_attr_repo__foreach(void)
|
|||||||
cl_assert(count == 2);
|
cl_assert(count == 2);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
cl_git_pass(git_attr_foreach(g_repo, "subdir/subdir_test1",
|
cl_git_pass(git_attr_foreach(g_repo, "sub/subdir_test1",
|
||||||
&count_attrs, &count));
|
&count_attrs, &count));
|
||||||
cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */
|
cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
cl_git_pass(git_attr_foreach(g_repo, "subdir/subdir_test2.txt",
|
cl_git_pass(git_attr_foreach(g_repo, "sub/subdir_test2.txt",
|
||||||
&count_attrs, &count));
|
&count_attrs, &count));
|
||||||
cl_assert(count == 5); /* repoattr, rootattr, subattr, negattr, another */
|
cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_attr_repo__manpage_example(void)
|
void test_attr_repo__manpage_example(void)
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
cl_git_pass(git_attr_get(g_repo, "subdir/abc", "foo", &value));
|
cl_git_pass(git_attr_get(g_repo, "sub/abc", "foo", &value));
|
||||||
cl_assert(value == GIT_ATTR_TRUE);
|
cl_assert(value == GIT_ATTR_TRUE);
|
||||||
|
|
||||||
cl_git_pass(git_attr_get(g_repo, "subdir/abc", "bar", &value));
|
cl_git_pass(git_attr_get(g_repo, "sub/abc", "bar", &value));
|
||||||
cl_assert(value == NULL);
|
cl_assert(value == NULL);
|
||||||
|
|
||||||
cl_git_pass(git_attr_get(g_repo, "subdir/abc", "baz", &value));
|
cl_git_pass(git_attr_get(g_repo, "sub/abc", "baz", &value));
|
||||||
cl_assert(value == GIT_ATTR_FALSE);
|
cl_assert(value == GIT_ATTR_FALSE);
|
||||||
|
|
||||||
cl_git_pass(git_attr_get(g_repo, "subdir/abc", "merge", &value));
|
cl_git_pass(git_attr_get(g_repo, "sub/abc", "merge", &value));
|
||||||
cl_assert_strequal("filfre", value);
|
cl_assert_strequal("filfre", value);
|
||||||
|
|
||||||
cl_git_pass(git_attr_get(g_repo, "subdir/abc", "frotz", &value));
|
cl_git_pass(git_attr_get(g_repo, "sub/abc", "frotz", &value));
|
||||||
cl_assert(value == NULL);
|
cl_assert(value == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
tests-clay/status/ignore.c
Normal file
49
tests-clay/status/ignore.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "clay_libgit2.h"
|
||||||
|
#include "fileops.h"
|
||||||
|
#include "git2/attr.h"
|
||||||
|
|
||||||
|
static git_repository *g_repo = NULL;
|
||||||
|
|
||||||
|
void test_status_ignore__initialize(void)
|
||||||
|
{
|
||||||
|
/* Before each test, instantiate the attr repo from the fixtures and
|
||||||
|
* rename the .gitted to .git so it is a repo with a working dir. Also
|
||||||
|
* rename gitignore to .gitignore.
|
||||||
|
*/
|
||||||
|
cl_fixture_sandbox("attr");
|
||||||
|
cl_git_pass(p_rename("attr/.gitted", "attr/.git"));
|
||||||
|
cl_git_pass(p_rename("attr/gitignore", "attr/.gitignore"));
|
||||||
|
cl_git_pass(git_repository_open(&g_repo, "attr/.git"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_status_ignore__cleanup(void)
|
||||||
|
{
|
||||||
|
git_repository_free(g_repo);
|
||||||
|
g_repo = NULL;
|
||||||
|
cl_fixture_cleanup("attr");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_status_ignore__0(void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char *path;
|
||||||
|
int expected;
|
||||||
|
} test_cases[] = {
|
||||||
|
{ "file", 0 },
|
||||||
|
{ "ign", 1 },
|
||||||
|
{ "sub", 1 },
|
||||||
|
{ "sub/file", 0 },
|
||||||
|
{ "sub/ign", 1 },
|
||||||
|
{ "sub/sub", 1 },
|
||||||
|
{ "sub/sub/file", 0 },
|
||||||
|
{ "sub/sub/ign", 1 },
|
||||||
|
{ "sub/sub/sub", 1 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
}, *one_test;
|
||||||
|
|
||||||
|
for (one_test = test_cases; one_test->path != NULL; one_test++) {
|
||||||
|
int ignored;
|
||||||
|
cl_git_pass(git_status_should_ignore(g_repo, one_test->path, &ignored));
|
||||||
|
cl_assert_(ignored == one_test->expected, one_test->path);
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
BIN
tests/resources/attr/file
Normal file
BIN
tests/resources/attr/file
Normal file
Binary file not shown.
BIN
tests/resources/attr/gitignore
Normal file
BIN
tests/resources/attr/gitignore
Normal file
Binary file not shown.
BIN
tests/resources/attr/ign
Normal file
BIN
tests/resources/attr/ign
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/resources/attr/sub/file
Normal file
BIN
tests/resources/attr/sub/file
Normal file
Binary file not shown.
BIN
tests/resources/attr/sub/ign
Normal file
BIN
tests/resources/attr/sub/ign
Normal file
Binary file not shown.
BIN
tests/resources/attr/sub/sub/file
Normal file
BIN
tests/resources/attr/sub/sub/file
Normal file
Binary file not shown.
BIN
tests/resources/attr/sub/sub/subsub.txt
Normal file
BIN
tests/resources/attr/sub/sub/subsub.txt
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user