diff options
author | Patrick Steinhardt <ps@pks.im> | 2015-09-16 16:09:24 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2017-02-13 10:28:15 +0100 |
commit | e0a6c28eb3977ffb675195878345025025e41a83 (patch) | |
tree | 8b934e95e17a64f5dc1a95c214915551eec71c3d | |
parent | 71dd086195ff9f83b0225fc523a27807acc11ace (diff) | |
download | libgit2-e0a6c28eb3977ffb675195878345025025e41a83.tar.gz |
refdb: introduce commondir awareness
The refdb_fs_backend is not aware of the git commondir, which
stores common objects like the o bject database and packed/loose
refereensces when worktrees are used.
Make refdb_fs_backend aware of the common directory by
introducing a new commonpath variable that points to the actual
common path of the database and using it instead of the gitdir
for the mentioned objects.
-rw-r--r-- | src/refdb_fs.c | 34 | ||||
-rw-r--r-- | tests/worktree/refs.c | 68 |
2 files changed, 96 insertions, 6 deletions
diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 45a0963fe..cb279d9f9 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -57,6 +57,8 @@ typedef struct refdb_fs_backend { git_repository *repo; /* path to git directory */ char *gitpath; + /* path to common objects' directory */ + char *commonpath; git_sortedcache *refcache; int peeling_mode; @@ -363,6 +365,14 @@ static const char *loose_parse_symbolic(git_buf *file_content) return refname_start; } +static bool is_per_worktree_ref(const char *ref_name) +{ + return strcmp("HEAD", ref_name) == 0 || + strcmp("FETCH_HEAD", ref_name) == 0 || + strcmp("MERGE_HEAD", ref_name) == 0 || + strcmp("ORIG_HEAD", ref_name) == 0; +} + static int loose_lookup( git_reference **out, refdb_fs_backend *backend, @@ -370,11 +380,17 @@ static int loose_lookup( { git_buf ref_file = GIT_BUF_INIT; int error = 0; + const char *ref_dir; if (out) *out = NULL; - if ((error = loose_readbuffer(&ref_file, backend->gitpath, ref_name)) < 0) + if (is_per_worktree_ref(ref_name)) + ref_dir = backend->gitpath; + else + ref_dir = backend->commonpath; + + if ((error = loose_readbuffer(&ref_file, ref_dir, ref_name)) < 0) /* cannot read loose ref file - gah */; else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { const char *target; @@ -485,12 +501,12 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) git_iterator_options fsit_opts = GIT_ITERATOR_OPTIONS_INIT; const git_index_entry *entry = NULL; - if (!backend->gitpath) /* do nothing if no gitpath for loose refs */ + if (!backend->commonpath) /* do nothing if no commonpath for loose refs */ return 0; fsit_opts.flags = backend->iterator_flags; - if ((error = git_buf_printf(&path, "%s/refs", backend->gitpath)) < 0 || + if ((error = git_buf_printf(&path, "%s/refs", backend->commonpath)) < 0 || (error = git_iterator_for_filesystem(&fsit, path.ptr, &fsit_opts)) < 0) { git_buf_free(&path); return error; @@ -1410,6 +1426,7 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) git_sortedcache_free(backend->refcache); git__free(backend->gitpath); + git__free(backend->commonpath); git__free(backend); } @@ -1420,6 +1437,8 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) /* Not all repositories have a gitpath */ if (repo->path_repository == NULL) return 0; + if (repo->commondir == NULL) + return 0; /* Load the path to the repo first */ git_buf_puts(gitpath, repo->path_repository); @@ -1446,7 +1465,7 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) git__free(parts); /* Make sure that the folder with the namespace exists */ - if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->path_repository, + if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->commondir, 0777, GIT_MKDIR_PATH, NULL) < 0) return -1; @@ -1960,9 +1979,11 @@ int git_refdb_backend_fs( if (setup_namespace(&gitpath, repository) < 0) goto fail; - backend->gitpath = git_buf_detach(&gitpath); + backend->gitpath = backend->commonpath = git_buf_detach(&gitpath); + if (repository->commondir) + backend->commonpath = git__strdup(repository->commondir); - if (git_buf_joinpath(&gitpath, backend->gitpath, GIT_PACKEDREFS_FILE) < 0 || + if (git_buf_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 || git_sortedcache_new( &backend->refcache, offsetof(struct packref, name), NULL, NULL, packref_cmp, git_buf_cstr(&gitpath)) < 0) @@ -2002,6 +2023,7 @@ int git_refdb_backend_fs( fail: git_buf_free(&gitpath); git__free(backend->gitpath); + git__free(backend->commonpath); git__free(backend); return -1; } diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c new file mode 100644 index 000000000..e08e55372 --- /dev/null +++ b/tests/worktree/refs.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_refs__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_refs__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_refs__list(void) +{ + git_strarray refs, wtrefs; + unsigned i, j; + int error = 0; + + cl_git_pass(git_reference_list(&refs, fixture.repo)); + cl_git_pass(git_reference_list(&wtrefs, fixture.worktree)); + + if (refs.count != wtrefs.count) + { + error = GIT_ERROR; + goto exit; + } + + for (i = 0; i < refs.count; i++) + { + int found = 0; + + for (j = 0; j < wtrefs.count; j++) + { + if (!strcmp(refs.strings[i], wtrefs.strings[j])) + { + found = 1; + break; + } + } + + if (!found) + { + error = GIT_ERROR; + goto exit; + } + } + +exit: + git_strarray_free(&refs); + git_strarray_free(&wtrefs); + cl_git_pass(error); +} + +void test_worktree_refs__read_head(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.worktree)); + + git_reference_free(head); +} |