#!/usr/bin/perl -w
#
# rpmbootstrap application, a debootstrap like for RPM distros
#
# $Id$
#
# Copyright B. Cornec 2010
# Provided under the GPL v2

# Syntax: see at end

use strict 'vars';
use Getopt::Long qw(:config auto_abbrev no_ignore_case);
use Data::Dumper;
use English;
use LWP::UserAgent;
#use File::Basename;
#use File::Copy;
use ProjectBuilder::Version;
use ProjectBuilder::Base;
use ProjectBuilder::Env;
use ProjectBuilder::Conf;
use ProjectBuilder::Distribution;

# Global variables
my %opts;					# CLI Options

=pod

=head1 NAME

rpmbootstrap - creates a chrooted RPM based distribution a la debootstrap, aka Virtual Environment (VE)

=head1 DESCRIPTION

rpmboostrap creates a chroot environment (Virtual Environment or VE) with a minimal distribution in it,
suited for building packages for example. It's very much like debootstrap but for RPM based distribution. 
It aims at supporting all distributions supported by project-builder;org (RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...)

It is inspired by work done by Steve Kemp for rinse (http://www.steve.org.uk/), and similar to mock, but fully integrated with project-builder.org (which also supports rinse and mock).

=head1 SYNOPSIS

rpmbootstrap [-vhmqpdk][-s script][-i iso] distribution-version-arch [target-dir] [mirror [script]]

pb [--verbose][--help][--man][--quiet][--print-rpms][--download-only][--keep][--include pkg1, pkg2, ...][--script script][--iso iso] distribution-version-arch [target-dir] [mirror [script]]

=head1 OPTIONS

=over 4

=item B<-v|--verbose>

Print a brief help message and exits.

=item B<-h|--help>

Print a brief help message and exits.

=item B<--man>

Prints the manual page and exits.

=item B<-q|--quiet>

Do not print any output.

=item B<-p|--print-rpms>

Print the packages to be installed, and exit. Note that a target directory must be specified so
rpmbootstrap can determine which packages should be installed, and to resolve dependencies. The target directory will be deleted.

=item B<-d|--download-only>

Download packages, but don't perform installation.

=item B<-k|--keep>

Keep packages in the cache dir for later reuse. By default remove them.

=item B<-s|--script script>

Name of the script you want to execute on the related VEs after the installation.

=item B<-i|--iso iso_image>

Name of the ISO image of the distribution you want to install on the related VE.

=back 

=head1 ARGUMENTS

=item B<distribution-version-arch>

Full name of the distribution that needs to be installed in the VE. E.g. fedora-11-x86_64.

=item B<target-dir>

This is the target directory under which the VE will be created. Created on the fly if needed. If none is given use the default directory hosting VE for project-builder.org (Cf: vepath parameter in $HOME/.pbrc)

=head1 EXAMPLE

To setup a Fedora 12 distribution with an i386 architecture issue:

rpmbootstrap fedora-12-i386 /tmp/fedora/12/i386


=head1 WEB SITES

The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.

=head1 USER MAILING LIST

Cf: L<http://www.mondorescue.org/sympa/info/pb-announce> for announces and L<http://www.mondorescue.org/sympa/info/pb-devel> for the development of the pb project.

=head1 CONFIGURATION FILE

Uses Project-Builder.org configuration file (/etc/pb/pb.conf or /usr/local/etc/pb/pb.conf)

=head1 AUTHORS

The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.

=head1 COPYRIGHT

Project-Builder.org is distributed under the GPL v2.0 license
described in the file C<COPYING> included with the distribution.

=cut

# ---------------------------------------------------------------------------

my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
my $appname = "rpmbootstrap";

# Initialize the syntax string

pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n");

GetOptions("help|?|h" => \$opts{'h'}, 
		"man|m" => \$opts{'man'},
		"verbose|v+" => \$opts{'v'},
		"quiet|q" => \$opts{'q'},
		"log-files|l=s" => \$opts{'l'},
		"script|s=s" => \$opts{'s'},
		"print-rpms|p" => \$opts{'p'},
		"download-only|d" => \$opts{'d'},
		"keep|k" => \$opts{'k'},
		"iso|i=s" => \$opts{'i'},
		"version|V=s" => \$opts{'V'},
) || pb_syntax(-1,0);

if (defined $opts{'h'}) {
	pb_syntax(0,1);
}
if (defined $opts{'man'}) {
	pb_syntax(0,2);
}
if (defined $opts{'v'}) {
	$pbdebug = $opts{'v'};
}
if (defined $opts{'q'}) {
	$pbdebug=-1;
}
if (defined $opts{'S'}) {
	$pbsnap=1;
}
if (defined $opts{'l'}) {
	open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
	$pbLOG = \*pbLOG;
	$pbdebug = 0  if ($pbdebug == -1);
	}
pb_log_init($pbdebug, $pbLOG);
pb_display_init("text","");

if (defined $opts{'s'}) {
	$pbscript = $opts{'s'};
}
if (defined $opts{'i'}) {
	$iso = $opts{'i'};
}

# Get VE name
$ENV{'PBV'} = shift @ARGV;
die pb_syntax(-1,1) if (not defined $ENV{'PBV'});

die "Needs to be run as root" if ($EFFECTIVE_USER_ID != 0);

#
# Initialize distribution info from pb conf file
#
my ($name,$ver,$darch) = split(/-/,$ENV{'PBV'});
chomp($darch);
my ($ddir, $dver, $dfam, $dtype, $pbsuf, $dsuf, $dupd) = pb_distro_init($name,$ver,$darch);

#
# Check for command requirements
#
my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
pb_check_requirements($req->{$appname},$opt->{$appname});

#
# Check target dir
# Create if not existent and use default if none given
#
pb_env_init_pbrc(); # to get content of HOME/.pbrc
my $vepath = shift @ARGV;

if (not defined $vepath) {
	my ($vestdpath) = pb_conf_get_if("vepath");
	$vepath = "$vestdpath->{'default'}/$ddir/$dver/$darch";
}

die pb_log(0,"No target-dir specified and no default vepath found in $ENV{'PBETC'}\n" if (not defined $vepath);

pb_mkdir_p($vepath) if (! -d $vepath);

#
# Get the package list to download, store them in a cache directory
#
my ($rbsmindep,$rbsmirrorsrv) = pb_conf_get("rbsmindep","rbsmirrorsrv");
my ($rbscachedir) = pb_conf_get_if("rbscachedir");
my $pkgs = pb_distro_get_param($ddir,$dver,$darch,$rbsmindep);
my $mirror = pb_distro_get_param($ddir,$dver,$darch,$rbsmirrorsrv);

my $cachedir = "/var/cache/rpmbootstrap";
$cachedir = $rbscachedir->{'default'} if (defined $rbscachedir->{'default'});

# Point to the right subdir and create it if needed
$cachedir .= "/$ddir-$dver-$darch";
pb_mkdir_p($cachedir) if (! -d $cachedir);

# Get the complete package name from the mirror
#
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;

my $response = $ua->get($mirror);
if (! $response->is_success) {
	die "Unable to download packages from $mirror for $ddir-$dver-$darch";
}
pb_log(3,"Mirror $mirror gave answer: $response->dump(maxlength => 0)\n");

# Just print packages names if asked so. 
if ($opt{'p'}) {
	pb_log(0,"Should process package list: $pkgs\n") 
	exit(0);
}

# For each package to process, get it, put it in the cache dir 
# and extract it in the target dir. If not asked to keep, remove it
# Just download if asked so. 

foreach $p (split(/,/,$pkgs)) {
	pb_log(1,"Processing package $p ...\n") 
	}
