#!/usr/bin/perl -w

# Copyright (C) 2001 Anthony de Boer
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# I'm not including the usual "either version 2 of the License, or (at your
# option) any later version" text since I want to reserve the chance to
# read version 3 before using it, just to be sure it doesn't promise free
# phone support or sexual favours from the program's author.

use strict;

my %makevar;

$makevar{'BLURB'} = 'undefined';
$makevar{'COPYRIGHT'} = 'undefined';
$makevar{'GROUP'} = 'Applications/Networking';
$makevar{'RPM_BUILD_ROOT'} = '';

my $err;
my $mprev = '';
my %tab;
my %perm;
my %usr;
my %grp;
my $tsec = '';
my %rules;
my %manifest;

my $T_NEED = 1;
my $T_INST = 2;
my $T_TARG = 4;
my $T_DIR = 8;
my $T_FOUND = 16;

system 'mkdir', '-p', 'contrib/redhat-rpm';
my $makefile = (-f 'makefile') ? 'makefile' : 'Makefile';
$tab{$makefile} |= $T_NEED;
$tab{'MANIFEST'} |= $T_NEED | $T_FOUND;

open(MAKEFILE, $makefile) || die "Cannot read $makefile: $!\n";
while(<MAKEFILE>) {
	chop;
	$mprev .= $_, next if s/\s*\\\s*$/ /;
	$_ = $mprev . $_, $mprev = '' if $mprev ne '';
	s/\#.*//;
	$makevar{$1} = $2, next if /^([^\s\=]+)\s*\=\s*(.*)$/;
	s/\$\((\S+)\)/$makevar{$1}/g;
	# line is reassembled
	if (/^\s+install.*\s(\S+)\s+(\S+)\s*$/) {
		$tab{$1} |= $T_NEED;
		$tab{$2} |= $T_INST;
		}
	if (/^\s+ln\s.*\s(\S+)\s*$/) {
		$tab{$1} |= $T_INST;
		}
	if (/^\s+mkdir\s+(.*)$/) {
		for my $x (split(/\s+/, $1)) {
			$tab{$x} |= $T_DIR;
			}
		}
	if (/\schmod\s+(\S+)\s+(.*)$/) {
		my $p = $1;
		for my $x (split(/\s+/, $2)) {
			$perm{$x} = $p;
			}
		}
	if (/\schown\s+(\S+)\s+(.*)$/) {
		my $p = $1;
		my $fls = $2;
		my $g = ($p =~ s/\.(\S+)//) ? $1 : undef;
		for my $x (split(/\s+/, $fls)) {
			$usr{$x} = $p;
			$grp{$x} = $g if $g;
			}
		}
	if (/\s+chgrp\s+(\S+)\s+(.*)$/) {
		my $p = $1;
		for my $x (split(/\s+/, $2)) {
			$grp{$x} = $p;
			}
		}
	if (s/^\s+//) {
		$rules{$tsec} .= "$_\n";
		}
	else {
		s/\:/ \: /;
		s/\s+$//;
		my $fflag = $T_TARG;
		for my $target (split) {
			$fflag = $T_NEED, next if $target eq ':';
			$tab{$target} |= $fflag if $target =~ /^[^\/]+$/;
			$tsec = $target if $fflag == $T_TARG;
			}
		}
	}
close(MAKEFILE);
delete ($tab{'-p'});

$makevar{'BLURB'} =~ s/^\"(.*)\"$/$1/;
my $blurb = (-f 'BLURB') ? `cat BLURB` : $makevar{'BLURB'};

for my $x (qw/MYNAME VERSION BLURB/) {
	unless ($makevar{$x}) {
		print STDERR "$x not defined in makefile\n";
		$err = 1;
		}
	}
exit($err) if $err;

my $spec = "contrib\/redhat-rpm\/$makevar{'MYNAME'}.spec";
my $NAMEVER = "$makevar{'MYNAME'}-$makevar{'VERSION'}";
unlink($NAMEVER) if readlink($NAMEVER);

my %pdir;
for my $x (keys %tab) {
	$pdir{$1} = 1 if $x =~ /^(\/.*)\/[^\/]+$/;
	}

my $pd = '';
for my $x (sort (keys %pdir)) {
	$pd .= "mkdir -p \$RPM_BUILD_ROOT$x\n" unless $tab{$x} && $tab{$x} | $T_DIR;
	}
$pd = "mkdir -p \$RPM_BUILD_ROOT\n" if $pd eq '';

opendir(DIR, ".") || die "Cannot open current directory: $!\n";
for my $f (sort (readdir(DIR))) {
	next if $f =~ /^\./;
	$tab{$f} |= $T_FOUND;
	}
closedir(DIR);

print STDERR "Writing $spec MANIFEST $NAMEVER.tar.gz\n";

open(SPEC, ">$spec") || die "Cannot write $spec: $!\n";

print SPEC <<EOF1;
Name: $makevar{'MYNAME'}
Summary: $makevar{'BLURB'}
Version: $makevar{'VERSION'}
Release: 0
Copyright: $makevar{'COPYRIGHT'}
Group: $makevar{'GROUP'}
Source: $NAMEVER.tar.gz
BuildRoot: /tmp/$makevar{'MYNAME'}.build
EOF1

print SPEC "Requires: $makevar{'REQUIRES'}\n" if $makevar{'REQUIRES'};

print SPEC <<EOF2;

%description
$blurb

%prep
rm -rf \$RPM_BUILD_ROOT
$pd
%setup

%build
make

%install
make install

EOF2

for my $t (qw/pre post/) {
	print SPEC "%$t\n$rules{$t}\n" if $rules{$t};
	}

print SPEC <<EOF3;
%files
%defattr(-, root, root)
EOF3

if ($makevar{'DOC'}) {
	print SPEC "%doc $makevar{'DOC'}\n";
	for my $f (split(/\s+/, $makevar{'DOC'})) {
		$tab{$f} |= $T_NEED;
		}
	}

for my $f (qw/contrib contrib\/redhat-rpm MANIFEST/) {
	$tab{$f} = $T_FOUND | $T_NEED;
	}

$tab{$makefile} = $T_FOUND | $T_NEED;
$tab{$spec} = $T_FOUND | $T_NEED;

my $fl = '';
my $excess = '';
for my $x (sort (keys %tab)) {
	my $tp = $tab{$x};
	if ($tp & $T_FOUND) {
		if ($tp & $T_NEED) {
			if ($tp & $T_TARG) {
				# ignore - make clean should clean
				}
			else {
				$manifest{$x} = 1;
				}
			}
		else {
			$excess .= " $x" unless $x eq 'RCS' || $x eq "$NAMEVER.tar.gz";
			}
		}
	if ($tp & $T_DIR && $x =~ /^\//) {
		print SPEC "%dir $x\n";
		next;
		}
	elsif ($tp & $T_INST) {
		my $p = $perm{$x} || '-';
		my $o = $usr{$x} || '-';
		my $g = $grp{$x} || '-';
		my $a = "%attr($p,$o,$g)";
		$a = '' if $a eq '%attr(-,-,-)';
		my $s = ($x =~ /\/man\/man\d\//) ? '.gz' : '';
		$fl .= "$a$x$s\n";
		}
	}
print SPEC $fl;
close(SPEC) || die "Failed writing $spec: $!\n";

open(MAN, ">MANIFEST") || die "Cannot write MANIFEST: $!\n";
print MAN join("\n", sort(keys %manifest)), "\n";
close(MAN) || die "Failed writing MANIFEST: $!\n";

print STDERR "Excess files:$excess\n" if $excess;

symlink('.', $NAMEVER) || die "Cannot symlink . to $NAMEVER: $!\n";

delete ($manifest{'contrib/redhat-rpm'});
delete ($manifest{$spec});
open(TAR, "|tar czfT $NAMEVER.tar.gz -") || die "Cannot pipe tar: $!\n";
for my $f (sort(keys %manifest)) {
	print TAR "$NAMEVER\/$f\n";
	}
close(TAR) || die "Failed writing to tar: $!\n";
unlink($NAMEVER);
print STDERR "done.\n";
