summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-02-03 00:03:49 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2015-02-04 14:15:12 +0000
commitd4b1b76701cb0495993b31b1b0e98c0a4b49c0ce (patch)
treee05cb53262e45ac7db6a6f3ea65cb34dbde742ff
parent9f779aacdd950fd53a407da615ca60d628e31d35 (diff)
downloadlibgit2-d4b1b76701cb0495993b31b1b0e98c0a4b49c0ce.tar.gz
checkout: cache system attributes file location
-rw-r--r--src/attr.c68
-rw-r--r--src/attr_file.c10
-rw-r--r--src/attr_file.h4
3 files changed, 65 insertions, 17 deletions
diff --git a/src/attr.c b/src/attr.c
index df139e082..020bb1c8b 100644
--- a/src/attr.c
+++ b/src/attr.c
@@ -249,6 +249,46 @@ static int preload_attr_file(
return error;
}
+static int system_attr_file(
+ git_buf *out,
+ git_repository *repo,
+ git_attr_session *attr_session)
+{
+ int error;
+
+ if (!attr_session) {
+ error = git_sysdir_find_system_file(out, GIT_ATTR_FILE_SYSTEM);
+
+ if (error == GIT_ENOTFOUND)
+ giterr_clear();
+
+ return error;
+ }
+
+ if (!attr_session->init_sysdir) {
+ error = git_sysdir_find_system_file(&attr_session->sysdir, GIT_ATTR_FILE_SYSTEM);
+
+ if (error == GIT_ENOTFOUND)
+ giterr_clear();
+ else if (error)
+ return error;
+
+ attr_session->init_sysdir = 1;
+ }
+
+ if (attr_session->sysdir.size == 0)
+ return GIT_ENOTFOUND;
+
+ /* We can safely provide a git_buf with no allocation (asize == 0) to
+ * a consumer. This allows them to treat this as a regular `git_buf`,
+ * but their call to `git_buf_free` will not attempt to free it.
+ */
+ out->ptr = attr_session->sysdir.ptr;
+ out->size = attr_session->sysdir.size;
+ out->asize = 0;
+ return 0;
+}
+
static int attr_setup(git_repository *repo, git_attr_session *attr_session)
{
int error = 0;
@@ -256,7 +296,7 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
git_index *idx = NULL;
git_buf sys = GIT_BUF_INIT;
- if (attr_session && attr_session->setup)
+ if (attr_session && attr_session->init_setup)
return 0;
if ((error = git_attr_cache__init(repo)) < 0)
@@ -266,18 +306,15 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
* definitions will be available for later file parsing
*/
- if (!(error = git_sysdir_find_system_file(&sys, GIT_ATTR_FILE_SYSTEM))) {
+ error = system_attr_file(&sys, repo, attr_session);
+
+ if (error == 0)
error = preload_attr_file(
repo, attr_session, 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;
- }
+ else if (error != GIT_ENOTFOUND)
+ return error;
+
+ git_buf_free(&sys);
if ((error = preload_attr_file(
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
@@ -300,7 +337,7 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
return error;
if (attr_session)
- attr_session->setup = 1;
+ attr_session->init_setup = 1;
return error;
}
@@ -489,15 +526,14 @@ static int collect_attr_files(
}
if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
- error = git_sysdir_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
+ error = system_attr_file(&dir, repo, attr_session);
+
if (!error)
error = push_attr_file(
repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
NULL, dir.ptr);
- else if (error == GIT_ENOTFOUND) {
- giterr_clear();
+ else if (error == GIT_ENOTFOUND)
error = 0;
- }
}
cleanup:
diff --git a/src/attr_file.c b/src/attr_file.c
index 9896df4f9..2ebd3b91f 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -854,3 +854,13 @@ int git_attr_session__init(git_attr_session *session, git_repository *repo)
return 0;
}
+
+void git_attr_session__free(git_attr_session *session)
+{
+ if (!session)
+ return;
+
+ git_buf_free(&session->sysdir);
+
+ memset(session, 0, sizeof(git_attr_session));
+}
diff --git a/src/attr_file.h b/src/attr_file.h
index b8e37256b..5c64f7cc3 100644
--- a/src/attr_file.h
+++ b/src/attr_file.h
@@ -111,7 +111,9 @@ typedef struct {
typedef struct {
int key;
- unsigned int setup;
+ unsigned int init_setup:1,
+ init_sysdir:1;
+ git_buf sysdir;
} git_attr_session;
extern int git_attr_session__init(git_attr_session *attr_session, git_repository *repo);