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(''."\n",
esc_param($project), href(action=>"rss"));
+ printf(''."\n",
+ esc_param($project), href(action=>"atom"));
} else {
printf(''."\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 <
-$project $my_uri $my_url
-${\esc_html("$my_url?p=$project;a=summary")}
-$project log
+${\esc_html("$project $my_uri $my_url")}
+${\esc_url("$my_url?p=$project;a=summary")}
+${\esc_html($project)} log
en
XML
@@ -4128,32 +4151,138 @@ XML
"\n" .
"" . esc_html($co{'author'}) . "\n" .
"$cd{'rfc2822'}\n" .
- "" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "\n" .
- "" . esc_html("$my_url?p=$project;a=commit;h=$commit") . "\n" .
+ "" . esc_url("$my_url?p=$project;a=commit;h=$commit") . "\n" .
+ "" . esc_url("$my_url?p=$project;a=commit;h=$commit") . "\n" .
"" . esc_html($co{'title'}) . "\n" .
"" .
"\n";
foreach my $line (@$comment) {
- $line = to_utf8($line);
- print "$line
\n";
+ $line = esc_html($line);
+ print "$line\n";
}
- print "
\n";
+ print "\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
\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 "- $file
\n";
}
- print "]]>\n" .
+ print "
]]>\n" .
"\n" .
"\n";
}
print "";
}
+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 <
+
+${\esc_html("$project $my_uri $my_url")}
+
+
+$project log
+${\esc_url("$my_url?p=$project")}
+XML
+ if (!defined(%latest_date)) {
+ # dummy date to keep the feed valid until commits trickle in:
+ print "1970-01-01T00:00:00Z";
+ } else {
+ print "".$latest_date{'iso-8601'}."\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 "\n" .
+ "" .
+ esc_html($co{'author_name'}) . ": " . esc_html($co{'title'}) .
+ "\n" .
+ "$cd{'iso-8601'}\n" .
+ "" . esc_html($co{'author_name'}) . "\n" .
+ "$cd{'iso-8601'}\n" .
+ "\n" .
+ "" . esc_url("$my_url?p=$project;a=commit;h=$co{'id'}") . "\n" .
+ "" .
+ "\n";
+ foreach my $line (@$comment) {
+ $line = to_utf8(esc_html($line));
+ print "$line\n";
+ }
+ print "\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 "- [";
+ print "D";
+ if (gitweb_check_feature('blame')) {
+ print "B";
+ }
+ print "H";
+ print "] $file";
+ print "
\n";
+ }
+ print "
]]>\n" .
+ "\n" .
+ "\n";
+ }
+ print "";
+}
+
sub git_opml {
my @list = git_get_projects_list();