From a51cd8e6f6724079a552b75e014f792f3f68e158 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 16 Jan 2012 16:58:27 -0800 Subject: [PATCH] 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. --- src/attr.c | 7 +- src/attr.h | 2 +- src/attr_file.c | 113 +++++++++++------- src/attr_file.h | 14 ++- src/ignore.c | 28 ++--- src/util.c | 17 +++ src/util.h | 2 + tests-clay/attr/file.c | 20 ++-- tests-clay/attr/lookup.c | 25 ++-- tests-clay/attr/repo.c | 47 ++++---- tests-clay/status/ignore.c | 49 ++++++++ tests/resources/attr/.gitted/info/attributes | Bin 28 -> 71 bytes tests/resources/attr/file | Bin 0 -> 3 bytes tests/resources/attr/gitignore | Bin 0 -> 8 bytes tests/resources/attr/ign | Bin 0 -> 10 bytes .../attr/{subdir => sub}/.gitattributes | Bin 98 -> 138 bytes tests/resources/attr/{subdir => sub}/abc | Bin tests/resources/attr/sub/file | Bin 0 -> 3 bytes tests/resources/attr/sub/ign | Bin 0 -> 10 bytes tests/resources/attr/sub/sub/file | Bin 0 -> 3 bytes tests/resources/attr/sub/sub/subsub.txt | Bin 0 -> 7 bytes .../attr/{subdir => sub}/subdir_test1 | Bin .../attr/{subdir => sub}/subdir_test2.txt | Bin tests/resources/attr/subdir2/subdir2_test1 | Bin 19 -> 0 bytes 24 files changed, 220 insertions(+), 104 deletions(-) create mode 100644 tests-clay/status/ignore.c create mode 100644 tests/resources/attr/file create mode 100644 tests/resources/attr/gitignore create mode 100644 tests/resources/attr/ign rename tests/resources/attr/{subdir => sub}/.gitattributes (52%) rename tests/resources/attr/{subdir => sub}/abc (100%) create mode 100644 tests/resources/attr/sub/file create mode 100644 tests/resources/attr/sub/ign create mode 100644 tests/resources/attr/sub/sub/file create mode 100644 tests/resources/attr/sub/sub/subsub.txt rename tests/resources/attr/{subdir => sub}/subdir_test1 (100%) rename tests/resources/attr/{subdir => sub}/subdir_test2.txt (100%) delete mode 100644 tests/resources/attr/subdir2/subdir2_test1 diff --git a/src/attr.c b/src/attr.c index dc42379ff..3fe76d124 100644 --- a/src/attr.c +++ b/src/attr.c @@ -214,7 +214,7 @@ int git_attr_cache__push_file( git_vector *stack, const char *base, 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; 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 */ file = git_hashtable_lookup(cache->files, filename); 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); } - if (file != NULL) { + if (error == GIT_SUCCESS && file != NULL) { /* add file to vector, if we found it */ error = git_vector_insert(stack, file); diff --git a/src/attr.h b/src/attr.h index 5edff30d1..a758cc4bd 100644 --- a/src/attr.h +++ b/src/attr.h @@ -25,6 +25,6 @@ extern int git_attr_cache__push_file( git_vector *stack, const char *base, const char *filename, - int (*loader)(git_repository *, const char *, git_attr_file **)); + int (*loader)(git_repository *, const char *, git_attr_file *)); #endif diff --git a/src/attr_file.c b/src/attr_file.c index 5ea07c984..f6eaad69d 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -31,21 +31,46 @@ int git_attr_file__new(git_attr_file **attrs_ptr) 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( - git_repository *repo, const char *buffer, git_attr_file **out) + git_repository *repo, const char *buffer, git_attr_file *attrs) { int error = GIT_SUCCESS; - git_attr_file *attrs = NULL; const char *scan = NULL; + char *context = NULL; git_attr_rule *rule = NULL; - *out = NULL; - - if ((error = git_attr_file__new(&attrs)) < GIT_SUCCESS) - goto cleanup; + assert(buffer && attrs); 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) { /* allocate rule if needed */ 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 */ - 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))) { if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) @@ -76,35 +101,30 @@ int git_attr_file__from_buffer( } } -cleanup: - if (error != GIT_SUCCESS) { - git_attr_rule__free(rule); - git_attr_file__free(attrs); - } else { - *out = attrs; - } + git_attr_rule__free(rule); + git__free(context); return error; } 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; git_fbuffer fbuf = GIT_FBUFFER_INIT; - *out = NULL; + assert(path && file); - if ((error = git_futils_readbuffer(&fbuf, path)) < GIT_SUCCESS || - (error = git_attr_file__from_buffer(repo, fbuf.data, out)) < GIT_SUCCESS) - { - git__rethrow(error, "Could not open attribute file '%s'", path); - } else { - /* save path (okay to fail) */ - (*out)->path = git__strdup(path); - } + if (file->path == NULL) + error = git_attr_file__set_path(repo, path, file); + + if (error == GIT_SUCCESS && + (error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS) + error = git_attr_file__from_buffer(repo, fbuf.data, file); git_futils_freebuffer(&fbuf); + if (error != GIT_SUCCESS) + git__rethrow(error, "Could not open attribute file '%s'", path); return error; } @@ -267,6 +287,7 @@ int git_attr_path__init( */ int git_attr_fnmatch__parse( git_attr_fnmatch *spec, + const char *source, const char **base) { const char *pattern, *scan; @@ -312,30 +333,38 @@ int git_attr_fnmatch__parse( *base = scan; 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) { *base = git__next_line(pattern); return GIT_ENOMEM; } else { /* remove '\' that might have be used for internal whitespace */ - char *from = spec->pattern, *to = 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; + spec->length = git__removechar(spec->pattern, '\\'); } return GIT_SUCCESS; diff --git a/src/attr_file.h b/src/attr_file.h index 7190c4c7b..304c7a854 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -62,14 +62,17 @@ typedef struct { * 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 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( git_attr_file *file, 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( git_attr_fnmatch *spec, + const char *source, const char **base); extern int git_attr_fnmatch__match( diff --git a/src/ignore.c b/src/ignore.c index 1040574d7..388a4b280 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -8,22 +8,25 @@ #define GIT_IGNORE_CONFIG "core.excludesfile" 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; git_fbuffer fbuf = GIT_FBUFFER_INIT; - git_attr_file *ignores = NULL; git_attr_fnmatch *match = 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) - error = git_attr_file__new(&ignores); - - ignores->path = git__strdup(path); + if (error == GIT_SUCCESS) + error = git_futils_readbuffer(&fbuf, path); scan = fbuf.data; @@ -33,7 +36,7 @@ static int load_ignore_file( 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; scan = git__next_line(scan); error = git_vector_insert(&ignores->rules, match); @@ -52,13 +55,10 @@ static int load_ignore_file( git_futils_freebuffer(&fbuf); 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_attr_file__free(ignores); - } else { - *out = ignores; - } return error; } diff --git a/src/util.c b/src/util.c index 1ca9d850c..f47de9e53 100644 --- a/src/util.c +++ b/src/util.c @@ -156,6 +156,23 @@ void git__strtolower(char *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) { for (;;) { diff --git a/src/util.h b/src/util.h index 6c929cf0a..818e6f0f2 100644 --- a/src/util.h +++ b/src/util.h @@ -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__strtolower(char *str); +extern size_t git__removechar(char *str, char remove); + GIT_INLINE(const char *) git__next_line(const char *s) { while (*s && *s != '\n') s++; diff --git a/tests-clay/attr/file.c b/tests-clay/attr/file.c index acca0c653..652ee273c 100644 --- a/tests-clay/attr/file.c +++ b/tests-clay/attr/file.c @@ -6,11 +6,12 @@ void test_attr_file__simple_read(void) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_assignment *assign; 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(file->rules.length == 1); @@ -32,11 +33,12 @@ void test_attr_file__simple_read(void) void test_attr_file__match_variants(void) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_rule *rule; 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(file->rules.length == 10); @@ -119,11 +121,12 @@ static void check_one_assign( void test_attr_file__assign_variants(void) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_rule *rule; 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(file->rules.length == 11); @@ -184,11 +187,12 @@ void test_attr_file__assign_variants(void) void test_attr_file__check_attr_examples(void) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_rule *rule; 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(file->rules.length == 3); diff --git a/tests-clay/attr/lookup.c b/tests-clay/attr/lookup.c index fcade5225..b251562ba 100644 --- a/tests-clay/attr/lookup.c +++ b/tests-clay/attr/lookup.c @@ -3,11 +3,12 @@ void test_attr_lookup__simple(void) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_path path; 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(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) { - git_attr_file *file = NULL; + git_attr_file *file; git_attr_path path; test_case cases[] = { /* pat0 -> simple match */ @@ -132,7 +133,8 @@ void test_attr_lookup__match_variants(void) { 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(file->rules.length == 10); @@ -146,7 +148,7 @@ void test_attr_lookup__match_variants(void) void test_attr_lookup__assign_variants(void) { - git_attr_file *file = NULL; + git_attr_file *file; test_case cases[] = { /* pat0 -> simple assign */ { "pat0", "simple", GIT_ATTR_TRUE, 0, 0 }, @@ -190,7 +192,8 @@ void test_attr_lookup__assign_variants(void) { 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); run_test_cases(file, cases); @@ -200,7 +203,7 @@ void test_attr_lookup__assign_variants(void) void test_attr_lookup__check_attr_examples(void) { - git_attr_file *file = NULL; + git_attr_file *file; test_case cases[] = { { "foo.java", "diff", "java", 1, 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 } }; - 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); run_test_cases(file, cases); @@ -234,7 +238,7 @@ void test_attr_lookup__check_attr_examples(void) void test_attr_lookup__from_buffer(void) { - git_attr_file *file = NULL; + git_attr_file *file; test_case cases[] = { { "abc", "foo", 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 } }; - 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); run_test_cases(file, cases); diff --git a/tests-clay/attr/repo.c b/tests-clay/attr/repo.c index 3e9b9de1b..13f28ca84 100644 --- a/tests-clay/attr/repo.c +++ b/tests-clay/attr/repo.c @@ -45,19 +45,24 @@ void test_attr_repo__get_one(void) { "root_test3", "rootattr", NULL }, { "root_test3", "multiattr", "3" }, { "root_test3", "multi2", NULL }, - { "subdir/subdir_test1", "repoattr", GIT_ATTR_TRUE }, - { "subdir/subdir_test1", "rootattr", GIT_ATTR_TRUE }, - { "subdir/subdir_test1", "missingattr", NULL }, - { "subdir/subdir_test1", "subattr", "yes" }, - { "subdir/subdir_test1", "negattr", GIT_ATTR_FALSE }, - { "subdir/subdir_test1", "another", NULL }, - { "subdir/subdir_test2.txt", "repoattr", GIT_ATTR_TRUE }, - { "subdir/subdir_test2.txt", "rootattr", GIT_ATTR_TRUE }, - { "subdir/subdir_test2.txt", "missingattr", NULL }, - { "subdir/subdir_test2.txt", "subattr", "yes" }, - { "subdir/subdir_test2.txt", "negattr", GIT_ATTR_FALSE }, - { "subdir/subdir_test2.txt", "another", "one" }, + { "sub/subdir_test1", "repoattr", GIT_ATTR_TRUE }, + { "sub/subdir_test1", "rootattr", GIT_ATTR_TRUE }, + { "sub/subdir_test1", "missingattr", NULL }, + { "sub/subdir_test1", "subattr", "yes" }, + { "sub/subdir_test1", "negattr", GIT_ATTR_FALSE }, + { "sub/subdir_test1", "another", NULL }, + { "sub/subdir_test2.txt", "repoattr", GIT_ATTR_TRUE }, + { "sub/subdir_test2.txt", "rootattr", GIT_ATTR_TRUE }, + { "sub/subdir_test2.txt", "missingattr", NULL }, + { "sub/subdir_test2.txt", "subattr", "yes" }, + { "sub/subdir_test2.txt", "negattr", GIT_ATTR_FALSE }, + { "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" }, + { "sub/deep/file", "deepdeep", GIT_ATTR_TRUE }, { NULL, NULL, NULL } }, *scan; @@ -105,7 +110,7 @@ void test_attr_repo__get_many(void) cl_assert(values[2] == 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[1] == GIT_ATTR_TRUE); @@ -136,33 +141,33 @@ void test_attr_repo__foreach(void) cl_assert(count == 2); 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)); cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */ 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)); - 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) { 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_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_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_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_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); } diff --git a/tests-clay/status/ignore.c b/tests-clay/status/ignore.c new file mode 100644 index 000000000..f14e10c8e --- /dev/null +++ b/tests-clay/status/ignore.c @@ -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); + } +} diff --git a/tests/resources/attr/.gitted/info/attributes b/tests/resources/attr/.gitted/info/attributes index 2e9643a53d5783c1404ab877bbed0a9d59aa4662..5fe62a37a557431cf6412e813a6a0d47b6914023 100644 GIT binary patch delta 48 icmb1fpCF@MT$-e>rB_l>qEM7tkPqZ>fkZGwK@tFp@({ED delta 4 LcmZ>lnIHoI0iFx@Y8L36KRjEb!T*akH6J=dRQc_b3^wTnPQaKesOc3S* E0QNr;EC2ui delta 15 WcmeBTOqw9hR$Q8tl36s-&=mkE4h1U! diff --git a/tests/resources/attr/subdir/abc b/tests/resources/attr/sub/abc similarity index 100% rename from tests/resources/attr/subdir/abc rename to tests/resources/attr/sub/abc diff --git a/tests/resources/attr/sub/file b/tests/resources/attr/sub/file new file mode 100644 index 0000000000000000000000000000000000000000..45b983be36b73c0788dc9cbcb76cbb80fc7bb057 GIT binary patch literal 3 Kcmd1EthQ literal 0 HcmV?d00001 diff --git a/tests/resources/attr/subdir/subdir_test1 b/tests/resources/attr/sub/subdir_test1 similarity index 100% rename from tests/resources/attr/subdir/subdir_test1 rename to tests/resources/attr/sub/subdir_test1 diff --git a/tests/resources/attr/subdir/subdir_test2.txt b/tests/resources/attr/sub/subdir_test2.txt similarity index 100% rename from tests/resources/attr/subdir/subdir_test2.txt rename to tests/resources/attr/sub/subdir_test2.txt diff --git a/tests/resources/attr/subdir2/subdir2_test1 b/tests/resources/attr/subdir2/subdir2_test1 deleted file mode 100644 index dccada462d3df8ac6de596fb8c896aba9344f941..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19 acmeZB&B@7ENGr