summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/MGA/DrakISO/BuildRoot.pm115
1 files changed, 113 insertions, 2 deletions
diff --git a/lib/MGA/DrakISO/BuildRoot.pm b/lib/MGA/DrakISO/BuildRoot.pm
index a0cc6a2..9ad155a 100644
--- a/lib/MGA/DrakISO/BuildRoot.pm
+++ b/lib/MGA/DrakISO/BuildRoot.pm
@@ -27,10 +27,13 @@ package MGA::DrakISO::BuildRoot;
use strict;
use MDK::Common;
-use Try::Tiny;
use common;
use File::Temp qw(tmpnam);
+use Try::Tiny;
+use urpm;
+use urpm::media;
+use urpm::select;
use MGA::DrakISO::LiveBuild;
use MGA::DrakISO::Loopback;
@@ -40,6 +43,8 @@ use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(install_live_system customise_live_system);
+my $local_repo_dir = '/var/local/mga_rpms/';
+
###############################################################################
# System Installation
###############################################################################
@@ -170,6 +175,9 @@ sub install_live_system {
$cmd .= "--method $remote_method" if $remote_method;
run_in_root($chroot, $arch, 'sh', '-c', "$env $cmd")
or die "ERROR: failed to install base system\n";
+
+ # Add a local repository if the user has requested it.
+ build_local_repo($build);
} catch {
$error_message = $_;
} finally {
@@ -198,6 +206,7 @@ sub write_auto_inst_cfg {
my $include_packages = $build->{system}{include_packages};
my $exclude_packages = $build->{system}{exclude_packages};
my $preferred_packages = $build->{system}{preferred_packages};
+ my $local_repo_packages = $build->{system}{local_repo_packages};
my @desktops = split(/\|/, $build->{settings}{desktop});
my $default_user = $build->{settings}{default_user};
my $post_install_nr = $build->{system}{post_install_nr};
@@ -256,7 +265,7 @@ sub write_auto_inst_cfg {
) if $include_packages;
push @text, (
" skipped_packages => [",
- (map { " '$_'," } @$exclude_packages),
+ (map { " '$_'," } (@$exclude_packages, @$local_repo_packages)),
" ],",
) if $exclude_packages;
push @text, (
@@ -352,6 +361,98 @@ sub create_initial_symlinks {
}
}
+sub build_local_repo {
+ my ($build) = @_;
+
+ my $requested_packages = $build->{system}{local_repo_packages} || [];
+ return if !@$requested_packages;
+
+ print "Building local repository\n" if $::verbose > 1;
+
+ my $root = $build->get_live_root;
+ my $arch = $build->{settings}{arch};
+
+ # We aren't going to run in the chroot, so we need to adjust the paths
+ # in the urpmi configuration.
+ my $base_repository = $build->{settings}{repository};
+ my $arch_repository = $base_repository . '/' . $arch;
+ my $i586_repository = $base_repository . '/' . 'i586';
+ run_as_root('sed', '-i', "s!/tmp/image!$arch_repository!", $root . '/etc/urpmi/urpmi.cfg');
+ run_as_root('sed', '-i', "s!/tmp/i586!$i586_repository!", $root . '/etc/urpmi/urpmi.cfg') if $arch eq 'x86_64';
+
+ # When we pass a chroot directory to urpmi, it wants a /dev/null in
+ # that root.
+ mk_dev_null($root);
+
+ # Initialise a urpm object to let us query the database.
+ my $urpm = urpm->new;
+
+ urpm::set_files($urpm, $root);
+ urpm::get_global_options($urpm);
+
+ $urpm->{info} = sub { };
+ $urpm->{log} = sub { };
+
+ urpm::media::configure($urpm, cmdline_skiplist => join(',', @{$build->{system}{exclude_packages} || []}));
+
+ print "..selecting RPMs\n" if $::verbose > 1;
+
+ # For each requested package in turn, find any dependencies that aren't
+ # already installed and add them to our hash of selected packages. Do
+ # this for each package separately, because some of the requested packages
+ # may conflict.
+ my $error;
+ my %selected;
+ foreach my $name (@$requested_packages) {
+ my (%requested, %state);
+ urpm::select::search_packages($urpm, \%requested, [ $name ], no_substring => 1);
+ if (!%requested) {
+ print "ERROR: couldn't find '$name' package in selected media\n";
+ $error = 1;
+ next;
+ }
+ urpm::select::resolve_dependencies($urpm, \%state, \%requested, auto_select => 1, no_recommends => 1);
+ my @unselected = urpm::select::unselected_packages(\%state);
+ if (@unselected) {
+ print "ERROR: couldn't add '$name' package to local repository\n";
+ print urpm::select::translate_why_unselected($urpm, \%state, @unselected);
+ $error = 1;
+ next;
+ }
+ $selected{$_} = 1 foreach keys %{$state{selected}};
+ }
+
+ print "..copying RPMs\n" if $::verbose > 1;
+
+ # Find the URLs for the selected RPMs and copy them to the appropriate
+ # media directory. Note that in the local repository there is only a
+ # single medium for each class, so we ignore the source media type.
+ # Record the classes we find so we know what hdlists we need.
+ my %classes;
+ my @selected_packages = @{$urpm->{depslist}}[keys %selected];
+ foreach my $pkg (@selected_packages) {
+ my @medium = grep { $pkg->id >= $_->{start} && $pkg->id <= $_->{end} } @{$urpm->{media}};
+ my $src_path = $medium[0]->{url} . '/' . $pkg->filename;
+ my @path_parts = split('/', $src_path);
+ my $class = $path_parts[-3];
+ my $name = $path_parts[-1];
+ my $dst_dir = $local_repo_dir . $class;
+ mkdir_in_root($root, $dst_dir) if ! -d $root . $dst_dir;
+ # TODO: support remote repositories
+ copy_to_root($root, $dst_dir, undef, $src_path);
+ $classes{$class} = 1;
+ }
+
+ print "..generating media info\n" if $::verbose > 1;
+
+ foreach my $class (keys %classes) {
+ run_in_root($root, $arch, 'genhdlist2', if_($::verbose < 2, '-q'), $local_repo_dir . $class)
+ or die "ERROR: failed to generate hdlists for '$class' local repository\n";
+ }
+
+ $error and die "ERROR: some requested packages have not been added to the local repository\n";
+}
+
###############################################################################
# System Customisation
###############################################################################
@@ -421,6 +522,16 @@ sub customise_live_system {
run_in_root($root, undef, 'urpmi.removemedia', if_($::verbose < 3, '-q'),'-a');
}
+ print "..adding local repository media\n" if $::verbose > 1;
+
+ # Add local repository media
+ foreach my $path (glob($root . $local_repo_dir . '*')) {
+ my $name = basename($path);
+ run_in_root($root, undef, 'urpmi.addmedia', if_($::verbose < 3, '-q'),
+ 'Live ' . ucfirst($name), $local_repo_dir . $name)
+ or die "ERROR: unable to add $name medium from local repository\n";
+ }
+
print "..removing unwanted packages\n" if $::verbose > 1;
# Remove any packages as requested by the user.