#!/usr/bin/perl 

use warnings;
use strict;
use Text::Template;
use Archive::Tar;
use File::stat;
use Getopt::Long;

my $tmpDir=$ENV{'HOME'}."/tmp";
my $srcDir=$ENV{'HOME'}."/fedora/SOURCES";
my $specDir=$ENV{'HOME'}."/fedora/SPECS";

my $line="";
my @files=();
my @defFiles=();
my @instFiles=();


Getopt::Long::Configure('bundling');

my ($on, $ov, $or, $op, $oI, $oE, $oh, $ob, $od, $oV, $oD, $oS);
GetOptions
    ("h"   => \$oh, "help"       => \$oh,
     "n=s" => \$on, "name=s"  	 => \$on,
     "b" => \$ob, "build"  	 => \$ob,
     "V" => \$oV, "verbose"  	 => \$oV,
     "v=s" => \$ov, "version=s"  => \$ov,
     "d=s" => \$od, "directory=s"=> \$od,
     "D=s" => \$oD, "description=s"=> \$oD,
     "S=s" => \$oS, "summary=s"=> \$oS,
     "r=s" => \$or, "release=s"  => \$or,
     "p=s" => \$op, "packager=s" => \$op);

print_usage() if ($oh); 
($on) || ($on = shift) || ($on = "TailTail");
($ov) || ($ov = shift) || ($ov = "0.1");
($or) || ($or = shift) || ($or = "1");
($op) || ($op = shift) || ($op = "Jean-Marie Renouard<jean-marie.renouard at alcove.fr>");
($od) || ($od = shift) || ($od = "/");
($oD) || ($oD = shift) || ($oD = "A standard description for this package ;)");
($oS) || ($oS = shift) || ($oS = "A standard summary for this package ;)");

my %lusers;
my %lgroups;

while (defined($line = <>)) {
	chop($line);
	my $mode=stat($line)->mode or die (" $line does nt exists");
	my $uid =stat($line)->uid;
	my $gid =stat($line)->gid;
	my $cmd="cat /etc/passwd | cut -d ':' -f 1,3 | grep $uid";
	my @nameu=split (':', `$cmd`);
	
	$cmd="cat /etc/group | cut -d ':' -f 1,3 | grep $gid";
	my @nameg=split (':', `$cmd`);

#	print "\n* util=".$nameu[0];
#	print "\n* group=".$nameg[0];
	$lusers{$nameu[0]}++;
	$lgroups{$nameg[0]}++;

	my $trueMode=sprintf( "%04o", $mode & 07777);
	push @files, $line;
	$line =~ s/^$od\///;
	push @instFiles, "mkdir -p `dirname %{buildroot}/$line` || 1";
	push @instFiles, "%{__install} -m $trueMode $line %{buildroot}/$line";
	push @defFiles, "%defattr(-, $nameu[0], $nameg[0], $trueMode)", "/$line";
}

my $pre_code = "echo -e 'PRE'";
foreach my $g (keys(%lgroups)) { $pre_code.="\ngroupadd $g || 1";}
foreach my $u (keys(%lusers) ) { $pre_code.="\nadduser $u || 1"; }


############################
# THE TEMPLATE
############################
my $templDef= 'Summary: 		<$summary> 
Name:			<$name>
Version: 		<$version>
Release:	   	<$release>	
License: 		GPL
URL: 			http://www.alcove.fr
Source0: 		%{name}-%{version}.tar.gz
Group: 			System/Administration
Vendor:			Alcôve
Packager:		<$packager>
Buildarch: 		i486
BuildRoot: 		%{_tmppath}/%{name}-%{version}-root

%description 
<$description>

%prep
#%setup -q -n %{name}-%{version}
%setup -c 

%pre
<$pre_code>

%build
echo -e \'BUILD\'

%install
mkdir -p %{buildroot}
< foreach $i (@instFiles) { $OUT.= "$i\n"; }>

%post
<$post_code>

%preun
<$preun_code>

%postun
<$postun_code>

%clean
rm -rf %{buildroot}

%files
< foreach $i (@listOfFiles) { $OUT.= "$i\n"; }>
 
%changelog
* <$date> <$packager> <$name>-<$version>-<$release>
- <$ChangeLog>
-  Generated version.';

	
my $template = Text::Template->new(SOURCE => "$templDef", TYPE => 'STRING', DELIMITERS => ["<", ">"])
          or die "Couldn't construct template: $Text::Template::ERROR";

	  my @monthname = qw(January February March April May June
                           July August September October November December);
	  my %vars = (name => "$on",
	      summary => "$oS",
	      version => "$ov",
	      release => "$or", 
	      packager => "$op",
	      pre_code => "$pre_code",
	      post_code => "echo -e 'POST'",
	      preun_code => "echo -e 'PREUN'",
	      postun_code => "echo -e 'POSTUN'",
	      listOfFiles =>\@defFiles,      
	      instFiles =>\@instFiles,      
	      ChangeLog	=> 'Test release at the starting point',
	      date => 'Wed May 04 2005',#`date +"%a %b %d %Y"` ,
	      description => "$oD",
);

my $result = $template->fill_in(HASH => \%vars);
die "Couldn't fill in template: $Text::Template::ERROR" unless (defined $result); 

print "#File to add : \n", join ("\nA=", @files) if ($oV);

chdir($od) if ($od);
#generate Tarball
my $tar = Archive::Tar->new;

foreach my $file (@files) {
	$file =~ s/^$od/\./;
	print "# Adding $file \n";
	$tar->add_files( $file);
}

$tar->write("$srcDir/$vars{'name'}-$vars{'version'}.tar.gz", 1);
#Writing spec file
open F, "> $specDir/$vars{'name'}-$vars{'version'}.spec";
	print F $result if (defined($result));
	print $result if (defined($result) && $oV);
close F;

#my $editor=$ENV{'EDITOR'};
#$editor="/bin/sh /usr/bin/vim" unless (defined($editor));
#`$editor $specDir/$vars{'name'}-$vars{'version'}.spec` if ($oe);

#Compiling pakage
my $cmd="rpmbuild -ba $specDir/$vars{'name'}-$vars{'version'}.spec";

print "\n#Executing to build package : $cmd\n" if ($oV);
print `$cmd` if ($ob);
exit 0;

sub print_usage {
print " Usage: myrpm.pl [OPTION]... \n";
print "myrpm.pl is a automatic spec file generator and builder.\n";
print "Allow you to install freely software on a rpm compliant system and realize a binary package\n";
print "from a list of file. This program manages rigths and users.\n";
print "It s a simple tool that simplify packaging in chroot mode.\n";

print "\nGeneral Options :";
print "\n -h, --help\t\t\t: Print this help.";
print "\n -V, --verbose\t\t\t: Print debug information, verbose mode";
print "\n -b, --build\t\t\t: Build the package automattically at the end.";
print "\n -d, --directory=<directory>\t: Root directory ( / by default )";

print "\n\nPackage Options :";
print "\n -n, --name=<name>\t\t: Package name";
print "\n -v, --version=<version>\t: Package version";
print "\n -r, --release=<release>\t: Package release";
print "\n -D, --description=<description>: Package Description";
print "\n -S, --summary=<summary>\t: Package Summary";
print "\n -p, --packager=<packager>\t: Packager identity";

print "\n\nExamples :";
print "\ncd /home/jmrenouard/myrpmBuildDir && find `pwd` -iname '*' -print | myrpm.pl -V -d /home/jmrenouard/myrpmBuildDir -n toto -b";
print "\n\t\t * Find build the list of all the files in /home/jmrenouard/myrpmBuildDir";
print "\n\t\t * myrpm.pl packages all the files /home/jmrenouard/myrpmBuildDir  in a package with toto as name.";
print "\n\t\t * myrpm.pl consider /home/jmrenouard/myrpmBuildDir as the root of all the files so all this files will be installed from the root file system by the rpm program.";

print "\n\nrpm -ql yum |  myrpm.pl -V -n yum -r 1_jmr -b";
print "\n\t\t * Rpm gives the list of the files in the yum package installed on the system.";
print "\n\t\t * myrpm.pl packages all the files in a package with yum as name and 1_jmr as release.";
print "\n\t\t * This is a new way to package modification on a installed system.";

print "\n\nSubmit bugs at Jean-Marie Renouard <jmrenouard at gmail.com>\n";      
exit;
}
