]> git.proxmox.com Git - libgit2.git/blobdiff - src/attr.c
Merge pull request #968 from arrbee/diff-support-typechange
[libgit2.git] / src / attr.c
index 1aa965de35f56034c60f5cfee22d5bbb98f03502..025ad3c87236712fe67c2caa8b7ce114776c2992 100644 (file)
@@ -1,10 +1,30 @@
 #include "repository.h"
 #include "fileops.h"
 #include "config.h"
+#include "git2/oid.h"
 #include <ctype.h>
 
 GIT__USE_STRMAP;
 
+const char *git_attr__true  = "[internal]__TRUE__";
+const char *git_attr__false = "[internal]__FALSE__";
+const char *git_attr__unset = "[internal]__UNSET__";
+
+git_attr_t git_attr_value(const char *attr)
+{
+       if (attr == NULL || attr == git_attr__unset)
+               return GIT_ATTR_UNSPECIFIED_T;
+
+       if (attr == git_attr__true)
+               return GIT_ATTR_TRUE_T;
+
+       if (attr == git_attr__false)
+               return GIT_ATTR_FALSE_T;
+
+       return GIT_ATTR_VALUE_T;
+}
+
+
 static int collect_attr_files(
        git_repository *repo,
        uint32_t flags,
@@ -13,16 +33,16 @@ static int collect_attr_files(
 
 
 int git_attr_get(
+       const char **value,
     git_repository *repo,
        uint32_t flags,
        const char *pathname,
-       const char *name,
-       const char **value)
+       const char *name)
 {
        int error;
        git_attr_path path;
        git_vector files = GIT_VECTOR_INIT;
-       unsigned int i, j;
+       size_t i, j;
        git_attr_file *file;
        git_attr_name attr;
        git_attr_rule *rule;
@@ -64,17 +84,17 @@ typedef struct {
 } attr_get_many_info;
 
 int git_attr_get_many(
+       const char **values,
     git_repository *repo,
        uint32_t flags,
        const char *pathname,
     size_t num_attr,
-       const char **names,
-       const char **values)
+       const char **names)
 {
        int error;
        git_attr_path path;
        git_vector files = GIT_VECTOR_INIT;
-       unsigned int i, j, k;
+       size_t i, j, k;
        git_attr_file *file;
        git_attr_rule *rule;
        attr_get_many_info *info = NULL;
@@ -138,7 +158,7 @@ int git_attr_foreach(
        int error;
        git_attr_path path;
        git_vector files = GIT_VECTOR_INIT;
-       unsigned int i, j, k;
+       size_t i, j, k;
        git_attr_file *file;
        git_attr_rule *rule;
        git_attr_assignment *assign;
@@ -163,11 +183,15 @@ int git_attr_foreach(
                                        continue;
 
                                git_strmap_insert(seen, assign->name, assign, error);
-                               if (error >= 0)
-                                       error = callback(assign->name, assign->value, payload);
+                               if (error < 0)
+                                       goto cleanup;
 
-                               if (error != 0)
+                               error = callback(assign->name, assign->value, payload);
+                               if (error) {
+                                       giterr_clear();
+                                       error = GIT_EUSER;
                                        goto cleanup;
+                               }
                        }
                }
        }
@@ -352,6 +376,7 @@ int git_attr_cache__push_file(
        const char *filename,
        git_attr_file_source source,
        git_attr_file_parser parse,
+       void* parsedata,
        git_vector *stack)
 {
        int error = 0;
@@ -403,14 +428,19 @@ int git_attr_cache__push_file(
                goto finish;
        }
 
-       if (!file &&
-               (error = git_attr_file__new(&file, source, relfile, &cache->pool)) < 0)
-               goto finish;
+       /* if we got here, we have to parse and/or reparse the file */
+       if (file)
+               git_attr_file__clear_rules(file);
+       else {
+               error = git_attr_file__new(&file, source, relfile, &cache->pool);
+               if (error < 0)
+                       goto finish;
+       }
 
-       if (parse && (error = parse(repo, content, file)) < 0)
+       if (parse && (error = parse(repo, parsedata, content, file)) < 0)
                goto finish;
 
-       git_strmap_insert(cache->files, file->key, file, error);
+       git_strmap_insert(cache->files, file->key, file, error); //-V595
        if (error > 0)
                error = 0;
 
@@ -439,7 +469,7 @@ finish:
 }
 
 #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))
+       git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,NULL,(S))
 
 typedef struct {
        git_repository *repo;
@@ -488,7 +518,7 @@ static int push_one_attr(void *ref, git_buf *path)
        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);
+                       git_attr_file__parse_buffer, NULL, info->files);
 
        return error;
 }
@@ -562,6 +592,18 @@ static int collect_attr_files(
        return error;
 }
 
+static char *try_global_default(const char *relpath)
+{
+       git_buf dflt = GIT_BUF_INIT;
+       char *rval = NULL;
+
+       if (!git_futils_find_global_file(&dflt, relpath))
+               rval = git_buf_detach(&dflt);
+
+       git_buf_free(&dflt);
+
+       return rval;
+}
 
 int git_attr_cache__init(git_repository *repo)
 {
@@ -576,13 +618,17 @@ int git_attr_cache__init(git_repository *repo)
        if (git_repository_config__weakptr(&cfg, repo) < 0)
                return -1;
 
-       ret = git_config_get_string(cfg, GIT_ATTR_CONFIG, &cache->cfg_attr_file);
+       ret = git_config_get_string(&cache->cfg_attr_file, cfg, GIT_ATTR_CONFIG);
        if (ret < 0 && ret != GIT_ENOTFOUND)
                return ret;
+       if (ret == GIT_ENOTFOUND)
+               cache->cfg_attr_file = try_global_default(GIT_ATTR_CONFIG_DEFAULT);
 
-       ret = git_config_get_string(cfg, GIT_IGNORE_CONFIG, &cache->cfg_excl_file);
+       ret = git_config_get_string(&cache->cfg_excl_file, cfg, GIT_IGNORE_CONFIG);
        if (ret < 0 && ret != GIT_ENOTFOUND)
                return ret;
+       if (ret == GIT_ENOTFOUND)
+               cache->cfg_excl_file = try_global_default(GIT_IGNORE_CONFIG_DEFAULT);
 
        giterr_clear();