#!/usr/bonsaitools/bin/perl -- # -*- Mode: perl; indent-tabs-mode: nil -*- # # The contents of this file are subject to the Netscape Public License # Version 1.0 (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/ # # 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. # # The Original Code is the Bonsai CVS tool. # # The Initial Developer of the Original Code is Netscape Communications # Corporation. Portions created by Netscape are Copyright (C) 1998 # Netscape Communications Corporation. All Rights Reserved. # cvslog.cgi -- cvslog with logs as popups and allowing html in comments. # # Created: Steve Lamm , 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 # require 'lloydcgi.pl'; require 'cvsblame.pl'; require 'utils.pl'; use SourceChecker; # Some Globals # $| = 1; print "Content-Type:text/html\n\n"; @src_roots = getRepositoryList(); # Handle the "file" argument # $filename = ''; $filename = $form{'file'} if defined($form{'file'}); if ($filename eq '') { &print_usage; exit; } ($file_head, $file_tail) = $filename =~ m@(.*/)?(.+)@; # Handle the "rev" argument # $opt_rev = $form{'rev'} if defined($form{'rev'} && $form{'rev'} ne 'HEAD'); $browse_revtag = 'HEAD'; $browse_revtag = $opt_rev if ($opt_rev =~ /[A-Za-z]/); $revision = ''; # Handle the "root" argument # if (defined($root = $form{'root'}) && $root ne '') { $root =~ s|/$||; validateRepository($root); if (-d $root) { unshift(@src_roots, $root); } else { &print_top; print "Error: Root, $root, is not a directory.

\n"; print "\n"; &print_bottom; exit; } } # Find the rcs file # foreach (@src_roots) { $root = $_; $rcs_filename = "$root/$filename,v"; goto found_file if -r $rcs_filename; $rcs_filename = "$root/${file_head}Attic/$file_tail,v"; goto found_file if -r $rcs_filename; } # File not found &print_top; print "Rcs file, $filename, does not exist.

\n"; print "\n"; &print_bottom; exit; found_file: ($rcs_path) = $rcs_filename =~ m@$root/(.*)/.+?,v@; # Parse the rcs file ($opt_rev is passed as a global) # $revision = &parse_cvs_file($rcs_filename); $file_rev = $revision; # Handle the "mark" argument # $mark_arg = ''; $mark_arg = $form{'mark'} if defined($form{'mark'}); foreach $rev (split(',',$mark_arg)) { $mark{$rev} = 1; } # Handle the "author" argument # $author_arg = ''; $author_arg = $form{'author'} if defined($form{'author'}); foreach $author (split(',',$author_arg)) { $use_author{$author} = 1; } # Handle the "sort" argument $opt_sort = ''; $opt_sort = $form{'sort'}; # Start printing out the page # &print_top; if ($ENV{'HTTP_USER_AGENT'} =~ /Win/) { $font_tag = ""; } else { # We don't want your stinking Windows font $font_tag = ""; } # Print link at top for directory browsing # $output = "
"; foreach $path (split('/',$rcs_path)) { $link_path .= $path; $output .= "$path/ "; $link_path .= '/'; } $output .= "$file_tail ("; $output .= "$browse_revtag:" unless $browse_revtag eq 'HEAD'; $output .= $revision if $revision; $output .= ")"; EmitHtmlHeader("CVS Log", $output); &print_useful_links($filename); # Create a table with header links to sort by column. # $table_tag = ""; if ($opt_sort eq 'author') { $table_header_tag .= "
RevAuthorDateLog"; } else { $table_header_tag .= "RevAuthorDateLog"; } $table_header_tag = &url_encode3($table_header_tag); print "$font_tag$table_tag$table_header_tag"; # Print each line of the revision, preceded by its annotation. # 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); } $row_count = 0; $max_rev_length = length($start_rev); $max_author_length = 8; @revisions = ($start_rev, ancestor_revisions($start_rev)); @revisions = sort by_author @revisions if $opt_sort eq 'author'; #@revisions = sort by_author @revisions if $opt_sort eq 'date' && $rev eq 'all'; foreach $revision (@revisions) { $author = $revision_author{$revision}; next unless $author_arg eq '' || $use_author{$author}; $log = $revision_log{$revision}; $log =~ s/&/&/g; $log =~ s//>/g; eval ('$log =~ s@\d{4,6}@' . $BUGSYSTEMEXPR . '@g;'); $log =~ s/\n|\r|\r\n/
/g; if ($bgcolor eq '') { #$bgcolor = ' BGCOLOR="#EEEEEE"';# My browser translates this to white. $bgcolor = ' BGCOLOR="#E7E7E7"'; # Pick a grey that shows up on 8-bit. } else { $bgcolor = ''; } $output = ''; $row_count++; if ($row_count > 20) { $output .= "
\n$table_tag"; $row_count = 0; } $output .= "" .""; $anchor = "'; $output .= "".$author .' ' x ($max_author_length - length($author)).''; $rev_time = $revision_ctime{$revision}; # $rev_time =~ s/(19\d\d) (.\d:\d\d)/$1
$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; my ($rday, $rmon, $ryear, $rhour, $rmin) = m/([0-9]+) ([A-Z][a-z]+) ([0-9][0-9]+) +([0-9]+):([0-9]+)/; $rmon =~ s/^(...).*$/$1/; if (!$rday) { # parse error -- be annoying so somebody complains. $rev_time = "\"$rev_time\""; } elsif ($cyear ne $ryear) { $rev_time = sprintf("%s %2d %04d", $rmon, $rday, $ryear); } else { $rev_time = sprintf("%s %2d %02d:%02d", $rmon, $rday, $rhour, $rmin); } $rev_time = "$rev_time"; } $output .= "$rev_time"; $output .= " $log"; $output .= "\n"; print $output; } print ""; &print_bottom; ## END of main script sub by_revision { local (@a_parts) = split(/\./,$a); local (@b_parts) = split(/\./,$b); while(1) { local ($aa) = shift @a_parts; local ($bb) = shift @b_parts; return 1 if $aa eq ''; return -1 if $bb eq ''; return $bb <=> $aa if $aa ne $bb; } } sub by_author { local ($a_author) = $revision_author{$a}; local ($b_author) = $revision_author{$b}; return $a_author cmp $b_author if $a_author ne $b_author; return by_revision; } sub revision_pad { local ($revision) = @_; return ' ' x ($max_rev_length - length($revision)); } sub sprint_author { local ($revision) = @_; local ($author) = $revision_author{$revision}; return } sub print_top { local ($title_text) = "for $file_tail ("; $title_text .= "$browse_revtag:" unless $browse_revtag eq 'HEAD'; $title_text .= $revision if $revision; $title_text .= ")"; $title_text =~ s/\(\)//; print <<__TOP__; CVS Log $title_text __TOP__ } # print_top sub print_usage { local ($linenum_message) = ''; local ($new_linenum, $src_roots_list); local ($title_text) = "Usage"; $src_roots_list = join('
', @src_roots); print <<__USAGE__; CVS Log $title_text

CVS Log Usage

Add parameters to the query string to view a file.

Param Default Example Description
file -- ns/cmd/Makefile Path to file name
root $src_roots_list /warp/webroot CVS root
rev HEAD 1.3
ACTRA_branch
Revision
author -- slamm,mtoy Filter out these authors
#<rev_number> -- #1.2 Jump to a revision

Examples:
  cvslog.cgi?file=ns/cmd/Makefile
  cvslog.cgi?file=ns/cmd/xfe/mozilla.c&rev=Dogbert4xEscalation_BRANCH
  cvslog.cgi?file=projects/bonsai/cvslog.cgi&root=/warp/webroot
  cvslog.cgi?file=ns/cmd/xfe/dialogs.c#1.19

You may also begin a query with the CVS Query Form.

__USAGE__ &print_bottom; } # sub print_usage sub print_bottom { print <<__BOTTOM__;
Page configuration and help. Mail feedback to <slamm\@netscape.com>. __BOTTOM__ } # print_bottom sub print_useful_links { my ($path) = @_; my ($dir, $file) = $path =~ m@(.*/)?(.+)@; $dir =~ s@/$@@; my $diff_base = "cvsview2.cgi"; my $blame_base = "cvsblame.cgi"; # total kludge!! lxr omits the top-level "mozilla" directory... my $lxr_path = $path; if ($mozilla_lxr_kludge eq 'TRUE') { $lxr_path =~ s@^ns/@@; $lxr_path =~ s@^mozilla/@@; } my $lxr_link = "$lxr_base/$lxr_path"; my $diff_link = "$diff_base?command=DIRECTORY\&subdir=$dir\&files=$file"; my $blame_link = "$blame_base?root=$CVS_ROOT\&file=$path"; print "
lxr: browse the source code as hypertext.
diff: compare any two versions.
blame: annotate the author of each line.
"; }