Merge pull request #4154 from libgit2/ethomson/namespaces Support namespaced references again
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index e2a69d6..ac5a6a6 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 0000000..bb6bb1c
--- /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);
+}