summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--file/git-file.c2
-rw-r--r--file/git-hist.c4
-rw-r--r--file/git-util.c35
-rw-r--r--file/git-util.h3
4 files changed, 41 insertions, 3 deletions
diff --git a/file/git-file.c b/file/git-file.c
index 24c90fb..10e70a4 100644
--- a/file/git-file.c
+++ b/file/git-file.c
@@ -79,7 +79,7 @@ static git_repository *select_repo(const char *path)
*/
while (1) {
progress(3, "trying \"%s\"", tmp);
- if (!git_repository_open_ext(&repo, *tmp ? tmp : "/",
+ if (!git_repository_open_ext_caching(&repo, *tmp ? tmp : "/",
GIT_REPOSITORY_OPEN_CROSS_FS, NULL))
break;
slash = strrchr(tmp, '/');
diff --git a/file/git-hist.c b/file/git-hist.c
index 0359673..24d0252 100644
--- a/file/git-hist.c
+++ b/file/git-hist.c
@@ -210,7 +210,7 @@ bool vcs_git_try(const char *path)
* exists, but then it would complain about the file not existing,
* which would be at best confusing.
*/
- if (git_repository_open_ext(&repo, path,
+ if (git_repository_open_ext_caching(&repo, path,
GIT_REPOSITORY_OPEN_CROSS_FS, NULL))
return 0;
if (git_repository_is_empty(repo))
@@ -267,7 +267,7 @@ struct vcs_history *vcs_git_history(const char *path, unsigned depth)
git_init_once();
- if (git_repository_open_ext(&history->repo, path,
+ if (git_repository_open_ext_caching(&history->repo, path,
GIT_REPOSITORY_OPEN_CROSS_FS, NULL))
pfatal_git(path);
diff --git a/file/git-util.c b/file/git-util.c
index 5d604f5..aeeb65f 100644
--- a/file/git-util.c
+++ b/file/git-util.c
@@ -10,11 +10,13 @@
* (at your option) any later version.
*/
+#include <stddef.h>
#include <stdbool.h>
#include <assert.h>
#include <git2.h>
+#include "misc/util.h"
#include "file/git-util.h"
@@ -65,6 +67,39 @@ bool git_repo_is_dirty(git_repository *repo)
}
+int git_repository_open_ext_caching(git_repository **out, const char *path,
+ unsigned int flags, const char *ceiling_dirs)
+{
+#if LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR < 22
+ static struct repo_cache {
+ const char *path;
+ git_repository *repo;
+ struct repo_cache *next;
+ } *repo_cache = NULL;
+ struct repo_cache *c;
+ int res;
+
+ assert(flags == GIT_REPOSITORY_OPEN_CROSS_FS);
+ assert(ceiling_dirs == NULL);
+ for (c = repo_cache; c; c = c->next)
+ if (!strcmp(c->path, path)) {
+ *out = c->repo;
+ return 0;
+ }
+ res = git_repository_open_ext(out, path, flags, ceiling_dirs);
+ if (res)
+ return res;
+ c = alloc_type(struct repo_cache);
+ c->path = stralloc(path);
+ c->repo = *out;
+ c->next = repo_cache;
+ repo_cache = c;
+ return 0;
+#else
+ return git_repository_open_ext(out, path, flags, ceiling_dirs);
+#endif
+}
+
/*
* Git documentation says that git_libgit2_init can be called more then once
* but doesn't quite what happens then, e.g., whether references obtained
diff --git a/file/git-util.h b/file/git-util.h
index 4c7e329..6f11573 100644
--- a/file/git-util.h
+++ b/file/git-util.h
@@ -18,6 +18,9 @@
#include <git2.h>
+int git_repository_open_ext_caching(git_repository **out, const char *path,
+ unsigned int flags, const char *ceiling_dirs);
+
bool git_repo_is_dirty(git_repository *repo);
void git_init_once(void);