summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2017-03-17 08:54:53 +0100
committerPatrick Steinhardt <ps@pks.im>2017-03-17 09:27:56 +0100
commit097f0105b4f49be3f26273f2323a5b39404180db (patch)
treedc1b4959652a0b046e5d24f59dded0b2c450d0b7
parent8f154be3eb04c44755e7b0a5020dc9b82c0c1f24 (diff)
downloadlibgit2-097f0105b4f49be3f26273f2323a5b39404180db.tar.gz
refdb: create references in commondir
References for a repository are usually created inside of its gitdir. When using worktrees, though, these references are not to be created inside the worktree gitdir, but instead inside the gitdir of its parent repository, which is the commondir. Like this, branches will still be available after the worktree itself has been deleted. The filesystem refdb currently still creates new references inside of the gitdir. Fix this and have it create references in commondir.
-rw-r--r--src/refdb_fs.c10
-rw-r--r--tests/worktree/refs.c26
2 files changed, 34 insertions, 2 deletions
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index ac5a6a6a5..713095865 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -738,6 +738,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
{
int error;
git_buf ref_path = GIT_BUF_INIT;
+ const char *basedir;
assert(file && backend && name);
@@ -746,13 +747,18 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
return GIT_EINVALIDSPEC;
}
+ if (is_per_worktree_ref(name))
+ basedir = backend->gitpath;
+ else
+ basedir = backend->commonpath;
+
/* Remove a possibly existing empty directory hierarchy
* which name would collide with the reference name
*/
- if ((error = git_futils_rmdir_r(name, backend->gitpath, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
+ if ((error = git_futils_rmdir_r(name, basedir, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
return error;
- if (git_buf_joinpath(&ref_path, backend->gitpath, name) < 0)
+ if (git_buf_joinpath(&ref_path, basedir, name) < 0)
return -1;
error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE);
diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c
index ccac8be29..b9a05606d 100644
--- a/tests/worktree/refs.c
+++ b/tests/worktree/refs.c
@@ -1,4 +1,6 @@
#include "clar_libgit2.h"
+#include "path.h"
+#include "refs.h"
#include "worktree.h"
#include "worktree_helpers.h"
@@ -128,3 +130,27 @@ void test_worktree_refs__delete_succeeds_after_pruning_worktree(void)
cl_git_pass(git_branch_delete(branch));
git_reference_free(branch);
}
+
+void test_worktree_refs__creating_refs_uses_commondir(void)
+{
+ git_reference *head, *branch, *lookup;
+ git_commit *commit;
+ git_buf refpath = GIT_BUF_INIT;
+
+ cl_git_pass(git_buf_joinpath(&refpath,
+ git_repository_commondir(fixture.worktree), "refs/heads/testbranch"));
+ cl_assert(!git_path_exists(refpath.ptr));
+
+ cl_git_pass(git_repository_head(&head, fixture.worktree));
+ cl_git_pass(git_commit_lookup(&commit, fixture.worktree, git_reference_target(head)));
+ cl_git_pass(git_branch_create(&branch, fixture.worktree, "testbranch", commit, 0));
+ cl_git_pass(git_branch_lookup(&lookup, fixture.worktree, "testbranch", GIT_BRANCH_LOCAL));
+ cl_assert(git_reference_cmp(branch, lookup) == 0);
+ cl_assert(git_path_exists(refpath.ptr));
+
+ git_reference_free(lookup);
+ git_reference_free(branch);
+ git_reference_free(head);
+ git_commit_free(commit);
+ git_buf_free(&refpath);
+}