#!/usr/bin/perl -w # -*- perl -*- use P4CGI ; use strict ; # ################################################################# # CONFIGURATION INFORMATION # All config info should be in P4CGI.pm # ################################################################# # # P4 file diff viewer # View diff between two files or two revisions # ################################################################# # Get file spec argument my @files = split / /,P4CGI::cgi()->param("FSPC") ; &P4CGI::bail("No file specified") unless @files > 0 ; my @revs = split / /,P4CGI::cgi()->param("REV") ; $files[0] =~ s/^([^\#]+)\#(\d+)/$1/ and do { $revs[0] = $2 ; } ; &P4CGI::bail("No revision specified") unless @revs > 0 ; my @modes = split / /,P4CGI::cgi()->param("ACT") ; &P4CGI::bail("No mode specified") unless @modes > 0 ; my @files2 = split / /,P4CGI::cgi()->param("FSPC2") ; my @revs2 = split / /,P4CGI::cgi()->param("REV2") ; if(defined $files2[0]) { $files2[0] =~ s/^([^\#]+)\#(\d+)/$1/ and do { $revs2[0] = $2 ; } ; } ; my $change = P4CGI::cgi()->param("CH") ; my $n ; for($n = 0; $n < @files ; $n++) { $files2[$n] = $files[$n] unless defined $files2[$n] ; $revs2[$n] = $revs[$n]-1 unless defined $revs2[$n] ; } if((@files != @revs) || (@files != @files2) || (@files != @revs2)) { &P4CGI::bail("Argument counts not correct") ; } ; my $title ; if(@files == 1) { if($files[0] eq $files2[0]) { if($revs[0] < $revs2[0]) { my $r = $revs2[0] ; $revs2[0] = $revs[0] ; $revs[0] = $r ; } $title = "Diff<br><code>$files[0]</code><br>\#$revs2[0] -> \#$revs[0] " ; } else { $title = "Diff between<br><code>$files[0]\#$revs[0]</code><br>and<br><code>$files2[0]\#$revs2[0]" ; } } else { $title = "Diffs for change $change" ; } print "", &P4CGI::start_page($title,"") ; # Constants for the file diff display my $MAXCONTEXT = 30; my $NCONTEXT = 10; while(@files>0) { my $f1start= "<font color=blue>" ; my $f1end="</font>" ; my $f2start = "<font color=red><strike>" ; my $f2end = "</strike></font>" ; my $file = shift @files ; my $file2 = shift @files2 ; my $rev = shift @revs ; my $rev2 = shift @revs2 ; my $mode = shift @modes ; if($file eq $file2) { if($rev < $rev2) { my $r = $rev2 ; $rev2 = $rev ; $rev = $r ; } } else { $f2start = "<font color=green>" ; $f2end = "</font>" ; } print &P4CGI::start_table("width=100% align=center bgcolor=white"), &P4CGI::table_row({-align=>"center", -text =>"<BIG>$f1start$file\#$rev$f1end<br>$f2start$file2\#$rev2$f2end</BIG>"}), &P4CGI::end_table(), "<pre>" ; local *P4 ; my $f1 = "$file#$rev"; my $f2 = "$file2#$rev2"; my $nchunk = 0; my @start ; my @dels ; my @adds ; my @lines ; if ($mode ne 'add' && $mode ne 'delete' && $mode ne 'branch') { &P4CGI::p4call(*P4, "diff2 $f2 $f1"); $_ = <P4>; while (<P4>) { my ( $dels, $adds ); /(\d+),?(\d*)([acd])(\d+),?(\d*)/; my ( $la, $lb, $op, $ra, $rb ) = ($1,$2,$3,$4,$5) ; next unless $ra; if( !$lb ) { $lb = $op ne 'a' ? $la : $la - 1; } if( !$rb ) { $rb = $op ne 'd' ? $ra : $ra - 1; } $start[ $nchunk ] = $op ne 'd' ? $ra : $ra + 1; $dels[ $nchunk ] = $dels = $lb - $la + 1; $adds[ $nchunk ] = $adds = $rb - $ra + 1; $lines[ $nchunk ] = ""; # deletes while( $dels-- ) { $_ = <P4>; s/^. //; $_ = &P4CGI::fixSpecChar($_) ; $lines[ $nchunk ] .= $_; } # separator if ($op eq 'c') { $_ = <P4>; } # adds while( $adds-- ) { $_ = <P4>; } $nchunk++; } close P4; } # Now walk through the diff chunks, reading the current rev and # displaying it as necessary. my $curlin = 1; &P4CGI::p4call(*P4, "print -q $f1"); my $n ; for( $n = 0; $n < $nchunk; $n++ ) { # print up to this chunk. &catchup( *P4, $start[ $n ] - $curlin ); # display deleted lines -- we saved these from the diff if( $dels[ $n ] ) { print "$f2start"; print $lines[ $n ]; print "$f2end"; } # display added lines -- these are in the file stream. if( $adds[ $n ] ) { print "$f1start"; &display( *P4, $adds[ $n ] ); print "$f1end"; } $curlin = $start[ $n ] + $adds[ $n ]; } &catchup( *P4, 999999999 ); close P4; print "</pre>" ; } print &P4CGI::end_page() ; # Support for processing diff chunks. # # skip: skip lines in source file # display: display lines in source file, handling funny chars # catchup: display & skip as necessary # sub skip { my ( $handle, $to ) = @_; while( $to > 0 && ( $_ = <$handle> ) ) { $to--; } return $to; } sub display { my ( $handle, $to ) = @_; while( $to-- > 0 && ( $_ = <$handle> ) ) { $_ = &P4CGI::fixSpecChar($_) ; print $_; } } sub catchup { my ( $handle, $to ) = @_; if( $to > $MAXCONTEXT ) { my $skipped = $to - $NCONTEXT * 2; &display( $handle, $NCONTEXT ); $skipped -= &skip( $handle, $skipped ); print "<hr><center><strong>", "$skipped lines skipped", "</strong></center><hr>\n" if( $skipped ); &display( $handle, $NCONTEXT ); } else { &display; } } # # That's it folks #
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 2778 | Jay Han | creating guest branch per tutorial http://public.perforce.com/public/tutorial.html | ||
//guest/perforce_software/utils/p4db/P4DB_0/fdv.cgi | |||||
#1 | 1885 | rmg |
For posterity: Make the old version appear in a "P4DB_0" subdirectory. (I'd have called it 0.99, but I'm not sure it really *is* 0.99!) |
||
//guest/perforce_software/utils/p4db/fdv.cgi | |||||
#1 | 11 | Perforce maintenance | Add Fredric Fredricson's depot browser, P4DB. |