Commit 8cddf9b83a542bd66fcf0c4a1b692d47ff6556c2

Vicent Marti 2013-05-01T18:21:10

refdb: Properly load namespaces

diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 6f2162e..85444b6 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -997,6 +997,43 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend)
 	git__free(backend);
 }
 
+static int setup_namespace(git_buf *path, git_repository *repo)
+{
+	char *parts, *start, *end; 
+
+	/* Load the path to the repo first */
+	git_buf_puts(path, repo->path_repository);
+
+	/* if the repo is not namespaced, nothing else to do */
+	if (repo->namespace == NULL)
+		return 0;
+
+	parts = end = git__strdup(repo->namespace);
+	if (parts == NULL)
+		return -1;
+
+	/**
+	 * From `man gitnamespaces`:
+	 *  namespaces which include a / will expand to a hierarchy
+	 *  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(path, "refs/namespaces/%s/", start);
+	}
+
+	git_buf_printf(path, "refs/namespaces/%s/refs", end);
+	free(parts);
+
+	/* Make sure that the folder with the namespace exists */
+	if (git_futils_mkdir_r(git_buf_cstr(path), repo->path_repository, 0777) < 0) 
+		return -1;
+
+	/* Return the root of the namespaced path, i.e. without the trailing '/refs' */
+	git_buf_rtruncate_at_char(path, '/');
+	return 0;
+}
+
 int git_refdb_backend_fs(
 	git_refdb_backend **backend_out,
 	git_repository *repository)
@@ -1009,9 +1046,10 @@ int git_refdb_backend_fs(
 
 	backend->repo = repository;
 
-	git_buf_puts(&path, repository->path_repository);
-	if (repository->namespace != NULL)
-		git_buf_printf(&path, "refs/namespaces/%s/", repository->namespace);
+	if (setup_namespace(&path, repository) < 0) {
+		git__free(backend);
+		return -1;
+	}
 
 	backend->path = git_buf_detach(&path);