#!/usr/bin/perl -w
# -*- perl -*-
use P4CGI ;
use strict ;
#
#################################################################
#  CONFIGURATION INFORMATION 
#  All config info should be in P4CGI.pm
#
#################################################################
#
#  P4 label diff viewer
#  View diff between two labels
#
#################################################################

# Define variables set by command arguments
my $label1 ; # Labels to diff
my $label2 ;
my $showSame ; # defined if files that are the same in both labels
	       # should be listed
my $showNotSame ; # defined if files that are not the same in botha labels
                  # should be listed
my $showDiff ; # defined if files that exists only in one of the labels
               # shold be displayed

# Get arguments
$label1 = P4CGI::cgi()->param("LABEL1") ;
&P4CGI::bail("No label first specified") unless defined $label1 ;

$label2 = P4CGI::cgi()->param("LABEL2") ;
&P4CGI::bail("No label second specified") unless defined $label2 ;

$showSame = P4CGI::cgi()->param("SHOWSAME") ;
undef $showSame if $showSame ne "Y" ;

$showNotSame = P4CGI::cgi()->param("SHOWNOTSAME") ;
undef $showNotSame if $showNotSame ne "Y" ;

$showDiff = P4CGI::cgi()->param("SHOWDIFF") ;
undef $showDiff if $showDiff ne "Y" ;

#
# Start page
#
print 
    "",
    &P4CGI::start_page("Diff between label<br> $label1 and $label2","") ;

# Define a typeglob for use as file handle
local *P4 ;

#
# Get basic data for labels
#
my ($date1,$time1,$owner1,$desc1,$opt1,$view1,@view1) = &getLabelData($label1) ;
my ($date2,$time2,$owner2,$desc2,$opt2,$view2,@view2) = &getLabelData($label2) ;

#
# Print basic label data
#
print "",			# Start table
    &P4CGI::start_table(""),
    &P4CGI::table_row(-type => "th",
		      -bgcolor=>"white",
		      "",$label1,$label2),
    &P4CGI::table_row({-align   => "right",
		       -text    => "<b>Date:</b>"},
		      {-bgcolor => "white",
		       -text    => "$time1 $date1"},
		      {-bgcolor => "white",
		       -text    => "$time2 $date2"});    
if($owner1 eq $owner2) {
    print "",
    &P4CGI::table_row({-align => "right",
		       -text  => "<b>Owner:</b>"},
		      undef,
		       {-bgcolor => "white",
			-align => "center",
		       -text    =>$owner2});    
}
else {
    print "",
    &P4CGI::table_row({-align => "right",
		       -text  => "<b>Owner:</b>"},
		      {-bgcolor => "white",
		       -text    =>$owner1},
		      {-bgcolor => "white",
		       -text    =>$owner2});    
}

if($desc1 eq $desc2) {
    print "",
    &P4CGI::table_row({-align=>"right",
		       -valign=>"top",
		       -text=>"<b>Description</b>"},
		      undef,
		      {-bgcolor => "white",
		       -text    =>$desc2});    
}
else {
    print "",
    &P4CGI::table_row({-align=>"right",
		       -valign=>"top",
		       -text=>"<b>Description</b>"},
		      {-bgcolor => "white",
		       -text    =>$desc1},
		      {-bgcolor => "white",
		       -text    =>$desc2});    
}

if(( $opt1 ne "") or
   ( $opt2 ne "")) {
    if($opt1 eq $opt2) {
	print "", 
	&P4CGI::table_row({-align => "right",
			   -text  => "<b>Options:</b>"},
			  undef,			  
			  {-bgcolor => "white",
			   -text    =>$opt2});    
    }
    else {
	print "", 
	&P4CGI::table_row({-align => "right",
			   -text => "<b>Options:</b>"},
			  {-bgcolor => "white",
			   -text    =>$opt1},
			  {-bgcolor => "white",
			   -text    =>$opt2});    
    }
} ;
if($view1 eq $view2) {
    print "",
    &P4CGI::table_row({-align => "right",
		       -valign=>"top",
		       -text  => "<b>View:</b>"},
		      undef,
		      {-bgcolor => "white",
		       -text    =>$view2});    
}
else {
    print "",
    &P4CGI::table_row({-align => "right",
		       -valign=>"top",
		       -text  => "<b>View:</b>"},
		      {-bgcolor => "white",
		       -text    =>$view1},
		      {-bgcolor => "white",
		       -text    =>$view2});  
}  
print "",
    &P4CGI::end_table(),
    "<hr>";
    
#
# Get files for labels
#
my (@lfiles1,@lfiles2);
my %files1 ;
my $v ;
my @tmp1 ;
foreach $v (@view1) {
    &P4CGI::p4call(*P4, "files $v\@$label1" );
    while(<P4>) {
	push @tmp1,$_ ;
	$_ =~ s/\#(\d+).*// ;  ;
	$files1{$_} = $1  ;
    }
    close P4 ;
} ;
@lfiles1 = sort @tmp1 ;

my @tmp2 ;
my $commonFound=0 ;
my $commonAndSameRev=0 ;
foreach $v (@view2) {
    &P4CGI::p4call(*P4, "files $v\@$label2" );
    while(<P4>) {
	push @tmp2,$_ ;
	$_ =~ s/\#(\d+).*// ;  
	my $otherRev = $files1{$_} ;
	if(defined $otherRev) {
	    $commonFound++ ;
	    $commonAndSameRev++ if ($otherRev == $1) ;
	}
    }
    close P4 ;
} ;
@lfiles2 = sort @tmp2 ;

my ($nfiles1,$nfiles2) ;
$nfiles1 = @lfiles1 ;
$nfiles2 = @lfiles2 ;
    
my $fileslisted = "Yes" ;
print
    "Label \"$label1\" has $nfiles1 files<br>", 
    "Label \"$label2\" has $nfiles2 files<br>",
    "Label \"$label1\" and \"$label2\" has $commonFound file",
    $commonFound==1?"":"s",
    " in common ($commonAndSameRev with same revision)<br>";
if($commonFound == 0) {
    print 
	"<FONT SIZE=+2 COLOR=red>",
	"The two labels has no files in common, comparsion aborted.</FONT>" ;
}
else {
    if(defined $showSame and defined $showNotSame and defined $showDiff) {
	print "<B>Files:</B><br>\n" ;
    }
    elsif(!defined $showSame and !defined $showNotSame and !defined $showDiff) {
	print "No files listed!<br>\n" ;
	$fileslisted = undef ;
    }
    else {
	print "<B>Listed files are:<BR>\n" ;
	defined $showSame and do { 
	    print "<LI> Files not modified\n" ; } ;
	defined $showNotSame and do { 
	    print "<LI> Modified files (different rev.)\n" ; } ;
	defined $showDiff and do {
	    print "<LI> Files only in one of the labels $label1 and $label2\n" ; } ;
	print "</B>\n" ;
    } ;
    
#
# Start print list of files
#
    if(defined $fileslisted) {
	print 
	    "",
	    &P4CGI::start_table("border bgcolor=white"),
	    &P4CGI::table_row("-type","th",
			      "File",undef,"$label1<br>Rev.",undef,"$label2<br>Rev.") ;
	
	my $f1 = shift @lfiles1 ;
	my $f2 = shift @lfiles2 ;
	while(defined $f1 or defined $f2) { 
	    my ($name1,$rev1,$name2,$rev2) = ("",0,"",0) ;
	    if(defined $f1) {
		$f1 =~ /^([^\#]+)\#(\d+)/ ;
		$name1 = $1 ; $rev1 = $2 ;
	    }
	    if(defined $f2) {
		$f2 =~ /^([^\#]+)\#(\d+)/ ;
		$name2 = $1 ; $rev2 = $2 ;
	    }
	    if($name1 eq $name2) {
		if((defined $showSame    and ($rev1 == $rev2)) or
		   (defined $showNotSame and ($rev1 != $rev2))) {
		    if($rev1 == $rev2) {
			print &P4CGI::table_row(&P4CGI::ahref("-url",&P4CGI::FLV_URL(),
							      "FSPC=$name1","$name1"),
						undef,undef,undef,
						{-text=>"<font color=green> $rev1 </font>",
						 -align=>"center"}) ;
		    }
		    else {
			print &P4CGI::table_row(&P4CGI::ahref("-url",&P4CGI::FLV_URL(),
							      "FSPC=$name1","$name1"),
						{-text=>"$rev1",
						 -align=>"center"},
						undef,
						{-text=>&P4CGI::ahref("-url",&P4CGI::FDV_URL(),
								      "FSPC=$name1",
								      "REV=$rev1",
								      "REV2=$rev2",
								      "ACT=edit",
								      "&lt;-&gt"),
						 -align=>"center"},
						{-text=>"$rev2",
						 -align=>"center"}) ;
		    }
		}
		if(defined $f1) { $f1 = shift @lfiles1 ;} ;
		if(defined $f2) { $f2 = shift @lfiles2 ;} ;
	    }
	    elsif (($name2 ne "") and ($name1 eq "" or $name1 gt $name2)) {
		if(defined $showDiff) {
		    print &P4CGI::table_row(&P4CGI::ahref(-url => &P4CGI::FLV_URL(),
							  "FSPC=$name2","$name2"),
					    undef,
					    {-text    => "----",
					     -align   => "center",
					     -bgcolor => "red"},
					    undef,
					    {-text  => "$rev2",
					     -align => "center"}) ;
		}
		$f2 = shift @lfiles2 if(defined $f2) ;
	    }
	    else {
		if(defined $showDiff) {
		    print &P4CGI::table_row(&P4CGI::ahref("-url",&P4CGI::FLV_URL(),
							  "FSPC=$name1","$name1"),
					    undef,
					    {-text    => "$rev1",
					     -align   => "center"},
					    undef,
					    {-text    => "----",
					     -align   => "center",
					     -bgcolor => "red"}) ;
		}
		$f1 = shift @lfiles1 if(defined $f1) ;
	    }
	}
	print
	    "",
	    &P4CGI::end_table() ;
    }
}
print &P4CGI::end_page() ;


###
### Subroutines
###

#
# Get label data. 
# Returns list containg "Mod date","mod time","owner","description","view"
#
sub getLabelData($ ) {
    my $label = shift @_ ;
    local *P4 ;
    my ($date,$time,$owner,$desc,$options,$view,@view) ;
    # Mod. date, mod. time, owner, description, view
    &P4CGI::p4call( *P4, "label -o $label" );
				# Get label, time, date, owner
    while(<P4>) {
	chop ;
	$_ = P4CGI::fixSpecChar($_) ;
	/^Label:\s+(\S+)/        && do { $label=$1 ; next ; } ;
	/^Date:\s+(\S+)\s+(\S+)/ && do { $date=$1 ; $time=$2 ;  next ; } ;
	/^Owner:\s+(\S+)/        && do { $owner=$1 ; next ; } ;
	/^Description:/          && do { last ;} ;
    } ;
				# Get description
    while(<P4>) {
	chomp ;
	s/^\s+// ;
	next if /^\s*$/ ;
	/^Options:\s*(.*)/ and do { $options = $1 ; next ; } ;
	last if /^View:/ ;
	if(defined $desc) {
	    $desc .= "<br>\n$_" ;
	}
	else {
	    $desc = $_ ;
	}
    } ;
				# Get view
    while(<P4>) {
	chomp ;
	s/^\s+// ;
	s/\s+$// ;
	next if /^\s*$/ ;	
	push @view,$_ ;
	if(defined $view) {
	    $view .= "<br>\n$_" ;
	}
	else {
	    $view = $_ ;
	}
    } ;
    close P4 ;
    return ($date,$time,$owner,"<tt>$desc</tt>",$options,"<tt>$view</tt>",@view) ;
};

#
# That's it folks
#