From 9ce5d05f86f64dfad589e0ec58bb1e06a76d2d8c Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:22 +0200
Subject: Fix small typo in cgitrc example

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cgitrc.5.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index d74d9e7..1f7ac1e 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -430,7 +430,7 @@ snapshots=tar.gz tar.bz2 zip
 ## List of common mimetypes
 ##
 
-mimetype.git=image/git
+mimetype.gif=image/gif
 mimetype.html=text/html
 mimetype.jpg=image/jpeg
 mimetype.jpeg=image/jpeg
-- 
cgit v1.2.3


From 026980c270354c59b8a192f5e6db7efe9c66dd62 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:23 +0200
Subject: Remove unused variable in shared.c

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 shared.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/shared.c b/shared.c
index 5f46793..6e8f0ce 100644
--- a/shared.c
+++ b/shared.c
@@ -10,7 +10,6 @@
 
 struct cgit_repolist cgit_repolist;
 struct cgit_context ctx;
-int cgit_cmd;
 
 int chk_zero(int result, char *msg)
 {
-- 
cgit v1.2.3


From c3f23d4571c06c979eddbd4c973163ba76c7e50f Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:24 +0200
Subject: ui-shared: Improve const-ness in API

This is needed to prevent const-related warnings in later patches.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 76 ++++++++++++++++++++++++++++++++-----------------------------
 ui-shared.h | 69 ++++++++++++++++++++++++++++++++-----------------------
 2 files changed, 80 insertions(+), 65 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index 8827fff..7d7fff0 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -27,7 +27,7 @@ static char *http_date(time_t t)
 		   tm->tm_hour, tm->tm_min, tm->tm_sec);
 }
 
-void cgit_print_error(char *msg)
+void cgit_print_error(const char *msg)
 {
 	html("<div class='error'>");
 	html_txt(msg);
@@ -133,7 +133,7 @@ char *cgit_currurl()
 		return fmt("%s/", ctx.cfg.virtual_root);
 }
 
-static void site_url(char *page, char *search, int ofs)
+static void site_url(const char *page, const char *search, int ofs)
 {
 	char *delim = "?";
 
@@ -160,8 +160,8 @@ static void site_url(char *page, char *search, int ofs)
 	}
 }
 
-static void site_link(char *page, char *name, char *title, char *class,
-		      char *search, int ofs)
+static void site_link(const char *page, const char *name, const char *title,
+		      const char *class, const char *search, int ofs)
 {
 	html("<a");
 	if (title) {
@@ -181,14 +181,14 @@ static void site_link(char *page, char *name, char *title, char *class,
 	html("</a>");
 }
 
-void cgit_index_link(char *name, char *title, char *class, char *pattern,
-		     int ofs)
+void cgit_index_link(const char *name, const char *title, const char *class,
+		     const char *pattern, int ofs)
 {
 	site_link(NULL, name, title, class, pattern, ofs);
 }
 
-static char *repolink(char *title, char *class, char *page, char *head,
-		      char *path)
+static char *repolink(const char *title, const char *class, const char *page,
+		      const char *head, const char *path)
 {
 	char *delim = "?";
 
@@ -240,8 +240,9 @@ static char *repolink(char *title, char *class, char *page, char *head,
 	return fmt("%s", delim);
 }
 
-static void reporevlink(char *page, char *name, char *title, char *class,
-			char *head, char *rev, char *path)
+static void reporevlink(const char *page, const char *name, const char *title,
+			const char *class, const char *head, const char *rev,
+			const char *path)
 {
 	char *delim;
 
@@ -256,32 +257,33 @@ static void reporevlink(char *page, char *name, char *title, char *class,
 	html("</a>");
 }
 
-void cgit_summary_link(char *name, char *title, char *class, char *head)
+void cgit_summary_link(const char *name, const char *title, const char *class,
+		       const char *head)
 {
 	reporevlink(NULL, name, title, class, head, NULL, NULL);
 }
 
-void cgit_tag_link(char *name, char *title, char *class, char *head,
-		   char *rev)
+void cgit_tag_link(const char *name, const char *title, const char *class,
+		   const char *head, const char *rev)
 {
 	reporevlink("tag", name, title, class, head, rev, NULL);
 }
 
-void cgit_tree_link(char *name, char *title, char *class, char *head,
-		    char *rev, char *path)
+void cgit_tree_link(const char *name, const char *title, const char *class,
+		    const char *head, const char *rev, const char *path)
 {
 	reporevlink("tree", name, title, class, head, rev, path);
 }
 
-void cgit_plain_link(char *name, char *title, char *class, char *head,
-		     char *rev, char *path)
+void cgit_plain_link(const char *name, const char *title, const char *class,
+		     const char *head, const char *rev, const char *path)
 {
 	reporevlink("plain", name, title, class, head, rev, path);
 }
 
-void cgit_log_link(char *name, char *title, char *class, char *head,
-		   char *rev, char *path, int ofs, char *grep, char *pattern,
-		   int showmsg)
+void cgit_log_link(const char *name, const char *title, const char *class,
+		   const char *head, const char *rev, const char *path,
+		   int ofs, const char *grep, const char *pattern, int showmsg)
 {
 	char *delim;
 
@@ -316,8 +318,8 @@ void cgit_log_link(char *name, char *title, char *class, char *head,
 	html("</a>");
 }
 
-void cgit_commit_link(char *name, char *title, char *class, char *head,
-		      char *rev, int toggle_ssdiff)
+void cgit_commit_link(char *name, const char *title, const char *class,
+		      const char *head, const char *rev, int toggle_ssdiff)
 {
 	if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) {
 		name[ctx.cfg.max_msg_len] = '\0';
@@ -344,21 +346,22 @@ void cgit_commit_link(char *name, char *title, char *class, char *head,
 	html("</a>");
 }
 
-void cgit_refs_link(char *name, char *title, char *class, char *head,
-		    char *rev, char *path)
+void cgit_refs_link(const char *name, const char *title, const char *class,
+		    const char *head, const char *rev, const char *path)
 {
 	reporevlink("refs", name, title, class, head, rev, path);
 }
 
-void cgit_snapshot_link(char *name, char *title, char *class, char *head,
-			char *rev, char *archivename)
+void cgit_snapshot_link(const char *name, const char *title, const char *class,
+			const char *head, const char *rev,
+			const char *archivename)
 {
 	reporevlink("snapshot", name, title, class, head, rev, archivename);
 }
 
-void cgit_diff_link(char *name, char *title, char *class, char *head,
-		    char *new_rev, char *old_rev, char *path,
-		    int toggle_ssdiff)
+void cgit_diff_link(const char *name, const char *title, const char *class,
+		    const char *head, const char *new_rev, const char *old_rev,
+		    const char *path, int toggle_ssdiff)
 {
 	char *delim;
 
@@ -384,14 +387,14 @@ void cgit_diff_link(char *name, char *title, char *class, char *head,
 	html("</a>");
 }
 
-void cgit_patch_link(char *name, char *title, char *class, char *head,
-		     char *rev)
+void cgit_patch_link(const char *name, const char *title, const char *class,
+		     const char *head, const char *rev)
 {
 	reporevlink("patch", name, title, class, head, rev, NULL);
 }
 
-void cgit_stats_link(char *name, char *title, char *class, char *head,
-		     char *path)
+void cgit_stats_link(const char *name, const char *title, const char *class,
+		     const char *head, const char *path)
 {
 	reporevlink("stats", name, title, class, head, NULL, path);
 }
@@ -417,7 +420,7 @@ void cgit_object_link(struct object *obj)
 	reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL);
 }
 
-void cgit_print_date(time_t secs, char *format, int local_time)
+void cgit_print_date(time_t secs, const char *format, int local_time)
 {
 	char buf[64];
 	struct tm *time;
@@ -432,7 +435,7 @@ void cgit_print_date(time_t secs, char *format, int local_time)
 	html_txt(buf);
 }
 
-void cgit_print_age(time_t t, time_t max_relative, char *format)
+void cgit_print_age(time_t t, time_t max_relative, const char *format)
 {
 	time_t now, secs;
 
@@ -611,7 +614,8 @@ int print_archive_ref(const char *refname, const unsigned char *sha1,
 	return 0;
 }
 
-void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page)
+void cgit_add_hidden_formfields(int incl_head, int incl_search,
+				const char *page)
 {
 	char *url;
 
diff --git a/ui-shared.h b/ui-shared.h
index 9ebc1f9..308c982 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -10,36 +10,47 @@ extern char *cgit_fileurl(const char *reponame, const char *pagename,
 extern char *cgit_pageurl(const char *reponame, const char *pagename,
 			  const char *query);
 
-extern void cgit_index_link(char *name, char *title, char *class,
-			    char *pattern, int ofs);
-extern void cgit_summary_link(char *name, char *title, char *class, char *head);
-extern void cgit_tag_link(char *name, char *title, char *class, char *head,
-			  char *rev);
-extern void cgit_tree_link(char *name, char *title, char *class, char *head,
-			   char *rev, char *path);
-extern void cgit_plain_link(char *name, char *title, char *class, char *head,
-			    char *rev, char *path);
-extern void cgit_log_link(char *name, char *title, char *class, char *head,
-			  char *rev, char *path, int ofs, char *grep,
-			  char *pattern, int showmsg);
-extern void cgit_commit_link(char *name, char *title, char *class, char *head,
-			     char *rev, int toggle_ssdiff);
-extern void cgit_patch_link(char *name, char *title, char *class, char *head,
-			    char *rev);
-extern void cgit_refs_link(char *name, char *title, char *class, char *head,
-			   char *rev, char *path);
-extern void cgit_snapshot_link(char *name, char *title, char *class,
-			       char *head, char *rev, char *archivename);
-extern void cgit_diff_link(char *name, char *title, char *class, char *head,
-			   char *new_rev, char *old_rev, char *path,
-			   int toggle_ssdiff);
-extern void cgit_stats_link(char *name, char *title, char *class, char *head,
-			    char *path);
+extern void cgit_index_link(const char *name, const char *title,
+			    const char *class, const char *pattern, int ofs);
+extern void cgit_summary_link(const char *name, const char *title,
+			      const char *class, const char *head);
+extern void cgit_tag_link(const char *name, const char *title,
+			  const char *class, const char *head,
+			  const char *rev);
+extern void cgit_tree_link(const char *name, const char *title,
+			   const char *class, const char *head,
+			   const char *rev, const char *path);
+extern void cgit_plain_link(const char *name, const char *title,
+			    const char *class, const char *head,
+			    const char *rev, const char *path);
+extern void cgit_log_link(const char *name, const char *title,
+			  const char *class, const char *head, const char *rev,
+			  const char *path, int ofs, const char *grep,
+			  const char *pattern, int showmsg);
+extern void cgit_commit_link(char *name, const char *title,
+			     const char *class, const char *head,
+			     const char *rev, int toggle_ssdiff);
+extern void cgit_patch_link(const char *name, const char *title,
+			    const char *class, const char *head,
+			    const char *rev);
+extern void cgit_refs_link(const char *name, const char *title,
+			   const char *class, const char *head,
+			   const char *rev, const char *path);
+extern void cgit_snapshot_link(const char *name, const char *title,
+			       const char *class, const char *head,
+			       const char *rev, const char *archivename);
+extern void cgit_diff_link(const char *name, const char *title,
+			   const char *class, const char *head,
+			   const char *new_rev, const char *old_rev,
+			   const char *path, int toggle_ssdiff);
+extern void cgit_stats_link(const char *name, const char *title,
+			    const char *class, const char *head,
+			    const char *path);
 extern void cgit_object_link(struct object *obj);
 
-extern void cgit_print_error(char *msg);
-extern void cgit_print_date(time_t secs, char *format, int local_time);
-extern void cgit_print_age(time_t t, time_t max_relative, char *format);
+extern void cgit_print_error(const char *msg);
+extern void cgit_print_date(time_t secs, const char *format, int local_time);
+extern void cgit_print_age(time_t t, time_t max_relative, const char *format);
 extern void cgit_print_http_headers(struct cgit_context *ctx);
 extern void cgit_print_docstart(struct cgit_context *ctx);
 extern void cgit_print_docend();
@@ -48,5 +59,5 @@ extern void cgit_print_filemode(unsigned short mode);
 extern void cgit_print_snapshot_links(const char *repo, const char *head,
 				      const char *hex, int snapshots);
 extern void cgit_add_hidden_formfields(int incl_head, int incl_search,
-				       char *page);
+				       const char *page);
 #endif /* UI_SHARED_H */
-- 
cgit v1.2.3


From 0e34c6d1ef32ea8f69019272fe72dbf2aeaba392 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:25 +0200
Subject: ui-shared: Remove needless cgit_get_cmd() call, and refactor hc()
 accordingly

The call to cgit_get_cmd() and the following fallback handling (to "summary"
or "repoindex") in cgit_print_pageheader() is unnecessary, since the same
fallback handling was already done when ctx.qry.page was set when
cgit_get_cmd() was called from process_request() in cgit.c.

As such, hc() can also be rewritten to simply compare the given 'page' string
against ctx.qry.page.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index 7d7fff0..137e469 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -645,11 +645,9 @@ void cgit_add_hidden_formfields(int incl_head, int incl_search,
 	}
 }
 
-const char *fallback_cmd = "repolist";
-
-char *hc(struct cgit_cmd *cmd, const char *page)
+static const char *hc(struct cgit_context *ctx, const char *page)
 {
-	return (strcmp(cmd ? cmd->name : fallback_cmd, page) ? NULL : "active");
+	return strcmp(ctx->qry.page, page) ? NULL : "active";
 }
 
 static void print_header(struct cgit_context *ctx)
@@ -701,35 +699,30 @@ static void print_header(struct cgit_context *ctx)
 
 void cgit_print_pageheader(struct cgit_context *ctx)
 {
-	struct cgit_cmd *cmd = cgit_get_cmd(ctx);
-
-	if (!cmd && ctx->repo)
-		fallback_cmd = "summary";
-
 	html("<div id='cgit'>");
 	if (!ctx->cfg.noheader)
 		print_header(ctx);
 
 	html("<table class='tabs'><tr><td>\n");
 	if (ctx->repo) {
-		cgit_summary_link("summary", NULL, hc(cmd, "summary"),
+		cgit_summary_link("summary", NULL, hc(ctx, "summary"),
 				  ctx->qry.head);
-		cgit_refs_link("refs", NULL, hc(cmd, "refs"), ctx->qry.head,
+		cgit_refs_link("refs", NULL, hc(ctx, "refs"), ctx->qry.head,
 			       ctx->qry.sha1, NULL);
-		cgit_log_link("log", NULL, hc(cmd, "log"), ctx->qry.head,
+		cgit_log_link("log", NULL, hc(ctx, "log"), ctx->qry.head,
 			      NULL, NULL, 0, NULL, NULL, ctx->qry.showmsg);
-		cgit_tree_link("tree", NULL, hc(cmd, "tree"), ctx->qry.head,
+		cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head,
 			       ctx->qry.sha1, NULL);
-		cgit_commit_link("commit", NULL, hc(cmd, "commit"),
+		cgit_commit_link("commit", NULL, hc(ctx, "commit"),
 				 ctx->qry.head, ctx->qry.sha1, 0);
-		cgit_diff_link("diff", NULL, hc(cmd, "diff"), ctx->qry.head,
+		cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head,
 			       ctx->qry.sha1, ctx->qry.sha2, NULL, 0);
 		if (ctx->repo->max_stats)
-			cgit_stats_link("stats", NULL, hc(cmd, "stats"),
+			cgit_stats_link("stats", NULL, hc(ctx, "stats"),
 					ctx->qry.head, NULL);
 		if (ctx->repo->readme)
 			reporevlink("about", "about", NULL,
-				    hc(cmd, "about"), ctx->qry.head, NULL,
+				    hc(ctx, "about"), ctx->qry.head, NULL,
 				    NULL);
 		html("</td><td class='form'>");
 		html("<form class='right' method='get' action='");
@@ -749,9 +742,9 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 		html("<input type='submit' value='search'/>\n");
 		html("</form>\n");
 	} else {
-		site_link(NULL, "index", NULL, hc(cmd, "repolist"), NULL, 0);
+		site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0);
 		if (ctx->cfg.root_readme)
-			site_link("about", "about", NULL, hc(cmd, "about"),
+			site_link("about", "about", NULL, hc(ctx, "about"),
 				  NULL, 0);
 		html("</td><td class='form'>");
 		html("<form method='get' action='");
-- 
cgit v1.2.3


From 0ff143df7043b7dd87c31c50fa875bc96d1a7779 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:26 +0200
Subject: struct cgit_cmd: Differentiate between various usages of ctx.qry.path

For many commands/pages (e.g. 'tree', 'diff', 'plain', etc.), the
ctx.qry.path argument is interpreted as a path within the "virtual" project
directory structure. However, for some other commands (notably 'refs', and
the clone-related commands) ctx.qry.path is used in a different context (as
a more or less "real" path within the '.git' directory).

This patch differentiates between these two usages of ctx.qry.path, by
introducing a new variable - ctx.qry.vpath - which is equal to ctx.qry.path
in the former case, and NULL in the latter.

This will become useful in future patches when we want various pages and the
links between them to preserve existing in-project paths.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cgit.c |  6 ++++++
 cgit.h |  1 +
 cmd.c  | 42 +++++++++++++++++++++---------------------
 cmd.h  |  3 ++-
 4 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/cgit.c b/cgit.c
index 9305d0a..2c3ad73 100644
--- a/cgit.c
+++ b/cgit.c
@@ -424,6 +424,12 @@ static void process_request(void *cbdata)
 		return;
 	}
 
+	/* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual"
+	 * in-project path limit to be made available at ctx->qry.vpath.
+	 * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL).
+	 */
+	ctx->qry.vpath = cmd->want_vpath ? ctx->qry.path : NULL;
+
 	if (cmd->want_repo && !ctx->repo) {
 		cgit_print_http_headers(ctx);
 		cgit_print_docstart(ctx);
diff --git a/cgit.h b/cgit.h
index cd4af72..f990b15 100644
--- a/cgit.h
+++ b/cgit.h
@@ -145,6 +145,7 @@ struct cgit_query {
 	char *sort;
 	int showmsg;
 	int ssdiff;
+	char *vpath;
 };
 
 struct cgit_config {
diff --git a/cmd.c b/cmd.c
index 766f903..a9e426a 100644
--- a/cmd.c
+++ b/cmd.c
@@ -129,31 +129,31 @@ static void tree_fn(struct cgit_context *ctx)
 	cgit_print_tree(ctx->qry.sha1, ctx->qry.path);
 }
 
-#define def_cmd(name, want_repo, want_layout) \
-	{#name, name##_fn, want_repo, want_layout}
+#define def_cmd(name, want_repo, want_layout, want_vpath) \
+	{#name, name##_fn, want_repo, want_layout, want_vpath}
 
 struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
 {
 	static struct cgit_cmd cmds[] = {
-		def_cmd(HEAD, 1, 0),
-		def_cmd(atom, 1, 0),
-		def_cmd(about, 0, 1),
-		def_cmd(blob, 1, 0),
-		def_cmd(commit, 1, 1),
-		def_cmd(diff, 1, 1),
-		def_cmd(info, 1, 0),
-		def_cmd(log, 1, 1),
-		def_cmd(ls_cache, 0, 0),
-		def_cmd(objects, 1, 0),
-		def_cmd(patch, 1, 0),
-		def_cmd(plain, 1, 0),
-		def_cmd(refs, 1, 1),
-		def_cmd(repolist, 0, 0),
-		def_cmd(snapshot, 1, 0),
-		def_cmd(stats, 1, 1),
-		def_cmd(summary, 1, 1),
-		def_cmd(tag, 1, 1),
-		def_cmd(tree, 1, 1),
+		def_cmd(HEAD, 1, 0, 0),
+		def_cmd(atom, 1, 0, 0),
+		def_cmd(about, 0, 1, 0),
+		def_cmd(blob, 1, 0, 0),
+		def_cmd(commit, 1, 1, 1),
+		def_cmd(diff, 1, 1, 1),
+		def_cmd(info, 1, 0, 0),
+		def_cmd(log, 1, 1, 1),
+		def_cmd(ls_cache, 0, 0, 0),
+		def_cmd(objects, 1, 0, 0),
+		def_cmd(patch, 1, 0, 1),
+		def_cmd(plain, 1, 0, 0),
+		def_cmd(refs, 1, 1, 0),
+		def_cmd(repolist, 0, 0, 0),
+		def_cmd(snapshot, 1, 0, 0),
+		def_cmd(stats, 1, 1, 1),
+		def_cmd(summary, 1, 1, 0),
+		def_cmd(tag, 1, 1, 0),
+		def_cmd(tree, 1, 1, 1),
 	};
 	int i;
 
diff --git a/cmd.h b/cmd.h
index ec9e691..8dc01bd 100644
--- a/cmd.h
+++ b/cmd.h
@@ -7,7 +7,8 @@ struct cgit_cmd {
 	const char *name;
 	cgit_cmd_fn fn;
 	unsigned int want_repo:1,
-		want_layout:1;
+		want_layout:1,
+		want_vpath:1;
 };
 
 extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx);
-- 
cgit v1.2.3


From c8e3295469bd3b8e38a9ea4478d517d3861e6c93 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:27 +0200
Subject: ui-shared: Replace ctx.qry.path with ctx.qry.vpath

In all cases where ui-shared uses ctx.qry.path, it is done so in the context
of a in-project path, and not in the context in which the 'refs' page or the
'clone'-related functionality uses ctx.qry.path. Make this explicit by using
ctx.qry.vpath instead.

This path introduces no fundamental difference in functionality except for
fixing some minor bugs, for example the Atom feed reference from a
"$repo/refs/heads/" page.

Note that the usage of ctx.qry.path in the other ui-<page>.c files is ok,
since that code presumably is only executed in the context of its own <page>,
so the correct interpretation of ctx.qry.path is never in question.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index 137e469..3d5030b 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -534,7 +534,7 @@ void cgit_print_docstart(struct cgit_context *ctx)
 		html("<link rel='alternate' title='Atom feed' href='");
 		html(cgit_httpscheme());
 		html_attr(cgit_hosturl());
-		html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path,
+		html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.vpath,
 				       fmt("h=%s", ctx->qry.head)));
 		html("' type='application/atom+xml'/>\n");
 	}
@@ -621,8 +621,8 @@ void cgit_add_hidden_formfields(int incl_head, int incl_search,
 
 	if (!ctx.cfg.virtual_root) {
 		url = fmt("%s/%s", ctx.qry.repo, page);
-		if (ctx.qry.path)
-			url = fmt("%s/%s", url, ctx.qry.path);
+		if (ctx.qry.vpath)
+			url = fmt("%s/%s", url, ctx.qry.vpath);
 		html_hidden("url", url);
 	}
 
@@ -728,7 +728,7 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 		html("<form class='right' method='get' action='");
 		if (ctx->cfg.virtual_root)
 			html_url_path(cgit_fileurl(ctx->qry.repo, "log",
-						   ctx->qry.path, NULL));
+						   ctx->qry.vpath, NULL));
 		html("'>\n");
 		cgit_add_hidden_formfields(1, 0, "log");
 		html("<select name='qt'>\n");
-- 
cgit v1.2.3


From c93ef96aaf77437abeb552bd9e30973f90365f3a Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:28 +0200
Subject: ui-shared: Display path limit directly beneath tab bar in relevant
 pages

Design-wise, the path is shown by "expanding" the grey border between the
tab bar and the content area of the page to house the current path limit.

This is only displayed on pages where the path limit is relevant, and only
when a path limit is in effect.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cgit.css    | 8 ++++++++
 ui-shared.c | 6 ++++++
 2 files changed, 14 insertions(+)

diff --git a/cgit.css b/cgit.css
index 0cb894a..563f8e1 100644
--- a/cgit.css
+++ b/cgit.css
@@ -102,6 +102,14 @@ table.tabs td.form select {
 	font-size: 90%;
 }
 
+div.path {
+	margin: 0px;
+	padding: 5px 2em 2px 2em;
+	color: #000;
+	background-color: #ccc;
+	font-weight: bold;
+}
+
 div.content {
 	margin: 0px;
 	padding: 2em;
diff --git a/ui-shared.c b/ui-shared.c
index 3d5030b..bc14e70 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -757,6 +757,12 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 		html("</form>");
 	}
 	html("</td></tr></table>\n");
+	if (ctx->qry.vpath) {
+		html("<div class='path'>");
+		html("path: ");
+		html_txt(ctx->qry.vpath);
+		html("</div>");
+	}
 	html("<div class='content'>");
 }
 
-- 
cgit v1.2.3


From 24fd7e54c82294efa68ecae5dd9cb8a8986c04bf Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:29 +0200
Subject: ui-shared: Teach "breadcrumb" navigation to path limit display
 beneath tab bar

When a path limit is in effect, and displayed directly beneath the tab bar,
it should offer breadcrumb navigation (like what the 'tree' page does), to
allow changing the path limit easily.

Implementing this requires a robust way to link back to the current page with
a changed ctx->qry.path, but without losing track of the other query
arguments. This is solved by adding the new cgit_self_link() function, which
is then invoked repeatedly by the new cgit_print_path_crumbs() function while
manipulating ctx->qry.path.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 ui-shared.h |  2 ++
 2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/ui-shared.c b/ui-shared.c
index bc14e70..4fa506f 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -399,6 +399,64 @@ void cgit_stats_link(const char *name, const char *title, const char *class,
 	reporevlink("stats", name, title, class, head, NULL, path);
 }
 
+void cgit_self_link(char *name, const char *title, const char *class,
+		    struct cgit_context *ctx)
+{
+	if (!strcmp(ctx->qry.page, "repolist"))
+		return cgit_index_link(name, title, class, ctx->qry.search,
+				       ctx->qry.ofs);
+	else if (!strcmp(ctx->qry.page, "summary"))
+		return cgit_summary_link(name, title, class, ctx->qry.head);
+	else if (!strcmp(ctx->qry.page, "tag"))
+		return cgit_tag_link(name, title, class, ctx->qry.head,
+				     ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL);
+	else if (!strcmp(ctx->qry.page, "tree"))
+		return cgit_tree_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path);
+	else if (!strcmp(ctx->qry.page, "plain"))
+		return cgit_plain_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path);
+	else if (!strcmp(ctx->qry.page, "log"))
+		return cgit_log_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path, ctx->qry.ofs,
+				      ctx->qry.grep, ctx->qry.search,
+				      ctx->qry.showmsg);
+	else if (!strcmp(ctx->qry.page, "commit"))
+		return cgit_commit_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path, 0);
+	else if (!strcmp(ctx->qry.page, "patch"))
+		return cgit_patch_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path);
+	else if (!strcmp(ctx->qry.page, "refs"))
+		return cgit_refs_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path);
+	else if (!strcmp(ctx->qry.page, "snapshot"))
+		return cgit_snapshot_link(name, title, class, ctx->qry.head,
+				      ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
+				      ctx->qry.path);
+	else if (!strcmp(ctx->qry.page, "diff"))
+		return cgit_diff_link(name, title, class, ctx->qry.head,
+				      ctx->qry.sha1, ctx->qry.sha2,
+				      ctx->qry.path, 0);
+	else if (!strcmp(ctx->qry.page, "stats"))
+		return cgit_stats_link(name, title, class, ctx->qry.head,
+				      ctx->qry.path);
+
+	/* Don't known how to make link for this page */
+	repolink(title, class, ctx->qry.page, ctx->qry.head, ctx->qry.path);
+	html("><!-- cgit_self_link() doesn't know how to make link for page '");
+	html_txt(ctx->qry.page);
+	html("' -->");
+	html_txt(name);
+	html("</a>");
+}
+
 void cgit_object_link(struct object *obj)
 {
 	char *page, *shortrev, *fullrev, *name;
@@ -650,6 +708,27 @@ static const char *hc(struct cgit_context *ctx, const char *page)
 	return strcmp(ctx->qry.page, page) ? NULL : "active";
 }
 
+static void cgit_print_path_crumbs(struct cgit_context *ctx, char *path)
+{
+	char *old_path = ctx->qry.path;
+	char *p = path, *q, *end = path + strlen(path);
+
+	ctx->qry.path = NULL;
+	cgit_self_link("root", NULL, NULL, ctx);
+	ctx->qry.path = p = path;
+	while (p < end) {
+		if (!(q = strchr(p, '/')))
+			q = end;
+		*q = '\0';
+		html_txt("/");
+		cgit_self_link(p, NULL, NULL, ctx);
+		if (q < end)
+			*q = '/';
+		p = q + 1;
+	}
+	ctx->qry.path = old_path;
+}
+
 static void print_header(struct cgit_context *ctx)
 {
 	html("<table id='header'>\n");
@@ -760,7 +839,7 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 	if (ctx->qry.vpath) {
 		html("<div class='path'>");
 		html("path: ");
-		html_txt(ctx->qry.vpath);
+		cgit_print_path_crumbs(ctx, ctx->qry.vpath);
 		html("</div>");
 	}
 	html("<div class='content'>");
diff --git a/ui-shared.h b/ui-shared.h
index 308c982..3df5464 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -46,6 +46,8 @@ extern void cgit_diff_link(const char *name, const char *title,
 extern void cgit_stats_link(const char *name, const char *title,
 			    const char *class, const char *head,
 			    const char *path);
+extern void cgit_self_link(char *name, const char *title,
+			   const char *class, struct cgit_context *ctx);
 extern void cgit_object_link(struct object *obj);
 
 extern void cgit_print_error(const char *msg);
-- 
cgit v1.2.3


From 48f7b982d3bb52f1307df73ceb6dd4cab3fdcc80 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:30 +0200
Subject: ui-tree: Remove unnecessary path breadcrumb navigation

The path breadcrumb navigation at the top of the 'tree' page has now been
duplicated in ui-shared, which leaves the ui-tree implementation unnecessary.

This patch removes the breadcrumb navigation from ui-tree, and moves the
"(plain)" link that followed the breadcrumb when displaying blobs to the
end of the next line, following the blob SHA1.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-tree.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/ui-tree.c b/ui-tree.c
index 0ee38f2..75ec9cb 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -102,10 +102,10 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
 		return;
 	}
 
-	html(" (");
+	htmlf("blob: %s (", sha1_to_hex(sha1));
 	cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
 		        curr_rev, path);
-	htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
+	html(")\n");
 
 	if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
 		htmlf("<div class='error'>blob size (%dKB) exceeds display size limit (%dKB).</div>",
@@ -225,17 +225,10 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
 {
 	static int state;
 	static char buffer[PATH_MAX];
-	char *url;
 
 	if (state == 0) {
 		memcpy(buffer, base, baselen);
 		strcpy(buffer+baselen, pathname);
-		url = cgit_pageurl(ctx.qry.repo, "tree",
-				   fmt("h=%s&amp;path=%s", curr_rev, buffer));
-		html("/");
-		cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
-			       curr_rev, buffer);
-
 		if (strcmp(match_path, buffer))
 			return READ_TREE_RECURSIVE;
 
@@ -278,10 +271,6 @@ void cgit_print_tree(const char *rev, char *path)
 		return;
 	}
 
-	html("path: <a href='");
-	html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
-	html("'>root</a>");
-
 	if (path == NULL) {
 		ls_tree(commit->tree->object.sha1, NULL);
 		return;
-- 
cgit v1.2.3


From c46e468dd229d5a20d99801072b4a8f8d970104f Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:31 +0200
Subject: ui-diff: Teach diffstat to obey path limit

Also indicate in the diffstat header if a path limit is in effect.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-diff.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/ui-diff.c b/ui-diff.c
index a92a768..fb836df 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -154,17 +154,19 @@ static void inspect_filepair(struct diff_filepair *pair)
 }
 
 void cgit_print_diffstat(const unsigned char *old_sha1,
-			 const unsigned char *new_sha1)
+			 const unsigned char *new_sha1, const char *prefix)
 {
 	int i;
 
 	html("<div class='diffstat-header'>");
 	cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
 		       ctx.qry.sha2, NULL, 0);
+	if (prefix)
+		htmlf(" (limited to '%s')", prefix);
 	html("</div>");
 	html("<table summary='diffstat' class='diffstat'>");
 	max_changes = 0;
-	cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL);
+	cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, prefix);
 	for(i = 0; i<files; i++)
 		print_fileinfo(&items[i]);
 	html("</table>");
@@ -338,7 +340,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi
 		use_ssdiff = 1;
 
 	print_ssdiff_link();
-	cgit_print_diffstat(old_rev_sha1, new_rev_sha1);
+	cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix);
 
 	if (use_ssdiff) {
 		html("<table summary='ssdiff' class='ssdiff'>");
-- 
cgit v1.2.3


From ab42741c49d369e41c1e1915c6c024d79509f7d6 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:32 +0200
Subject: ui-commit: Limit diff based on path limit in qry.path

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cmd.c       | 2 +-
 ui-commit.c | 4 ++--
 ui-commit.h | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/cmd.c b/cmd.c
index a9e426a..893ae25 100644
--- a/cmd.c
+++ b/cmd.c
@@ -51,7 +51,7 @@ static void blob_fn(struct cgit_context *ctx)
 
 static void commit_fn(struct cgit_context *ctx)
 {
-	cgit_print_commit(ctx->qry.sha1);
+	cgit_print_commit(ctx->qry.sha1, ctx->qry.path);
 }
 
 static void diff_fn(struct cgit_context *ctx)
diff --git a/ui-commit.c b/ui-commit.c
index b5e3c01..2f4c6d4 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -12,7 +12,7 @@
 #include "ui-diff.h"
 #include "ui-log.h"
 
-void cgit_print_commit(char *hex)
+void cgit_print_commit(char *hex, const char *prefix)
 {
 	struct commit *commit, *parent;
 	struct commitinfo *info;
@@ -117,7 +117,7 @@ void cgit_print_commit(char *hex)
 			tmp = sha1_to_hex(commit->parents->item->object.sha1);
 		else
 			tmp = NULL;
-		cgit_print_diff(ctx.qry.sha1, tmp, NULL);
+		cgit_print_diff(ctx.qry.sha1, tmp, prefix);
 	}
 	cgit_free_commitinfo(info);
 }
diff --git a/ui-commit.h b/ui-commit.h
index 40bcb31..8198b4b 100644
--- a/ui-commit.h
+++ b/ui-commit.h
@@ -1,6 +1,6 @@
 #ifndef UI_COMMIT_H
 #define UI_COMMIT_H
 
-extern void cgit_print_commit(char *hex);
+extern void cgit_print_commit(char *hex, const char *prefix);
 
 #endif /* UI_COMMIT_H */
-- 
cgit v1.2.3


From eac1b675414722ae90df75abc727b2795bc096f0 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:33 +0200
Subject: ui-patch: Apply path limit to generated patch

Also indicate in the comment section of the patch that a path limit was
applied, too easily see when a generated patch is only partial.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cmd.c       | 2 +-
 ui-commit.c | 2 +-
 ui-patch.c  | 6 ++++--
 ui-patch.h  | 2 +-
 ui-shared.c | 4 ++--
 ui-shared.h | 2 +-
 6 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/cmd.c b/cmd.c
index 893ae25..605876b 100644
--- a/cmd.c
+++ b/cmd.c
@@ -90,7 +90,7 @@ static void repolist_fn(struct cgit_context *ctx)
 
 static void patch_fn(struct cgit_context *ctx)
 {
-	cgit_print_patch(ctx->qry.sha1);
+	cgit_print_patch(ctx->qry.sha1, ctx->qry.path);
 }
 
 static void plain_fn(struct cgit_context *ctx)
diff --git a/ui-commit.c b/ui-commit.c
index 2f4c6d4..b3a2063 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -60,7 +60,7 @@ void cgit_print_commit(char *hex, const char *prefix)
 	tmp = sha1_to_hex(commit->object.sha1);
 	cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, 0);
 	html(" (");
-	cgit_patch_link("patch", NULL, NULL, NULL, tmp);
+	cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
 	html(") (");
 	if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
 		cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, 1);
diff --git a/ui-patch.c b/ui-patch.c
index 2a8f7a5..25dc9fe 100644
--- a/ui-patch.c
+++ b/ui-patch.c
@@ -77,7 +77,7 @@ static void filepair_cb(struct diff_filepair *pair)
 		html("Binary files differ\n");
 }
 
-void cgit_print_patch(char *hex)
+void cgit_print_patch(char *hex, const char *prefix)
 {
 	struct commit *commit;
 	struct commitinfo *info;
@@ -122,7 +122,9 @@ void cgit_print_patch(char *hex)
 			html("\n");
 	}
 	html("---\n");
-	cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL);
+	if (prefix)
+		htmlf("(limited to '%s')\n\n", prefix);
+	cgit_diff_tree(old_sha1, sha1, filepair_cb, prefix);
 	html("--\n");
 	htmlf("cgit %s\n", CGIT_VERSION);
 	cgit_free_commitinfo(info);
diff --git a/ui-patch.h b/ui-patch.h
index 9f68212..1641cea 100644
--- a/ui-patch.h
+++ b/ui-patch.h
@@ -1,6 +1,6 @@
 #ifndef UI_PATCH_H
 #define UI_PATCH_H
 
-extern void cgit_print_patch(char *hex);
+extern void cgit_print_patch(char *hex, const char *prefix);
 
 #endif /* UI_PATCH_H */
diff --git a/ui-shared.c b/ui-shared.c
index 4fa506f..d5c4c10 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -388,9 +388,9 @@ void cgit_diff_link(const char *name, const char *title, const char *class,
 }
 
 void cgit_patch_link(const char *name, const char *title, const char *class,
-		     const char *head, const char *rev)
+		     const char *head, const char *rev, const char *path)
 {
-	reporevlink("patch", name, title, class, head, rev, NULL);
+	reporevlink("patch", name, title, class, head, rev, path);
 }
 
 void cgit_stats_link(const char *name, const char *title, const char *class,
diff --git a/ui-shared.h b/ui-shared.h
index 3df5464..c0e5c55 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -32,7 +32,7 @@ extern void cgit_commit_link(char *name, const char *title,
 			     const char *rev, int toggle_ssdiff);
 extern void cgit_patch_link(const char *name, const char *title,
 			    const char *class, const char *head,
-			    const char *rev);
+			    const char *rev, const char *path);
 extern void cgit_refs_link(const char *name, const char *title,
 			   const char *class, const char *head,
 			   const char *rev, const char *path);
-- 
cgit v1.2.3


From 34c2331d2c33ea28743a2ee3e62f7337ae9887f6 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:34 +0200
Subject: ui-commit: Preserve path limit in links to tree and diff pages

For tree links, the original link is unchanged, but in the case of a path
limit, a subtree link is added to the right of the original tree link.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-commit.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/ui-commit.c b/ui-commit.c
index b3a2063..1793921 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -71,6 +71,10 @@ void cgit_print_commit(char *hex, const char *prefix)
 	tmp = xstrdup(hex);
 	cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL,
 		       ctx.qry.head, tmp, NULL);
+	if (prefix) {
+		html(" /");
+		cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tmp, prefix);
+	}
 	html("</td></tr>\n");
       	for (p = commit->parents; p ; p = p->next) {
 		parent = lookup_commit_reference(p->item->object.sha1);
@@ -86,7 +90,7 @@ void cgit_print_commit(char *hex, const char *prefix)
 				 ctx.qry.head, sha1_to_hex(p->item->object.sha1), 0);
 		html(" (");
 		cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex,
-			       sha1_to_hex(p->item->object.sha1), NULL, 0);
+			       sha1_to_hex(p->item->object.sha1), prefix, 0);
 		html(")</td></tr>");
 		parents++;
 	}
-- 
cgit v1.2.3


From 685872b770be2af643d00365d5358e46687f7385 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:35 +0200
Subject: ui-commit: Preserve path limit in links to commit page

This includes adding a path argument to cgit_commit_link() and updating all
its callers. The callers from within the commit page (i.e. the "commit",
"unidiff"/"side-by-side diff" and "parent" links) all preserve the path
limit of the current commit page. All other callers pass NULL (i.e. no path
limit).

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-commit.c | 9 +++++----
 ui-log.c    | 4 ++--
 ui-refs.c   | 2 +-
 ui-shared.c | 9 +++++----
 ui-shared.h | 3 ++-
 5 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/ui-commit.c b/ui-commit.c
index 1793921..2d98ed9 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -58,14 +58,14 @@ void cgit_print_commit(char *hex, const char *prefix)
 	html("</td></tr>\n");
 	html("<tr><th>commit</th><td colspan='2' class='sha1'>");
 	tmp = sha1_to_hex(commit->object.sha1);
-	cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, 0);
+	cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
 	html(" (");
 	cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
 	html(") (");
 	if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
-		cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, 1);
+		cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
 	else
-		cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, 1);
+		cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
 	html(")</td></tr>\n");
 	html("<tr><th>tree</th><td colspan='2' class='sha1'>");
 	tmp = xstrdup(hex);
@@ -87,7 +87,8 @@ void cgit_print_commit(char *hex, const char *prefix)
 		html("<tr><th>parent</th>"
 		     "<td colspan='2' class='sha1'>");
 		cgit_commit_link(sha1_to_hex(p->item->object.sha1), NULL, NULL,
-				 ctx.qry.head, sha1_to_hex(p->item->object.sha1), 0);
+				 ctx.qry.head,
+				 sha1_to_hex(p->item->object.sha1), prefix, 0);
 		html(" (");
 		cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex,
 			       sha1_to_hex(p->item->object.sha1), prefix, 0);
diff --git a/ui-log.c b/ui-log.c
index 0947604..282eca3 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -66,7 +66,7 @@ void show_commit_decorations(struct commit *commit)
 		else {
 			strncpy(buf, deco->name, sizeof(buf) - 1);
 			cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
-				sha1_to_hex(commit->object.sha1), 0);
+				sha1_to_hex(commit->object.sha1), NULL, 0);
 		}
 		deco = deco->next;
 	}
@@ -89,7 +89,7 @@ void print_commit(struct commit *commit)
 	htmlf("</td><td%s>",
 		ctx.qry.showmsg ? " class='logsubject'" : "");
 	cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
-			 sha1_to_hex(commit->object.sha1), 0);
+			 sha1_to_hex(commit->object.sha1), NULL, 0);
 	show_commit_decorations(commit);
 	html("</td><td>");
 	html_txt(info->author);
diff --git a/ui-refs.c b/ui-refs.c
index 98738db..94ff6be 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -74,7 +74,7 @@ static int print_branch(struct refinfo *ref)
 	html("</td><td>");
 
 	if (ref->object->type == OBJ_COMMIT) {
-		cgit_commit_link(info->subject, NULL, NULL, name, NULL, 0);
+		cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL, 0);
 		html("</td><td>");
 		html_txt(info->author);
 		html("</td><td colspan='2'>");
diff --git a/ui-shared.c b/ui-shared.c
index d5c4c10..372b9e7 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -319,7 +319,8 @@ void cgit_log_link(const char *name, const char *title, const char *class,
 }
 
 void cgit_commit_link(char *name, const char *title, const char *class,
-		      const char *head, const char *rev, int toggle_ssdiff)
+		      const char *head, const char *rev, const char *path,
+		      int toggle_ssdiff)
 {
 	if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) {
 		name[ctx.cfg.max_msg_len] = '\0';
@@ -330,7 +331,7 @@ void cgit_commit_link(char *name, const char *title, const char *class,
 
 	char *delim;
 
-	delim = repolink(title, class, "commit", head, NULL);
+	delim = repolink(title, class, "commit", head, path);
 	if (rev && strcmp(rev, ctx.qry.head)) {
 		html(delim);
 		html("id=");
@@ -466,7 +467,7 @@ void cgit_object_link(struct object *obj)
 	shortrev[10] = '\0';
 	if (obj->type == OBJ_COMMIT) {
                 cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
-				 ctx.qry.head, fullrev, 0);
+				 ctx.qry.head, fullrev, NULL, 0);
 		return;
 	} else if (obj->type == OBJ_TREE)
 		page = "tree";
@@ -793,7 +794,7 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 		cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head,
 			       ctx->qry.sha1, NULL);
 		cgit_commit_link("commit", NULL, hc(ctx, "commit"),
-				 ctx->qry.head, ctx->qry.sha1, 0);
+				 ctx->qry.head, ctx->qry.sha1, NULL, 0);
 		cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head,
 			       ctx->qry.sha1, ctx->qry.sha2, NULL, 0);
 		if (ctx->repo->max_stats)
diff --git a/ui-shared.h b/ui-shared.h
index c0e5c55..3cc1258 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -29,7 +29,8 @@ extern void cgit_log_link(const char *name, const char *title,
 			  const char *pattern, int showmsg);
 extern void cgit_commit_link(char *name, const char *title,
 			     const char *class, const char *head,
-			     const char *rev, int toggle_ssdiff);
+			     const char *rev, const char *path,
+			     int toggle_ssdiff);
 extern void cgit_patch_link(const char *name, const char *title,
 			    const char *class, const char *head,
 			    const char *rev, const char *path);
-- 
cgit v1.2.3


From 7fdff2460440c09d13fc76af3b75e85434e6f563 Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Thu, 10 Jun 2010 01:09:36 +0200
Subject: ui-shared: Preserve path limit in "tab bar" links

When using the "tab bar" in the pageheader to navigate between pages, any
path limit in effect on the current page is forgotten in the link to the
target page, even if the target page can interpret and use the path limit
constructively.

Instead, preserve the current page's path limit in the "tab bar" links to
other pages, where the path limit is useful to the target page.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index 372b9e7..e991799 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -790,16 +790,17 @@ void cgit_print_pageheader(struct cgit_context *ctx)
 		cgit_refs_link("refs", NULL, hc(ctx, "refs"), ctx->qry.head,
 			       ctx->qry.sha1, NULL);
 		cgit_log_link("log", NULL, hc(ctx, "log"), ctx->qry.head,
-			      NULL, NULL, 0, NULL, NULL, ctx->qry.showmsg);
+			      NULL, ctx->qry.vpath, 0, NULL, NULL,
+			      ctx->qry.showmsg);
 		cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head,
-			       ctx->qry.sha1, NULL);
+			       ctx->qry.sha1, ctx->qry.vpath);
 		cgit_commit_link("commit", NULL, hc(ctx, "commit"),
-				 ctx->qry.head, ctx->qry.sha1, NULL, 0);
+				 ctx->qry.head, ctx->qry.sha1, ctx->qry.vpath, 0);
 		cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head,
-			       ctx->qry.sha1, ctx->qry.sha2, NULL, 0);
+			       ctx->qry.sha1, ctx->qry.sha2, ctx->qry.vpath, 0);
 		if (ctx->repo->max_stats)
 			cgit_stats_link("stats", NULL, hc(ctx, "stats"),
-					ctx->qry.head, NULL);
+					ctx->qry.head, ctx->qry.vpath);
 		if (ctx->repo->readme)
 			reporevlink("about", "about", NULL,
 				    hc(ctx, "about"), ctx->qry.head, NULL,
-- 
cgit v1.2.3


From afc40725c1bd5a25446a704995ce3a02270537df Mon Sep 17 00:00:00 2001
From: Johan Herland <johan@herland.net>
Date: Fri, 11 Jun 2010 14:50:47 +0200
Subject: ui-log: Preserve path limit in outgoing links

This allows navigation through the 'log' page/command without losing the
active path limit.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-log.c | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/ui-log.c b/ui-log.c
index 282eca3..bfbe436 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -46,8 +46,9 @@ void show_commit_decorations(struct commit *commit)
 	while (deco) {
 		if (!prefixcmp(deco->name, "refs/heads/")) {
 			strncpy(buf, deco->name + 11, sizeof(buf) - 1);
-			cgit_log_link(buf, NULL, "branch-deco", buf, NULL, NULL,
-				0, NULL, NULL, ctx.qry.showmsg);
+			cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
+				      ctx.qry.vpath, 0, NULL, NULL,
+				      ctx.qry.showmsg);
 		}
 		else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
 			strncpy(buf, deco->name + 15, sizeof(buf) - 1);
@@ -60,13 +61,15 @@ void show_commit_decorations(struct commit *commit)
 		else if (!prefixcmp(deco->name, "refs/remotes/")) {
 			strncpy(buf, deco->name + 13, sizeof(buf) - 1);
 			cgit_log_link(buf, NULL, "remote-deco", NULL,
-				sha1_to_hex(commit->object.sha1), NULL,
-				0, NULL, NULL, ctx.qry.showmsg);
+				      sha1_to_hex(commit->object.sha1),
+				      ctx.qry.vpath, 0, NULL, NULL,
+				      ctx.qry.showmsg);
 		}
 		else {
 			strncpy(buf, deco->name, sizeof(buf) - 1);
 			cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
-				sha1_to_hex(commit->object.sha1), NULL, 0);
+					 sha1_to_hex(commit->object.sha1),
+					 ctx.qry.vpath, 0);
 		}
 		deco = deco->next;
 	}
@@ -82,14 +85,14 @@ void print_commit(struct commit *commit)
 	htmlf("<tr%s><td>",
 		ctx.qry.showmsg ? " class='logheader'" : "");
 	tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
-	tmp = cgit_pageurl(ctx.repo->url, "commit", tmp);
+	tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
 	html_link_open(tmp, NULL, NULL);
 	cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
 	html_link_close();
 	htmlf("</td><td%s>",
 		ctx.qry.showmsg ? " class='logsubject'" : "");
 	cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
-			 sha1_to_hex(commit->object.sha1), NULL, 0);
+			 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
 	show_commit_decorations(commit);
 	html("</td><td>");
 	html_txt(info->author);
@@ -176,7 +179,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
 		html(" (");
 		cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
 			      NULL, ctx.qry.head, ctx.qry.sha1,
-			      ctx.qry.path, ctx.qry.ofs, ctx.qry.grep,
+			      ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
 			      ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
 		html(")");
 	}
@@ -213,22 +216,22 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
 		     columns);
 		if (ofs > 0) {
 			cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
-				      ctx.qry.sha1, ctx.qry.path,
+				      ctx.qry.sha1, ctx.qry.vpath,
 				      ofs - cnt, ctx.qry.grep,
 				      ctx.qry.search, ctx.qry.showmsg);
 			html("&nbsp;");
 		}
 		if ((commit = get_revision(&rev)) != NULL) {
 			cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
-				      ctx.qry.sha1, ctx.qry.path,
+				      ctx.qry.sha1, ctx.qry.vpath,
 				      ofs + cnt, ctx.qry.grep,
 				      ctx.qry.search, ctx.qry.showmsg);
 		}
 		html("</div>");
 	} else if ((commit = get_revision(&rev)) != NULL) {
 		html("<tr class='nohover'><td colspan='3'>");
-		cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, NULL, 0,
-			      NULL, NULL, ctx.qry.showmsg);
+		cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
+			      ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
 		html("</td></tr>\n");
 	}
 }
-- 
cgit v1.2.3


From a2cbd3c30b64a26b52b2003ba6569f3c083f4092 Mon Sep 17 00:00:00 2001
From: Lars Hjemli <hjemli@gmail.com>
Date: Sat, 19 Jun 2010 11:35:57 +0200
Subject: ui-shared.c: path-limit style nitpick

This subjectively makes the path-limit bar less visually intrusive.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cgit.css | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/cgit.css b/cgit.css
index 563f8e1..28a2eeb 100644
--- a/cgit.css
+++ b/cgit.css
@@ -64,7 +64,7 @@ table#header td.sub {
 }
 
 table.tabs {
-	/* border-bottom: solid 2px #ccc; */
+	border-bottom: solid 3px #ccc;
 	border-collapse: collapse;
 	margin-top: 2em;
 	margin-bottom: 0px;
@@ -106,14 +106,12 @@ div.path {
 	margin: 0px;
 	padding: 5px 2em 2px 2em;
 	color: #000;
-	background-color: #ccc;
-	font-weight: bold;
+	background-color: #eee;
 }
 
 div.content {
 	margin: 0px;
 	padding: 2em;
-	border-top: solid 3px #ccc;
 	border-bottom: solid 3px #ccc;
 }
 
-- 
cgit v1.2.3