#!/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. require 'CGI.pl'; require 'cvsquery.pl'; $CVS_ROOT = $::FORM{'cvsroot'}; $CVS_ROOT = pickDefaultRepository() unless $CVS_ROOT; $::TreeID = $::FORM{'module'} if (!exists($::FORM{'treeid'}) && exists($::FORM{'module'}) && exists($::TreeInfo{$::FORM{'module'}}{'repository'})); $::TreeID = 'default' if (!exists($::TreeInfo{$::TreeID}{'repository'}) || exists($::TreeInfo{$::TreeID}{'nobonsai'})); LoadTreeConfig(); my $userdomain = Param('userdomain'); $| = 1; $sm_font_tag = ""; my $generateBackoutCVSCommands = 0; if (defined $::FORM{'generateBackoutCVSCommands'}) { $generateBackoutCVSCommands = 1; } if (!$generateBackoutCVSCommands) { print "Content-type: text/html "; $script_str=''; &setup_script; print "$script_str"; } #print "
";


$CVS_REPOS_SUFIX = $CVS_ROOT;
$CVS_REPOS_SUFIX =~ s/\//_/g;

$CHECKIN_DATA_FILE = "data/checkinlog${CVS_REPOS_SUFIX}";
$CHECKIN_INDEX_FILE = "data/index${CVS_REPOS_SUFIX}";


$SORT_HEAD="bgcolor=\"#DDDDDD\"";

#
# Log the query
Log("Query [$ENV{'REMOTE_ADDR'}]: $ENV{'QUERY_STRING'}");

#
# build a module map
#
$query_module = $::FORM{'module'};

#
# allow ?file=/a/b/c/foo.c to be synonymous with ?dir=/a/b/c&file=foo.c
#
if ( $::FORM{'dir'} eq '' ) {
    $::FORM{'file'} = Fix_BonsaiLink($::FORM{'file'});
    if ($::FORM{'file'} =~ m@(.*?/)([^/]*)$@) {
        $::FORM{'dir'} = $1;
        $::FORM{'file'} = $2;
    }
}

#
# build a directory map
#
@query_dirs = split(/[;, \t]+/, $::FORM{'dir'});

$query_file = $::FORM{'file'};
$query_filetype = $::FORM{'filetype'};
$query_logexpr = $::FORM{'logexpr'};

#
# date
#
$query_date_type = $::FORM{'date'};
if( $query_date_type eq 'hours' ){
    $query_date_min = time - $::FORM{'hours'}*60*60;
}
elsif( $query_date_type eq 'day' ){
    $query_date_min = time - 24*60*60;
}
elsif( $query_date_type eq 'week' ){
    $query_date_min = time - 7*24*60*60;
}
elsif( $query_date_type eq 'month' ){
    $query_date_min = time - 30*24*60*60;
}
elsif( $query_date_type eq 'all' ){
    $query_date_min = 0;
}
elsif( $query_date_type eq 'explicit' ){
    if ($::FORM{'mindate'} ne "") {
        $query_date_min = parse_date($::FORM{'mindate'});
    }

    if ($::FORM{'maxdate'} ne "") {
        $query_date_max = parse_date($::FORM{'maxdate'});
    }
}
else {
    $query_date_min = time-60*60*2;
}

#
# who
#
$query_who = $::FORM{'who'};
$query_whotype = $::FORM{'whotype'};


$show_raw = 0;
$show_raw = $::FORM{'raw'} ne ''
     if $::FORM{'raw'};

#
# branch
#
$query_branch = $::FORM{'branch'};
if (!defined $query_branch) {
    $query_branch = 'HEAD';
}
$query_branchtype = $::FORM{'branchtype'};


#
# tags
#
$query_begin_tag = $::FORM{'begin_tag'};
$query_end_tag = $::FORM{'end_tag'};


#
# Get the query in english and print it.
#
$t = $e = &query_to_english;
$t =~ s/<[^>]*>//g;

$query_debug = $::FORM{'debug'};

my %mod_map = ();
$result= &query_checkins( %mod_map );

for $i (@{$result}) {
    $w{"$i->[$CI_WHO]\@$userdomain"} = 1;
}

@p = sort keys %w;
$pCount = @p;
$s = join(",%20", @p);

$e =~ s/Checkins in/In/;

my $menu = "

$e

Modify Query
Mail everyone on this page ($pCount people)
Show commands which could be used to back out these changes "; if (defined $::FORM{'generateBackoutCVSCommands'}) { print "Content-type: text/plain # This page can be saved as a shell script and executed. It should be # run at the top of your CVS work area. It will update your workarea to # backout the changes selected by your query. "; foreach my $ci (@{$result}) { if ($ci->[$CI_REV] eq "") { print "echo 'Changes made to $ci->[$CI_DIR]/$ci->[$CI_FILE] need to be backed out by hand'\n"; next; } my $prev_revision = PrevRev($ci->[$CI_REV]); print "cvs update -j$ci->[$CI_REV] -j$prev_revision $ci->[$CI_DIR]/$ci->[$CI_FILE]\n"; } exit; } PutsHeader($t, "CVS Checkins", "$menu"); # # Test code to print the results # $|=1; $head_who = ''; $head_file = ''; $head_directory = ''; $head_delta = ''; $head_date = ''; if( !$show_raw ) { if( $::FORM{"sortby"} eq "Who" ){ $result = [sort { $a->[$CI_WHO] cmp $b->[$CI_WHO] || $b->[$CI_DATE] <=> $a->[$CI_DATE] } @{$result}] ; $head_who = $SORT_HEAD; } elsif( $::FORM{"sortby"} eq "File" ){ $result = [sort { $a->[$CI_FILE] cmp $b->[$CI_FILE] || $b->[$CI_DATE] <=> $a->[$CI_DATE] || $a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY] } @{$result}] ; $head_file = $SORT_HEAD; } elsif( $::FORM{"sortby"} eq "Directory" ){ $result = [sort { $a->[$CI_DIRECTORY] cmp $b->[$CI_DIRECTORY] || $a->[$CI_FILE] cmp $b->[$CI_FILE] || $b->[$CI_DATE] <=> $a->[$CI_DATE] } @{$result}] ; $head_directory = $SORT_HEAD; } elsif( $::FORM{"sortby"} eq "Change Size" ){ $result = [sort { ($b->[$CI_LINES_ADDED]- $b->[$CI_LINES_REMOVED]) <=> ($a->[$CI_LINES_ADDED]- $a->[$CI_LINES_REMOVED]) #|| $b->[$CI_DATE] <=> $a->[$CI_DATE] } @{$result}] ; $head_delta = $SORT_HEAD; } else{ $result = [sort {$b->[$CI_DATE] <=> $a->[$CI_DATE]} @{$result}] ; $head_date = $SORT_HEAD; } &print_result($result); } else { print "

";
    for $ci (@$result) {
        $ci->[$CI_LOG] = '';
        $s = join("|",@$ci);
        print "$s\n";
    }
}

#
#
#
sub print_result {
    local($result) = @_;
    local($ci,$i,$k,$j,$max, $l, $span);

    &print_head;

    $i = 20;
    $k = 0;
    $max = @{$result};

    while( $k < $max ){
        $ci = $result->[$k];
        $span = 1;
        if( ($l = $ci->[$CI_LOG]) ne '' ){
            #
            # Calculate the number of consequitive logs that are
            #  the same and nuke them
            #
            $j = $k+1;
            while( $j < $max && $result->[$j]->[$CI_LOG] eq $l ){
                $result->[$j]->[$CI_LOG] = '';
                $j++;
            }

            #
            # Make sure we don't break over a description block
            #
            $span = $j-$k;
            if( $span-1 > $i ){
                $i = $j-$k;
            }
        }

        &print_ci( $ci, $span );


        if( $i <= 0 ){
            $i = 20;
            print "\n";
        }
        else {
            $i--;
        }
        $k++;
    }

    &print_foot;
}

sub print_ci {
    local($ci, $span) = @_;
    local($sec,$minute,$hour,$mday,$mon,$year,$t);
    local($log);

    ($sec,$minute,$hour,$mday,$mon,$year) = localtime( $ci->[$CI_DATE] );
    $t = sprintf("%02d/%02d/%04d %02d:%02d",$mon+1,$mday,$year+1900,$hour,$minute);

    $log = &html_log($ci->[$CI_LOG]);
    $rev = $ci->[$CI_REV];

    print "\n";
    print "\n";
}

sub print_head {

if ($versioninfo ne "") {
    print "";
    print "";
    print "";
    print "";
    print "";
    print "(+$lines_added/$lines_removed) Lines changed.";
}

$anchor = $ENV{QUERY_STRING};
$anchor =~ s/\&sortby\=[A-Za-z\ \+]*//g;
$anchor = "\n";
print "\n";
print "\n";
}


sub print_foot {
    print "
${sm_font_tag}$t"; print "[$CI_WHO]','',event);\" >" . "$ci->[$CI_WHO]\n"; print "[$CI_DIR]','$ci->[$CI_FILE]','$ci->[$CI_REV]','$query_branch',event)\">\n"; # if( (length $ci->[$CI_FILE]) + (length $ci->[$CI_DIR]) > 30 ){ # $d = $ci->[$CI_DIR]; # if( (length $ci->[$CI_DIR]) > 30 ){ # $d =~ s/([^\n]*\/)(classes\/)/$1classes\/
  /; # # Insert a
before any directory named # # 'classes.' # } # print " $d/
  $ci->[$CI_FILE]
\n"; # } # else{ # print " $ci->[$CI_DIR]/$ci->[$CI_FILE]\n"; # } $d = "$ci->[$CI_DIR]/$ci->[$CI_FILE]"; if( $query_module eq 'allrepositories' ){ $d = "$ci->[$CI_REPOSITORY]/$d"; } $d =~ s:/:/ :g; # Insert a whitespace after any slash, so that # we'll break long names at a reasonable place. print "$d\n"; if( $rev ne '' ){ $prevrev = &PrevRev( $rev ); print "
${sm_font_tag}$rev\n"; } else { print "\ \n"; } if( !$query_branch_head ){ print "$ci->[$CI_BRANCH] \n"; } print "${sm_font_tag}$ci->[$CI_LINES_ADDED]/$ci->[$CI_LINES_REMOVED] \n"; if( $log ne '' ){ $log = MarkUpText($log); # Makes numbers into links to bugsplat. $log =~ s/\n/
/g; # Makes newlines into
's if( $span > 1 ){ print "
$log\n"; } else { print "$log\n"; } } print "
$anchor>When\n"; print "${anchor}&sortby=Who>Who\n"; print "${anchor}&sortby=File>File\n"; print "Rev\n"; $descwidth = 47; if( !$query_branch_head ){ print "Branch\n"; $descwidth -= 2; } print "${anchor}&sortby=Change+Size>+/-\n"; print "Description\n"; print "
"; print "

"; } sub html_log { local( $log ) = @_; $log =~ s/&/&/g; $log =~ s/ 7000000) { return $d; } return 0; } sub setup_script { $script_str =<<'ENDJS'; ENDJS } # # Actually do the query # sub query_to_english { my $english = 'Checkins '; if( $query_module eq 'allrepositories' ){ $english .= "to All Repositories "; } elsif( $query_module ne 'all' && @query_dirs == 0 ){ $english .= "to module $query_module "; } elsif( $::FORM{dir} ne "" ) { my $word = "directory"; if (@query_dirs > 1) { $word = "directories"; } $english .= "to $word $::FORM{dir} "; } if ($query_file ne "") { if ($english ne 'Checkins ') { $english .= "and "; } $english .= "to file $query_file "; } if( ! ($query_branch =~ /^[ ]*HEAD[ ]*$/i) ){ if($query_branch eq '' ){ $english .= "on all branches "; } else { $english .= "on branch $query_branch "; } } if( $query_who ne '' ){ $english .= "by $query_who "; } $query_date_type = $::FORM{'date'}; if( $query_date_type eq 'hours' ){ $english .="in the last $::FORM{hours} hours"; } elsif( $query_date_type eq 'day' ){ $english .="in the last day"; } elsif( $query_date_type eq 'week' ){ $english .="in the last week"; } elsif( $query_date_type eq 'month' ){ $english .="in the last month"; } elsif( $query_date_type eq 'all' ){ $english .="since the beginning of time"; } elsif( $query_date_type eq 'explicit' ){ if ( $::FORM{mindate} ne "" && $::FORM{maxdate} ne "" ) { $w1 = "between"; $w2 = "and" ; } else { $w1 = "since"; $w2 = "before"; } if( $::FORM{'mindate'} ne "" ){ $dd = &parse_date($::FORM{'mindate'}); ($sec,$minute,$hour,$mday,$mon,$year) = localtime( $dd ); $t = sprintf("%02d/%02d/%04d %02d:%02d",$mon+1,$mday,$year+1900,$hour,$minute); $english .= "$w1 $t "; } if( $::FORM{'maxdate'} ne "" ){ $dd = &parse_date($::FORM{'maxdate'}); ($sec,$minute,$hour,$mday,$mon,$year) = localtime( $dd ); $t = sprintf("%02d/%02d/%04d %02d:%02d",$mon+1,$mday,$year+1900,$hour,$minute); $english .= "$w2 $t "; } } return $english . ":"; } PutsTrailer();