Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2012-05-19 03:46:11 +0400
committerVicent Marti <tanoku@gmail.com>2012-05-19 03:46:11 +0400
commit5b9fac39d8a76b9139667c26a63e6b3f204b3977 (patch)
treee6ba28025f92c16563c4ffa8bc60b95f17d69691 /src/attr.c
parent7ef9f1b5606c2672105ecbbf34c022a71ef212fe (diff)
parentad5df35a47d56c3d716d7a56eac4aeb611987c11 (diff)
Merge branch 'development'v0.17.0
Conflicts: .travis.yml
Diffstat (limited to 'src/attr.c')
-rw-r--r--src/attr.c560
1 files changed, 407 insertions, 153 deletions
diff --git a/src/attr.c b/src/attr.c
index 17571f6a8..093f64d5c 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -3,13 +3,21 @@
#include "config.h"
#include <ctype.h>
+GIT__USE_STRMAP;
+
static int collect_attr_files(
- git_repository *repo, const char *path, git_vector *files);
+ git_repository *repo,
+ uint32_t flags,
+ const char *path,
+ git_vector *files);
int git_attr_get(
- git_repository *repo, const char *pathname,
- const char *name, const char **value)
+ const char **value,
+ git_repository *repo,
+ uint32_t flags,
+ const char *pathname,
+ const char *name)
{
int error;
git_attr_path path;
@@ -21,10 +29,11 @@ int git_attr_get(
*value = NULL;
- if ((error = git_attr_path__init(
- &path, pathname, git_repository_workdir(repo))) < GIT_SUCCESS ||
- (error = collect_attr_files(repo, pathname, &files)) < GIT_SUCCESS)
- return git__rethrow(error, "Could not get attribute for %s", pathname);
+ if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
+ return -1;
+
+ if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
+ goto cleanup;
attr.name = name;
attr.name_hash = git_attr_file__name_hash(name);
@@ -33,18 +42,17 @@ int git_attr_get(
git_attr_file__foreach_matching_rule(file, &path, j, rule) {
int pos = git_vector_bsearch(&rule->assigns, &attr);
- git_clearerror(); /* okay if search failed */
-
if (pos >= 0) {
*value = ((git_attr_assignment *)git_vector_get(
&rule->assigns, pos))->value;
- goto found;
+ goto cleanup;
}
}
}
-found:
+cleanup:
git_vector_free(&files);
+ git_attr_path__free(&path);
return error;
}
@@ -56,8 +64,12 @@ typedef struct {
} attr_get_many_info;
int git_attr_get_many(
- git_repository *repo, const char *pathname,
- size_t num_attr, const char **names, const char **values)
+ const char **values,
+ git_repository *repo,
+ uint32_t flags,
+ const char *pathname,
+ size_t num_attr,
+ const char **names)
{
int error;
git_attr_path path;
@@ -70,15 +82,14 @@ int git_attr_get_many(
memset((void *)values, 0, sizeof(const char *) * num_attr);
- if ((error = git_attr_path__init(
- &path, pathname, git_repository_workdir(repo))) < GIT_SUCCESS ||
- (error = collect_attr_files(repo, pathname, &files)) < GIT_SUCCESS)
- return git__rethrow(error, "Could not get attributes for %s", pathname);
+ if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
+ return -1;
- if ((info = git__calloc(num_attr, sizeof(attr_get_many_info))) == NULL) {
- git__rethrow(GIT_ENOMEM, "Could not get attributes for %s", pathname);
+ if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
goto cleanup;
- }
+
+ info = git__calloc(num_attr, sizeof(attr_get_many_info));
+ GITERR_CHECK_ALLOC(info);
git_vector_foreach(&files, i, file) {
@@ -96,8 +107,6 @@ int git_attr_get_many(
}
pos = git_vector_bsearch(&rule->assigns, &info[k].name);
- git_clearerror(); /* okay if search failed */
-
if (pos >= 0) {
info[k].found = (git_attr_assignment *)
git_vector_get(&rule->assigns, pos);
@@ -112,6 +121,7 @@ int git_attr_get_many(
cleanup:
git_vector_free(&files);
+ git_attr_path__free(&path);
git__free(info);
return error;
@@ -119,7 +129,9 @@ cleanup:
int git_attr_foreach(
- git_repository *repo, const char *pathname,
+ git_repository *repo,
+ uint32_t flags,
+ const char *pathname,
int (*callback)(const char *name, const char *value, void *payload),
void *payload)
{
@@ -130,18 +142,16 @@ int git_attr_foreach(
git_attr_file *file;
git_attr_rule *rule;
git_attr_assignment *assign;
- git_hashtable *seen = NULL;
+ git_strmap *seen = NULL;
- if ((error = git_attr_path__init(
- &path, pathname, git_repository_workdir(repo))) < GIT_SUCCESS ||
- (error = collect_attr_files(repo, pathname, &files)) < GIT_SUCCESS)
- return git__rethrow(error, "Could not get attributes for %s", pathname);
+ if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
+ return -1;
- seen = git_hashtable_alloc(8, git_hash__strhash_cb, git_hash__strcmp_cb);
- if (!seen) {
- error = GIT_ENOMEM;
+ if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
goto cleanup;
- }
+
+ seen = git_strmap_alloc();
+ GITERR_CHECK_ALLOC(seen);
git_vector_foreach(&files, i, file) {
@@ -149,27 +159,23 @@ int git_attr_foreach(
git_vector_foreach(&rule->assigns, k, assign) {
/* skip if higher priority assignment was already seen */
- if (git_hashtable_lookup(seen, assign->name))
+ if (git_strmap_exists(seen, assign->name))
continue;
- error = git_hashtable_insert(seen, assign->name, assign);
- if (error != GIT_SUCCESS)
- goto cleanup;
+ git_strmap_insert(seen, assign->name, assign, error);
+ if (error >= 0)
+ error = callback(assign->name, assign->value, payload);
- error = callback(assign->name, assign->value, payload);
- if (error != GIT_SUCCESS)
+ if (error != 0)
goto cleanup;
}
}
}
cleanup:
- if (seen)
- git_hashtable_free(seen);
+ git_strmap_free(seen);
git_vector_free(&files);
-
- if (error != GIT_SUCCESS)
- (void)git__rethrow(error, "Could not get attributes for %s", pathname);
+ git_attr_path__free(&path);
return error;
}
@@ -182,124 +188,332 @@ int git_attr_add_macro(
{
int error;
git_attr_rule *macro = NULL;
+ git_pool *pool;
- if ((error = git_attr_cache__init(repo)) < GIT_SUCCESS)
- return error;
+ if (git_attr_cache__init(repo) < 0)
+ return -1;
macro = git__calloc(1, sizeof(git_attr_rule));
- if (!macro)
- return GIT_ENOMEM;
+ GITERR_CHECK_ALLOC(macro);
- macro->match.pattern = git__strdup(name);
- if (!macro->match.pattern) {
- git__free(macro);
- return GIT_ENOMEM;
- }
+ pool = &git_repository_attr_cache(repo)->pool;
+
+ macro->match.pattern = git_pool_strdup(pool, name);
+ GITERR_CHECK_ALLOC(macro->match.pattern);
macro->match.length = strlen(macro->match.pattern);
macro->match.flags = GIT_ATTR_FNMATCH_MACRO;
- error = git_attr_assignment__parse(repo, &macro->assigns, &values);
+ error = git_attr_assignment__parse(repo, pool, &macro->assigns, &values);
- if (error == GIT_SUCCESS)
+ if (!error)
error = git_attr_cache__insert_macro(repo, macro);
- if (error < GIT_SUCCESS)
+ if (error < 0)
git_attr_rule__free(macro);
return error;
}
-int git_attr_cache__is_cached(git_repository *repo, const char *path)
+bool git_attr_cache__is_cached(
+ git_repository *repo, git_attr_file_source source, const char *path)
{
- const char *cache_key = path;
- if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
- cache_key += strlen(git_repository_workdir(repo));
- return (git_hashtable_lookup(repo->attrcache.files, cache_key) == NULL);
+ git_buf cache_key = GIT_BUF_INIT;
+ git_strmap *files = git_repository_attr_cache(repo)->files;
+ const char *workdir = git_repository_workdir(repo);
+ bool rval;
+
+ if (workdir && git__prefixcmp(path, workdir) == 0)
+ path += strlen(workdir);
+ if (git_buf_printf(&cache_key, "%d#%s", (int)source, path) < 0)
+ return false;
+
+ rval = git_strmap_exists(files, git_buf_cstr(&cache_key));
+
+ git_buf_free(&cache_key);
+
+ return rval;
+}
+
+static int load_attr_file(
+ const char **data,
+ git_attr_file_stat_sig *sig,
+ const char *filename)
+{
+ int error;
+ git_buf content = GIT_BUF_INIT;
+ struct stat st;
+
+ if (p_stat(filename, &st) < 0)
+ return GIT_ENOTFOUND;
+
+ if (sig != NULL &&
+ (git_time_t)st.st_mtime == sig->seconds &&
+ (git_off_t)st.st_size == sig->size &&
+ (unsigned int)st.st_ino == sig->ino)
+ return GIT_ENOTFOUND;
+
+ error = git_futils_readbuffer_updated(&content, filename, NULL, NULL);
+ if (error < 0)
+ return error;
+
+ if (sig != NULL) {
+ sig->seconds = (git_time_t)st.st_mtime;
+ sig->size = (git_off_t)st.st_size;
+ sig->ino = (unsigned int)st.st_ino;
+ }
+
+ *data = git_buf_detach(&content);
+
+ return 0;
+}
+
+static int load_attr_blob_from_index(
+ const char **content,
+ git_blob **blob,
+ git_repository *repo,
+ const git_oid *old_oid,
+ const char *relfile)
+{
+ int error;
+ git_index *index;
+ git_index_entry *entry;
+
+ if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
+ (error = git_index_find(index, relfile)) < 0)
+ return error;
+
+ entry = git_index_get(index, error);
+
+ if (old_oid && git_oid_cmp(old_oid, &entry->oid) == 0)
+ return GIT_ENOTFOUND;
+
+ if ((error = git_blob_lookup(blob, repo, &entry->oid)) < 0)
+ return error;
+
+ *content = git_blob_rawcontent(*blob);
+ return 0;
+}
+
+static int load_attr_from_cache(
+ git_attr_file **file,
+ git_attr_cache *cache,
+ git_attr_file_source source,
+ const char *relative_path)
+{
+ git_buf cache_key = GIT_BUF_INIT;
+ khiter_t cache_pos;
+
+ *file = NULL;
+
+ if (!cache || !cache->files)
+ return 0;
+
+ if (git_buf_printf(&cache_key, "%d#%s", (int)source, relative_path) < 0)
+ return -1;
+
+ cache_pos = git_strmap_lookup_index(cache->files, cache_key.ptr);
+
+ git_buf_free(&cache_key);
+
+ if (git_strmap_valid_index(cache->files, cache_pos))
+ *file = git_strmap_value_at(cache->files, cache_pos);
+
+ return 0;
+}
+
+int git_attr_cache__internal_file(
+ git_repository *repo,
+ const char *filename,
+ git_attr_file **file)
+{
+ int error = 0;
+ git_attr_cache *cache = git_repository_attr_cache(repo);
+ khiter_t cache_pos = git_strmap_lookup_index(cache->files, filename);
+
+ if (git_strmap_valid_index(cache->files, cache_pos)) {
+ *file = git_strmap_value_at(cache->files, cache_pos);
+ return 0;
+ }
+
+ if (git_attr_file__new(file, 0, filename, &cache->pool) < 0)
+ return -1;
+
+ git_strmap_insert(cache->files, (*file)->key + 2, *file, error);
+ if (error > 0)
+ error = 0;
+
+ return error;
}
-/* add git_attr_file to vector of files, loading if needed */
int git_attr_cache__push_file(
git_repository *repo,
- git_vector *stack,
- const char *base,
- const char *filename,
- int (*loader)(git_repository *, const char *, git_attr_file *))
+ const char *base,
+ const char *filename,
+ git_attr_file_source source,
+ git_attr_file_parser parse,
+ git_vector *stack)
{
- int error = GIT_SUCCESS;
- git_attr_cache *cache = &repo->attrcache;
+ int error = 0;
git_buf path = GIT_BUF_INIT;
+ const char *workdir = git_repository_workdir(repo);
+ const char *relfile, *content = NULL;
+ git_attr_cache *cache = git_repository_attr_cache(repo);
git_attr_file *file = NULL;
- int add_to_cache = 0;
- const char *cache_key;
+ git_blob *blob = NULL;
+ git_attr_file_stat_sig st;
- if (base != NULL) {
- if ((error = git_buf_joinpath(&path, base, filename)) < GIT_SUCCESS)
- goto cleanup;
+ assert(filename && stack);
+
+ /* join base and path as needed */
+ if (base != NULL && git_path_root(filename) < 0) {
+ if (git_buf_joinpath(&path, base, filename) < 0)
+ return -1;
filename = path.ptr;
}
- /* either get attr_file from cache or read from disk */
- cache_key = filename;
- 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;
- }
+ relfile = filename;
+ if (workdir && git__prefixcmp(relfile, workdir) == 0)
+ relfile += strlen(workdir);
+
+ /* check cache */
+ if (load_attr_from_cache(&file, cache, source, relfile) < 0)
+ return -1;
+
+ /* if not in cache, load data, parse, and cache */
+
+ if (source == GIT_ATTR_FILE_FROM_FILE) {
+ if (file)
+ memcpy(&st, &file->cache_data.st, sizeof(st));
+ else
+ memset(&st, 0, sizeof(st));
+
+ error = load_attr_file(&content, &st, filename);
+ } else {
+ error = load_attr_blob_from_index(&content, &blob,
+ repo, file ? &file->cache_data.oid : NULL, relfile);
+ }
+
+ if (error) {
+ /* not finding a file is not an error for this function */
+ if (error == GIT_ENOTFOUND) {
+ giterr_clear();
+ error = 0;
}
- add_to_cache = (error == GIT_SUCCESS);
+ goto finish;
}
- if (error == GIT_SUCCESS && file != NULL) {
- /* add file to vector, if we found it */
+ if (!file &&
+ (error = git_attr_file__new(&file, source, relfile, &cache->pool)) < 0)
+ goto finish;
+
+ if (parse && (error = parse(repo, content, file)) < 0)
+ goto finish;
+
+ git_strmap_insert(cache->files, file->key, file, error);
+ if (error > 0)
+ error = 0;
+
+ /* remember "cache buster" file signature */
+ if (blob)
+ git_oid_cpy(&file->cache_data.oid, git_object_id((git_object *)blob));
+ else
+ memcpy(&file->cache_data.st, &st, sizeof(st));
+
+finish:
+ /* push file onto vector if we found one*/
+ if (!error && 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);
- }
+ if (error != 0)
+ git_attr_file__free(file);
+
+ if (blob)
+ git_blob_free(blob);
+ else
+ git__free((void *)content);
-cleanup:
git_buf_free(&path);
+
return error;
}
-#define push_attrs(R,S,B,F) \
- git_attr_cache__push_file((R),(S),(B),(F),git_attr_file__from_file)
+#define push_attr_file(R,S,B,F) \
+ git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,(S))
typedef struct {
git_repository *repo;
+ uint32_t flags;
+ const char *workdir;
+ git_index *index;
git_vector *files;
} attr_walk_up_info;
+int git_attr_cache__decide_sources(
+ uint32_t flags, bool has_wd, bool has_index, git_attr_file_source *srcs)
+{
+ int count = 0;
+
+ switch (flags & 0x03) {
+ case GIT_ATTR_CHECK_FILE_THEN_INDEX:
+ if (has_wd)
+ srcs[count++] = GIT_ATTR_FILE_FROM_FILE;
+ if (has_index)
+ srcs[count++] = GIT_ATTR_FILE_FROM_INDEX;
+ break;
+ case GIT_ATTR_CHECK_INDEX_THEN_FILE:
+ if (has_index)
+ srcs[count++] = GIT_ATTR_FILE_FROM_INDEX;
+ if (has_wd)
+ srcs[count++] = GIT_ATTR_FILE_FROM_FILE;
+ break;
+ case GIT_ATTR_CHECK_INDEX_ONLY:
+ if (has_index)
+ srcs[count++] = GIT_ATTR_FILE_FROM_INDEX;
+ break;
+ }
+
+ return count;
+}
+
static int push_one_attr(void *ref, git_buf *path)
{
+ int error = 0, n_src, i;
attr_walk_up_info *info = (attr_walk_up_info *)ref;
- return push_attrs(info->repo, info->files, path->ptr, GIT_ATTR_FILE);
+ git_attr_file_source src[2];
+
+ n_src = git_attr_cache__decide_sources(
+ info->flags, info->workdir != NULL, info->index != NULL, src);
+
+ for (i = 0; !error && i < n_src; ++i)
+ error = git_attr_cache__push_file(
+ info->repo, path->ptr, GIT_ATTR_FILE, src[i],
+ git_attr_file__parse_buffer, info->files);
+
+ return error;
}
static int collect_attr_files(
- git_repository *repo, const char *path, git_vector *files)
+ git_repository *repo,
+ uint32_t flags,
+ const char *path,
+ git_vector *files)
{
- int error = GIT_SUCCESS;
+ int error;
git_buf dir = GIT_BUF_INIT;
- git_config *cfg;
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info;
- if ((error = git_attr_cache__init(repo)) < GIT_SUCCESS)
- goto cleanup;
-
- if ((error = git_vector_init(files, 4, NULL)) < GIT_SUCCESS)
- goto cleanup;
+ if (git_attr_cache__init(repo) < 0 ||
+ git_vector_init(files, 4, NULL) < 0)
+ return -1;
- if ((error = git_path_find_dir(&dir, path, workdir)) < GIT_SUCCESS)
+ /* Resolve path in a non-bare repo */
+ if (workdir != NULL)
+ error = git_path_find_dir(&dir, path, workdir);
+ else
+ error = git_path_dirname_r(&dir, path);
+ if (error < 0)
goto cleanup;
/* in precendence order highest to lowest:
@@ -309,38 +523,40 @@ static int collect_attr_files(
* - $GIT_PREFIX/etc/gitattributes
*/
- error = push_attrs(repo, files, repo->path_repository, GIT_ATTR_FILE_INREPO);
- if (error < GIT_SUCCESS)
+ error = push_attr_file(
+ repo, files, git_repository_path(repo), GIT_ATTR_FILE_INREPO);
+ if (error < 0)
goto cleanup;
- info.repo = repo;
+ info.repo = repo;
+ info.flags = flags;
+ info.workdir = workdir;
+ if (git_repository_index__weakptr(&info.index, repo) < 0)
+ giterr_clear(); /* no error even if there is no index */
info.files = files;
+
error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
- if (error < GIT_SUCCESS)
+ if (error < 0)
goto cleanup;
- if ((error = git_repository_config(&cfg, repo)) == GIT_SUCCESS) {
- const char *core_attribs = NULL;
- git_config_get_string(cfg, GIT_ATTR_CONFIG, &core_attribs);
- git_clearerror(); /* don't care if attributesfile is not set */
- if (core_attribs)
- error = push_attrs(repo, files, NULL, core_attribs);
- git_config_free(cfg);
+ if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) {
+ error = push_attr_file(
+ repo, files, NULL, git_repository_attr_cache(repo)->cfg_attr_file);
+ if (error < 0)
+ goto cleanup;
}
- if (error == GIT_SUCCESS) {
+ if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
- if (error == GIT_SUCCESS)
- error = push_attrs(repo, files, NULL, dir.ptr);
+ if (!error)
+ error = push_attr_file(repo, files, NULL, dir.ptr);
else if (error == GIT_ENOTFOUND)
- error = GIT_SUCCESS;
+ error = 0;
}
cleanup:
- if (error < GIT_SUCCESS) {
- git__rethrow(error, "Could not get attributes for '%s'", path);
+ if (error < 0)
git_vector_free(files);
- }
git_buf_free(&dir);
return error;
@@ -349,70 +565,108 @@ static int collect_attr_files(
int git_attr_cache__init(git_repository *repo)
{
- int error = GIT_SUCCESS;
- git_attr_cache *cache = &repo->attrcache;
+ int ret;
+ git_attr_cache *cache = git_repository_attr_cache(repo);
+ git_config *cfg;
if (cache->initialized)
- return GIT_SUCCESS;
+ return 0;
+
+ /* cache config settings for attributes and ignores */
+ if (git_repository_config__weakptr(&cfg, repo) < 0)
+ return -1;
+
+ ret = git_config_get_string(&cache->cfg_attr_file, cfg, GIT_ATTR_CONFIG);
+ if (ret < 0 && ret != GIT_ENOTFOUND)
+ return ret;
+
+ ret = git_config_get_string(&cache->cfg_excl_file, cfg, GIT_IGNORE_CONFIG);
+ if (ret < 0 && ret != GIT_ENOTFOUND)
+ return ret;
+
+ giterr_clear();
+ /* allocate hashtable for attribute and ignore file contents */
if (cache->files == NULL) {
- cache->files = git_hashtable_alloc(
- 8, git_hash__strhash_cb, git_hash__strcmp_cb);
- if (!cache->files)
- return git__throw(GIT_ENOMEM, "Could not initialize attribute cache");
+ cache->files = git_strmap_alloc();
+ GITERR_CHECK_ALLOC(cache->files);
}
+ /* allocate hashtable for attribute macros */
if (cache->macros == NULL) {
- cache->macros = git_hashtable_alloc(
- 8, git_hash__strhash_cb, git_hash__strcmp_cb);
- if (!cache->macros)
- return git__throw(GIT_ENOMEM, "Could not initialize attribute cache");
+ cache->macros = git_strmap_alloc();
+ GITERR_CHECK_ALLOC(cache->macros);
}
+ /* allocate string pool */
+ if (git_pool_init(&cache->pool, 1, 0) < 0)
+ return -1;
+
cache->initialized = 1;
/* insert default macros */
- error = git_attr_add_macro(repo, "binary", "-diff -crlf");
-
- return error;
+ return git_attr_add_macro(repo, "binary", "-diff -crlf -text");
}
void git_attr_cache_flush(
git_repository *repo)
{
+ git_attr_cache *cache;
+
if (!repo)
return;
- if (repo->attrcache.files) {
- const void *GIT_UNUSED(name);
+ cache = git_repository_attr_cache(repo);
+
+ if (cache->files != NULL) {
git_attr_file *file;
- GIT_HASHTABLE_FOREACH(repo->attrcache.files, name, file,
- git_attr_file__free(file));
+ git_strmap_foreach_value(cache->files, file, {
+ git_attr_file__free(file);
+ });
- git_hashtable_free(repo->attrcache.files);
- repo->attrcache.files = NULL;
+ git_strmap_free(cache->files);
}
- if (repo->attrcache.macros) {
- const void *GIT_UNUSED(name);
+ if (cache->macros != NULL) {
git_attr_rule *rule;
- GIT_HASHTABLE_FOREACH(repo->attrcache.macros, name, rule,
- git_attr_rule__free(rule));
+ git_strmap_foreach_value(cache->macros, rule, {
+ git_attr_rule__free(rule);
+ });
- git_hashtable_free(repo->attrcache.macros);
- repo->attrcache.macros = NULL;
+ git_strmap_free(cache->macros);
}
- repo->attrcache.initialized = 0;
+ git_pool_clear(&cache->pool);
+
+ cache->initialized = 0;
}
int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
{
+ git_strmap *macros = git_repository_attr_cache(repo)->macros;
+ int error;
+
+ /* TODO: generate warning log if (macro->assigns.length == 0) */
if (macro->assigns.length == 0)
- return git__throw(GIT_EMISSINGOBJDATA, "git attribute macro with no values");
+ return 0;
- return git_hashtable_insert(
- repo->attrcache.macros, macro->match.pattern, macro);
+ git_strmap_insert(macros, macro->match.pattern, macro, error);
+ return (error < 0) ? -1 : 0;
}
+
+git_attr_rule *git_attr_cache__lookup_macro(
+ git_repository *repo, const char *name)
+{
+ git_strmap *macros = git_repository_attr_cache(repo)->macros;
+ khiter_t pos;
+
+ pos = git_strmap_lookup_index(macros, name);
+
+ if (!git_strmap_valid_index(macros, pos))
+ return NULL;
+
+ return (git_attr_rule *)git_strmap_value_at(macros, pos);
+}
+