* [PATCH] gitweb: Make RSS feed output prettier
@ 2006-11-15 0:10 asf
2006-11-15 0:24 ` Jakub Narebski
0 siblings, 1 reply; 8+ messages in thread
From: asf @ 2006-11-15 0:10 UTC (permalink / raw)
To: git; +Cc: Andreas Fuchs
From: Andreas Fuchs <asf@boinkor.net>
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
---
gitweb/gitweb.perl | 22 ++++++++++++++++------
1 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index e54a29e..2a79895 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -4134,20 +4134,30 @@ XML
"<content:encoded>" .
"<![CDATA[\n";
my $comment = $co{'comment'};
+ print "<pre>\n";
foreach my $line (@$comment) {
- $line = to_utf8($line);
- print "$line<br/>\n";
+ $line = to_utf8(esc_html($line));
+ print "$line\n";
}
- print "<br/>\n";
+ print "</pre><ul>\n";
foreach my $line (@difftree) {
if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
next;
}
- my $file = esc_path(unquote($7));
+ my $file_name = unquote($7);
+ my $file = esc_html($file_name);
+ my $parent = $co{'parent'};
+ my $hash = git_get_hash_by_path($commit, $file_name);
+ my $hashparent = git_get_hash_by_path($parent, $file_name);
+
$file = to_utf8($file);
- print "$file<br/>\n";
+ print "<li>$file ";
+ print "[<a href=\"". esc_html("$my_url?p=$project;a=blobdiff;f=$file;h=$hash;hp=$hashparent;hb=$commit;hpb=$parent") ."\">diff</a>] ";
+ print "[<a href=\"". esc_html("$my_url?p=$project;a=blame;f=$file;hb=$commit") ."\">blame</a>] " if gitweb_check_feature('blame');
+ print "[<a href=\"". esc_html("$my_url?p=$project;a=history;f=$file;h=$commit") ."\">history</a>] ";
+ print "</li>\n";
}
- print "]]>\n" .
+ print "</ul>]]>\n" .
"</content:encoded>\n" .
"</item>\n";
}
--
1.4.3.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] gitweb: Make RSS feed output prettier
2006-11-15 0:10 [PATCH] gitweb: Make RSS feed output prettier asf
@ 2006-11-15 0:24 ` Jakub Narebski
2006-11-16 21:45 ` [PATCH] gitweb: Atom feeds (was: gitweb: Make RSS feed output prettier) Andreas Fuchs
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Narebski @ 2006-11-15 0:24 UTC (permalink / raw)
To: git
Andreas Fuchs <asf@boinkor.net> wrote:
> * Wrap the commit message in <pre>
We use <div class="pre"> in "commit" view if I remember correctly.
> * Make file names into an unordered list
Good idea.
> * Add links (diff, conditional blame, history) to the file list.
I'd rather keep RSS output as simple as possible, no frills.
> ---
> gitweb/gitweb.perl | 22 ++++++++++++++++------
> 1 files changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index e54a29e..2a79895 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -4134,20 +4134,30 @@ XML
> "<content:encoded>" .
> "<![CDATA[\n";
> my $comment = $co{'comment'};
> + print "<pre>\n";
> foreach my $line (@$comment) {
> - $line = to_utf8($line);
> - print "$line<br/>\n";
> + $line = to_utf8(esc_html($line));
esc_html does to_utf8, so to_utf8 is unnecessary (and spurious).
But it is a good catch: esc_html is certainly needed.
> + print "$line\n";
> }
> - print "<br/>\n";
> + print "</pre><ul>\n";
> foreach my $line (@difftree) {
> if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
> next;
> }
> - my $file = esc_path(unquote($7));
> + my $file_name = unquote($7);
> + my $file = esc_html($file_name);
We have introduced esc_path for escaping pathnames. Use it!
> + my $parent = $co{'parent'};
> + my $hash = git_get_hash_by_path($commit, $file_name);
> + my $hashparent = git_get_hash_by_path($parent, $file_name);
Two unnecessary calls to git command. Use
my %difftree = parse_difftree_raw_line($line)
instead. The conditions would probably be
next if (!$difftree{'from_id'});
(or equivalent).
> +
> $file = to_utf8($file);
> - print "$file<br/>\n";
> + print "<li>$file ";
> + print "[<a href=\"". esc_html("$my_url?p=$project;a=blobdiff;f=$file;h=$hash;hp=$hashparent;hb=$commit;hpb=$parent") ."\">diff</a>] ";
> + print "[<a href=\"". esc_html("$my_url?p=$project;a=blame;f=$file;hb=$commit") ."\">blame</a>] " if gitweb_check_feature('blame');
> + print "[<a href=\"". esc_html("$my_url?p=$project;a=history;f=$file;h=$commit") ."\">history</a>] ";
> + print "</li>\n";
esc_url, not esc_html here. Or use the href() subroutine with -full=>1
option (after applying the patch I send which added this to href()).
P.S. Please reply also to git mailing list.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] gitweb: Atom feeds (was: gitweb: Make RSS feed output prettier)
2006-11-15 0:24 ` Jakub Narebski
@ 2006-11-16 21:45 ` Andreas Fuchs
2006-11-17 9:01 ` [PATCH] gitweb: Atom feeds Junio C Hamano
0 siblings, 1 reply; 8+ messages in thread
From: Andreas Fuchs @ 2006-11-16 21:45 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2301 bytes --]
Jakub Narebski wrote:
> Andreas Fuchs <asf@boinkor.net> wrote:
>
>> * Wrap the commit message in <pre>
> We use <div class="pre"> in "commit" view if I remember correctly.
That's ok for rendered HTML output, but in my experience, the way feed
readers interpret that ranges from "badly" to "not at all"; it's better
to stick to explicit structure hints only in feeds. /-:
So, this is the only thing I haven't fixed in the attached patch (:
>> * Make file names into an unordered list
> Good idea.
>
>> * Add links (diff, conditional blame, history) to the file list.
> I'd rather keep RSS output as simple as possible, no frills.
I can see that, but it would be very useful on aggregation sites like
http://planet.sbcl.org/. You mentioned on IRC that you'd prefer to
forward-port the current RSS generation to a more modern feed format
like Atom 1.0.
I took the liberty to back out that change from the RSS generator, and
implement Atom 1.0 output that is more fully featured. For testing, I
left both in. Both feeds validate at feedvalidator.org for me, the
choice is yours (:
> esc_html does to_utf8, so to_utf8 is unnecessary (and spurious).
> But it is a good catch: esc_html is certainly needed.
The attached patch doesn't use to_utf8 on already-escaped strings anymore.
> We have introduced esc_path for escaping pathnames. Use it!
I changed that, too.
> Two unnecessary calls to git command. Use
> my %difftree = parse_difftree_raw_line($line)
> instead. The conditions would probably be
> next if (!$difftree{'from_id'});
> (or equivalent).
Thanks for the hint; I included that in the Atom output and re-worked
the RSS generator to not use the hideous regexp anymore.
> esc_url, not esc_html here. Or use the href() subroutine with -full=>1
> option (after applying the patch I send which added this to href()).
Okay; I changed all occurrences of esc_html where URLs are escaped to
use esc_url.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
Hope you like it,
--
Andreas Fuchs, (http://|im:asf@|mailto:asf@)boinkor.net, antifuchs
[-- Attachment #2: atom-and-last-modified.diff --]
[-- Type: text/plain, Size: 9067 bytes --]
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index e54a29e..b39dc65 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -425,6 +425,7 @@ my %actions = (
"history" => \&git_history,
"log" => \&git_log,
"rss" => \&git_rss,
+ "atom" => \&git_atom,
"search" => \&git_search,
"search_help" => \&git_search_help,
"shortlog" => \&git_shortlog,
@@ -1180,7 +1181,9 @@ sub parse_date {
$days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;
$date{'mday-time'} = sprintf "%d %s %02d:%02d",
$mday, $months[$mon], $hour ,$min;
-
+ $date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ",
+ 1900+$year, $mon, $mday, $hour ,$min, $sec;
+
$tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/;
my $local = $epoch + ((int $1 + ($2/60)) * 3600);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($local);
@@ -1653,6 +1656,9 @@ #provides backwards capability for those
printf('<link rel="alternate" title="%s log" '.
'href="%s" type="application/rss+xml"/>'."\n",
esc_param($project), href(action=>"rss"));
+ printf('<link rel="alternate" title="%s log" '.
+ 'href="%s" type="application/atom+xml"/>'."\n",
+ esc_param($project), href(action=>"atom"));
} else {
printf('<link rel="alternate" title="%s projects list" '.
'href="%s" type="text/plain; charset=utf-8"/>'."\n",
@@ -1724,6 +1730,8 @@ sub git_footer_html {
}
print $cgi->a({-href => href(action=>"rss"),
-class => "rss_logo"}, "RSS") . "\n";
+ print $cgi->a({-href => href(action=>"atom"),
+ -class => "rss_logo"}, "Atom") . "\n";
} else {
print $cgi->a({-href => href(project=>undef, action=>"opml"),
-class => "rss_logo"}, "OPML") . " ";
@@ -4097,14 +4105,29 @@ sub git_rss {
or die_error(undef, "Open git-rev-list failed");
my @revlist = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading git-rev-list failed");
- print $cgi->header(-type => 'text/xml', -charset => 'utf-8');
+
+ my %latest_commit;
+ my %latest_date;
+ if (defined($revlist[0])) {
+ %latest_commit = parse_commit($revlist[0]);
+ %latest_date = parse_date($latest_commit{'committer_epoch'});
+ print $cgi->header(-type => 'application/atom+xml', -charset => 'utf-8',
+ -last_modified => $latest_date{'rfc2822'});
+ } else {
+ print $cgi->header(-type => 'application/atom+xml', -charset => 'utf-8');
+ }
+
+ # Optimization: skip generating the body if client asks only
+ # for Last-Modified date.
+ return if ($cgi->request_method() eq 'HEAD');
+
print <<XML;
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
-<title>$project $my_uri $my_url</title>
-<link>${\esc_html("$my_url?p=$project;a=summary")}</link>
-<description>$project log</description>
+<title>${\esc_html("$project $my_uri $my_url")}</title>
+<link>${\esc_url("$my_url?p=$project;a=summary")}</link>
+<description>${\esc_html($project)} log</description>
<language>en</language>
XML
@@ -4128,32 +4151,138 @@ XML
"</title>\n" .
"<author>" . esc_html($co{'author'}) . "</author>\n" .
"<pubDate>$cd{'rfc2822'}</pubDate>\n" .
- "<guid isPermaLink=\"true\">" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "</guid>\n" .
- "<link>" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "</link>\n" .
+ "<guid isPermaLink=\"true\">" . esc_url("$my_url?p=$project;a=commit;h=$commit") . "</guid>\n" .
+ "<link>" . esc_url("$my_url?p=$project;a=commit;h=$commit") . "</link>\n" .
"<description>" . esc_html($co{'title'}) . "</description>\n" .
"<content:encoded>" .
"<![CDATA[\n";
my $comment = $co{'comment'};
+ print "<pre>\n";
foreach my $line (@$comment) {
- $line = to_utf8($line);
- print "$line<br/>\n";
+ $line = esc_html($line);
+ print "$line\n";
}
- print "<br/>\n";
+ print "</pre><ul>\n";
foreach my $line (@difftree) {
- if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
- next;
- }
- my $file = esc_path(unquote($7));
- $file = to_utf8($file);
- print "$file<br/>\n";
+ my %difftree = parse_difftree_raw_line($line);
+ next if !$difftree{'from_id'};
+
+ my $file_name = $difftree{'file'};
+ my $file = esc_path($file_name);
+
+ print "<li>$file</li>\n";
}
- print "]]>\n" .
+ print "</ul>]]>\n" .
"</content:encoded>\n" .
"</item>\n";
}
print "</channel></rss>";
}
+sub git_atom {
+ open my $fd, "-|", git_cmd(), "rev-list", "--max-count=150",
+ git_get_head_hash($project), "--"
+ or die_error(undef, "Open git-rev-list failed");
+ my @revlist = map { chomp; $_ } <$fd>;
+ close $fd or die_error(undef, "Reading git-rev-list failed");
+
+ my %latest_commit;
+ my %latest_date;
+ if (defined($revlist[0])) {
+ %latest_commit = parse_commit($revlist[0]);
+ %latest_date = parse_date($latest_commit{'committer_epoch'});
+ print $cgi->header(-type => 'application/atom+xml', -charset => 'utf-8',
+ -last_modified => $latest_date{'rfc2822'});
+ } else {
+ print $cgi->header(-type => 'application/atom+xml', -charset => 'utf-8');
+ }
+
+ # Optimization: skip generating the body if client asks only
+ # for Last-Modified date.
+ return if ($cgi->request_method() eq 'HEAD');
+
+ print <<XML;
+<?xml version="1.0" encoding="utf-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title type="html">${\esc_html("$project $my_uri $my_url")}</title>
+<link rel="alternate" type="text/html" href="${\esc_url("$my_url?p=$project;a=summary")}" />
+<link rel="self" type="application/atom+xml" href="${\esc_url("$my_url?p=$project;a=atom")}" />
+<subtitle>$project log</subtitle>
+<id>${\esc_url("$my_url?p=$project")}</id>
+XML
+ if (!defined(%latest_date)) {
+ # dummy date to keep the feed valid until commits trickle in:
+ print "<updated>1970-01-01T00:00:00Z</updated>";
+ } else {
+ print "<updated>".$latest_date{'iso-8601'}."</updated>\n";
+ }
+
+ for (my $i = 0; $i <= $#revlist; $i++) {
+ my $commit = $revlist[$i];
+ my %co = parse_commit($commit);
+ # we read 150, we always show 30 and the ones more recent than 48 hours
+ if (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {
+ last;
+ }
+ my %cd = parse_date($co{'committer_epoch'});
+
+ open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
+ $co{'parent'}, $co{'id'}, "--"
+ or next;
+ my @difftree = map { chomp; $_ } <$fd>;
+ close $fd
+ or next;
+ print "<entry>\n" .
+ "<title type=\"html\">" .
+ esc_html($co{'author_name'}) . ": " . esc_html($co{'title'}) .
+ "</title>\n" .
+ "<updated>$cd{'iso-8601'}</updated>\n" .
+ "<author><name>" . esc_html($co{'author_name'}) . "</name></author>\n" .
+ "<published>$cd{'iso-8601'}</published>\n" .
+ "<link rel=\"alternate\" type=\"text/html\" href=\"" .
+ esc_url("$my_url?p=$project;a=commit;h=$commit") . "\" />\n" .
+ "<id>" . esc_url("$my_url?p=$project;a=commit;h=$co{'id'}") . "</id>\n" .
+ "<content type=\"html\" xml:base=\"".esc_url($my_url)."\">" .
+ "<![CDATA[\n";
+ my $comment = $co{'comment'};
+ print "<pre>\n";
+ foreach my $line (@$comment) {
+ $line = to_utf8(esc_html($line));
+ print "$line\n";
+ }
+ print "</pre><ul>\n";
+ foreach my $line (@difftree) {
+ my %difftree = parse_difftree_raw_line($line);
+ next if !$difftree{'from_id'};
+
+ my $file_name = $difftree{'file'};
+ my $file = esc_path($file_name);
+ my $parent = $co{'parent'};
+ my $hash = $difftree{'to_id'};
+ my $hashparent = $difftree{'from_id'};
+
+ print "<li>[";
+ print "<a title=\"diff\" href=\"".
+ esc_url("$my_url?p=$project;a=blobdiff;f=$file;h=$hash;hp=$hashparent;hb=$commit;hpb=$parent") .
+ "\">D</a>";
+ if (gitweb_check_feature('blame')) {
+ print "<a title=\"blame\" href=\"".
+ esc_url("$my_url?p=$project;a=blame;f=$file;hb=$commit") .
+ "\">B</a>";
+ }
+ print "<a title=\"history\" href=\"".
+ esc_url("?p=$project;a=history;f=$file;h=$commit") .
+ "\">H</a>";
+ print "] $file";
+ print "</li>\n";
+ }
+ print "</ul>]]>\n" .
+ "</content>\n" .
+ "</entry>\n";
+ }
+ print "</feed>";
+}
+
sub git_opml {
my @list = git_get_projects_list();
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] gitweb: Atom feeds
2006-11-16 21:45 ` [PATCH] gitweb: Atom feeds (was: gitweb: Make RSS feed output prettier) Andreas Fuchs
@ 2006-11-17 9:01 ` Junio C Hamano
2006-11-17 11:36 ` Jakub Narebski
0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2006-11-17 9:01 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git, Andreas Fuchs, Petr Baudis
Andreas Fuchs <asf@boinkor.net> writes:
> Jakub Narebski wrote:
>> Andreas Fuchs <asf@boinkor.net> wrote:
>>
>>> * Wrap the commit message in <pre>
>> We use <div class="pre"> in "commit" view if I remember correctly.
>
> That's ok for rendered HTML output, but in my experience, the way feed
> readers interpret that ranges from "badly" to "not at all"; it's better
> to stick to explicit structure hints only in feeds. /-:
>
> So, this is the only thing I haven't fixed in the attached patch (:
> ...
> In addition to the above points, the attached patch emits a
> Last-Changed: HTTP response header field, and doesn't compute the feed
> body if the HTTP request type was HEAD. This helps keep the web server
> load down for well-behaved feed readers that check if the feed needs
> updating.
>
> Hope you like it,
Seems sane to me. Jakub, how do you like this one? If it looks
Ok to you, please arrange to include your one-liner that this
depends on and forward a readily applicable patch with
appropriate commit log message.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] gitweb: Atom feeds
2006-11-17 9:01 ` [PATCH] gitweb: Atom feeds Junio C Hamano
@ 2006-11-17 11:36 ` Jakub Narebski
2006-11-19 14:05 ` [PATCH 1/2] gitweb: Add an option to href() to return full URL Jakub Narebski
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Narebski @ 2006-11-17 11:36 UTC (permalink / raw)
To: Junio C Hamano, Andreas Fuchs; +Cc: git, Petr Baudis
Junio C Hamano wrote:
> Andreas Fuchs <asf@boinkor.net> writes:
>
>> Jakub Narebski wrote:
>>> Andreas Fuchs <asf@boinkor.net> wrote:
>>>
>>>> * Wrap the commit message in <pre>
>>> We use <div class="pre"> in "commit" view if I remember correctly.
>>
>> That's ok for rendered HTML output, but in my experience, the way feed
>> readers interpret that ranges from "badly" to "not at all"; it's better
>> to stick to explicit structure hints only in feeds. /-:
True. "<pre>" in RSS feed is better (I don't know if you can give CSS
for RSS, be it RSS 2.01 or Atom; rather not).
>> So, this is the only thing I haven't fixed in the attached patch (:
Good.
>> In addition to the above points, the attached patch emits a
>> Last-Changed: HTTP response header field, and doesn't compute the feed
>> body if the HTTP request type was HEAD. This helps keep the web server
>> load down for well-behaved feed readers that check if the feed needs
>> updating.
Very nice.
>> Hope you like it,
>
> Seems sane to me. Jakub, how do you like this one?
I like it. Ack.
> If it looks Ok to you, please arrange to include your one-liner
> that this depends on and forward a readily applicable patch with
> appropriate commit log message.
Which one liner? As far as I can see the patch does NOT use
href(-full=>1,...) but esc_url(...).
Perhaps this is for next patch.
BTW I have encountered something calles Atom Publishing Protocol (APP):
perhaps we should also add this in addition to currently used OPML.
--
Jakub Narebski
Torun, Poland
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] gitweb: Add an option to href() to return full URL
2006-11-17 11:36 ` Jakub Narebski
@ 2006-11-19 14:05 ` Jakub Narebski
2006-11-19 14:05 ` [PATCH 2/2] gitweb: Refactor feed generation, make output prettier, add Atom feed Jakub Narebski
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Narebski @ 2006-11-19 14:05 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
href subroutine by default generates absolute URL (generated using
CGI::url(-absolute=>1), and saved in $my_uri) using $my_uri as base;
add an option to generate full URL using $my_url as base.
New feature usage: href(..., -full=>1)
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/gitweb.perl | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 5875ba0..8739501 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -459,7 +459,8 @@ exit;
sub href(%) {
my %params = @_;
- my $href = $my_uri;
+ # default is to use -absolute url() i.e. $my_uri
+ my $href = $params{-full} ? $my_url : $my_uri;
# XXX: Warning: If you touch this, check the search form for updating,
# too.
--
1.4.3.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] gitweb: Refactor feed generation, make output prettier, add Atom feed
2006-11-19 14:05 ` [PATCH 1/2] gitweb: Add an option to href() to return full URL Jakub Narebski
@ 2006-11-19 14:05 ` Jakub Narebski
2006-11-20 14:45 ` Jakub Narebski
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Narebski @ 2006-11-19 14:05 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Andreas Fuchs
Add support for more modern Atom web feed format. Both RSS and Atom
feeds are generated by git_feed subroutine to avoid code duplication;
git_rss and git_atom are thin wrappers around git_feed. Add links to
Atom feed in HTML header and in page footer (but not in OPML; we
should use APP, Atom Publishing Proptocol instead).
Allow for feed generation for branches other than current (HEAD)
branch, and for generation of feeds for file or directory history.
Do not use "pre ${\sub_returning_scalar(...)} post" trick, but join
strings instead: "pre " . sub_returning_scalar(...) . " post".
Use href(-full=>1, ...) instead of hand-crafting gitweb urls.
Make output prettier:
* Use title similar to the title of web page
* Use project description (if exists) for description/subtitle
* Do not add anything (committer name, commit date) to feed entry title
* Wrap the commit message in <pre>
* Make file names into an unordered list
* Add links (diff, conditional blame, history) to the file list.
In addition to the above points, the attached patch emits a
Last-Changed: HTTP response header field, and doesn't compute the feed
body if the HTTP request type was HEAD. This helps keep the web server
load down for well-behaved feed readers that check if the feed needs
updating.
If browser (feed reader) sent Accept: header, and it prefers 'text/xml' type
to 'application/rss+xml' (in the case of RSS feed) or 'application/atom+xml'
(in the case of Atom feed), then use 'text/xml' as content type.
Both RSS and Atom feeds validate at http://feedvalidator.org
and at http://validator.w3.org/feed/
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Andreas Fuchs <asf@boinkor.net>
---
Compared to implementation by Andreas Fuchs (antifuchs on #git) in
Message-ID: <ejim5q$31b$1@sea.gmane.org>
http://permalink.gmane.org/gmane.comp.version-control.git/31624
this consolidates generation of RSS and Atom feeds, cleans up feed
generation code, and uses 'text/xml' as content type if browser prefers
this (for Mozilla).
This requires:
"gitweb: Add an option to href() to return full URL"
(sent just in case before this one), which is last patch in my previous
gitweb patches series.
This patch DOES NOT add feed links for branches (in "heads" view), nor
feed links for files (as alternate representation of "history" view).
Neither it adds Atom links to "OPML" view (we should use APP for that,
I think).
gitweb/gitweb.perl | 255 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 210 insertions(+), 45 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 8739501..a32a6b7 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -425,6 +425,7 @@ my %actions = (
"history" => \&git_history,
"log" => \&git_log,
"rss" => \&git_rss,
+ "atom" => \&git_atom,
"search" => \&git_search,
"search_help" => \&git_search_help,
"shortlog" => \&git_shortlog,
@@ -1198,10 +1199,12 @@ sub parse_date {
$date{'mday'} = $mday;
$date{'day'} = $days[$wday];
$date{'month'} = $months[$mon];
- $date{'rfc2822'} = sprintf "%s, %d %s %4d %02d:%02d:%02d +0000",
- $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;
+ $date{'rfc2822'} = sprintf "%s, %d %s %4d %02d:%02d:%02d +0000",
+ $days[$wday], $mday, $months[$mon], 1900+$year, $hour ,$min, $sec;
$date{'mday-time'} = sprintf "%d %s %02d:%02d",
$mday, $months[$mon], $hour ,$min;
+ $date{'iso-8601'} = sprintf "%04d-%02d-%02dT%02d:%02d:%02dZ",
+ 1900+$year, $mon, $mday, $hour ,$min, $sec;
$tz =~ m/^([+\-][0-9][0-9])([0-9][0-9])$/;
my $local = $epoch + ((int $1 + ($2/60)) * 3600);
@@ -1209,9 +1212,9 @@ sub parse_date {
$date{'hour_local'} = $hour;
$date{'minute_local'} = $min;
$date{'tz_local'} = $tz;
- $date{'iso-tz'} = sprintf ("%04d-%02d-%02d %02d:%02d:%02d %s",
- 1900+$year, $mon+1, $mday,
- $hour, $min, $sec, $tz);
+ $date{'iso-tz'} = sprintf("%04d-%02d-%02d %02d:%02d:%02d %s",
+ 1900+$year, $mon+1, $mday,
+ $hour, $min, $sec, $tz);
return %date;
}
@@ -1672,14 +1675,17 @@ EOF
}
}
if (defined $project) {
- printf('<link rel="alternate" title="%s log" '.
- 'href="%s" type="application/rss+xml"/>'."\n",
+ printf('<link rel="alternate" title="%s log RSS feed" '.
+ 'href="%s" type="application/rss+xml" />'."\n",
esc_param($project), href(action=>"rss"));
+ printf('<link rel="alternate" title="%s log Atom feed" '.
+ 'href="%s" type="application/atom+xml" />'."\n",
+ esc_param($project), href(action=>"atom"));
} else {
printf('<link rel="alternate" title="%s projects list" '.
'href="%s" type="text/plain; charset=utf-8"/>'."\n",
$site_name, href(project=>undef, action=>"project_index"));
- printf('<link rel="alternate" title="%s projects logs" '.
+ printf('<link rel="alternate" title="%s projects feeds" '.
'href="%s" type="text/x-opml"/>'."\n",
$site_name, href(project=>undef, action=>"opml"));
}
@@ -1745,7 +1751,9 @@ sub git_footer_html {
print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
}
print $cgi->a({-href => href(action=>"rss"),
- -class => "rss_logo"}, "RSS") . "\n";
+ -class => "rss_logo"}, "RSS") . " ";
+ print $cgi->a({-href => href(action=>"atom"),
+ -class => "rss_logo"}, "Atom") . "\n";
} else {
print $cgi->a({-href => href(project=>undef, action=>"opml"),
-class => "rss_logo"}, "OPML") . " ";
@@ -4150,26 +4158,125 @@ sub git_shortlog {
}
## ......................................................................
-## feeds (RSS, OPML)
+## feeds (RSS, Atom; OPML)
-sub git_rss {
- # http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
+sub git_feed {
+ my $format = shift || 'atom';
+ my ($have_blame) = gitweb_check_feature('blame');
+
+ # Atom: http://www.atomenabled.org/developers/syndication/
+ # RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
+ if ($format ne 'rss' && $format ne 'atom') {
+ die_error(undef, "Unknown web feed format");
+ }
+
+ # log/feed of current (HEAD) branch, log of given branch, history of file/directory
+ my $head = $hash || 'HEAD';
open my $fd, "-|", git_cmd(), "rev-list", "--max-count=150",
- git_get_head_hash($project), "--"
+ $head, "--", (defined $file_name ? $file_name : ())
or die_error(undef, "Open git-rev-list failed");
my @revlist = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading git-rev-list failed");
- print $cgi->header(-type => 'text/xml', -charset => 'utf-8');
- print <<XML;
-<?xml version="1.0" encoding="utf-8"?>
+
+ my %latest_commit;
+ my %latest_date;
+ my $content_type = "application/$format+xml";
+ if (defined $cgi->http('HTTP_ACCEPT') &&
+ $cgi->Accept('text/xml') > $cgi->Accept($content_type)) {
+ # browser (feed reader) prefers text/xml
+ $content_type = 'text/xml';
+ }
+ if (defined($revlist[0])) {
+ %latest_commit = parse_commit($revlist[0]);
+ %latest_date = parse_date($latest_commit{'committer_epoch'});
+ print $cgi->header(
+ -type => $content_type,
+ -charset => 'utf-8',
+ -last_modified => $latest_date{'rfc2822'});
+ } else {
+ print $cgi->header(
+ -type => $content_type,
+ -charset => 'utf-8');
+ }
+
+ # Optimization: skip generating the body if client asks only
+ # for Last-Modified date.
+ return if ($cgi->request_method() eq 'HEAD');
+
+ # header variables
+ my $title = "$site_name - $project/$action";
+ my $feed_type = 'log';
+ if (defined $hash) {
+ $title .= " - '$hash'";
+ $feed_type = 'branch log';
+ if (defined $file_name) {
+ $title .= " :: $file_name";
+ $feed_type = 'history';
+ }
+ } elsif (defined $file_name) {
+ $title .= " - $file_name";
+ $feed_type = 'history';
+ }
+ $title .= " $feed_type";
+ my $descr = git_get_project_description($project);
+ if (defined $descr) {
+ $descr = esc_html($descr);
+ } else {
+ $descr = "$project " .
+ ($format eq 'rss' ? 'RSS' : 'Atom') .
+ " feed";
+ }
+ my $owner = git_get_project_owner($project);
+ $owner = esc_html($owner);
+
+ #header
+ my $alt_url;
+ if (defined $file_name) {
+ $alt_url = href(-full=>1, action=>"history", hash=>$hash, file_name=>$file_name);
+ } elsif (defined $hash) {
+ $alt_url = href(-full=>1, action=>"log", hash=>$hash);
+ } else {
+ $alt_url = href(-full=>1, action=>"summary");
+ }
+ print qq!<?xml version="1.0" encoding="utf-8"?>\n!;
+ if ($format eq 'rss') {
+ print <<XML;
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
-<title>$project $my_uri $my_url</title>
-<link>${\esc_html("$my_url?p=$project;a=summary")}</link>
-<description>$project log</description>
-<language>en</language>
XML
+ print "<title>$title</title>\n" .
+ "<link>$alt_url</link>\n" .
+ "<description>$descr</description>\n" .
+ "<language>en</language>\n";
+ } elsif ($format eq 'atom') {
+ print <<XML;
+<feed xmlns="http://www.w3.org/2005/Atom">
+XML
+ print "<title>$title</title>\n" .
+ "<subtitle>$descr</subtitle>\n" .
+ '<link rel="alternate" type="text/html" href="' .
+ $alt_url . '" />' . "\n" .
+ '<link rel="self" type="' . $content_type . '" href="' .
+ $cgi->self_url() . '" />' . "\n" .
+ "<id>" . href(-full=>1) . "</id>\n" .
+ # use project owner for feed author
+ "<author><name>$owner</name></author>\n";
+ if (defined $favicon) {
+ print "<icon>" . esc_url($favicon) . "</icon>\n";
+ }
+ if (defined $logo_url) {
+ # not twice as wide as tall: 72 x 27 pixels
+ print "<logo>" . esc_url($logo_url) . "</logo>\n";
+ }
+ if (! %latest_date) {
+ # dummy date to keep the feed valid until commits trickle in:
+ print "<updated>1970-01-01T00:00:00Z</updated>\n";
+ } else {
+ print "<updated>$latest_date{'iso-8601'}</updated>\n";
+ }
+ }
+ # contents
for (my $i = 0; $i <= $#revlist; $i++) {
my $commit = $revlist[$i];
my %co = parse_commit($commit);
@@ -4178,42 +4285,100 @@ XML
last;
}
my %cd = parse_date($co{'committer_epoch'});
+
+ # get list of changed files
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
- $co{'parent'}, $co{'id'}, "--"
+ $co{'parent'}, $co{'id'}, "--", (defined $file_name ? $file_name : ())
or next;
my @difftree = map { chomp; $_ } <$fd>;
close $fd
or next;
- print "<item>\n" .
- "<title>" .
- sprintf("%d %s %02d:%02d", $cd{'mday'}, $cd{'month'}, $cd{'hour'}, $cd{'minute'}) . " - " . esc_html($co{'title'}) .
- "</title>\n" .
- "<author>" . esc_html($co{'author'}) . "</author>\n" .
- "<pubDate>$cd{'rfc2822'}</pubDate>\n" .
- "<guid isPermaLink=\"true\">" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "</guid>\n" .
- "<link>" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "</link>\n" .
- "<description>" . esc_html($co{'title'}) . "</description>\n" .
- "<content:encoded>" .
- "<![CDATA[\n";
+
+ # print element (entry, item)
+ my $co_url = href(-full=>1, action=>"commit", hash=>$commit);
+ if ($format eq 'rss') {
+ print "<item>\n" .
+ "<title>" . esc_html($co{'title'}) . "</title>\n" .
+ "<author>" . esc_html($co{'author'}) . "</author>\n" .
+ "<pubDate>$cd{'rfc2822'}</pubDate>\n" .
+ "<guid isPermaLink=\"true\">$co_url</guid>\n" .
+ "<link>$co_url</link>\n" .
+ "<description>" . esc_html($co{'title'}) . "</description>\n" .
+ "<content:encoded>" .
+ "<![CDATA[\n";
+ } elsif ($format eq 'atom') {
+ print "<entry>\n" .
+ "<title type=\"html\">" . esc_html($co{'title'}) . "</title>\n" .
+ "<updated>$cd{'iso-8601'}</updated>\n" .
+ "<author><name>" . esc_html($co{'author_name'}) . "</name></author>\n" .
+ # use committer for contributor
+ "<contributor><name>" . esc_html($co{'committer_name'}) . "</name></contributor>\n" .
+ "<published>$cd{'iso-8601'}</published>\n" .
+ "<link rel=\"alternate\" type=\"text/html\" href=\"$co_url\" />\n" .
+ "<id>$co_url</id>\n" .
+ "<content type=\"xhtml\" xml:base=\"" . esc_url($my_url) . "\">\n" .
+ "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n";
+ }
my $comment = $co{'comment'};
+ print "<pre>\n";
foreach my $line (@$comment) {
- $line = to_utf8($line);
- print "$line<br/>\n";
+ $line = esc_html($line);
+ print "$line\n";
}
- print "<br/>\n";
- foreach my $line (@difftree) {
- if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
- next;
+ print "</pre><ul>\n";
+ foreach my $difftree_line (@difftree) {
+ my %difftree = parse_difftree_raw_line($difftree_line);
+ next if !$difftree{'from_id'};
+
+ my $file = $difftree{'file'} || $difftree{'to_file'};
+
+ print "<li>" .
+ "[" .
+ $cgi->a({-href => href(-full=>1, action=>"blobdiff",
+ hash=>$difftree{'to_id'}, hash_parent=>$difftree{'from_id'},
+ hash_base=>$co{'id'}, hash_parent_base=>$co{'parent'},
+ file_name=>$file, file_parent=>$difftree{'from_file'}),
+ -title => "diff"}, 'D');
+ if ($have_blame) {
+ print $cgi->a({-href => href(-full=>1, action=>"blame",
+ file_name=>$file, hash_base=>$commit),
+ -title => "blame"}, 'B');
}
- my $file = esc_path(unquote($7));
- $file = to_utf8($file);
- print "$file<br/>\n";
+ # if this is not a feed of a file history
+ if (!defined $file_name || $file_name ne $file) {
+ print $cgi->a({-href => href(-full=>1, action=>"history",
+ file_name=>$file, hash=>$commit),
+ -title => "history"}, 'H');
+ }
+ $file = esc_path($file);
+ print "] ".
+ "$file</li>\n";
+ }
+ if ($format eq 'rss') {
+ print "</ul>]]>\n" .
+ "</content:encoded>\n" .
+ "</item>\n";
+ } elsif ($format eq 'atom') {
+ print "</ul>\n</div>\n" .
+ "</content>\n" .
+ "</entry>\n";
}
- print "]]>\n" .
- "</content:encoded>\n" .
- "</item>\n";
}
- print "</channel></rss>";
+
+ # end of feed
+ if ($format eq 'rss') {
+ print "</channel>\n</rss>\n";
+ } elsif ($format eq 'atom') {
+ print "</feed>\n";
+ }
+}
+
+sub git_rss {
+ git_feed('rss');
+}
+
+sub git_atom {
+ git_feed('atom');
}
sub git_opml {
--
1.4.3.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] gitweb: Refactor feed generation, make output prettier, add Atom feed
2006-11-19 14:05 ` [PATCH 2/2] gitweb: Refactor feed generation, make output prettier, add Atom feed Jakub Narebski
@ 2006-11-20 14:45 ` Jakub Narebski
0 siblings, 0 replies; 8+ messages in thread
From: Jakub Narebski @ 2006-11-20 14:45 UTC (permalink / raw)
To: git
Jakub Narebski wrote:
> Allow for feed generation for branches other than current (HEAD)
> branch, and for generation of feeds for file or directory history.
By the way, which feed format use for branch feeds? Atom or RSS?
Or perhaps leave this configurable? But which way:
our $default_feed_format = 'atom';
or use 'feedformat' feature?
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-11-20 14:45 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-15 0:10 [PATCH] gitweb: Make RSS feed output prettier asf
2006-11-15 0:24 ` Jakub Narebski
2006-11-16 21:45 ` [PATCH] gitweb: Atom feeds (was: gitweb: Make RSS feed output prettier) Andreas Fuchs
2006-11-17 9:01 ` [PATCH] gitweb: Atom feeds Junio C Hamano
2006-11-17 11:36 ` Jakub Narebski
2006-11-19 14:05 ` [PATCH 1/2] gitweb: Add an option to href() to return full URL Jakub Narebski
2006-11-19 14:05 ` [PATCH 2/2] gitweb: Refactor feed generation, make output prettier, add Atom feed Jakub Narebski
2006-11-20 14:45 ` Jakub Narebski
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).