From 6a67a812c224878483659c6f25ca21573d1c309b Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Wed, 11 Jan 2012 16:01:48 -0800 Subject: [PATCH] Allow ignores (and attribs) for nonexistent files This fixes issue 532 that attributes (and gitignores) could not be checked for files that don't exist. It should be possible to query such things regardless of the existence of the file. --- src/fileops.c | 24 ++++++++++++++++++------ src/fileops.h | 6 ++++-- src/ignore.c | 14 ++++++++++++++ src/ignore.h | 2 ++ tests-clay/attr/repo.c | 1 + tests-clay/status/worktree.c | 17 +++++++++++++++++ tests/resources/attr/gitattributes | Bin 602 -> 625 bytes 7 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index f481bb01d..1d991b36d 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -536,13 +536,25 @@ int git_futils_find_system_file(git_buf *path, const char *filename) int git_futils_dir_for_path(git_buf *dir, const char *path, const char *base) { - if (git_path_prettify(dir, path, base) == GIT_SUCCESS) { - /* call dirname if this is not a directory */ - if (git_futils_isdir(dir->ptr) != GIT_SUCCESS) - git_path_dirname_r(dir, dir->ptr); + int error = GIT_SUCCESS; - git_path_to_dir(dir); + if (base != NULL && git_path_root(path) < 0) + error = git_buf_joinpath(dir, base, path); + else + error = git_buf_sets(dir, path); + + if (error == GIT_SUCCESS) { + char buf[GIT_PATH_MAX]; + if (p_realpath(dir->ptr, buf) != NULL) + error = git_buf_sets(dir, buf); } - return git_buf_lasterror(dir); + /* call dirname if this is not a directory */ + if (error == GIT_SUCCESS && git_futils_isdir(dir->ptr) != GIT_SUCCESS) + error = git_path_dirname_r(dir, dir->ptr); + + if (error == GIT_SUCCESS) + error = git_path_to_dir(dir); + + return error; } diff --git a/src/fileops.h b/src/fileops.h index f3f09ec9f..91903a731 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -104,8 +104,10 @@ extern int git_futils_rmdir_r(const char *path, int force); /** * Get the directory for a path. * - * If the path is a directory, this does nothing (save append a '/' as needed). - * If path is a normal file, this gets the directory containing it. + * If the path is a directory, this does nothing (save append a '/' as + * needed). If path is a normal file, this gets the directory containing + * it. If the path does not exist, then this treats it a filename and + * returns the dirname of it. */ extern int git_futils_dir_for_path(git_buf *dir, const char *path, const char *base); diff --git a/src/ignore.c b/src/ignore.c index 8bf22e34a..7639b7ba9 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -146,3 +146,17 @@ found: return error; } + +int git_ignore_is_ignored(git_repository *repo, const char *path, int *ignored) +{ + int error; + git_vector ignores = GIT_VECTOR_INIT; + + if ((error = git_ignore__for_path(repo, path, &ignores)) == GIT_SUCCESS) + error = git_ignore__lookup(&ignores, path, ignored); + + git_ignore__free(&ignores); + + return error; +} + diff --git a/src/ignore.h b/src/ignore.h index 2954445b5..a6e6a1a34 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -14,4 +14,6 @@ extern int git_ignore__for_path(git_repository *repo, const char *path, git_vect extern void git_ignore__free(git_vector *stack); extern int git_ignore__lookup(git_vector *stack, const char *path, int *ignored); +extern int git_ignore_is_ignored(git_repository *repo, const char *path, int *ignored); + #endif diff --git a/tests-clay/attr/repo.c b/tests-clay/attr/repo.c index f87e7bf55..3e9b9de1b 100644 --- a/tests-clay/attr/repo.c +++ b/tests-clay/attr/repo.c @@ -57,6 +57,7 @@ void test_attr_repo__get_one(void) { "subdir/subdir_test2.txt", "subattr", "yes" }, { "subdir/subdir_test2.txt", "negattr", GIT_ATTR_FALSE }, { "subdir/subdir_test2.txt", "another", "one" }, + { "does-not-exist", "foo", "yes" }, { NULL, NULL, NULL } }, *scan; diff --git a/tests-clay/status/worktree.c b/tests-clay/status/worktree.c index 15cbb2828..af6f005a7 100644 --- a/tests-clay/status/worktree.c +++ b/tests-clay/status/worktree.c @@ -1,5 +1,6 @@ #include "clay_libgit2.h" #include "fileops.h" +#include "ignore.h" #include "status_data.h" @@ -135,3 +136,19 @@ void test_status_worktree__single_file(void) cl_assert(entry_statuses0[i] == status_flags); } } + +void test_status_worktree__ignores(void) +{ + int i, ignored; + + for (i = 0; i < (int)entry_count0; i++) { + cl_git_pass(git_ignore_is_ignored(_repository, entry_paths0[i], &ignored)); + cl_assert(ignored == (entry_statuses0[i] == GIT_STATUS_IGNORED)); + } + + cl_git_pass(git_ignore_is_ignored(_repository, "nonexistent_file", &ignored)); + cl_assert(!ignored); + + cl_git_pass(git_ignore_is_ignored(_repository, "ignored_nonexistent_file", &ignored)); + cl_assert(ignored); +} diff --git a/tests/resources/attr/gitattributes b/tests/resources/attr/gitattributes index 2b40c5aca159b04ea8d20ffe36cdf8b09369b14a..c0c2a56d0bfc4c576b8b6c1a4b7e905bb812c3c9 100644 GIT binary patch delta 33 ocmcb`@{wgitXN8ZYO!u!eu-{sMP_k{LRx;lZDnfl#+ZMM0N