summaryrefslogtreecommitdiff
path: root/src/attr.c
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2012-02-21 14:46:24 -0800
committerRussell Belfer <arrbee@arrbee.com>2012-02-21 14:46:24 -0800
commitb6c93aef4276051f9c4536ecbed48f4cd093bd1b (patch)
treea15962c672890c0c8cc021dafa7d29487f81c75a /src/attr.c
parent9c94a356cc61daa85e17c6342db9b3d62f788802 (diff)
downloadlibgit2-b6c93aef4276051f9c4536ecbed48f4cd093bd1b.tar.gz
Uniform iterators for trees, index, and workdir
This create a new git_iterator type of object that provides a uniform interface for iterating over the index, an arbitrary tree, or the working directory of a repository. As part of this, git ignore support was extended to support push and pop of directory-based ignore files as the working directory is being traversed (so the array of ignores does not have to be recreated at each directory during traveral). There are a number of other small utility functions in buffer, path, vector, and fileops that are included in this patch that made the iterator implementation cleaner.
Diffstat (limited to 'src/attr.c')
-rw-r--r--src/attr.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/src/attr.c b/src/attr.c
index 17571f6a8..a7c65f94c 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -218,6 +218,48 @@ int git_attr_cache__is_cached(git_repository *repo, const char *path)
return (git_hashtable_lookup(repo->attrcache.files, cache_key) == NULL);
}
+int git_attr_cache__lookup_or_create_file(
+ git_repository *repo,
+ const char *key,
+ const char *filename,
+ int (*loader)(git_repository *, const char *, git_attr_file *),
+ git_attr_file **file_ptr)
+{
+ int error;
+ git_attr_cache *cache = &repo->attrcache;
+ git_attr_file *file = NULL;
+
+ file = git_hashtable_lookup(cache->files, key);
+ if (file) {
+ *file_ptr = file;
+ return GIT_SUCCESS;
+ }
+
+ if (loader && git_path_exists(filename) != GIT_SUCCESS) {
+ *file_ptr = NULL;
+ return GIT_SUCCESS;
+ }
+
+ if ((error = git_attr_file__new(&file)) < GIT_SUCCESS)
+ return error;
+
+ if (loader)
+ error = loader(repo, filename, file);
+ else
+ error = git_attr_file__set_path(repo, key, file);
+
+ if (error == GIT_SUCCESS)
+ error = git_hashtable_insert(cache->files, file->path, file);
+
+ if (error < GIT_SUCCESS) {
+ git_attr_file__free(file);
+ file = NULL;
+ }
+
+ *file_ptr = file;
+ return error;
+}
+
/* add git_attr_file to vector of files, loading if needed */
int git_attr_cache__push_file(
git_repository *repo,
@@ -226,16 +268,14 @@ int git_attr_cache__push_file(
const char *filename,
int (*loader)(git_repository *, const char *, git_attr_file *))
{
- int error = GIT_SUCCESS;
- git_attr_cache *cache = &repo->attrcache;
+ int error;
git_buf path = GIT_BUF_INIT;
git_attr_file *file = NULL;
- int add_to_cache = 0;
const char *cache_key;
if (base != NULL) {
if ((error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS)
- goto cleanup;
+ return error;
filename = path.ptr;
}
@@ -244,28 +284,12 @@ int git_attr_cache__push_file(
if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
cache_key += strlen(git_repository_workdir(repo));
- file = git_hashtable_lookup(cache->files, cache_key);
- if (file == NULL && git_path_exists(filename) == GIT_SUCCESS) {
- if ((error = git_attr_file__new(&file)) == GIT_SUCCESS) {
- if ((error = loader(repo, filename, file)) < GIT_SUCCESS) {
- git_attr_file__free(file);
- file = NULL;
- }
- }
- add_to_cache = (error == GIT_SUCCESS);
- }
+ error = git_attr_cache__lookup_or_create_file(
+ repo, cache_key, filename, loader, &file);
- if (error == GIT_SUCCESS && file != NULL) {
- /* add file to vector, if we found it */
+ if (error == GIT_SUCCESS && file != NULL)
error = git_vector_insert(stack, file);
- /* add file to cache, if it is new */
- /* do this after above step b/c it is not critical */
- if (error == GIT_SUCCESS && add_to_cache && file->path != NULL)
- error = git_hashtable_insert(cache->files, file->path, file);
- }
-
-cleanup:
git_buf_free(&path);
return error;
}