summaryrefslogtreecommitdiff
path: root/src/attr.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-01-29 14:40:55 -0600
committerEdward Thomson <ethomson@microsoft.com>2015-02-03 00:31:08 -0500
commit9f779aacdd950fd53a407da615ca60d628e31d35 (patch)
tree55819aa11a18e2d272d75118239d23243b49357a /src/attr.c
parent60561d54468d7097e04466fd8125be5231cea637 (diff)
downloadlibgit2-9f779aacdd950fd53a407da615ca60d628e31d35.tar.gz
attrcache: don't re-read attrs during checkout
During checkout, assume that the .gitattributes files aren't modified during the checkout. Instead, create an "attribute session" during checkout. Assume that attribute data read in the same checkout "session" hasn't been modified since the checkout started. (But allow subsequent checkouts to invalidate the cache.) Further, cache nonexistent git_attr_file data even when .gitattributes files are not found to prevent re-scanning for nonexistent files.
Diffstat (limited to 'src/attr.c')
-rw-r--r--src/attr.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/src/attr.c b/src/attr.c
index a02172689..df139e082 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -29,6 +29,7 @@ git_attr_t git_attr_value(const char *attr)
static int collect_attr_files(
git_repository *repo,
+ git_attr_session *attr_session,
uint32_t flags,
const char *path,
git_vector *files);
@@ -57,7 +58,7 @@ int git_attr_get(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1;
- if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
+ if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0)
goto cleanup;
memset(&attr, 0, sizeof(attr));
@@ -90,9 +91,10 @@ typedef struct {
git_attr_assignment *found;
} attr_get_many_info;
-int git_attr_get_many(
+int git_attr_get_many_with_session(
const char **values,
git_repository *repo,
+ git_attr_session *attr_session,
uint32_t flags,
const char *pathname,
size_t num_attr,
@@ -115,7 +117,7 @@ int git_attr_get_many(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1;
- if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
+ if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0)
goto cleanup;
info = git__calloc(num_attr, sizeof(attr_get_many_info));
@@ -161,6 +163,17 @@ cleanup:
return error;
}
+int git_attr_get_many(
+ const char **values,
+ git_repository *repo,
+ uint32_t flags,
+ const char *pathname,
+ size_t num_attr,
+ const char **names)
+{
+ return git_attr_get_many_with_session(
+ values, repo, NULL, flags, pathname, num_attr, names);
+}
int git_attr_foreach(
git_repository *repo,
@@ -183,7 +196,7 @@ int git_attr_foreach(
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1;
- if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0 ||
+ if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 ||
(error = git_strmap_alloc(&seen)) < 0)
goto cleanup;
@@ -219,6 +232,7 @@ cleanup:
static int preload_attr_file(
git_repository *repo,
+ git_attr_session *attr_session,
git_attr_file_source source,
const char *base,
const char *file)
@@ -229,19 +243,22 @@ static int preload_attr_file(
if (!file)
return 0;
if (!(error = git_attr_cache__get(
- &preload, repo, source, base, file, git_attr_file__parse_buffer)))
+ &preload, repo, attr_session, source, base, file, git_attr_file__parse_buffer)))
git_attr_file__free(preload);
return error;
}
-static int attr_setup(git_repository *repo)
+static int attr_setup(git_repository *repo, git_attr_session *attr_session)
{
int error = 0;
const char *workdir = git_repository_workdir(repo);
git_index *idx = NULL;
git_buf sys = GIT_BUF_INIT;
+ if (attr_session && attr_session->setup)
+ return 0;
+
if ((error = git_attr_cache__init(repo)) < 0)
return error;
@@ -251,7 +268,7 @@ static int attr_setup(git_repository *repo)
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);
+ repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, sys.ptr);
git_buf_free(&sys);
}
if (error < 0) {
@@ -263,25 +280,28 @@ static int attr_setup(git_repository *repo)
}
if ((error = preload_attr_file(
- repo, GIT_ATTR_FILE__FROM_FILE,
+ repo, attr_session, 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,
+ repo, attr_session, 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)
+ repo, attr_session, 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)
+ repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0)
return error;
+ if (attr_session)
+ attr_session->setup = 1;
+
return error;
}
@@ -321,6 +341,7 @@ int git_attr_add_macro(
typedef struct {
git_repository *repo;
+ git_attr_session *attr_session;
uint32_t flags;
const char *workdir;
git_index *index;
@@ -356,6 +377,7 @@ static int attr_decide_sources(
static int push_attr_file(
git_repository *repo,
+ git_attr_session *attr_session,
git_vector *list,
git_attr_file_source source,
const char *base,
@@ -364,8 +386,9 @@ static int push_attr_file(
int error = 0;
git_attr_file *file = NULL;
- error = git_attr_cache__get(
- &file, repo, source, base, filename, git_attr_file__parse_buffer);
+ error = git_attr_cache__get(&file, repo, attr_session,
+ source, base, filename, git_attr_file__parse_buffer);
+
if (error < 0)
return error;
@@ -387,8 +410,8 @@ static int push_one_attr(void *ref, const char *path)
info->flags, info->workdir != NULL, info->index != NULL, src);
for (i = 0; !error && i < n_src; ++i)
- error = push_attr_file(
- info->repo, info->files, src[i], path, GIT_ATTR_FILE);
+ error = push_attr_file(info->repo, info->attr_session,
+ info->files, src[i], path, GIT_ATTR_FILE);
return error;
}
@@ -407,6 +430,7 @@ static void release_attr_files(git_vector *files)
static int collect_attr_files(
git_repository *repo,
+ git_attr_session *attr_session,
uint32_t flags,
const char *path,
git_vector *files)
@@ -416,7 +440,7 @@ static int collect_attr_files(
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
- if ((error = attr_setup(repo)) < 0)
+ if ((error = attr_setup(repo, attr_session)) < 0)
return error;
/* Resolve path in a non-bare repo */
@@ -435,12 +459,13 @@ static int collect_attr_files(
*/
error = push_attr_file(
- repo, files, GIT_ATTR_FILE__FROM_FILE,
+ repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
git_repository_path(repo), GIT_ATTR_FILE_INREPO);
if (error < 0)
goto cleanup;
- info.repo = repo;
+ info.repo = repo;
+ info.attr_session = attr_session;
info.flags = flags;
info.workdir = workdir;
if (git_repository_index__weakptr(&info.index, repo) < 0)
@@ -457,7 +482,7 @@ static int collect_attr_files(
if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) {
error = push_attr_file(
- repo, files, GIT_ATTR_FILE__FROM_FILE,
+ repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
NULL, git_repository_attr_cache(repo)->cfg_attr_file);
if (error < 0)
goto cleanup;
@@ -467,7 +492,8 @@ static int collect_attr_files(
error = git_sysdir_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
if (!error)
error = push_attr_file(
- repo, files, GIT_ATTR_FILE__FROM_FILE, NULL, dir.ptr);
+ repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
+ NULL, dir.ptr);
else if (error == GIT_ENOTFOUND) {
giterr_clear();
error = 0;