summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2012-01-16 16:58:27 -0800
committerRussell Belfer <arrbee@arrbee.com>2012-01-16 16:58:27 -0800
commita51cd8e6f6724079a552b75e014f792f3f68e158 (patch)
treefcf526f2a7575e215d95589d1a8e07277981fd18
parent6e03b12f5715cb3f5cb5c8be6512e041cdf44a05 (diff)
downloadlibgit2-a51cd8e6f6724079a552b75e014f792f3f68e158.tar.gz
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.
-rw-r--r--src/attr.c7
-rw-r--r--src/attr.h2
-rw-r--r--src/attr_file.c113
-rw-r--r--src/attr_file.h12
-rw-r--r--src/ignore.c28
-rw-r--r--src/util.c17
-rw-r--r--src/util.h2
-rw-r--r--tests-clay/attr/file.c20
-rw-r--r--tests-clay/attr/lookup.c25
-rw-r--r--tests-clay/attr/repo.c47
-rw-r--r--tests-clay/status/ignore.c49
-rw-r--r--tests/resources/attr/.gitted/info/attributes2
-rw-r--r--tests/resources/attr/file1
-rw-r--r--tests/resources/attr/gitignore2
-rw-r--r--tests/resources/attr/ign1
-rw-r--r--tests/resources/attr/sub/.gitattributes (renamed from tests/resources/attr/subdir/.gitattributes)4
-rw-r--r--tests/resources/attr/sub/abc (renamed from tests/resources/attr/subdir/abc)0
-rw-r--r--tests/resources/attr/sub/file1
-rw-r--r--tests/resources/attr/sub/ign1
-rw-r--r--tests/resources/attr/sub/sub/file1
-rw-r--r--tests/resources/attr/sub/sub/subsub.txt1
-rw-r--r--tests/resources/attr/sub/subdir_test1 (renamed from tests/resources/attr/subdir/subdir_test1)0
-rw-r--r--tests/resources/attr/sub/subdir_test2.txt (renamed from tests/resources/attr/subdir/subdir_test2.txt)0
-rw-r--r--tests/resources/attr/subdir2/subdir2_test11
24 files changed, 232 insertions, 105 deletions
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,32 +333,40 @@ int git_attr_fnmatch__parse(
*base = scan;
spec->length = scan - pattern;
- 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;
}
+ 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 */
+ 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,13 +62,16 @@ typedef struct {
* git_attr_file API
*/
+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 **out);
+ 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 **out);
+ git_repository *repo, const char *path, git_attr_file *file);
-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__set_path(
+ git_repository *repo, const char *path, git_attr_file *file);
extern int git_attr_file__lookup_one(
git_attr_file *file,
@@ -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 ((error = git_futils_readbuffer(&fbuf, path)) == GIT_SUCCESS)
- error = git_attr_file__new(&ignores);
+ 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;
+ }
- 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 2e9643a53..5fe62a37a 100644
--- a/tests/resources/attr/.gitted/info/attributes
+++ b/tests/resources/attr/.gitted/info/attributes
@@ -1,2 +1,4 @@
* repoattr
a* foo !bar -baz
+sub/*.txt reposub
+sub/sub/*.txt reposubsub
diff --git a/tests/resources/attr/file b/tests/resources/attr/file
new file mode 100644
index 000000000..45b983be3
--- /dev/null
+++ b/tests/resources/attr/file
@@ -0,0 +1 @@
+hi
diff --git a/tests/resources/attr/gitignore b/tests/resources/attr/gitignore
new file mode 100644
index 000000000..66f77694e
--- /dev/null
+++ b/tests/resources/attr/gitignore
@@ -0,0 +1,2 @@
+sub
+ign
diff --git a/tests/resources/attr/ign b/tests/resources/attr/ign
new file mode 100644
index 000000000..592fd2594
--- /dev/null
+++ b/tests/resources/attr/ign
@@ -0,0 +1 @@
+ignore me
diff --git a/tests/resources/attr/subdir/.gitattributes b/tests/resources/attr/sub/.gitattributes
index 99eae4768..329c1c5b8 100644
--- a/tests/resources/attr/subdir/.gitattributes
+++ b/tests/resources/attr/sub/.gitattributes
@@ -1,5 +1,7 @@
* subattr=yes -negattr
-subdir/*.txt another=one
+*.txt another=zero
+sub/*.txt another=one
ab* merge=filfre
abc -foo -bar
*.c frotz
+deep/file deepdeep
diff --git a/tests/resources/attr/subdir/abc b/tests/resources/attr/sub/abc
index 3e42ffc54..3e42ffc54 100644
--- a/tests/resources/attr/subdir/abc
+++ b/tests/resources/attr/sub/abc
diff --git a/tests/resources/attr/sub/file b/tests/resources/attr/sub/file
new file mode 100644
index 000000000..45b983be3
--- /dev/null
+++ b/tests/resources/attr/sub/file
@@ -0,0 +1 @@
+hi
diff --git a/tests/resources/attr/sub/ign b/tests/resources/attr/sub/ign
new file mode 100644
index 000000000..592fd2594
--- /dev/null
+++ b/tests/resources/attr/sub/ign
@@ -0,0 +1 @@
+ignore me
diff --git a/tests/resources/attr/sub/sub/file b/tests/resources/attr/sub/sub/file
new file mode 100644
index 000000000..45b983be3
--- /dev/null
+++ b/tests/resources/attr/sub/sub/file
@@ -0,0 +1 @@
+hi
diff --git a/tests/resources/attr/sub/sub/subsub.txt b/tests/resources/attr/sub/sub/subsub.txt
new file mode 100644
index 000000000..9e5bdc47d
--- /dev/null
+++ b/tests/resources/attr/sub/sub/subsub.txt
@@ -0,0 +1 @@
+subsub
diff --git a/tests/resources/attr/subdir/subdir_test1 b/tests/resources/attr/sub/subdir_test1
index e563cf475..e563cf475 100644
--- a/tests/resources/attr/subdir/subdir_test1
+++ b/tests/resources/attr/sub/subdir_test1
diff --git a/tests/resources/attr/subdir/subdir_test2.txt b/tests/resources/attr/sub/subdir_test2.txt
index fb5067b1a..fb5067b1a 100644
--- a/tests/resources/attr/subdir/subdir_test2.txt
+++ b/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 dccada462..000000000
--- a/tests/resources/attr/subdir2/subdir2_test1
+++ /dev/null
@@ -1 +0,0 @@
-Hello from subdir2