diff options
author | Russell Belfer <arrbee@arrbee.com> | 2012-02-21 14:46:24 -0800 |
---|---|---|
committer | Russell Belfer <arrbee@arrbee.com> | 2012-02-21 14:46:24 -0800 |
commit | b6c93aef4276051f9c4536ecbed48f4cd093bd1b (patch) | |
tree | a15962c672890c0c8cc021dafa7d29487f81c75a /src/attr.c | |
parent | 9c94a356cc61daa85e17c6342db9b3d62f788802 (diff) | |
download | libgit2-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.c | 70 |
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; } |