summaryrefslogtreecommitdiff
path: root/file/git-util.c
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2016-10-29 17:08:02 -0300
committerWerner Almesberger <werner@almesberger.net>2016-10-29 17:16:19 -0300
commit7bea1c432cbc60844eca08c044f559b4411f8887 (patch)
treefd77371f087ec0e9f22cd2325cb571c38528d4c8 /file/git-util.c
parentda077cfcc19b21ebc994e6d1fb5ab85c99f9cc72 (diff)
downloadeeshow-7bea1c432cbc60844eca08c044f559b4411f8887.tar.gz
eeshow-7bea1c432cbc60844eca08c044f559b4411f8887.tar.bz2
eeshow-7bea1c432cbc60844eca08c044f559b4411f8887.zip
file/: implement caching version of git_repository_open_ext for libgit2 < 0.22
In version 0.22, this was added: Share open packfiles across repositories to share descriptors and mmaps Unfortunately, some people are unable to upgrade to modern libraries. Without FD sharing, eeshow may run out of file descriptors when loading large repositories. This commit adds a cache to reduce the number of times a repository is opened, which may in turn reduce the number of open files.
Diffstat (limited to 'file/git-util.c')
-rw-r--r--file/git-util.c35
1 files changed, 35 insertions, 0 deletions
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