diff --git a/src/refdb_fs.c b/src/refdb_fs.c index e2a69d6ed..ac5a6a6a5 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1433,26 +1433,25 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) git__free(backend); } -static int setup_namespace(git_buf *gitpath, git_repository *repo) +static char *setup_namespace(git_repository *repo, const char *in) { - char *parts, *start, *end; + git_buf path = GIT_BUF_INIT; + char *parts, *start, *end, *out = NULL; - /* Not all repositories have a gitpath */ - if (repo->gitdir == NULL) - return 0; - if (repo->commondir == NULL) - return 0; + if (!in) + goto done; - /* Load the path to the repo first */ - git_buf_puts(gitpath, repo->gitdir); + git_buf_puts(&path, in); /* if the repo is not namespaced, nothing else to do */ - if (repo->namespace == NULL) - return 0; + if (repo->namespace == NULL) { + out = git_buf_detach(&path); + goto done; + } parts = end = git__strdup(repo->namespace); if (parts == NULL) - return -1; + goto done; /* * From `man gitnamespaces`: @@ -1460,21 +1459,24 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) * of namespaces; for example, GIT_NAMESPACE=foo/bar will store * refs under refs/namespaces/foo/refs/namespaces/bar/ */ - while ((start = git__strsep(&end, "/")) != NULL) { - git_buf_printf(gitpath, "refs/namespaces/%s/", start); - } + while ((start = git__strsep(&end, "/")) != NULL) + git_buf_printf(&path, "refs/namespaces/%s/", start); - git_buf_printf(gitpath, "refs/namespaces/%s/refs", end); + git_buf_printf(&path, "refs/namespaces/%s/refs", end); git__free(parts); /* Make sure that the folder with the namespace exists */ - if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->commondir, - 0777, GIT_MKDIR_PATH, NULL) < 0) - return -1; + if (git_futils_mkdir_relative(git_buf_cstr(&path), in, 0777, + GIT_MKDIR_PATH, NULL) < 0) + goto done; /* Return root of the namespaced gitpath, i.e. without the trailing '/refs' */ - git_buf_rtruncate_at_char(gitpath, '/'); - return 0; + git_buf_rtruncate_at_char(&path, '/'); + out = git_buf_detach(&path); + +done: + git_buf_free(&path); + return out; } static int reflog_alloc(git_reflog **reflog, const char *name) @@ -1979,12 +1981,19 @@ int git_refdb_backend_fs( backend->repo = repository; - if (setup_namespace(&gitpath, repository) < 0) - goto fail; + if (repository->gitdir) { + backend->gitpath = setup_namespace(repository, repository->gitdir); - backend->gitpath = backend->commonpath = git_buf_detach(&gitpath); - if (repository->commondir) - backend->commonpath = git__strdup(repository->commondir); + if (backend->gitpath == NULL) + goto fail; + } + + if (repository->commondir) { + backend->commonpath = setup_namespace(repository, repository->commondir); + + if (backend->commonpath == NULL) + goto fail; + } if (git_buf_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 || git_sortedcache_new( diff --git a/tests/refs/namespaces.c b/tests/refs/namespaces.c new file mode 100644 index 000000000..bb6bb1ce0 --- /dev/null +++ b/tests/refs/namespaces.c @@ -0,0 +1,36 @@ +#include "clar_libgit2.h" + +#include "repository.h" + +static git_repository *g_repo; + +void test_refs_namespaces__initialize(void) +{ + g_repo = cl_git_sandbox_init("testrepo"); +} + +void test_refs_namespaces__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_refs_namespaces__get_and_set(void) +{ + cl_assert_equal_s(NULL, git_repository_get_namespace(g_repo)); + + cl_git_pass(git_repository_set_namespace(g_repo, "namespace")); + cl_assert_equal_s("namespace", git_repository_get_namespace(g_repo)); + + cl_git_pass(git_repository_set_namespace(g_repo, NULL)); + cl_assert_equal_s(NULL, git_repository_get_namespace(g_repo)); +} + +void test_refs_namespaces__namespace_doesnt_show_normal_refs(void) +{ + static git_strarray ref_list; + + cl_git_pass(git_repository_set_namespace(g_repo, "namespace")); + cl_git_pass(git_reference_list(&ref_list, g_repo)); + cl_assert_equal_i(0, ref_list.count); + git_strarray_free(&ref_list); +}