#!/usr/bin/perl -w
# $Id: diffstat2css,v 1.8 2016/01/17 22:22:42 tom Exp $
#
# This is based on diffstat2html - a first try.
#
# Process one or more patch files, using diffstat's -C (color) option to
# markup the files (with SGR).  We want to modify those so they all use
# reverse-video (since colored text is too hard to read), and produce html.
# To make the result a little more flexible, use the diffstat.css stylesheet.

# The script expects one of two parameter conventions:
# a) patch-file, simply process with diffstat
# b) two directories as parameters, to pass those to diffstat using -S/-D

use strict;
use Getopt::Std;
use File::Temp qw/ :mktemp  /;

our ( $opt_o, $opt_w );

sub get_diffstat($) {
    my $params = $_[0];
    my @result;
    my $n;

    $params .= " -w$opt_w" if $opt_w;
    printf "** $params\n";
    open( FP, "diffstat -C $params |" ) || do {
        print STDERR "Can't open $params: $!\n";
        return;
    };
    (@result) = <FP>;
    close(FP);

    print OUTPUT <<"EOF";
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
  <link rel="stylesheet" href="/css/simplestyle.css" type="text/css">
  <link rel="stylesheet" href="/css/diffstat.css" type="text/css">
</head>

<body>
  <p style="font-family: monospace; font-size: 10pt;">
EOF
    for $n ( 0 .. $#result ) {
        chomp $result[$n];
        $result[$n] =~ s/&/&amp;/g;
        $result[$n] =~ s/\</&lt;/g;
        $result[$n] =~ s/\>/&gt;/g;
        $result[$n] =~ s/$/<br>/;
        $result[$n] =~ s/ /&nbsp;/g;
        $result[$n] =~ s/\x1b\[31m/\<font class="deleted"\>/g;
        $result[$n] =~ s/\x1b\[32m/\<font class="added"\>/g;
        $result[$n] =~ s/\x1b\[34m/\<font class="unchanged"\>/g;
        $result[$n] =~ s/\x1b\[36m/\<font class="modified"\>/g;
        $result[$n] =~ s/\x1b\[0;39m/\<\/font\>/g;
        printf OUTPUT "%s\n", $result[$n];
    }
    print OUTPUT <<EOF;
</p>
</body>
</html>
EOF
    return @result;
}

sub is_file($) {
    my $name = $_[0];
    die "not a file: $name" if !-f $name;
    return $name;
}

sub is_dir($) {
    my $name = $_[0];
    die "not a file: $name" if !-d $name;
    return $name;
}

sub do_file($) {
    my $filename = &is_file( $_[0] );
    my @input    = &get_diffstat($filename);
}

sub do_dirs($$) {
    my $src = &is_dir( $_[0] );
    my $dst = &is_dir( $_[1] );

    my $mktmp;
    my $patch = $dst . ".patch";
    $patch .= ".gz" if !-f $patch;
    if ( !-f $patch ) {

        # make the patch on the fly, in a temporary file
        my $template = "diffstatXXXXXXXXX";
        $mktmp = mktemp($template);
        $patch = $mktmp;
        system("diff -Nru \"$src\" \"$dst\" >$patch");
    }

    # FIXME what level should I use for -p option?
    my @input = &get_diffstat("-p1 -S $src -D $dst $patch");
    printf "** %s %s\n", $src, $dst;

    unlink $mktmp if ($mktmp);
}

sub main::HELP_MESSAGE() {
    printf STDERR <<EOF
Usage: $0 [options] [patch-file]
Usage: $0 [options] [dir1] [dir2]

Options:

-o FILE  redirect output to FILE
-w WIDTH passed to diffstat
EOF
      ;
    exit;
}

&getopts('o:w:') || main::HELP_MESSAGE;

if ($opt_o) {
    open( OUTPUT, ">$opt_o" ) || die "cannot open $opt_o: $!";
}
else {
    *OUTPUT = *STDOUT;
}

if ( $#ARGV == 0 ) {
    &do_file( $ARGV[0] );
}
elsif ( $#ARGV == 1 ) {
    &do_dirs( $ARGV[0], $ARGV[1] );
}
else {
    die "No patch file specified";
}
