diff options
Diffstat (limited to '')
-rw-r--r--MANUAL.txt28
-rw-r--r--source/filter.c4
-rw-r--r--source/ui-repolist.c2
-rw-r--r--source/ui-shared.c87
-rw-r--r--source/ui-shared.h8
-rw-r--r--source/ui-summary.c10
-rwxr-xr-xtests/t0201-filters.sh26
7 files changed, 122 insertions, 43 deletions
diff --git a/MANUAL.txt b/MANUAL.txt
index 9f6c6f1..6ea6266 100644
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -19,12 +19,13 @@ Global settings
about-filter::
Specifies a command which will be invoked to format the content of about
pages (both top-level and for each repository). The command will get the
- content of the about-file on its stdin, the name of the file as the
- first argument, and the stdout from the command will be included
- verbatim on the about page. Default value: none. When no about-filter is
- set, the readme is escaped and served as plain text. A bundled Lua
- filter, about-render.lua, renders markdown, man pages and plain text
- when about-filter points at it. See also: "Filter API".
+ content of the about-file on its stdin and the name of the file, with
+ the tree url its links resolve against, as arguments, and the stdout
+ from the command will be included verbatim on the about page. Default
+ value: none. When no about-filter is set, the readme is escaped and
+ served as plain text. A bundled Lua filter, about-render.lua, renders
+ markdown, man pages and plain text when about-filter points at it. See
+ also: "Filter API".
age-file::
Specifies a path, relative to each repository path, which can be used to
@@ -794,11 +795,16 @@ specification with one of these strings.
Parameters are provided to filters as follows.
about filter::
- This filter is given a single parameter, the filename of the source file
- to filter. The filter can use the filename to determine (for example)
- the type of syntax to follow when formatting the readme file. The about
- text that is to be filtered is available on standard input and the
- filtered text is expected on standard output.
+ This filter is given three parameters. The first is the filename of the
+ source file to filter, which the filter can use to determine (for
+ example) the type of syntax to follow when formatting the readme file.
+ For a readme tracked in the repository, the second is the url of the
+ repository's tree page at the ref the readme was read from, ending in a
+ slash so a path in the tree can follow it, and the third is the query
+ that has to come after such a path, empty for the default branch. Both
+ are escaped for a url, and both are empty for a readme on disk and for
+ the site readme. The about text that is to be filtered is available on
+ standard input and the filtered text is expected on standard output.
auth filter::
The authentication filter receives 12 parameters, in this order.
diff --git a/source/filter.c b/source/filter.c
index 5f96cc0..ec48007 100644
--- a/source/filter.c
+++ b/source/filter.c
@@ -498,8 +498,10 @@ struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
case TRAILER:
argument_count = 2;
break;
- case SOURCE:
case ABOUT:
+ argument_count = 3;
+ break;
+ case SOURCE:
argument_count = 1;
break;
case COMMIT:
diff --git a/source/ui-repolist.c b/source/ui-repolist.c
index daf18f5..1c081c7 100644
--- a/source/ui-repolist.c
+++ b/source/ui-repolist.c
@@ -463,7 +463,7 @@ void cgit_print_site_readme(void)
cgit_print_layout_start();
if (!ctx.cfg.root_readme)
goto done;
- cgit_open_filter(ctx.cfg.about_filter, ctx.cfg.root_readme);
+ cgit_open_filter(ctx.cfg.about_filter, ctx.cfg.root_readme, "", "");
html_include(ctx.cfg.root_readme);
cgit_close_filter(ctx.cfg.about_filter);
done:
diff --git a/source/ui-shared.c b/source/ui-shared.c
index fd9cd20..94a749e 100644
--- a/source/ui-shared.c
+++ b/source/ui-shared.c
@@ -138,6 +138,47 @@ static void site_link(const char *page, const char *name, const char *title,
}
/*
+ * Write the url naming the repository, the page and the path, and return
+ * whether the url has opened its query string already.
+ */
+static int write_page_url(const char *page, const char *path)
+{
+ if (ctx.cfg.virtual_root) {
+ html_url_path(ctx.cfg.virtual_root);
+ html_url_path(ctx.repo->url);
+ if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+ html("/");
+ if (page) {
+ html_url_path(page);
+ html("/");
+ if (path)
+ html_url_path(path);
+ }
+ return 0;
+ }
+ html_url_path(ctx.cfg.script_name);
+ html("?url=");
+ html_url_arg(ctx.repo->url);
+ if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
+ html("/");
+ if (page) {
+ html_url_arg(page);
+ html("/");
+ if (path)
+ html_url_arg(path);
+ }
+ return 1;
+}
+
+/*
+ * Whether head needs naming in a url, which the default branch does not.
+ */
+static int head_is_named(const char *head)
+{
+ return head && ctx.repo->defbranch && strcmp(head, ctx.repo->defbranch);
+}
+
+/*
* Open an anchor and write the part of its href naming the repository, the
* page and the path, leaving the href quote open for the caller to add its own
* arguments and close. The return is the delimiter to put before the first of
@@ -146,7 +187,7 @@ static void site_link(const char *page, const char *name, const char *title,
static const char *repolink(const char *title, const char *class, const char *page,
const char *head, const char *path)
{
- const char *delim = "?";
+ const char *delim;
html("<a");
if (title) {
@@ -156,32 +197,8 @@ static const char *repolink(const char *title, const char *class, const char *pa
}
link_class(class);
html(" href='");
- if (ctx.cfg.virtual_root) {
- html_url_path(ctx.cfg.virtual_root);
- html_url_path(ctx.repo->url);
- if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
- html("/");
- if (page) {
- html_url_path(page);
- html("/");
- if (path)
- html_url_path(path);
- }
- } else {
- html_url_path(ctx.cfg.script_name);
- html("?url=");
- html_url_arg(ctx.repo->url);
- if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
- html("/");
- if (page) {
- html_url_arg(page);
- html("/");
- if (path)
- html_url_arg(path);
- }
- delim = "&amp;";
- }
- if (head && ctx.repo->defbranch && strcmp(head, ctx.repo->defbranch)) {
+ delim = write_page_url(page, path) ? "&amp;" : "?";
+ if (head_is_named(head)) {
html(delim);
html("h=");
html_url_arg(head);
@@ -911,6 +928,22 @@ char *cgit_pageurl(const char *reponame, const char *pagename, const char *query
return cgit_fileurl(reponame, pagename, NULL, query);
}
+void cgit_tree_url(const char *head, struct strbuf *base, struct strbuf *query)
+{
+ int query_open;
+
+ html_capture_begin(base);
+ query_open = write_page_url("tree", NULL);
+ html_capture_end();
+ if (!head_is_named(head))
+ return;
+ html_capture_begin(query);
+ html(query_open ? "&" : "?");
+ html("h=");
+ html_url_arg(head);
+ html_capture_end();
+}
+
const char *cgit_snapshot_prefix(const struct cgit_repo *repo)
{
if (repo->snapshot_prefix)
diff --git a/source/ui-shared.h b/source/ui-shared.h
index 93cc9d2..dd90196 100644
--- a/source/ui-shared.h
+++ b/source/ui-shared.h
@@ -32,6 +32,14 @@ extern char *cgit_fileurl(const char *reponame, const char *pagename, const char
extern char *cgit_pageurl(const char *reponame, const char *pagename, const char *query);
/*
+ * The url of the current repository's tree page at head, split where a path
+ * in the tree goes, for a filter to build links of its own from. Both parts
+ * are escaped for a url but not for HTML, and query stays empty for the
+ * default branch.
+ */
+extern void cgit_tree_url(const char *head, struct strbuf *base, struct strbuf *query);
+
+/*
* Call fn once for every URL this repository can be cloned from.
*/
extern void cgit_add_clone_urls(void (*fn)(const char *));
diff --git a/source/ui-summary.c b/source/ui-summary.c
index e7b229a..44abc6b 100644
--- a/source/ui-summary.c
+++ b/source/ui-summary.c
@@ -91,14 +91,22 @@ void cgit_print_repo_readme(void)
}
html("</pre>");
} else {
+ struct strbuf tree_base = STRBUF_INIT, tree_query = STRBUF_INIT;
+
+ // A tracked readme's links lead into the tree at the ref it was
+ // read from, while one on disk has no tree to lead into.
+ if (ref)
+ cgit_tree_url(ref, &tree_base, &tree_query);
// The filter is what makes the source safe here, so it is fed
// through unescaped.
- cgit_open_filter(ctx.repo->about_filter, filename);
+ cgit_open_filter(ctx.repo->about_filter, filename, tree_base.buf, tree_query.buf);
if (ref)
cgit_print_file(filename, ref, 1, 0);
else
html_include(filename);
cgit_close_filter(ctx.repo->about_filter);
+ strbuf_release(&tree_base);
+ strbuf_release(&tree_query);
}
html("</div>");
cgit_print_layout_end();
diff --git a/tests/t0201-filters.sh b/tests/t0201-filters.sh
index 11fa5f8..c6b23af 100755
--- a/tests/t0201-filters.sh
+++ b/tests/t0201-filters.sh
@@ -30,7 +30,7 @@ do
"
test_expect_success "check whether the $prefix about filter works" '
- grep "<div id='"'"'about'"'"'>a+b HELLO$" tmp
+ grep "<div id='"'"'about'"'"'>a+b /filter-$prefix/tree/ HELLO$" tmp
'
test_expect_success "generate filter-$prefix/commit/" "
@@ -61,10 +61,32 @@ do
test_expect_success "the $prefix about filter output stays inside its div" "
cgit_url 'filter-$prefix/about/' >tmp &&
- grep \"<div id='about'>a+b HELLO\" tmp
+ grep \"<div id='about'>a+b /filter-$prefix/tree/ HELLO\" tmp
"
done
+# A readme read at another branch links into the tree at that branch, which
+# the filter is told as the query to follow a path with.
+test_expect_success 'the about filter gets the tree url at the readme branch' '
+ {
+ echo "virtual-root=/" &&
+ echo "cache-size=0" &&
+ echo "readme=:a+b" &&
+ echo "about-filter=exec:$FILTER_DIRECTORY/dump.sh" &&
+ echo "root-readme=$PWD/root.txt" &&
+ echo "repo.url=filtered" &&
+ echo "repo.path=$PWD/repos/filter/.git"
+ } >aboutargsrc &&
+ CGIT_CONFIG="$PWD/aboutargsrc" QUERY_STRING="url=filtered/about/&h=1%2b2" cgit >tmp &&
+ grep "<div id=.about.>a+b /filtered/tree/ ?h=1%2B2 HELLO" tmp
+'
+
+test_expect_success 'the site readme leaves the tree url empty' '
+ echo site >root.txt &&
+ CGIT_CONFIG="$PWD/aboutargsrc" QUERY_STRING="p=about" cgit >tmp &&
+ grep "root.txt SITE" tmp
+'
+
test "$CGIT_HAS_LUA" -eq 1 && test_set_prereq CGIT_LUA
test "$CGIT_HAS_LUA" -eq 1 || say 'cgit built without lua, error page check skipped'