List for cgit developers and users
 help / color / mirror / Atom feed
* [PATCH v3 00/21] Add namespace support to cgit
@ 2016-08-01 21:35 richard.maw
  2016-08-01 21:35 ` [PATCH v3 01/21] Return a copy of "master" when guessing defbranch fails richard.maw
                   ` (21 more replies)
  0 siblings, 22 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


The following changes since commit ff9893ac8192579a00dd4c73ddff18ab232099a6:

  Fix qry.head leak on error (2016-07-12 01:06:04 +0200)

are available in the git repository at:

  git://git.gitano.org.uk/cgit.git richardmaw/namespaces

for you to fetch changes up to c8ab2ce6fe19a1a9eacf2a384a6fbbe915be9dbc:

  Add documentation for repo.agefile (2016-08-01 22:17:42 +0100)

This version fixes a couple of issues with the log view,
which I had overlooked in my previous version.

1.  It now displays the namespaced version of the ref
2.  Decorative tags now only display those appropriate to the namespace

It also fixes a couple of other minor bugs,
and tries to unify namespace resolving logic a bit.

It turned out that the reason I thought I needed the NO_RECURSE flag
was that my test repository was broken
in that it had symbolic refs pointing outside the namespace.

I'm going to try adding namespaced functions to libgit later in the week.

----------------------------------------------------------------
Richard Maw (21):
  Return a copy of "master" when guessing defbranch fails
  Fix archive generation
  Add a wrapper for get_sha1 called cgit_get_sha1
  Parse repo.namespace
  Print out parsed namespace on request
  Set GIT_NAMESPACE when repo.namespace is provided
  Add namespaced resolve ref helper
  Add cgit_namespaced_dwim_ref for resolving short refs
  Look up refs in namespace with cgit_get_sha1
  Use cgit_namespaced_dwim_ref for finding logs to show
  Render commit decorations correctly
  Guess the default branch based on current namespace
  Add cgit_for_each_namespaced_ref_in helper
  Find the default branch based on the contents of the namespace
  Only display refs in current namespace
  Add namespace support to dumb-clone
  Display notes from namespace
  Add documentation for repo.namespace
  Allow agefile to be set per-repository
  Update contrib script to update agefiles per namespace
  Add documentation for repo.agefile

 cgit.c                             | 51 ++++++++++++++++----
 cgit.h                             | 10 ++++
 cgitrc.5.txt                       | 47 +++++++++++++++++++
 contrib/hooks/post-receive.agefile | 15 +++++-
 shared.c                           | 95 ++++++++++++++++++++++++++++++++++++++
 ui-blob.c                          |  6 +--
 ui-clone.c                         | 18 +++++++-
 ui-commit.c                        |  2 +-
 ui-diff.c                          |  4 +-
 ui-log.c                           | 40 +++++++++++-----
 ui-patch.c                         |  4 +-
 ui-plain.c                         |  2 +-
 ui-refs.c                          |  6 +--
 ui-repolist.c                      |  3 +-
 ui-shared.c                        |  8 ++--
 ui-snapshot.c                      | 14 +++---
 ui-tag.c                           |  2 +-
 ui-tree.c                          |  2 +-
 18 files changed, 281 insertions(+), 48 deletions(-)

-- 
2.9.0


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 01/21] Return a copy of "master" when guessing defbranch fails
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 02/21] Fix archive generation richard.maw
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


When resolving HEAD fails or doesn't resolve to a branch
it falls back to returning "master".

This was returning a pointer to a statically allocated buffer,
which is inconsistent with every other assignment to defbranch
which are dynamically allocated.

This has not been problematic because the string is not freed.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cgit.c b/cgit.c
index 9427c4a..06c40ef 100644
--- a/cgit.c
+++ b/cgit.c
@@ -475,7 +475,7 @@ static char *guess_defbranch(void)
 
 	ref = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
 	if (!ref || !starts_with(ref, "refs/heads/"))
-		return "master";
+		return xstrdup("master");
 	return xstrdup(ref + 11);
 }
 /* The caller must free filename and ref after calling this. */
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 02/21] Fix archive generation
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
  2016-08-01 21:35 ` [PATCH v3 01/21] Return a copy of "master" when guessing defbranch fails richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 03/21] Add a wrapper for get_sha1 called cgit_get_sha1 richard.maw
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


The get_ref_from_filename function is expected to return a sha1.
It didn't actually do this,
instead returning the ref that would under normal circumstances resolve to that.

Since we're going to resolve refs in a way that is namespace aware
we need to return the sha1 rather than the ref,
since the archive is created by libgit code that is not namespace aware,
and it would try to resolve the ref again.

This previously worked fine
because it would resolve the ref the same way both times.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 ui-snapshot.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ui-snapshot.c b/ui-snapshot.c
index f68e877..c6c3656 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -174,10 +174,10 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
 		goto out;
 
 	result = 0;
-	strbuf_release(&snapshot);
 
 out:
-	return result ? strbuf_detach(&snapshot, NULL) : NULL;
+	strbuf_release(&snapshot);
+	return result ? xstrdup(sha1_to_hex(sha1)) : NULL;
 }
 
 void cgit_print_snapshot(const char *head, const char *hex,
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 03/21] Add a wrapper for get_sha1 called cgit_get_sha1
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
  2016-08-01 21:35 ` [PATCH v3 01/21] Return a copy of "master" when guessing defbranch fails richard.maw
  2016-08-01 21:35 ` [PATCH v3 02/21] Fix archive generation richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 04/21] Parse repo.namespace richard.maw
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This will later be changed to include namespace resolution,
but the call sites are changed now to keep the changes small.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c        |  2 +-
 cgit.h        |  2 ++
 shared.c      |  5 +++++
 ui-blob.c     |  6 +++---
 ui-commit.c   |  2 +-
 ui-diff.c     |  4 ++--
 ui-log.c      |  2 +-
 ui-patch.c    |  4 ++--
 ui-plain.c    |  2 +-
 ui-shared.c   |  8 ++++----
 ui-snapshot.c | 10 +++++-----
 ui-tag.c      |  2 +-
 ui-tree.c     |  2 +-
 13 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/cgit.c b/cgit.c
index 06c40ef..3763a30 100644
--- a/cgit.c
+++ b/cgit.c
@@ -615,7 +615,7 @@ static int prepare_repo_cmd(void)
 		return 1;
 	}
 
-	if (get_sha1(ctx.qry.head, sha1)) {
+	if (cgit_get_sha1(ctx.qry.head, sha1)) {
 		char *old_head = ctx.qry.head;
 		ctx.qry.head = xstrdup(ctx.repo->defbranch);
 		cgit_print_error_page(404, "Not found",
diff --git a/cgit.h b/cgit.h
index 325432b..49f0557 100644
--- a/cgit.h
+++ b/cgit.h
@@ -391,4 +391,6 @@ extern char *expand_macros(const char *txt);
 
 extern char *get_mimetype_for_filename(const char *filename);
 
+extern int cgit_get_sha1(const char *name, unsigned char *sha1);
+
 #endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index a63633b..d82c07b 100644
--- a/shared.c
+++ b/shared.c
@@ -601,3 +601,8 @@ char *get_mimetype_for_filename(const char *filename)
 	fclose(file);
 	return NULL;
 }
+
+int cgit_get_sha1(const char *name, unsigned char *sha1)
+{
+	return get_sha1(name, sha1);
+}
diff --git a/ui-blob.c b/ui-blob.c
index d388489..21d21ed 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -52,7 +52,7 @@ int cgit_ref_path_exists(const char *path, const char *ref, int file_only)
 		.file_only = file_only
 	};
 
-	if (get_sha1(ref, sha1))
+	if (cgit_get_sha1(ref, sha1))
 		return 0;
 	if (sha1_object_info(sha1, &size) != OBJ_COMMIT)
 		return 0;
@@ -82,7 +82,7 @@ int cgit_print_file(char *path, const char *head, int file_only)
 		.file_only = file_only
 	};
 
-	if (get_sha1(head, sha1))
+	if (cgit_get_sha1(head, sha1))
 		return -1;
 	type = sha1_object_info(sha1, &size);
 	if (type == OBJ_COMMIT) {
@@ -132,7 +132,7 @@ void cgit_print_blob(const char *hex, char *path, const char *head, int file_onl
 			return;
 		}
 	} else {
-		if (get_sha1(head, sha1)) {
+		if (cgit_get_sha1(head, sha1)) {
 			cgit_print_error_page(404, "Not found",
 					"Bad ref: %s", head);
 			return;
diff --git a/ui-commit.c b/ui-commit.c
index 099d294..5ba0791 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -26,7 +26,7 @@ void cgit_print_commit(char *hex, const char *prefix)
 	if (!hex)
 		hex = ctx.qry.head;
 
-	if (get_sha1(hex, sha1)) {
+	if (cgit_get_sha1(hex, sha1)) {
 		cgit_print_error_page(400, "Bad request",
 				"Bad object id: %s", hex);
 		return;
diff --git a/ui-diff.c b/ui-diff.c
index edee793..9256d12 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -402,7 +402,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
 
 	if (!new_rev)
 		new_rev = ctx.qry.head;
-	if (get_sha1(new_rev, new_rev_sha1)) {
+	if (cgit_get_sha1(new_rev, new_rev_sha1)) {
 		cgit_print_error_page(404, "Not found",
 			"Bad object name: %s", new_rev);
 		return;
@@ -416,7 +416,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
 	new_tree_sha1 = commit->tree->object.oid.hash;
 
 	if (old_rev) {
-		if (get_sha1(old_rev, old_rev_sha1)) {
+		if (cgit_get_sha1(old_rev, old_rev_sha1)) {
 			cgit_print_error_page(404, "Not found",
 				"Bad object name: %s", old_rev);
 			return;
diff --git a/ui-log.c b/ui-log.c
index c97b8e0..28ef3c0 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -325,7 +325,7 @@ static const char *disambiguate_ref(const char *ref, int *must_free_result)
 	struct strbuf longref = STRBUF_INIT;
 
 	strbuf_addf(&longref, "refs/heads/%s", ref);
-	if (get_sha1(longref.buf, oid.hash) == 0) {
+	if (cgit_get_sha1(longref.buf, oid.hash) == 0) {
 		*must_free_result = 1;
 		return strbuf_detach(&longref, NULL);
 	}
diff --git a/ui-patch.c b/ui-patch.c
index 4c051e8..ff09a8e 100644
--- a/ui-patch.c
+++ b/ui-patch.c
@@ -24,7 +24,7 @@ void cgit_print_patch(const char *new_rev, const char *old_rev,
 	if (!new_rev)
 		new_rev = ctx.qry.head;
 
-	if (get_sha1(new_rev, new_rev_sha1)) {
+	if (cgit_get_sha1(new_rev, new_rev_sha1)) {
 		cgit_print_error_page(404, "Not found",
 				"Bad object id: %s", new_rev);
 		return;
@@ -37,7 +37,7 @@ void cgit_print_patch(const char *new_rev, const char *old_rev,
 	}
 
 	if (old_rev) {
-		if (get_sha1(old_rev, old_rev_sha1)) {
+		if (cgit_get_sha1(old_rev, old_rev_sha1)) {
 			cgit_print_error_page(404, "Not found",
 					"Bad object id: %s", old_rev);
 			return;
diff --git a/ui-plain.c b/ui-plain.c
index 97cf639..88dd1a8 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -181,7 +181,7 @@ void cgit_print_plain(void)
 	if (!rev)
 		rev = ctx.qry.head;
 
-	if (get_sha1(rev, sha1)) {
+	if (cgit_get_sha1(rev, sha1)) {
 		cgit_print_error_page(404, "Not found", "Not found");
 		return;
 	}
diff --git a/ui-shared.c b/ui-shared.c
index e39d004..ca40d42 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -1079,11 +1079,11 @@ void cgit_compose_snapshot_prefix(struct strbuf *filename, const char *base,
 	 * name starts with {v,V}[0-9] and the prettify mapping is injective,
 	 * i.e. each stripped tag can be inverted without ambiguities.
 	 */
-	if (get_sha1(fmt("refs/tags/%s", ref), sha1) == 0 &&
+	if (cgit_get_sha1(fmt("refs/tags/%s", ref), sha1) == 0 &&
 	    (ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]) &&
-	    ((get_sha1(fmt("refs/tags/%s", ref + 1), sha1) == 0) +
-	     (get_sha1(fmt("refs/tags/v%s", ref + 1), sha1) == 0) +
-	     (get_sha1(fmt("refs/tags/V%s", ref + 1), sha1) == 0) == 1))
+	    ((cgit_get_sha1(fmt("refs/tags/%s", ref + 1), sha1) == 0) +
+	     (cgit_get_sha1(fmt("refs/tags/v%s", ref + 1), sha1) == 0) +
+	     (cgit_get_sha1(fmt("refs/tags/V%s", ref + 1), sha1) == 0) == 1))
 		ref++;
 
 	strbuf_addf(filename, "%s-%s", base, ref);
diff --git a/ui-snapshot.c b/ui-snapshot.c
index c6c3656..93af28e 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -111,7 +111,7 @@ static int make_snapshot(const struct cgit_snapshot_format *format,
 {
 	unsigned char sha1[20];
 
-	if (get_sha1(hex, sha1)) {
+	if (cgit_get_sha1(hex, sha1)) {
 		cgit_print_error_page(404, "Not found",
 				"Bad object id: %s", hex);
 		return 1;
@@ -150,7 +150,7 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
 	strbuf_addstr(&snapshot, filename);
 	strbuf_setlen(&snapshot, snapshot.len - strlen(format->suffix));
 
-	if (get_sha1(snapshot.buf, sha1) == 0)
+	if (cgit_get_sha1(snapshot.buf, sha1) == 0)
 		goto out;
 
 	reponame = cgit_repobasename(url);
@@ -162,15 +162,15 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
 		strbuf_splice(&snapshot, 0, new_start - snapshot.buf, "", 0);
 	}
 
-	if (get_sha1(snapshot.buf, sha1) == 0)
+	if (cgit_get_sha1(snapshot.buf, sha1) == 0)
 		goto out;
 
 	strbuf_insert(&snapshot, 0, "v", 1);
-	if (get_sha1(snapshot.buf, sha1) == 0)
+	if (cgit_get_sha1(snapshot.buf, sha1) == 0)
 		goto out;
 
 	strbuf_splice(&snapshot, 0, 1, "V", 1);
-	if (get_sha1(snapshot.buf, sha1) == 0)
+	if (cgit_get_sha1(snapshot.buf, sha1) == 0)
 		goto out;
 
 	result = 0;
diff --git a/ui-tag.c b/ui-tag.c
index 6b838cb..7372770 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -51,7 +51,7 @@ void cgit_print_tag(char *revname)
 		revname = ctx.qry.head;
 
 	strbuf_addf(&fullref, "refs/tags/%s", revname);
-	if (get_sha1(fullref.buf, sha1)) {
+	if (cgit_get_sha1(fullref.buf, sha1)) {
 		cgit_print_error_page(404, "Not found",
 			"Bad tag reference: %s", revname);
 		goto cleanup;
diff --git a/ui-tree.c b/ui-tree.c
index 120066c..ae2acce 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -306,7 +306,7 @@ void cgit_print_tree(const char *rev, char *path)
 	if (!rev)
 		rev = ctx.qry.head;
 
-	if (get_sha1(rev, sha1)) {
+	if (cgit_get_sha1(rev, sha1)) {
 		cgit_print_error_page(404, "Not found",
 			"Invalid revision name: %s", rev);
 		return;
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 04/21] Parse repo.namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (2 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 03/21] Add a wrapper for get_sha1 called cgit_get_sha1 richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 05/21] Print out parsed namespace on request richard.maw
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This contains the unexpanded name of the namespace
rather than the base ref of the namespace,
since the git namespace mechanism works by setting GIT_NAMESPACE
and on the first call to get_git_namespace() it gets expanded.

We need to save this for a later call to prepare_repo_cmd,
rather than trying to process it here,
since we can only do it once,
and we have other uses for the unexpanded name.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 2 ++
 cgit.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/cgit.c b/cgit.c
index 3763a30..304027c 100644
--- a/cgit.c
+++ b/cgit.c
@@ -45,6 +45,8 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 		repo->homepage = xstrdup(value);
 	else if (!strcmp(name, "defbranch"))
 		repo->defbranch = xstrdup(value);
+	else if (!strcmp(name, "namespace"))
+		repo->namespace = xstrdup(value);
 	else if (!strcmp(name, "snapshots"))
 		repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value);
 	else if (!strcmp(name, "enable-commit-graph"))
diff --git a/cgit.h b/cgit.h
index 49f0557..93de0ea 100644
--- a/cgit.h
+++ b/cgit.h
@@ -87,6 +87,7 @@ struct cgit_repo {
 	struct string_list readme;
 	char *section;
 	char *clone_url;
+	char *namespace;
 	char *logo;
 	char *logo_link;
 	int snapshots;
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 05/21] Print out parsed namespace on request
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (3 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 04/21] Parse repo.namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 06/21] Set GIT_NAMESPACE when repo.namespace is provided richard.maw
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This is not strictly necessary,
as we do not have any way to generate namespace entries from a scan-path,
but I'd rather not leave this as a surprise
to someone who comes up with a good namespace discovery mechanism.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/cgit.c b/cgit.c
index 304027c..7746102 100644
--- a/cgit.c
+++ b/cgit.c
@@ -778,6 +778,8 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 	fprintf(f, "repo.url=%s\n", repo->url);
 	fprintf(f, "repo.name=%s\n", repo->name);
 	fprintf(f, "repo.path=%s\n", repo->path);
+	if (repo->namespace)
+		fprintf(f, "repo.namespace=%s\n", repo->namespace);
 	if (repo->owner)
 		fprintf(f, "repo.owner=%s\n", repo->owner);
 	if (repo->desc) {
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 06/21] Set GIT_NAMESPACE when repo.namespace is provided
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (4 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 05/21] Print out parsed namespace on request richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 07/21] Add namespaced resolve ref helper richard.maw
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This causes any namespace-aware code
to only handle refs under that namespace.

Currently this doesn't do much
as the only namespace aware code is in recieve-pack and upload-pack,
which are not handled by CGit.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cgit.c b/cgit.c
index 7746102..5d55187 100644
--- a/cgit.c
+++ b/cgit.c
@@ -566,6 +566,11 @@ static int prepare_repo_cmd(void)
 	/* The path to the git repository. */
 	setenv("GIT_DIR", ctx.repo->path, 1);
 
+	/*  Set the namespace in the environment,
+	 *  so it gets loaded on the first get_git_namespace() */
+	if (ctx.repo->namespace)
+		setenv("GIT_NAMESPACE", ctx.repo->namespace, 1);
+
 	/* Do not look in /etc/ for gitconfig and gitattributes. */
 	setenv("GIT_CONFIG_NOSYSTEM", "1", 1);
 	setenv("GIT_ATTR_NOSYSTEM", "1", 1);
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 07/21] Add namespaced resolve ref helper
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (5 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 06/21] Set GIT_NAMESPACE when repo.namespace is provided richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 08/21] Add cgit_namespaced_dwim_ref for resolving short refs richard.maw
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


Unlike resolve_ref_unsafe, this does not return a substring or static buffer.
This is because the ref including the namespace can be longer.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.h   |  2 ++
 shared.c | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/cgit.h b/cgit.h
index 93de0ea..9129fd9 100644
--- a/cgit.h
+++ b/cgit.h
@@ -392,6 +392,8 @@ extern char *expand_macros(const char *txt);
 
 extern char *get_mimetype_for_filename(const char *filename);
 
+extern char *cgit_namespaced_resolve_ref(const char *name, int resolve_flags, unsigned char *sha1, int *flags);
+
 extern int cgit_get_sha1(const char *name, unsigned char *sha1);
 
 #endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index d82c07b..789fb5e 100644
--- a/shared.c
+++ b/shared.c
@@ -602,6 +602,26 @@ char *get_mimetype_for_filename(const char *filename)
 	return NULL;
 }
 
+char *cgit_namespaced_resolve_ref(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
+{
+	/* TODO: If libgit's resolve_ref_unsafe gains a flag for namespace support
+	         see if this function can be removed. */
+	const char *ref;
+	const char *namespace = get_git_namespace();
+	char *namespaced_ref = NULL;
+	char *ret = NULL;
+
+	if (namespace)
+		namespaced_ref = mkpathdup("%s%s", namespace, refname);
+
+	ref = resolve_ref_unsafe(namespaced_ref ?: refname, resolve_flags, sha1, flags);
+	if (ref)
+		ret = xstrdup(ref);
+
+	free(namespaced_ref);
+	return ret;
+}
+
 int cgit_get_sha1(const char *name, unsigned char *sha1)
 {
 	return get_sha1(name, sha1);
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 08/21] Add cgit_namespaced_dwim_ref for resolving short refs
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (6 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 07/21] Add namespaced resolve ref helper richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 09/21] Look up refs in namespace with cgit_get_sha1 richard.maw
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


CGit generates links to branches in a natural form,
with the refs/heads stripped off
provided it is unambigously identifiable.

Since humans are likely to change the URLs to point to branches
by their short name anyway, we need to support this.

It is not yet fesible to add namespaced ref resolving to libgit,
so this implements a subset of the ref parsing logic,
which we'll need to parse branches in links.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.h   |  2 ++
 shared.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/cgit.h b/cgit.h
index 9129fd9..f4c444e 100644
--- a/cgit.h
+++ b/cgit.h
@@ -394,6 +394,8 @@ extern char *get_mimetype_for_filename(const char *filename);
 
 extern char *cgit_namespaced_resolve_ref(const char *name, int resolve_flags, unsigned char *sha1, int *flags);
 
+extern int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char **ref);
+
 extern int cgit_get_sha1(const char *name, unsigned char *sha1);
 
 #endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index 789fb5e..77cb120 100644
--- a/shared.c
+++ b/shared.c
@@ -622,6 +622,51 @@ char *cgit_namespaced_resolve_ref(const char *refname, int resolve_flags, unsign
 	return ret;
 }
 
+int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char **ref)
+{
+	/* TODO: If libgit gets a version of dwim_ref that is namespace aware
+	         then rework this function to use it instead */
+	/* The standard git name disambiguation order is:
+	     $name
+	     refs/$name
+	     refs/tags/$name
+	     refs/heads/$name
+	     refs/remotes/$name
+	     refs/remotes/$name/HEAD
+	   we don't care about remotes, so we can skip those,
+	   and we can't specify a prefix for dwim_ref,
+	   so we have to use something that puts the namespace prefix on. */
+	static const char *namespaced_ref_patterns[] = {
+		"%s",
+		"refs/%s",
+		"refs/tags/%s",
+		"refs/heads/%s",
+		NULL,
+	};
+	int ret = 0;
+	struct strbuf fullref = STRBUF_INIT;
+
+	for (const char **p = namespaced_ref_patterns; *p; p++) {
+		char *r;
+		strbuf_reset(&fullref);
+		strbuf_addf(&fullref, *p, name);
+
+		r = cgit_namespaced_resolve_ref(fullref.buf, RESOLVE_REF_READING, sha1, NULL);
+		if (r) {
+			if (ref)
+				*ref = r;
+			else
+				free(r);
+
+			ret = 1;
+			break;
+		}
+	}
+
+	strbuf_release(&fullref);
+	return ret;
+}
+
 int cgit_get_sha1(const char *name, unsigned char *sha1)
 {
 	return get_sha1(name, sha1);
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 09/21] Look up refs in namespace with cgit_get_sha1
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (7 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 08/21] Add cgit_namespaced_dwim_ref for resolving short refs richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 10/21] Use cgit_namespaced_dwim_ref for finding logs to show richard.maw
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This causes all ref resolving to look for the requested branch
inside the current namespace.

Previously any form of git revision would be accepted,
but ref resolving isn't namespace aware
and it would be infeasible to replicate all its behaviour,
so we stick to providing the most common cases
of a sha1, an absolute ref, or a partial ref.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 shared.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/shared.c b/shared.c
index 77cb120..4c7bb9c 100644
--- a/shared.c
+++ b/shared.c
@@ -669,5 +669,19 @@ int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char **ref)
 
 int cgit_get_sha1(const char *name, unsigned char *sha1)
 {
+	/* TODO: If libgit's get_sha1_with_context gains a flag for namespace support,
+	         change this function to call that appropriately. */
+	if (ctx.repo->namespace) {
+		/* If we have a namespace, we can get either a sha1,
+		   or a possibly abbreviated ref.
+		   Advanced ref forms are not supported at this time
+		   as this would require reimplementing all of ref parsing.
+		   If get_sha1_with_context grows support for a namespaced flag
+		   then this code may go away. */
+		if (get_sha1_hex(name, sha1) == 0)
+			return 0;
+		return cgit_namespaced_dwim_ref(name, sha1, NULL) == 0;
+	}
+
 	return get_sha1(name, sha1);
 }
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 10/21] Use cgit_namespaced_dwim_ref for finding logs to show
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (8 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 09/21] Look up refs in namespace with cgit_get_sha1 richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 11/21] Render commit decorations correctly richard.maw
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This replaces the previous behaviour of disambiguate_ref,
which would only prepend refs/heads to the branch name,
so would not disambiguate tags to their full refs.

Now when an abbreviated ref is provided
the namespace is prepended to it
as well as the disambiguating path.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 ui-log.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/ui-log.c b/ui-log.c
index 28ef3c0..71ef3d4 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -322,16 +322,12 @@ static void print_commit(struct commit *commit, struct rev_info *revs)
 static const char *disambiguate_ref(const char *ref, int *must_free_result)
 {
 	struct object_id oid;
-	struct strbuf longref = STRBUF_INIT;
 
-	strbuf_addf(&longref, "refs/heads/%s", ref);
-	if (cgit_get_sha1(longref.buf, oid.hash) == 0) {
+	if (cgit_namespaced_dwim_ref(ref, oid.hash, (char**)&ref))
 		*must_free_result = 1;
-		return strbuf_detach(&longref, NULL);
-	}
+	else
+		*must_free_result = 0;
 
-	*must_free_result = 0;
-	strbuf_release(&longref);
 	return ref;
 }
 
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 11/21] Render commit decorations correctly
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (9 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 10/21] Use cgit_namespaced_dwim_ref for finding logs to show richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 12/21] Guess the default branch based on current namespace richard.maw
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


They must be displayed without the namespace prefix,
and refs from outside the namespace must not be shown.

Unfortunately decorations from tags within the namespace aren't always provided
while tags from outside it are, but at least it's not displaying broken links.

The decoration classification is not namespace aware,
so they need to be re-classified for HEAD and branches to be rendered.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 ui-log.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/ui-log.c b/ui-log.c
index 71ef3d4..fda2523 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -64,9 +64,32 @@ void show_commit_decorations(struct commit *commit)
 	if (!deco)
 		return;
 	html("<span class='decoration'>");
-	while (deco) {
-		strncpy(buf, prettify_refname(deco->name), sizeof(buf) - 1);
-		switch(deco->type) {
+	for (; deco; deco = deco->next) {
+		const char *name = strip_namespace(deco->name);
+		enum decoration_type type = deco->type;
+
+		/* Skip decorations for refs not in our namespace,
+		   since it's not possible to pre-filter decorations. */
+		if (!name)
+			continue;
+
+		/* DECORATION_NONE is given for namespced refs,
+		   so we have to re-classify sometimes. */
+		if (name != deco->name && type == DECORATION_NONE) {
+			if (starts_with(name, "refs/heads/"))
+				type = DECORATION_REF_LOCAL;
+			else if (starts_with(name, "refs/remotes/"))
+				type = DECORATION_REF_REMOTE;
+			else if (starts_with(name, "refs/tags/"))
+				type = DECORATION_REF_TAG;
+			else if (!strcmp(name, "refs/stash"))
+				type = DECORATION_REF_STASH;
+			else if (!strcmp(name, "HEAD"))
+				type = DECORATION_REF_HEAD;
+		}
+
+		strncpy(buf, prettify_refname(name), sizeof(buf) - 1);
+		switch(type) {
 		case DECORATION_NONE:
 			/* If the git-core doesn't recognize it,
 			 * don't display anything. */
@@ -93,7 +116,6 @@ void show_commit_decorations(struct commit *commit)
 					ctx.qry.vpath);
 			break;
 		}
-		deco = deco->next;
 	}
 	html("</span>");
 }
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 12/21] Guess the default branch based on current namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (10 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 11/21] Render commit decorations correctly richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 13/21] Add cgit_for_each_namespaced_ref_in helper richard.maw
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


resolve_ref_unsafe() can't be told to be namespace aware,
so we need to use our helper function for resolving refs,
which prepends the namespace before resolving.

As an additional check, if the ref points outside the namespace,
then it will use the default "master".

upload-pack is not so tolerant, so try to avoid having such broken repos.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/cgit.c b/cgit.c
index 5d55187..7b499ea 100644
--- a/cgit.c
+++ b/cgit.c
@@ -472,13 +472,18 @@ static char *find_default_branch(struct cgit_repo *repo)
 
 static char *guess_defbranch(void)
 {
-	const char *ref;
+	char *ref, *ret;
 	unsigned char sha1[20];
 
-	ref = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
-	if (!ref || !starts_with(ref, "refs/heads/"))
-		return xstrdup("master");
-	return xstrdup(ref + 11);
+	ref = cgit_namespaced_resolve_ref("HEAD", 0, sha1, NULL);
+
+	if (!ref || !strip_namespace(ref) || !starts_with(strip_namespace(ref), "refs/heads/"))
+		ret = xstrdup("master");
+	else
+		ret = xstrdup(strip_namespace(ref) + 11);
+
+	free(ref);
+	return ret;
 }
 /* The caller must free filename and ref after calling this. */
 static inline void parse_readme(const char *readme, char **filename, char **ref, struct cgit_repo *repo)
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 13/21] Add cgit_for_each_namespaced_ref_in helper
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (11 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 12/21] Guess the default branch based on current namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 14/21] Find the default branch based on the contents of the namespace richard.maw
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


libgit has a for_each_namespaced_ref,
but lacks equivalents for just branches, tags or remotes.

Rather than implementing all of those helpers,
it's more convenient to implement just one
that prepends the namespace to the provided ref base.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.h   |  2 ++
 shared.c | 11 +++++++++++
 2 files changed, 13 insertions(+)

diff --git a/cgit.h b/cgit.h
index f4c444e..e915490 100644
--- a/cgit.h
+++ b/cgit.h
@@ -398,4 +398,6 @@ extern int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char
 
 extern int cgit_get_sha1(const char *name, unsigned char *sha1);
 
+extern int cgit_for_each_namespaced_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
+
 #endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index 4c7bb9c..687aa4a 100644
--- a/shared.c
+++ b/shared.c
@@ -685,3 +685,14 @@ int cgit_get_sha1(const char *name, unsigned char *sha1)
 
 	return get_sha1(name, sha1);
 }
+
+int cgit_for_each_namespaced_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
+{
+	/* TODO: If libgit gets a for_each_namespaced_ref_in then remove this */
+	struct strbuf strbuf = STRBUF_INIT;
+	int ret;
+	strbuf_addf(&strbuf, "%s%s", get_git_namespace(), prefix);
+	ret = for_each_ref_in(strbuf.buf, fn, cb_data);
+	strbuf_release(&strbuf);
+	return ret;
+}
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 14/21] Find the default branch based on the contents of the namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (12 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 13/21] Add cgit_for_each_namespaced_ref_in helper richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 15/21] Only display refs in current namespace richard.maw
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


The find_current_ref callback does not need to be modified
to strip off the namespace prefix,
since the for_each_ref functions don't include the base ref prefix.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cgit.c b/cgit.c
index 7b499ea..d664ab4 100644
--- a/cgit.c
+++ b/cgit.c
@@ -458,7 +458,7 @@ static char *find_default_branch(struct cgit_repo *repo)
 	info.req_ref = repo->defbranch;
 	info.first_ref = NULL;
 	info.match = 0;
-	for_each_branch_ref(find_current_ref, &info);
+	cgit_for_each_namespaced_ref_in("refs/heads/", find_current_ref, &info);
 	if (info.match)
 		ref = info.req_ref;
 	else
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 15/21] Only display refs in current namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (13 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 14/21] Find the default branch based on the contents of the namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 16/21] Add namespace support to dumb-clone richard.maw
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 ui-refs.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/ui-refs.c b/ui-refs.c
index 75f2789..3e4edad 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -183,9 +183,9 @@ void cgit_print_branches(int maxcount)
 
 	list.refs = NULL;
 	list.alloc = list.count = 0;
-	for_each_branch_ref(cgit_refs_cb, &list);
+	cgit_for_each_namespaced_ref_in("refs/heads/", cgit_refs_cb, &list);
 	if (ctx.repo->enable_remote_branches)
-		for_each_remote_ref(cgit_refs_cb, &list);
+		cgit_for_each_namespaced_ref_in("refs/remotes/", cgit_refs_cb, &list);
 
 	if (maxcount == 0 || maxcount > list.count)
 		maxcount = list.count;
@@ -210,7 +210,7 @@ void cgit_print_tags(int maxcount)
 
 	list.refs = NULL;
 	list.alloc = list.count = 0;
-	for_each_tag_ref(cgit_refs_cb, &list);
+	cgit_for_each_namespaced_ref_in("refs/tags/", cgit_refs_cb, &list);
 	if (list.count == 0)
 		return;
 	qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age);
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 16/21] Add namespace support to dumb-clone
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (14 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 15/21] Only display refs in current namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 17/21] Display notes from namespace richard.maw
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This requires namespacing the HEAD symbolic ref
and the list of refs.

Sending HEAD required some tweaking,
since the file itself refers to a namespaced ref,
but we want to provide the ref with its namespace stripped off.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 ui-clone.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/ui-clone.c b/ui-clone.c
index 5f6606a..14380bf 100644
--- a/ui-clone.c
+++ b/ui-clone.c
@@ -85,7 +85,9 @@ void cgit_clone_info(void)
 	ctx.page.mimetype = "text/plain";
 	ctx.page.filename = "info/refs";
 	cgit_print_http_headers();
-	for_each_ref(print_ref_info, NULL);
+	/* NOTE: we pass an empty prefix because we want to enumerate everything
+	   not just all refs under $namespace/refs/ */
+	cgit_for_each_namespaced_ref_in("", print_ref_info, NULL);
 }
 
 void cgit_clone_objects(void)
@@ -105,5 +107,17 @@ void cgit_clone_objects(void)
 
 void cgit_clone_head(void)
 {
-	send_file(git_path("%s", "HEAD"));
+	unsigned char unused[20];
+	char *ref = cgit_namespaced_resolve_ref("HEAD", 0, unused, NULL);
+
+	if (!ref) {
+		cgit_print_error_page(404, "Not found", "Not found");
+		return;
+	}
+
+	ctx.page.mimetype = "application/octet-stream";
+	ctx.page.filename = xstrdup("HEAD");
+	cgit_print_http_headers();
+	htmlf("ref: %s\n", strip_namespace(ref));
+	free(ref);
 }
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 17/21] Display notes from namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (15 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 16/21] Add namespace support to dumb-clone richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-20 14:51   ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 18/21] Add documentation for repo.namespace richard.maw
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


We must not leave it at its default behaviour,
as that results in notes from the root namespace being used
and ignoring notes from the current namespace,
since it is not namespace aware.

We can handle this by instructing it to not load the default refs,
and providing a set of extra refs to use.

The provided extra refs are globs rather than ref names,
but ref names may not contain glob characters so this is safe.

We get an annoying warning if the provided ref does not exist,
so we check whether the ref exists before attempting to provide it.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/cgit.c b/cgit.c
index d664ab4..321a00f 100644
--- a/cgit.c
+++ b/cgit.c
@@ -586,7 +586,26 @@ static int prepare_repo_cmd(void)
 	 * load local configuration from the git repository, so we do them both while
 	 * the HOME variables are unset. */
 	setup_git_directory_gently(&nongit);
-	init_display_notes(NULL);
+	if (get_git_namespace()) {
+		struct display_notes_opt opt = {
+			.use_default_notes = 0,
+			.extra_notes_refs = STRING_LIST_INIT_NODUP,
+		};
+		struct strbuf namespaced_note_ref = STRBUF_INIT;
+
+		strbuf_add(&namespaced_note_ref, get_git_namespace(),
+		           strlen(get_git_namespace()));
+		strbuf_add(&namespaced_note_ref, "refs/notes/commits",
+		           strlen("refs/notes/commits"));
+
+		if (ref_exists(namespaced_note_ref.buf))
+			string_list_append(&opt.extra_notes_refs, namespaced_note_ref.buf);
+
+		init_display_notes(&opt);
+		string_list_clear(&opt.extra_notes_refs, 1);
+		strbuf_release(&namespaced_note_ref);
+	} else
+		init_display_notes(NULL);
 
 	if (nongit) {
 		const char *name = ctx.repo->name;
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 18/21] Add documentation for repo.namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (16 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 17/21] Display notes from namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 19/21] Allow agefile to be set per-repository richard.maw
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgitrc.5.txt | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 9fcf445..0de14a4 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -570,6 +570,11 @@ repo.max-stats::
 repo.name::
 	The value to show as repository name. Default value: <repo.url>.
 
+repo.namespace::
+	Set the git namespace, so that fetching, cloning, listing branches only
+	provide refs in the namespace, and only git notes in that namespace are shown
+	for commits in that namespace. Default value: none.
+
 repo.owner::
 	A value used to identify the owner of the repository. Default value:
 	none.
@@ -772,6 +777,34 @@ Conversely, when a ttl value is zero, the cache is disabled for that
 particular page type, and the page type is never cached.
 
 
+NAMESPACES
+----------
+
+A namespace may be created by creating a "HEAD" symbolic ref for the namespace,
+which may be done with the following command:
+
+....
+git symbolic-ref $namespace_ref_base/HEAD $namespace_ref_base/refs/heads/master
+....
+
+and adding "repo.namespace" for the repository.
+
+For a namespace called "foo/bar", the base ref would be
+"refs/namespaces/foo/refs/namespaces/bar/",
+so the command to create the HEAD ref is:
+
+....
+git symbolic-ref refs/namespaces/foo/refs/namespaces/bar/HEAD \
+                 refs/namespaces/foo/refs/namespaces/bar/refs/heads/master
+....
+
+The config setting for this repository would be:
+
+....
+repo.namespace = foo/bar
+....
+
+
 EXAMPLE CGITRC FILE
 -------------------
 
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 19/21] Allow agefile to be set per-repository
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (17 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 18/21] Add documentation for repo.namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 20/21] Update contrib script to update agefiles per namespace richard.maw
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This adds "repo.agefile", since namespaced repositories share the same files,
and we'd like to be able to see the ages of the refs for each namespace.

Whatever the git server uses for updating the age file must be namespace aware
and must write the age file to a path consistent with "repo.agefile".

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.c        | 2 ++
 cgit.h        | 1 +
 ui-repolist.c | 3 ++-
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/cgit.c b/cgit.c
index 321a00f..f7df288 100644
--- a/cgit.c
+++ b/cgit.c
@@ -88,6 +88,8 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 		repo->logo = xstrdup(value);
 	else if (!strcmp(name, "logo-link") && value != NULL)
 		repo->logo_link = xstrdup(value);
+	else if (!strcmp(name, "agefile") && value != NULL)
+		repo->agefile = xstrdup(value);
 	else if (!strcmp(name, "hide"))
 		repo->hide = atoi(value);
 	else if (!strcmp(name, "ignore"))
diff --git a/cgit.h b/cgit.h
index e915490..485949a 100644
--- a/cgit.h
+++ b/cgit.h
@@ -88,6 +88,7 @@ struct cgit_repo {
 	char *section;
 	char *clone_url;
 	char *namespace;
+	char *agefile;
 	char *logo;
 	char *logo_link;
 	int snapshots;
diff --git a/ui-repolist.c b/ui-repolist.c
index 30915df..6b1afb6 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -42,7 +42,8 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
 		*mtime = repo->mtime;
 		return 1;
 	}
-	strbuf_addf(&path, "%s/%s", repo->path, ctx.cfg.agefile);
+	strbuf_addf(&path, "%s/%s", repo->path,
+	            repo->agefile ? repo->agefile : ctx.cfg.agefile);
 	if (stat(path.buf, &s) == 0) {
 		*mtime = read_agefile(path.buf);
 		if (*mtime) {
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 20/21] Update contrib script to update agefiles per namespace
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (18 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 19/21] Allow agefile to be set per-repository richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-01 21:35 ` [PATCH v3 21/21] Add documentation for repo.agefile richard.maw
  2016-08-20 16:01 ` [PATCH v3 00/21] Add namespace support to cgit richard.maw
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


This uses the same age file as before if it's in the root namespace,
but puts the agefile in info/web/namespaces/$GIT_NAMESPACE/last-modified.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 contrib/hooks/post-receive.agefile | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/contrib/hooks/post-receive.agefile b/contrib/hooks/post-receive.agefile
index 2f72ae9..45ff329 100755
--- a/contrib/hooks/post-receive.agefile
+++ b/contrib/hooks/post-receive.agefile
@@ -10,10 +10,23 @@
 # each of your repositories.
 #
 
-agefile="$(git rev-parse --git-dir)"/info/web/last-modified
+agefile="$(git rev-parse --git-dir)"/info/web
+if [ -z "$GIT_NAMESPACE" ]; then
+	agefile="$agefile/last-modified"
+else
+	agefile="$agefile/namespaces/$GIT_NAMESPACE/last-modified"
+fi
+
+old_IFS="$IFS"
+IFS=/
+for comp in $GIT_NAMESPACE; do
+	nsref="${nsref}refs/namespaces/$comp/"
+done
+IFS="$old_IFS"
 
 mkdir -p "$(dirname "$agefile")" &&
 git for-each-ref \
 	--sort=-authordate --count=1 \
 	--format='%(authordate:iso8601)' \
+	$nsref \
 	>"$agefile"
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 21/21] Add documentation for repo.agefile
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (19 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 20/21] Update contrib script to update agefiles per namespace richard.maw
@ 2016-08-01 21:35 ` richard.maw
  2016-08-20 16:01 ` [PATCH v3 00/21] Add namespace support to cgit richard.maw
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-01 21:35 UTC (permalink / raw)


Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgitrc.5.txt | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 0de14a4..644e0ef 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -468,6 +468,10 @@ repo.about-filter::
 	Override the default about-filter. Default value: none. See also:
 	"enable-filter-overrides". See also: "FILTER API".
 
+repo.agefile::
+	Override the default agefile. Default value: none. See also:
+	"agefile". See also: "NAMESPACES".
+
 repo.branch-sort::
 	Flag which, when set to "age", enables date ordering in the branch ref
 	list, and when set to "name" enables ordering by branch name. Default
@@ -804,6 +808,16 @@ The config setting for this repository would be:
 repo.namespace = foo/bar
 ....
 
+It's also recommended to set a different age file for the namespace.
+The cgit repository contains a contrib script for generating age-files
+for namespaces in a subdirectory.
+
+The corresponding config for the "foo/bar" namespace would be:
+
+....
+repo.agefile = info/web/namespaces/foo/bar/last-modified
+....
+
 
 EXAMPLE CGITRC FILE
 -------------------
-- 
2.9.0



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 17/21] Display notes from namespace
  2016-08-01 21:35 ` [PATCH v3 17/21] Display notes from namespace richard.maw
@ 2016-08-20 14:51   ` richard.maw
  0 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-20 14:51 UTC (permalink / raw)


On 1 August 2016 at 22:35, Richard Maw <richard.maw at gmail.com> wrote:
> diff --git a/cgit.c b/cgit.c
> index d664ab4..321a00f 100644
> --- a/cgit.c
> +++ b/cgit.c
> @@ -586,7 +586,26 @@ static int prepare_repo_cmd(void)
>          * load local configuration from the git repository, so we do them both while
>          * the HOME variables are unset. */
>         setup_git_directory_gently(&nongit);
> -       init_display_notes(NULL);
> +       if (get_git_namespace()) {

This should have been ctx.repo->namespace, since get_git_namespace()
always returns a non-NULL string.
It returns the empty string when there is no namespace.

The new tip of the branch is 59b84b1640ed5def5df659c6269479a463524b5d.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 00/21] Add namespace support to cgit
  2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
                   ` (20 preceding siblings ...)
  2016-08-01 21:35 ` [PATCH v3 21/21] Add documentation for repo.agefile richard.maw
@ 2016-08-20 16:01 ` richard.maw
  21 siblings, 0 replies; 24+ messages in thread
From: richard.maw @ 2016-08-20 16:01 UTC (permalink / raw)


On 1 August 2016 at 22:35, Richard Maw <richard.maw at gmail.com> wrote:
> I'm going to try adding namespaced functions to libgit later in the week.

I tried.

Resolving refs all the way from high-level APIs like get_sha1,
dwim_ref and resolve_ref_unsafe
requires making read_raw_ref, reflog_exists and for_each_reflog*
namespace aware,
and threading a flag for opting into using namespaces through all the
functions in-between.

Actually doing all this is more than I can do in the hobby-programming
time I have available.

Are you willing to accept having the namespace awareness code in cgit?


^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-08-20 16:01 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-01 21:35 [PATCH v3 00/21] Add namespace support to cgit richard.maw
2016-08-01 21:35 ` [PATCH v3 01/21] Return a copy of "master" when guessing defbranch fails richard.maw
2016-08-01 21:35 ` [PATCH v3 02/21] Fix archive generation richard.maw
2016-08-01 21:35 ` [PATCH v3 03/21] Add a wrapper for get_sha1 called cgit_get_sha1 richard.maw
2016-08-01 21:35 ` [PATCH v3 04/21] Parse repo.namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 05/21] Print out parsed namespace on request richard.maw
2016-08-01 21:35 ` [PATCH v3 06/21] Set GIT_NAMESPACE when repo.namespace is provided richard.maw
2016-08-01 21:35 ` [PATCH v3 07/21] Add namespaced resolve ref helper richard.maw
2016-08-01 21:35 ` [PATCH v3 08/21] Add cgit_namespaced_dwim_ref for resolving short refs richard.maw
2016-08-01 21:35 ` [PATCH v3 09/21] Look up refs in namespace with cgit_get_sha1 richard.maw
2016-08-01 21:35 ` [PATCH v3 10/21] Use cgit_namespaced_dwim_ref for finding logs to show richard.maw
2016-08-01 21:35 ` [PATCH v3 11/21] Render commit decorations correctly richard.maw
2016-08-01 21:35 ` [PATCH v3 12/21] Guess the default branch based on current namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 13/21] Add cgit_for_each_namespaced_ref_in helper richard.maw
2016-08-01 21:35 ` [PATCH v3 14/21] Find the default branch based on the contents of the namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 15/21] Only display refs in current namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 16/21] Add namespace support to dumb-clone richard.maw
2016-08-01 21:35 ` [PATCH v3 17/21] Display notes from namespace richard.maw
2016-08-20 14:51   ` richard.maw
2016-08-01 21:35 ` [PATCH v3 18/21] Add documentation for repo.namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 19/21] Allow agefile to be set per-repository richard.maw
2016-08-01 21:35 ` [PATCH v3 20/21] Update contrib script to update agefiles per namespace richard.maw
2016-08-01 21:35 ` [PATCH v3 21/21] Add documentation for repo.agefile richard.maw
2016-08-20 16:01 ` [PATCH v3 00/21] Add namespace support to cgit richard.maw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).