File svn_wdiff.pl of Package jw-env

#! /usr/bin/perl -w
#
# svn_wdiff.pl -- a wrapper for svn diff for wdiff.
# this is needed, as wdiff cannot accept -L options.
#
# this also parses -rHEAD-1 syntax:
# - lookup the absolute revision number via svn log.
# 
# 2009-07-29, V0.3, jw, 	added -v for debugging'
# 2009-07-29, V0.4, jw, 	changed -N to do bold/underline, 
#                               added -P for NO_ANSI at all.
#
# TODO: print line numbers above context snippets. 
# This needs a wdiff extension.
# TODO: investigate into pdiff, which comes with a2ps

use strict;
use Data::Dumper;

my $version = '0.4';

my $gn = "\033[1;42m";		# bold black on green background
my $rt = "\033[1;41m";		# bold black on red background
my $no = "\033[m";

if ($ENV{NO_COLOR})
  {
    $gn = "\033[1m";		# bold
    $rt = "\033[4m";		# underline
  }
$gn = $rt = $no = '' if $ENV{NO_ANSI};

push @ARGV, '--help' unless @ARGV;
my $verbose = $ENV{SVN_WDIFF_VERBOSE} || 0;

my @wdiff = (
  "/usr/bin/wdiff",
  "--start-delete=\n[-${rt}", 
  "--end-delete=${no}-]",
  "--start-insert=\n{+${gn}",
  "--end-insert=${no}+}"
);
my @svn_diff = ('svn', 'diff', '--diff-cmd', $0);
my $svn_log = "svn log";
my $svn_status = "svn status";

my $opt_L_seen = 0;	# when called from svn diff

unless (-x $wdiff[0])
  {
    my $cmd = $wdiff[0]; $cmd =~ s{.*/}{};

    die "$wdiff[0] not found. Try sudo zypper in $cmd\n";
  }

my @ARGS;
my $rev;

while (my $a = shift)
  {
    if ($a eq '-L')
      {
        shift;
	$opt_L_seen++;
      }
    elsif ($a eq '-u')
      {
        push @ARGS, '-c', '3';
      }
    elsif ($a eq '-v')
      {
        $ENV{SVN_WDIFF_VERBOSE} = 1;
        $verbose++;
      }
    elsif ($a eq '-N')
      {
        $ENV{NO_COLOR} = 1;
      }
    elsif ($a eq '-P')
      {
        $ENV{NO_ANSI} = 1;
      }
    elsif ($a =~ m{^-r(\S*)})
      {
        $rev = $1; $rev = shift unless length $rev;
	push @ARGS, '-r', $rev;
      }
    elsif ($a eq '--help')
      {
        print qq{
$0 Version $version Usage:

svn_wdiff FILENAME
	show local modifications, if any, otherwise show changes from the
	latest revision.  removed text is shown in red inside [- ... -]
	markers, and inserted text is shown in green inside {+ ... +} markers.

svn_wdiff -r revision FILENAME
	show changes since the specified revision. In addition to the syntax FILENAME
	supported by svn ('HEAD', 'PREV', 'BASE', '{2009-07-15}', NNNN) we
	support negative numbers.  Negative numbers count file specific
	revisons backwards from the current version.  E.g. 'svn_wdiff -r -1 FILENAME' 
	is identical to 'svn_wdiff FILENAME' on an unmodified checkout.

svn_wdiff -N ...
env NO_COLOR=1 svn_wdiff ...
	use no red/green colors, but underline/bold face to highlight the diffs.

svn_wdiff -P ...
env NO_ANSI=1 svn_wdiff ...
	use no colors or terminal control codes at all. Just show the the markers.
	
};
	exit;
      }
    else
      {
        push @ARGS, $a;
      }
  }

$rev = '' if $opt_L_seen;	# second pass, wdiff options now. rev belongs to first pass, svn options.

if (!$rev && !$opt_L_seen)
  {
    unless (qx{$svn_status $ARGS[-1]})
      {
        $rev = '-1';
	splice @ARGS, -1, 1, '-r', $rev, $ARGS[-1];
      }
    print "local changes:\n" if !$rev;
  }


if ($rev and $rev =~ m{^(HEAD)?[-^](\d+)$})
  {
    my $back = $2+1;
    my @log = qx{$svn_log -l $back $ARGS[-1]};
    my @users;
    my $line;
    for my $i (1..$#log)
      {
        if ($log[$i-1] =~ m{^----------------------------*$} and 
	    $log[$i]   =~ m{^r(\d+)\s+\|\s+(\w+)\s+\|\s+\d\d\d\d-})
	  {
	    $rev = $1;
	    push @users, "$1:$2" if $line;
	    print "$log[$i]" unless $line;	# show first log line
	    $line = $log[$i];
	  }
      }
    if ($line)
      {
        pop @users;			# last one is shown in $line;
	print "\t(@users)\n" if @users;
	print "$line";			# and last log line
	$ARGS[-2] = $rev;
      }
  }

@wdiff = @svn_diff unless $opt_L_seen;
push @wdiff, @ARGS;	# after parsing.
print "$wdiff[0] .... @ARGS\n" if $verbose;

exec { $wdiff[0] } @wdiff;
openSUSE Build Service is sponsored by