summaryrefslogtreecommitdiff
path: root/src/attr.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2014-04-18 14:29:58 -0700
committerRussell Belfer <rb@github.com>2014-04-18 14:29:58 -0700
commite3a2a04ceff1d3657629fd6a7245d9a9fc53f24b (patch)
treefda2ccea16cfb9295ecad38ad16de9ec2eeee65e /src/attr.c
parent50e46d6018ede64e3e4b177baa4ad8156d928fbd (diff)
downloadlibgit2-e3a2a04ceff1d3657629fd6a7245d9a9fc53f24b.tar.gz
Preload attribute files that may contain macros
There was a latent bug where files that use macro definitions could be parsed before the macro definitions were loaded. Because of attribute file caching, preloading files that are going to be used doesn't add a significant amount of overhead, so let's always preload any files that could contain macros before we assemble the actual vector of files to scan for attributes.
Diffstat (limited to 'src/attr.c')
-rw-r--r--src/attr.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/src/attr.c b/src/attr.c
index 622874348..6b9a3d614 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -217,6 +217,74 @@ cleanup:
return error;
}
+static int preload_attr_file(
+ git_repository *repo,
+ git_attr_file_source source,
+ const char *base,
+ const char *file)
+{
+ int error;
+ git_attr_file *preload = NULL;
+
+ if (!file)
+ return 0;
+ if (!(error = git_attr_cache__get(
+ &preload, repo, source, base, file, git_attr_file__parse_buffer)))
+ git_attr_file__free(preload);
+
+ return error;
+}
+
+static int attr_setup(git_repository *repo)
+{
+ int error = 0;
+ const char *workdir = git_repository_workdir(repo);
+ git_index *idx = NULL;
+ git_buf sys = GIT_BUF_INIT;
+
+ if ((error = git_attr_cache__init(repo)) < 0)
+ return error;
+
+ /* preload attribute files that could contain macros so the
+ * definitions will be available for later file parsing
+ */
+
+ if (!(error = git_sysdir_find_system_file(&sys, GIT_ATTR_FILE_SYSTEM))) {
+ error = preload_attr_file(
+ repo, GIT_ATTR_FILE__FROM_FILE, NULL, sys.ptr);
+ git_buf_free(&sys);
+ }
+ if (error < 0) {
+ if (error == GIT_ENOTFOUND) {
+ giterr_clear();
+ error = 0;
+ } else
+ return error;
+ }
+
+ if ((error = preload_attr_file(
+ repo, GIT_ATTR_FILE__FROM_FILE,
+ NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
+ return error;
+
+ if ((error = preload_attr_file(
+ repo, GIT_ATTR_FILE__FROM_FILE,
+ git_repository_path(repo), GIT_ATTR_FILE_INREPO)) < 0)
+ return error;
+
+ if (workdir != NULL &&
+ (error = preload_attr_file(
+ repo, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0)
+ return error;
+
+ if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
+ (error = preload_attr_file(
+ repo, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0)
+ return error;
+
+ return error;
+}
+
int git_attr_add_macro(
git_repository *repo,
const char *name,
@@ -226,8 +294,8 @@ int git_attr_add_macro(
git_attr_rule *macro = NULL;
git_pool *pool;
- if (git_attr_cache__init(repo) < 0)
- return -1;
+ if ((error = attr_setup(repo)) < 0)
+ return error;
macro = git__calloc(1, sizeof(git_attr_rule));
GITERR_CHECK_ALLOC(macro);
@@ -348,7 +416,7 @@ static int collect_attr_files(
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
- if ((error = git_attr_cache__init(repo)) < 0)
+ if ((error = attr_setup(repo)) < 0)
return error;
/* Resolve path in a non-bare repo */