1999-10-18 22:55:01 +00:00
|
|
|
#!/usr/bonsaitools/bin/perl -w
|
1998-06-16 21:43:24 +00:00
|
|
|
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
|
|
|
#
|
1999-11-01 23:33:56 +00:00
|
|
|
# The contents of this file are subject to the Netscape Public
|
|
|
|
# License Version 1.1 (the "License"); you may not use this file
|
|
|
|
# except in compliance with the License. You may obtain a copy of
|
|
|
|
# the License at http://www.mozilla.org/NPL/
|
1998-06-16 21:43:24 +00:00
|
|
|
#
|
1999-11-01 23:33:56 +00:00
|
|
|
# Software distributed under the License is distributed on an "AS
|
|
|
|
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
# implied. See the License for the specific language governing
|
|
|
|
# rights and limitations under the License.
|
1998-06-16 21:43:24 +00:00
|
|
|
#
|
|
|
|
# The Original Code is the Bonsai CVS tool.
|
|
|
|
#
|
|
|
|
# The Initial Developer of the Original Code is Netscape Communications
|
1999-11-01 23:33:56 +00:00
|
|
|
# Corporation. Portions created by Netscape are
|
|
|
|
# Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
# Rights Reserved.
|
|
|
|
#
|
|
|
|
# Contributor(s):
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# cvslog.cgi -- cvslog with logs as popups and allowing html in comments.
|
|
|
|
#
|
|
|
|
# Created: Steve Lamm <slamm@netscape.com>, 31-Mar-98.
|
|
|
|
#
|
|
|
|
# Arguments (passed via GET or POST):
|
|
|
|
# file - path to file name (e.g. ns/cmd/xfe/Makefile)
|
|
|
|
# root - cvs root (e.g. /warp/webroot)
|
|
|
|
# rev - revision (default is the latest version)
|
|
|
|
# mark - highlight a revision
|
|
|
|
# author - filter based on author
|
|
|
|
#
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
use strict;
|
|
|
|
|
|
|
|
# Shut up misguided -w warnings about "used only once". "use vars" just
|
|
|
|
# doesn't work for me.
|
|
|
|
|
|
|
|
sub sillyness {
|
|
|
|
my $zz;
|
|
|
|
$zz = $::CVS_ROOT;
|
|
|
|
$zz = $::head_revision;
|
|
|
|
$zz = $::revision_ctime;
|
|
|
|
$zz = $::revision_log;
|
|
|
|
}
|
|
|
|
|
1999-07-23 18:39:31 +00:00
|
|
|
require 'CGI.pl';
|
1998-06-16 21:43:24 +00:00
|
|
|
require 'cvsblame.pl';
|
|
|
|
|
2004-10-10 04:54:56 +00:00
|
|
|
use Date::Parse;
|
|
|
|
use Date::Format;
|
|
|
|
|
1998-06-16 21:43:24 +00:00
|
|
|
# Some Globals
|
|
|
|
#
|
|
|
|
$| = 1;
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
my @src_roots = getRepositoryList();
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Handle the "file" argument
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my $filename = '';
|
1999-07-23 18:39:31 +00:00
|
|
|
$filename = $::FORM{'file'} if defined($::FORM{'file'});
|
1998-06-16 21:43:24 +00:00
|
|
|
if ($filename eq '')
|
|
|
|
{
|
2003-03-05 14:49:20 +00:00
|
|
|
print "Content-Type:text/html\n\n";
|
1998-06-16 21:43:24 +00:00
|
|
|
&print_usage;
|
2004-11-03 19:31:18 +00:00
|
|
|
PutsTrailer();
|
1998-06-16 21:43:24 +00:00
|
|
|
exit;
|
|
|
|
}
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($file_head, $file_tail) = $filename =~ m@(.*/)?(.+)@;
|
2004-09-15 15:48:18 +00:00
|
|
|
my $url_filename = url_quote($filename);
|
|
|
|
my $url_file_tail = url_quote($file_tail);
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# Handle the "rev" argument
|
|
|
|
#
|
1999-10-19 15:07:27 +00:00
|
|
|
$::opt_rev = "";
|
2004-11-30 23:56:13 +00:00
|
|
|
$::opt_rev = &SanitizeRevision($::FORM{'rev'}) if
|
2004-09-15 22:44:55 +00:00
|
|
|
defined $::FORM{'rev'} && $::FORM{'rev'} !~ m/^(HEAD|MAIN)$/;
|
2002-05-30 04:45:11 +00:00
|
|
|
my $revstr = '';
|
|
|
|
$revstr = "&rev=$::opt_rev" unless $::opt_rev eq '';
|
1999-10-18 22:55:01 +00:00
|
|
|
my $browse_revtag = 'HEAD';
|
|
|
|
$browse_revtag = $::opt_rev if ($::opt_rev =~ /[A-Za-z]/);
|
|
|
|
my $revision = '';
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Handle the "root" argument
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my $root = $::FORM{'root'};
|
|
|
|
if (defined $root && $root ne '') {
|
1998-06-16 21:43:24 +00:00
|
|
|
$root =~ s|/$||;
|
|
|
|
validateRepository($root);
|
|
|
|
if (-d $root) {
|
|
|
|
unshift(@src_roots, $root);
|
|
|
|
} else {
|
2003-03-05 14:49:20 +00:00
|
|
|
print "Content-Type:text/html\n\n";
|
1998-06-16 21:43:24 +00:00
|
|
|
&print_top;
|
|
|
|
print "Error: Root, $root, is not a directory.<BR><BR>\n";
|
2004-11-03 19:31:18 +00:00
|
|
|
PutsTrailer();
|
1998-06-16 21:43:24 +00:00
|
|
|
exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Find the rcs file
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my $rcs_filename;
|
2004-10-17 06:19:40 +00:00
|
|
|
my $found_rcs_file = 0;
|
1998-06-16 21:43:24 +00:00
|
|
|
foreach (@src_roots) {
|
|
|
|
$root = $_;
|
|
|
|
$rcs_filename = "$root/$filename,v";
|
1999-07-23 18:39:31 +00:00
|
|
|
$rcs_filename = Fix_BonsaiLink($rcs_filename);
|
2004-10-17 06:19:40 +00:00
|
|
|
$found_rcs_file = 1, last if -r $rcs_filename;
|
1998-06-16 21:43:24 +00:00
|
|
|
$rcs_filename = "$root/${file_head}Attic/$file_tail,v";
|
2004-10-17 06:19:40 +00:00
|
|
|
$found_rcs_file = 1, last if -r $rcs_filename;
|
1998-06-16 21:43:24 +00:00
|
|
|
}
|
2004-10-17 06:19:40 +00:00
|
|
|
|
1998-06-16 21:43:24 +00:00
|
|
|
# File not found
|
2004-10-17 06:19:40 +00:00
|
|
|
unless ($found_rcs_file) {
|
|
|
|
print "Content-Type:text/html\n\n";
|
|
|
|
&print_top;
|
|
|
|
my $escaped_filename = html_quote($filename);
|
|
|
|
print "Rcs file, $escaped_filename, does not exist.<BR><BR>\n";
|
2004-11-03 19:31:18 +00:00
|
|
|
PutsTrailer();
|
2004-10-17 06:19:40 +00:00
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
|
|
|
|
my $rcs_path;
|
|
|
|
($rcs_path) = $rcs_filename =~ m@$root/(.*)/.+?,v@;
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
# Parse the rcs file ($::opt_rev is passed as a global)
|
1998-06-16 21:43:24 +00:00
|
|
|
#
|
|
|
|
$revision = &parse_cvs_file($rcs_filename);
|
1999-10-18 22:55:01 +00:00
|
|
|
my $file_rev = $revision;
|
1998-06-16 21:43:24 +00:00
|
|
|
|
2003-03-05 14:49:20 +00:00
|
|
|
my $start_rev;
|
|
|
|
if ($browse_revtag eq 'HEAD') {
|
|
|
|
$start_rev = $::head_revision; # $::head_revision is a global from cvsblame.pl
|
|
|
|
} else {
|
|
|
|
$start_rev = map_tag_to_revision($browse_revtag);
|
|
|
|
}
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# Handle the "mark" argument
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my %mark;
|
2004-12-01 04:25:22 +00:00
|
|
|
my $mark_arg = &SanitizeMark($::FORM{'mark'});
|
1999-10-18 22:55:01 +00:00
|
|
|
foreach my $rev (split(',',$mark_arg)) {
|
2004-12-01 04:25:22 +00:00
|
|
|
$mark{$rev} = 1 if ($rev =~ m/^\d+$/);
|
1998-06-16 21:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Handle the "author" argument
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my %use_author;
|
2004-12-01 04:25:22 +00:00
|
|
|
my $author_arg = &SanitizeUsernames($::FORM{'author'});
|
1999-10-18 22:55:01 +00:00
|
|
|
foreach my $author (split(',',$author_arg)) {
|
1998-06-16 21:43:24 +00:00
|
|
|
$use_author{$author} = 1;
|
|
|
|
}
|
2004-10-10 04:54:56 +00:00
|
|
|
my $url_author_arg = url_quote($author_arg);
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Handle the "sort" argument
|
1999-10-18 22:55:01 +00:00
|
|
|
my $opt_sort = '';
|
|
|
|
$opt_sort = $::FORM{'sort'} if defined $::FORM{'sort'};
|
2004-10-10 04:54:56 +00:00
|
|
|
my $sortstr = $opt_sort eq "author" ? "&sort=author" : "";
|
|
|
|
|
|
|
|
print "Last-Modified: ".time2str("%a, %d %b %Y %T %Z", str2time($::revision_ctime{$start_rev}), "GMT")."\n";
|
|
|
|
print "Expires: ".time2str("%a, %d %b %Y %T %Z", time+1200, "GMT")."\n";
|
|
|
|
|
|
|
|
my $ctype = $::FORM{ctype};
|
|
|
|
if ($ctype eq "rss") {
|
|
|
|
print "Content-Type: application/rss+xml\n\n";
|
|
|
|
display_rss();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
print "Content-Type: text/html\n\n";
|
|
|
|
display_html();
|
|
|
|
}
|
|
|
|
|
|
|
|
exit;
|
|
|
|
|
|
|
|
## END of main script
|
1998-06-16 21:43:24 +00:00
|
|
|
|
2004-10-10 04:54:56 +00:00
|
|
|
sub display_html {
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# Start printing out the page
|
|
|
|
#
|
|
|
|
&print_top;
|
1999-07-23 18:39:31 +00:00
|
|
|
print Param('bannerhtml', 1);
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Print link at top for directory browsing
|
|
|
|
#
|
1999-03-20 01:50:52 +00:00
|
|
|
print q(
|
|
|
|
<TABLE BORDER=0 CELLPADDING=5 CELLSPACING=0 WIDTH="100%">
|
|
|
|
<TR>
|
|
|
|
<TD ALIGN=LEFT VALIGN=CENTER>
|
|
|
|
<NOBR><FONT SIZE="+2"><B>
|
|
|
|
CVS Log
|
|
|
|
</B></FONT></NOBR>
|
|
|
|
<BR><B>
|
|
|
|
);
|
1998-06-16 21:43:24 +00:00
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
my $link_path;
|
|
|
|
my $lxr_path;
|
|
|
|
foreach my $path (split('/',$rcs_path)) {
|
1999-07-23 18:39:31 +00:00
|
|
|
$link_path .= url_encode2($path).'/';
|
|
|
|
$lxr_path = Fix_LxrLink($link_path);
|
|
|
|
print "<A HREF='$lxr_path'>$path</a>/ ";
|
1998-06-16 21:43:24 +00:00
|
|
|
}
|
1999-07-23 18:39:31 +00:00
|
|
|
$lxr_path = Fix_LxrLink("$link_path$file_tail");
|
|
|
|
print "<A HREF='$lxr_path'>$file_tail</a> ";
|
1999-03-20 01:50:52 +00:00
|
|
|
|
2002-02-01 14:32:55 +00:00
|
|
|
my $graph_cell = Param('cvsgraph') ? <<"--endquote--" : "";
|
|
|
|
</TR><TR>
|
|
|
|
<TD>
|
2004-09-15 15:48:18 +00:00
|
|
|
<A HREF="cvsgraph.cgi?file=$url_filename">graph</A>
|
2002-02-01 14:32:55 +00:00
|
|
|
</TD><TD NOWRAP>
|
|
|
|
View the revision history as a graph
|
|
|
|
</TD>
|
|
|
|
--endquote--
|
|
|
|
|
1999-03-20 01:50:52 +00:00
|
|
|
print " (";
|
|
|
|
print "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
|
|
|
print $revision if $revision;
|
|
|
|
print ")";
|
|
|
|
|
|
|
|
print qq(
|
|
|
|
</B>
|
|
|
|
</TD>
|
|
|
|
|
|
|
|
<TD ALIGN=RIGHT VALIGN=TOP WIDTH="1%">
|
|
|
|
<TABLE BORDER CELLPADDING=10 CELLSPACING=0>
|
|
|
|
<TR>
|
|
|
|
<TD NOWRAP BGCOLOR="#FAFAFA">
|
|
|
|
<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
|
|
|
|
<TR>
|
|
|
|
<TD>
|
1999-07-23 18:39:31 +00:00
|
|
|
<A HREF="$lxr_path">lxr</A>
|
1999-03-22 20:16:33 +00:00
|
|
|
</TD><TD NOWRAP>
|
1999-03-20 01:50:52 +00:00
|
|
|
Browse the source code as hypertext.
|
|
|
|
</TD>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>
|
2004-09-15 15:48:18 +00:00
|
|
|
<A HREF="cvsview2.cgi?command=DIRECTORY&subdir=$rcs_path&files=$url_file_tail&branch=$::opt_rev">diff</A>
|
1999-03-22 20:16:33 +00:00
|
|
|
</TD><TD NOWRAP>
|
1999-03-20 01:50:52 +00:00
|
|
|
Compare any two version.
|
|
|
|
</TD>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>
|
2004-09-15 15:48:18 +00:00
|
|
|
<A HREF="cvsblame.cgi?file=$url_filename&rev=$::opt_rev&cvsroot=$root">blame</A>
|
1999-03-22 20:16:33 +00:00
|
|
|
</TD><TD NOWRAP>
|
1999-03-20 01:50:52 +00:00
|
|
|
Annotate the author of each line.
|
|
|
|
</TD>
|
2004-10-10 04:54:56 +00:00
|
|
|
</TR><TR>
|
|
|
|
<TD>
|
|
|
|
<A HREF="cvslog.cgi?file=$url_filename&root=$root$revstr$sortstr&author=$url_author_arg&ctype=rss">RSS</A>
|
|
|
|
</TD><TD NOWRAP>
|
|
|
|
Get an RSS version of this page.
|
|
|
|
</TD>
|
2002-02-01 14:32:55 +00:00
|
|
|
$graph_cell
|
1999-03-20 01:50:52 +00:00
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
);
|
|
|
|
|
|
|
|
#&print_useful_links($filename);
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# Create a table with header links to sort by column.
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my $table_tag = "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH='100%'>";
|
|
|
|
my $table_header_tag = "";
|
1998-06-16 21:43:24 +00:00
|
|
|
if ($opt_sort eq 'author') {
|
2004-10-10 04:54:56 +00:00
|
|
|
$table_header_tag .= "<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$url_filename&root=$root&rev=$browse_revtag&sort=revision&author=$url_author_arg'>Rev</A><TH ALIGN=LEFT>Author<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$url_filename&root=$root&rev=$browse_revtag&sort=date&author=$url_author_arg'>Date</A><TH><TH ALIGN=LEFT>Log";
|
1998-06-16 21:43:24 +00:00
|
|
|
} else {
|
2004-10-10 04:54:56 +00:00
|
|
|
$table_header_tag .= "<TH ALIGN=LEFT>Rev<TH ALIGN=LEFT><A HREF='cvslog.cgi?file=$url_filename&root=$root&rev=$browse_revtag&sort=author&author=$url_author_arg'>Author</A><TH ALIGN=LEFT>Date<TH><TH ALIGN=LEFT>Log";
|
1998-06-16 21:43:24 +00:00
|
|
|
}
|
|
|
|
|
1999-03-20 01:50:52 +00:00
|
|
|
print "$table_tag$table_header_tag";
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
# Print each line of the revision, preceded by its annotation.
|
|
|
|
#
|
1999-10-18 22:55:01 +00:00
|
|
|
my $row_count = 0;
|
|
|
|
my $max_rev_length = length($start_rev);
|
|
|
|
my $max_author_length = 8;
|
|
|
|
my @revisions = ($start_rev, ancestor_revisions($start_rev));
|
1998-06-16 21:43:24 +00:00
|
|
|
@revisions = sort by_author @revisions if $opt_sort eq 'author';
|
|
|
|
#@revisions = sort by_author @revisions if $opt_sort eq 'date' && $rev eq 'all';
|
1999-10-18 22:55:01 +00:00
|
|
|
my $bgcolor;
|
1998-06-16 21:43:24 +00:00
|
|
|
foreach $revision (@revisions)
|
|
|
|
{
|
1999-10-18 22:55:01 +00:00
|
|
|
my $author = $::revision_author{$revision};
|
1998-06-16 21:43:24 +00:00
|
|
|
next unless $author_arg eq '' || $use_author{$author};
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
my $log = $::revision_log{$revision};
|
1998-06-16 21:43:24 +00:00
|
|
|
$log =~ s/&/&/g;
|
|
|
|
$log =~ s/</</g;
|
|
|
|
$log =~ s/>/>/g;
|
1999-07-23 18:39:31 +00:00
|
|
|
$log = MarkUpText($log);
|
1998-06-16 21:43:24 +00:00
|
|
|
$log =~ s/\n|\r|\r\n/<BR>/g;
|
|
|
|
|
2002-10-21 19:36:40 +00:00
|
|
|
if ($revision eq $::opt_rev) {
|
|
|
|
$bgcolor = ' BGCOLOR="LIGHTBLUE"';
|
|
|
|
} elsif ($mark{$revision}) {
|
|
|
|
$bgcolor = ' BGCOLOR="LIGHTGREEN"';
|
|
|
|
} elsif (!defined $bgcolor || $bgcolor eq '') {
|
1998-06-16 21:43:24 +00:00
|
|
|
$bgcolor = ' BGCOLOR="#E7E7E7"'; # Pick a grey that shows up on 8-bit.
|
|
|
|
} else {
|
|
|
|
$bgcolor = '';
|
|
|
|
}
|
|
|
|
|
1999-10-18 22:55:01 +00:00
|
|
|
my $output = '';
|
1998-06-16 21:43:24 +00:00
|
|
|
$row_count++;
|
|
|
|
if ($row_count > 20) {
|
|
|
|
$output .= "</TABLE>\n$table_tag";
|
|
|
|
$row_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output .= "<TR$bgcolor VALIGN=TOP><TD>"
|
2004-10-10 04:54:56 +00:00
|
|
|
."<A NAME=$revision><A HREF=".value_quote(revision_link($revision)).">$revision</A>"
|
1998-06-16 21:43:24 +00:00
|
|
|
.' ' x ($max_rev_length - length($revision)).'</TD>';
|
|
|
|
|
|
|
|
$output .= "<TD>".$author
|
|
|
|
.' ' x ($max_author_length - length($author)).'</TD>';
|
1999-10-18 22:55:01 +00:00
|
|
|
my $rev_time = $::revision_ctime{$revision};
|
1998-06-16 21:43:24 +00:00
|
|
|
# $rev_time =~ s/(19\d\d) (.\d:\d\d)/$1<BR><FONT SIZE=-2>$2<\/FONT>/;
|
|
|
|
|
|
|
|
# jwz: print the date the way "ls" does.
|
|
|
|
#
|
|
|
|
# What ls does is actually: print "Mmm DD HH:MM" unless the file is
|
|
|
|
# more than six months old, or more than 1 hour in the future, in
|
|
|
|
# which case, print "Mmm DD YYYY".
|
|
|
|
#
|
|
|
|
# What the following does is: "Mmm DD HH:MM" unless the year is not
|
|
|
|
# the current year; else print "Mmm DD YYYY".
|
|
|
|
#
|
|
|
|
# If we had $rev_time as an actual time_t instead of as a string,
|
|
|
|
# it would be easy to do the "ls" thing (see the code I wrote for
|
|
|
|
# this in "lxr/source"). -jwz, 15-Jun-98.
|
|
|
|
#
|
|
|
|
{
|
|
|
|
my $current_time = time;
|
|
|
|
my @t = gmtime($current_time);
|
|
|
|
my ($csec, $cmin, $chour, $cmday, $cmon, $cyear) = @t;
|
|
|
|
$cyear += 1900;
|
|
|
|
$_ = $rev_time;
|
|
|
|
$rev_time = "<FONT SIZE=\"-1\">$rev_time</FONT>";
|
|
|
|
}
|
|
|
|
|
|
|
|
$output .= "<TD NOWRAP ALIGN=RIGHT>$rev_time</TD>";
|
|
|
|
$output .= "<TD> </TD><TD WIDTH=99%>$log</TD>";
|
|
|
|
|
|
|
|
$output .= "</TR>\n";
|
|
|
|
|
|
|
|
print $output;
|
|
|
|
}
|
|
|
|
print "</TABLE>";
|
2004-11-03 19:31:18 +00:00
|
|
|
PutsTrailer();
|
2004-10-10 04:54:56 +00:00
|
|
|
}
|
1998-06-16 21:43:24 +00:00
|
|
|
|
2004-10-10 04:54:56 +00:00
|
|
|
sub display_rss {
|
|
|
|
my @revisions = ($start_rev, ancestor_revisions($start_rev));
|
|
|
|
@revisions = sort by_author @revisions if $opt_sort eq 'author';
|
|
|
|
|
|
|
|
# The escaped path+name of the file; included in the channel title.
|
|
|
|
my $html_filename = html_quote($filename);
|
|
|
|
|
|
|
|
# The canonical URL of the file; we use a link to its revision history,
|
|
|
|
# but arguably this should be a link to the LXR page or, for web pages,
|
|
|
|
# a link to the actual web page.
|
|
|
|
my $link = Param("urlbase") . "cvslog.cgi?file=$url_filename";
|
|
|
|
$link .= "&root=$root" if $::FORM{'root'} ne "";
|
|
|
|
$link .= $revstr;
|
|
|
|
$link .= $sortstr;
|
|
|
|
$link .= "&author=$url_author_arg" if $author_arg ne "";
|
|
|
|
$link = value_quote($link);
|
|
|
|
|
|
|
|
print <<"END";
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
<rdf:RDF
|
|
|
|
xmlns="http://purl.org/rss/1.0/"
|
|
|
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
|
|
|
|
|
|
<channel rdf:about="$link">
|
|
|
|
<title>Revision History for $html_filename</title>
|
|
|
|
<link>$link</link>
|
|
|
|
<description>Revision History for $html_filename</description>
|
|
|
|
<items>
|
|
|
|
<rdf:Seq>
|
|
|
|
END
|
|
|
|
|
|
|
|
# We loop over revisions twice. The first time, here, it's just to populate
|
|
|
|
# the "items" list of revisions inside the channel tag. All we need to know
|
|
|
|
# is whether to skip this author and the link to the revision.
|
|
|
|
foreach my $revision (@revisions) {
|
|
|
|
next unless $author_arg eq '' || $use_author{$::revision_author{$revision}};
|
|
|
|
my $link = value_quote(revision_link($revision));
|
|
|
|
print <<"END";
|
|
|
|
<rdf:li resource="$link"/>
|
|
|
|
END
|
|
|
|
}
|
|
|
|
|
|
|
|
print <<"END";
|
|
|
|
</rdf:Seq>
|
|
|
|
</items>
|
|
|
|
</channel>
|
|
|
|
END
|
|
|
|
|
|
|
|
# The second time we loop over revisions, it's to generate "item" resources
|
|
|
|
# for each one.
|
|
|
|
foreach my $revision (@revisions) {
|
|
|
|
my $author = $::revision_author{$revision};
|
|
|
|
next unless $author_arg eq '' || $use_author{$author};
|
|
|
|
$author = html_quote($author);
|
|
|
|
|
|
|
|
my $link = value_quote(revision_link($revision));
|
|
|
|
|
|
|
|
my $log = $::revision_log{$revision};
|
|
|
|
$log = html_quote($log);
|
|
|
|
$log = MarkUpText($log);
|
|
|
|
$log =~ s/\n|\r|\r\n/<BR>/g;
|
|
|
|
|
|
|
|
my $date = date_to_w3cdtf($::revision_ctime{$revision});
|
|
|
|
|
|
|
|
print <<"END";
|
|
|
|
<item rdf:about="$link">
|
|
|
|
<title>Version $revision</title>
|
|
|
|
<link>$link</link>
|
|
|
|
<description><![CDATA[$log]]></description>
|
|
|
|
<dc:creator>$author</dc:creator>
|
|
|
|
<dc:date>$date</dc:date>
|
|
|
|
</item>
|
|
|
|
END
|
|
|
|
}
|
|
|
|
|
|
|
|
print <<"END";
|
|
|
|
</rdf:RDF>
|
|
|
|
END
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sub revision_link {
|
|
|
|
my $revision = shift;
|
|
|
|
|
|
|
|
my $link = Param('urlbase') . "cvsview2.cgi";
|
|
|
|
if (defined($::prev_revision{$revision})) {
|
|
|
|
$link .= "?diff_mode=context&whitespace_mode=show&file=$url_file_tail"
|
|
|
|
. "&branch=$::opt_rev&root=$root&subdir=$rcs_path"
|
|
|
|
. "&command=DIFF_FRAMESET&rev1=$::prev_revision{$revision}"
|
|
|
|
. "&rev2=$revision";
|
|
|
|
} else {
|
|
|
|
$link .= "?files=$url_file_tail&root=$root&subdir=$rcs_path"
|
|
|
|
. "\&command=DIRECTORY\&rev2=$revision&branch=$::opt_rev";
|
|
|
|
$link .= "&branch=$browse_revtag" unless $browse_revtag eq 'HEAD';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $link;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Format a date/time in W3CDTF per http://www.w3.org/TR/NOTE-datetime
|
|
|
|
sub date_to_w3cdtf {
|
|
|
|
my ($date) = @_;
|
|
|
|
|
|
|
|
$date = str2time($date);
|
|
|
|
|
|
|
|
# Date::Format returns timezone offsets without a colon, while W3CDTF
|
|
|
|
# requires a colon between the hour and minute offsets, so we have to
|
|
|
|
# convert the timezone specially.
|
|
|
|
my $timezone = time2str("%z", $date);
|
|
|
|
$timezone =~ s/([+-])(\d\d)(\d\d)/$1$2:$3/;
|
|
|
|
|
|
|
|
$date = time2str("%Y-%m-%dT%R", $date) . $timezone;
|
|
|
|
|
|
|
|
return $date;
|
|
|
|
}
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
sub by_revision {
|
1999-10-18 22:55:01 +00:00
|
|
|
my (@a_parts) = split(/\./,$a);
|
|
|
|
my (@b_parts) = split(/\./,$b);
|
1998-06-16 21:43:24 +00:00
|
|
|
while(1) {
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($aa) = shift @a_parts;
|
|
|
|
my ($bb) = shift @b_parts;
|
1998-06-16 21:43:24 +00:00
|
|
|
return 1 if $aa eq '';
|
|
|
|
return -1 if $bb eq '';
|
|
|
|
return $bb <=> $aa if $aa ne $bb;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub by_author {
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($a_author) = $::revision_author{$a};
|
|
|
|
my ($b_author) = $::revision_author{$b};
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
return $a_author cmp $b_author if $a_author ne $b_author;
|
|
|
|
return by_revision;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub sprint_author {
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($revision) = @_;
|
|
|
|
my ($author) = $::revision_author{$revision};
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub print_top {
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($title_text) = "for $file_tail (";
|
1998-06-16 21:43:24 +00:00
|
|
|
$title_text .= "$browse_revtag:" unless $browse_revtag eq 'HEAD';
|
|
|
|
$title_text .= $revision if $revision;
|
|
|
|
$title_text .= ")";
|
|
|
|
$title_text =~ s/\(\)//;
|
|
|
|
|
|
|
|
print <<__TOP__;
|
|
|
|
<HTML>
|
|
|
|
<HEAD>
|
1999-03-20 01:50:52 +00:00
|
|
|
<TITLE>CVS Log $title_text</TITLE>
|
2004-12-01 02:15:29 +00:00
|
|
|
<link rel="alternate" type="application/rss+xml" title="CVS Log $title_text"
|
|
|
|
href="cvslog.cgi?file=$url_filename&root=$root$revstr$sortstr&author=$url_author_arg&ctype=rss">
|
1998-06-16 21:43:24 +00:00
|
|
|
</HEAD>
|
|
|
|
<BODY BGCOLOR=WHITE TEXT=BLACK>
|
|
|
|
|
|
|
|
__TOP__
|
|
|
|
} # print_top
|
|
|
|
|
|
|
|
sub print_usage {
|
1999-10-18 22:55:01 +00:00
|
|
|
my ($linenum_message) = '';
|
|
|
|
my ($new_linenum, $src_roots_list);
|
|
|
|
my ($title_text) = "Usage";
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
$src_roots_list = join('<BR>', @src_roots);
|
|
|
|
|
|
|
|
print <<__USAGE__;
|
|
|
|
<HTML>
|
|
|
|
<HEAD>
|
|
|
|
<TITLE>CVS Log $title_text</TITLE>
|
|
|
|
</HEAD><BODY>
|
|
|
|
<H2>CVS Log Usage</H2>
|
|
|
|
Add parameters to the query string to view a file.
|
|
|
|
<P>
|
|
|
|
<TABLE BORDER CELLPADDING=3>
|
|
|
|
<TR ALIGN=LEFT>
|
|
|
|
<TH>Param</TH>
|
|
|
|
<TH>Default</TH>
|
|
|
|
<TH>Example</TH>
|
|
|
|
<TH>Description</TH>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>file</TD>
|
|
|
|
<TD>--</TD>
|
|
|
|
<TD>ns/cmd/Makefile</TD>
|
|
|
|
<TD>Path to file name</TD>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>root</TD>
|
|
|
|
<TD>$src_roots_list</TD>
|
|
|
|
<TD>/warp/webroot</TD>
|
|
|
|
<TD>CVS root</TD>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>rev</TD>
|
|
|
|
<TD>HEAD</TD>
|
|
|
|
<TD>1.3
|
|
|
|
<BR>ACTRA_branch</TD>
|
|
|
|
<TD>Revision</TD>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>author</TD>
|
|
|
|
<TD>--</TD>
|
|
|
|
<TD>slamm,mtoy</TD>
|
2004-11-03 19:31:18 +00:00
|
|
|
<TD>Only show changes by these authors</TD>
|
1998-06-16 21:43:24 +00:00
|
|
|
</TR>
|
|
|
|
</TR><TR>
|
|
|
|
<TD>#<rev_number></TD>
|
|
|
|
<TD>--</TD>
|
|
|
|
<TD>#1.2</TD>
|
|
|
|
<TD>Jump to a revision</TD>
|
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
|
|
|
|
<P>Examples:
|
|
|
|
<TABLE><TR><TD> </TD><TD>
|
|
|
|
<A HREF="cvslog.cgi?file=ns/cmd/Makefile">
|
|
|
|
cvslog.cgi?file=ns/cmd/Makefile</A>
|
|
|
|
</TD></TR><TR><TD> </TD><TD>
|
|
|
|
<A HREF="cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH">
|
|
|
|
cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH</A>
|
|
|
|
</TD></TR><TR><TD> </TD><TD>
|
|
|
|
<A HREF="cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot">
|
|
|
|
cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot</A>
|
|
|
|
</TD></TR><TR><TD> </TD><TD>
|
|
|
|
<A HREF="cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19">
|
|
|
|
cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19</A>
|
|
|
|
</TD></TR></TABLE>
|
|
|
|
<P>
|
|
|
|
You may also begin a query with the <A HREF="cvsqueryform.cgi">CVS Query Form</A>.
|
|
|
|
</P>
|
|
|
|
__USAGE__
|
2004-11-03 19:31:18 +00:00
|
|
|
}
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
sub print_useful_links {
|
|
|
|
my ($path) = @_;
|
|
|
|
my ($dir, $file) = $path =~ m@(.*/)?(.+)@;
|
|
|
|
$dir =~ s@/$@@;
|
|
|
|
|
|
|
|
my $diff_base = "cvsview2.cgi";
|
|
|
|
my $blame_base = "cvsblame.cgi";
|
|
|
|
|
|
|
|
my $lxr_path = $path;
|
1999-07-23 18:39:31 +00:00
|
|
|
my $lxr_link = Fix_LxrLink($lxr_path);
|
2002-06-27 03:41:42 +00:00
|
|
|
my $diff_link = "$diff_base?command=DIRECTORY\&subdir=$dir\&files=$file\&branch=$::opt_rev";
|
|
|
|
my $blame_link = "$blame_base?root=$::CVS_ROOT\&file=$path\&rev=$::opt_rev";
|
1998-06-16 21:43:24 +00:00
|
|
|
|
|
|
|
print "<DIV ALIGN=RIGHT>
|
|
|
|
<TABLE BORDER CELLPADDING=10 CELLSPACING=0>
|
|
|
|
<TR>
|
|
|
|
<TD>
|
|
|
|
<TABLE BORDER=0 CELLPADDING=1 CELLSPACING=0>
|
|
|
|
<TR>
|
|
|
|
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$lxr_link\"><B>lxr:</B></A> </TD>
|
|
|
|
<TD>browse the source code as hypertext.</TD>
|
|
|
|
</TR>
|
|
|
|
<TR>
|
|
|
|
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$diff_link\"><B>diff:</B></A> </TD>
|
|
|
|
<TD>compare any two versions.</TD>
|
|
|
|
</TR>
|
|
|
|
<TR>
|
|
|
|
<TD VALIGN=TOP ALIGN=RIGHT><A HREF=\"$blame_link\"><B>blame:</B></A> </TD>
|
|
|
|
<TD>annotate the author of each line.</TD>
|
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
</TABLE>
|
|
|
|
</DIV>
|
|
|
|
";
|
|
|
|
}
|