#!/usr/bin/perl -w # -*- perl -*- use P4CGI ; use strict ; use CGI::Carp ; # ################################################################# # CONFIGURATION INFORMATION # All config info should be in P4CGI.pm # ################################################################# # # P4 file log viewer # ################################################################# sub offsetOf($@ ) { my $v = shift @_ ; my $pos = 0 ; while(@_ > 0) { if($v eq (shift @_)) { return $pos ; } $pos++ ; } return -1 ; } my $err2null = &P4CGI::REDIRECT_ERROR_TO_NULL_DEVICE() ; my $err2stdout = &P4CGI::REDIRECT_ERROR_TO_STDOUT() ; local *P ; # File argument my $file = P4CGI::cgi()->param("FSPC") ; &P4CGI::bail("No file spec") unless defined $file ; # Label x-reference argument my $listLabel = P4CGI::cgi()->param("LISTLAB") ; $listLabel = "No" unless defined $listLabel ; # Show branch info argument my $showBranch = P4CGI::cgi()->param("SHOWBRANCH") ; $showBranch="No" unless defined $showBranch ; # Get file data my @filelog ; &P4CGI::p4call(\@filelog,"filelog \"$file\"") ; &P4CGI::bail("No data for file \"$file\"") if @filelog == 0 ; # Get info about opened status &P4CGI::p4call(*P,"opened -a \"$file\" $err2null") ; my %opened ; my $openedText = "" ; while(
) {
$openedText = "Opened by" ;
chomp ;
/\w+\#(\d+) - .* by (\w+)\@(\S+)/ or
&P4CGI::bail("Can not read info from \"p4 opened\"") ;
my $user = &P4CGI::ahref(-url => "userView.cgi",
"USER=$2",
"$2") ;
my $client = &P4CGI::ahref(-url => "clientView.cgi",
"CLIENT=$3",
"$3") ;
if(exists $opened{$1}) {
$opened{$1} .= "
and $user\@$client" ;
} else {
$opened{$1} = "$user\@$client" ;
} ;
} ;
close *P ;
# Get list of labels (if $listLabel is set)
my @labels ;
if($listLabel eq "Yes") {
&P4CGI::p4call(*P,"labels") ;
while(
) {
/^Label (\S+)/ and do { push @labels,$1 ; } ;
}
close P ;
}
# Create hash containing labels by file name and
# version
my %fileToLabels ;
if(@labels > 0) {
# Try to speed things up by looking up
# file view for each label and removing all
# labels that don't match
# This is an act of desperation because in our
# p4 depot the label search takes forever (well..
# a long time, 20 secs or so...)
if(1) {
my $l ;
my @l ;
LABEL: foreach $l (@labels) {
my %data ;
&P4CGI::p4readform("label -o \"$l\"",\%data) ;
if(exists $data{"View"}) {
my @v = split("\n",$data{"View"}) ;
foreach (@v) {
# p4-to-perl regexp conversion
my $in = $_ ;
my $re = "" ;
while($in =~ s/(.*?)(\Q...\E|\Q*\E)//) {
$re .= "\Q$1\E" ;
if($2 eq "...") { $re .= ".*" ; }
else { $re .= "[^/]*" ; }
}
$re .= "\Q$in\E" ;
if($file =~ /$re/) {
push @l,$l ;
next LABEL ;
}
}
}
}
my $lb = @labels ;
my $la = @l ;
&P4CGI::ERRLOG("reduced from $lb to $la labels") ; # DEBUG
@labels = @l ;
}
#
$lab" ;
}
else {
$fileToLabels{$1} = "$lab" ;
}
}
} ;
my @legendList ;
push @legendList,
"Revision Number -- see the file text",
"Action -- see the deltas (diffs)",
"User -- see info about user",
"Change -- see the complete change description, including other files",
&P4CGI::ahref("-url","changeList.cgi",
"FSPC=$file",
"Changes") . "-- see list of all changes for this file" ;
my @parsListLab ;
my @parsShowBranch ;
my $p ;
foreach $p (&P4CGI::cgi()->param()) {
push @parsListLab, "$p=" . &P4CGI::cgi()->param($p) unless $p eq "LISTLAB" ;
push @parsShowBranch, "$p=" . &P4CGI::cgi()->param($p) unless $p eq "SHOWBRANCH" ;
}
if($listLabel ne "Yes") {
push @legendList,
&P4CGI::ahref(@parsListLab,
"LISTLAB=Yes",
"List labels") . "-- list cross ref. for labels" ;
} ;
if($showBranch ne "No") {
push @legendList,
&P4CGI::ahref(@parsShowBranch,
"SHOWBRANCH=No",
"Hide branch info") . "-- hide info about branches, merges and copy of file" ;
}
else {
push @legendList,
&P4CGI::ahref(@parsShowBranch,
"SHOWBRANCH=Yes",
"Show branch info") . "-- show info about branches, merges and copy of file" ;
} ;
# Get file directory part
my $fileDir=$file ;
$fileDir =~ s#/[^/]+$## ;
push @legendList,
&P4CGI::ahref("-url","depotTreeBrowser.cgi",
"FSPC=$fileDir",
"Browse directory") .
"-- Browse depot tree at $fileDir" ;
print "",&P4CGI::start_page("File log
$file",&P4CGI::ul_list(@legendList)) ;
my $labelHead ="";
if($listLabel eq "Yes") {
$labelHead="In label(s)" ;
} ;
print
"",
&P4CGI::start_table(""),
&P4CGI::table_header("Rev/view file",
"Action/view diff",
"Date",
"User/view user",
"Change/view change",
"Type",
"Desc",
$labelHead,
$openedText) ;
my $log ;
my @revs ;
my %relatedFiles ;
my ($rev,$change,$act,$date,$user,$client,$type,$desc) ;
my $chbuffer = "" ;
while($log = shift @filelog) {
$_ = &P4CGI::fixSpecChar($log) ;
if(/^\.\.\. \#(\d+) \S+ (\d+) (\S+) on (\S+) by (\S*)@(\S*) (\S*)\s*'(.*)'/ ) {
print $chbuffer ;
$chbuffer = "" ;
($rev,$change,$act,$date,
$user,$client,$type,$desc) = ($1,$2,$3,$4,$5,$6,$7,$8) ;
$type =~ s/\((.*)\)/$1/ ;
$desc = &P4CGI::magic($desc) ;
push @revs,$rev ;
my $labels = $fileToLabels{"$file\#$rev"} ;
$labels = "" unless defined $labels ;
$labels = "$labels" ;
if ($act eq 'branch') {
$chbuffer .=
&P4CGI::table_row(-valign => "top",
&P4CGI::ahref("-url","fileViewer.cgi",
"FSPC=$file",
"REV=$rev",
"$rev"),
"$act",
"$date",
&P4CGI::ahref(-url => "userView.cgi" ,
"USER=$user",
"$user"),
&P4CGI::ahref("-url","changeView.cgi",
"CH=$change",
"$change"),
"$type",
"$desc",
$labels,
exists $opened{$rev}?$opened{$rev}:"") ;
}
elsif ($act eq 'delete') {
$chbuffer .=
&P4CGI::table_row(-valign => "top",
"$rev",
"delete",
"$date",
&P4CGI::ahref(-url => "userView.cgi" ,
"USER=$user",
"$user"),
&P4CGI::ahref("-url","changeView.cgi",
"CH=$change",
"$change"),
"$type",
"$desc",
$labels,
exists $opened{$rev}?$opened{$rev}:"") ;
}
else {
$chbuffer .=
&P4CGI::table_row(-valign => "top",
&P4CGI::ahref("-url","fileViewer.cgi",
"FSPC=$file",
"REV=$rev",
"$rev"),
&P4CGI::ahref("-url","fileDiffView.cgi",
"FSPC=$file",
"REV=$rev",
"ACT=$act",
"$act"),
"$date",
&P4CGI::ahref(-url => "userView.cgi" ,
"USER=$user",
"$user"),
&P4CGI::ahref("-url","changeView.cgi",
"CH=$change",
"$change"),
"$type",
"$desc",
$labels,
exists $opened{$rev}?$opened{$rev}:"") ;
}
}
else {
if(/^\.\.\. \.\.\. (\w+) (\w+) (\S+?)\#(\S+)/) {
my ($op,$direction,$ofile,$orev) = ($1,$2,$3,$4) ;
my $file = $ofile ;
$file =~ s/\#.*$// ;
$relatedFiles{$file} = 1 ;
if($showBranch ne "No") {
my ($b1,$b2) = ("","") ;
if($op eq "copy") {
($b1,$b2) = (" ! ","") ;
}
my $d = &P4CGI::table_row(-valign => "top",
"",
undef,
undef,
undef,
undef,
undef,
undef,
undef,
undef,
"$b1$op $direction ".
&P4CGI::ahref("-url","fileLogView.cgi",
"FSPC=$ofile",
"$ofile\#$orev"). "$b2") ;
if($direction ne "from") {
$chbuffer = "$d\n$chbuffer" ;
}
else {
print "$chbuffer\n$d\n" ;
$chbuffer = "" ;
}
}
}
}
}
print "$chbuffer\n" ;
print
"",
&P4CGI::end_table("") ;
if(@revs > 2) {
print
"