From b18fdab2af18841049d061de43e37f166eba1d36 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 13 Jan 2018 17:12:29 +0000 Subject: draklive: add support for building the local repository. --- lib/MGA/DrakISO/BuildRoot.pm | 115 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) (limited to 'lib/MGA/DrakISO') 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. -- cgit v1.2.1