[PATCH 1/8] Can add diffs to Atom feed entries

zwinkau at kit.edu zwinkau at kit.edu
Tue Jul 1 09:40:26 CEST 2014


From: Andreas Zwinkau <zwinkau at kit.edu>

Off by default. Set enable-atom-diff flag for repos to enable.

Uses HTML5's "scoped CSS" feature to colorize diff deletes and inserts.
Mainstream pre-HTML5 engines either ignore this or apply the style
document-wide, which should not break anything.

As cgit was not prepared to produce multiple diffs per run,
so this also reset some counters during the diff. Additionally,
the cgit_self_link had to be extended, as it is called during
the diffing.
---
 cgit.c              |  7 +++++++
 cgit.h              |  2 ++
 cgitrc.5.txt        |  4 ++++
 cmd.c               |  2 +-
 shared.c            |  1 +
 tests/t0112-atom.sh | 24 ++++++++++++++++++++++++
 ui-atom.c           | 22 +++++++++++++++++++---
 ui-atom.h           |  2 +-
 ui-diff.c           |  4 ++++
 ui-shared.c         |  4 ++++
 10 files changed, 67 insertions(+), 5 deletions(-)
 create mode 100755 tests/t0112-atom.sh

diff --git a/cgit.c b/cgit.c
index f488ebf..0b5d9e1 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->defbranch = xstrdup(value);
 	else if (!strcmp(name, "snapshots"))
 		repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value);
+	else if (!strcmp(name, "enable-atom-diff"))
+		repo->enable_atom_diff = atoi(value);
 	else if (!strcmp(name, "enable-commit-graph"))
 		repo->enable_commit_graph = atoi(value);
 	else if (!strcmp(name, "enable-log-filecount"))
@@ -144,6 +146,8 @@ static void config_cb(const char *name, const char *value)
 		ctx.cfg.noheader = atoi(value);
 	else if (!strcmp(name, "snapshots"))
 		ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
+	else if (!strcmp(name, "enable-atom-diff"))
+		ctx.cfg.enable_atom_diff = atoi(value);
 	else if (!strcmp(name, "enable-filter-overrides"))
 		ctx.cfg.enable_filter_overrides = atoi(value);
 	else if (!strcmp(name, "enable-http-clone"))
@@ -346,6 +350,7 @@ static void prepare_context(void)
 	ctx.cfg.logo = "/cgit.png";
 	ctx.cfg.favicon = "/favicon.ico";
 	ctx.cfg.local_time = 0;
+	ctx.cfg.enable_atom_diff = 0;
 	ctx.cfg.enable_http_clone = 1;
 	ctx.cfg.enable_index_owner = 1;
 	ctx.cfg.enable_tree_linenumbers = 1;
@@ -788,6 +793,8 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 		fprintf(f, "repo.section=%s\n", repo->section);
 	if (repo->clone_url)
 		fprintf(f, "repo.clone-url=%s\n", repo->clone_url);
+	fprintf(f, "repo.enable-atom-diff=%d\n",
+		repo->enable_atom_diff);
 	fprintf(f, "repo.enable-commit-graph=%d\n",
 	        repo->enable_commit_graph);
 	fprintf(f, "repo.enable-log-filecount=%d\n",
diff --git a/cgit.h b/cgit.h
index 0badc64..3db220e 100644
--- a/cgit.h
+++ b/cgit.h
@@ -87,6 +87,7 @@ struct cgit_repo {
 	char *logo;
 	char *logo_link;
 	int snapshots;
+	int enable_atom_diff;
 	int enable_commit_graph;
 	int enable_log_filecount;
 	int enable_log_linecount;
@@ -213,6 +214,7 @@ struct cgit_config {
 	int cache_snapshot_ttl;
 	int case_sensitive_sort;
 	int embedded;
+	int enable_atom_diff;
 	int enable_filter_overrides;
 	int enable_http_clone;
 	int enable_index_links;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index b7570db..b729294 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -141,6 +141,10 @@ embedded::
 	suitable for embedding in other html pages. Default value: none. See
 	also: "noheader".
 
+enable-atom-diff::
+	Flag which, when set to "1", will make cgit include a html-escaped diff
+	within the atom feed commit entries. Default value: "0".
+
 enable-commit-graph::
 	Flag which, when set to "1", will make cgit print an ASCII-art commit
 	history graph to the left of the commit messages in the repository
diff --git a/cmd.c b/cmd.c
index 188cd56..3d9f245 100644
--- a/cmd.c
+++ b/cmd.c
@@ -33,7 +33,7 @@ static void HEAD_fn(void)
 
 static void atom_fn(void)
 {
-	cgit_print_atom(ctx.qry.head, ctx.qry.path, ctx.cfg.max_atom_items);
+	cgit_print_atom(ctx.qry.head, ctx.qry.path, ctx.cfg.max_atom_items, ctx.repo->enable_atom_diff);
 }
 
 static void about_fn(void)
diff --git a/shared.c b/shared.c
index 8ed14c0..6bd82f9 100644
--- a/shared.c
+++ b/shared.c
@@ -57,6 +57,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
 	ret->owner = NULL;
 	ret->section = ctx.cfg.section;
 	ret->snapshots = ctx.cfg.snapshots;
+	ret->enable_atom_diff = ctx.cfg.enable_atom_diff;
 	ret->enable_commit_graph = ctx.cfg.enable_commit_graph;
 	ret->enable_log_filecount = ctx.cfg.enable_log_filecount;
 	ret->enable_log_linecount = ctx.cfg.enable_log_linecount;
diff --git a/tests/t0112-atom.sh b/tests/t0112-atom.sh
new file mode 100755
index 0000000..8b5bbce
--- /dev/null
+++ b/tests/t0112-atom.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+test_description='Check content on atom feed'
+. ./setup.sh
+
+test_expect_success 'fetch feed' 'cgit_url "foo/atom/" >tmp'
+
+test_expect_success 'find feed open tag' 'grep -e "^<feed xmlns=.http://www\.w3\.org/2005/Atom.>" tmp'
+
+test_expect_success 'find title' 'grep -e "^<title>foo" tmp'
+
+test_expect_success 'find entry title' 'grep -e "^<title>commit 5</title>" tmp'
+
+test_expect_success 'find entry diffstat' 'grep -e "^<div class=.diffstat-header.>" tmp'
+
+test_expect_success 'find entry diff' 'grep -e "<table summary=.diff. class=.diff.>" tmp'
+
+test_expect_success 'find diff content 1' 'grep -e "diff --git a/file-1 b/file-1" tmp'
+
+test_expect_success 'find diff content 2' 'grep -e "@@ -0,0 +1 @@" tmp'
+
+test_expect_success 'find diff content 3' 'grep -e "+1<" tmp'
+
+test_done
diff --git a/ui-atom.c b/ui-atom.c
index b22d745..6a6a98b 100644
--- a/ui-atom.c
+++ b/ui-atom.c
@@ -10,16 +10,23 @@
 #include "ui-atom.h"
 #include "html.h"
 #include "ui-shared.h"
+#include "ui-diff.h"
 
-static void add_entry(struct commit *commit, const char *host)
+static void add_entry(struct commit *commit, const char *host, int enable_atom_diff)
 {
 	char delim = '&';
 	char *hex;
+	char *hex_parent;
 	char *mail, *t, *t2;
 	struct commitinfo *info;
 
 	info = cgit_parse_commit(commit);
 	hex = sha1_to_hex(commit->object.sha1);
+	if (commit->parents) {
+		hex_parent = sha1_to_hex(commit->parents->item->object.sha1);
+	} else {
+		hex_parent = NULL; /* means before initial commit */
+	}
 	html("<entry>\n");
 	html("<title>");
 	html_txt(info->subject);
@@ -71,6 +78,15 @@ static void add_entry(struct commit *commit, const char *host)
 	html("<pre>\n");
 	html_txt(info->msg);
 	html("</pre>\n");
+	if (enable_atom_diff) {
+		html("<pre class='diff'>\n");
+		html("<style scoped=\"scoped\">\n"); /* HTML5 with graceful degradation */
+		html("table.diff .add, span.add { background-color: #afa; }");
+		html("table.diff .del, span.remove { background-color: #faa; }");
+		html("</style>\n");
+		cgit_print_diff(hex, hex_parent, NULL, 0, 0);
+		html("</pre>");
+	}
 	html("</div>\n");
 	html("</content>\n");
 	html("</entry>\n");
@@ -78,7 +94,7 @@ static void add_entry(struct commit *commit, const char *host)
 }
 
 
-void cgit_print_atom(char *tip, char *path, int max_count)
+void cgit_print_atom(char *tip, char *path, int max_count, int enable_atom_diff)
 {
 	const char *host;
 	const char *argv[] = {NULL, tip, NULL, NULL, NULL};
@@ -132,7 +148,7 @@ void cgit_print_atom(char *tip, char *path, int max_count)
 		html("'/>\n");
 	}
 	while ((commit = get_revision(&rev)) != NULL) {
-		add_entry(commit, host);
+		add_entry(commit, host, enable_atom_diff);
 		free(commit->buffer);
 		commit->buffer = NULL;
 		free_commit_list(commit->parents);
diff --git a/ui-atom.h b/ui-atom.h
index 749ffd3..e0043f1 100644
--- a/ui-atom.h
+++ b/ui-atom.h
@@ -1,6 +1,6 @@
 #ifndef UI_ATOM_H
 #define UI_ATOM_H
 
-extern void cgit_print_atom(char *tip, char *path, int max_count);
+extern void cgit_print_atom(char *tip, char *path, int max_count, int enable_atom_diff);
 
 #endif
diff --git a/ui-diff.c b/ui-diff.c
index 71273aa..eeeeb80 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -363,6 +363,10 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
 	struct commit *commit, *commit2;
 	const unsigned char *old_tree_sha1, *new_tree_sha1;
 
+	/* reset global data */
+	files = 0;
+	slots = total_adds = total_rems = 0;
+
 	if (!new_rev)
 		new_rev = ctx.qry.head;
 	if (get_sha1(new_rev, new_rev_sha1)) {
diff --git a/ui-shared.c b/ui-shared.c
index 1ede2b0..6bdb52e 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -483,6 +483,10 @@ static void cgit_self_link(char *name, const char *title, const char *class)
 	else if (!strcmp(ctx.qry.page, "stats"))
 		cgit_stats_link(name, title, class, ctx.qry.head,
 				ctx.qry.path);
+	else if (!strcmp(ctx.qry.page, "atom"))
+		return cgit_diff_link(name, title, class, ctx.qry.head,
+				      ctx.qry.sha1, ctx.qry.sha2,
+				      ctx.qry.path, 0);
 	else {
 		/* Don't known how to make link for this page */
 		repolink(title, class, ctx.qry.page, ctx.qry.head, ctx.qry.path);
-- 
1.9.1



More information about the CGit mailing list