diff options
Diffstat (limited to 'lib/Iurt/Urpmi.pm')
-rw-r--r-- | lib/Iurt/Urpmi.pm | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/lib/Iurt/Urpmi.pm b/lib/Iurt/Urpmi.pm new file mode 100644 index 0000000..f4628ee --- /dev/null +++ b/lib/Iurt/Urpmi.pm @@ -0,0 +1,789 @@ +package Iurt::Urpmi; + +use strict; +use RPM4::Header; +use File::Basename; +use File::NCopy qw(copy); +use MDV::Distribconf::Build; +use Iurt::Chroot qw(add_local_user create_temp_chroot check_build_chroot); +use Iurt::Process qw(perform_command clean clean_process sudo); +use Iurt::Config qw(dump_cache_par get_maint get_package_prefix); +use Iurt::Util qw(plog); + + +sub new { + my ($class, %opt) = @_; + my $self = bless { + config => $opt{config}, + run => $opt{run}, + urpmi_options => $opt{urpmi_options}, + }, $class; + my $config = $self->{config}; + my $run = $self->{run}; + + if ($run->{use_system_distrib}) { + $config->{basesystem_media_root} ||= $run->{use_system_distrib}; + } elsif ($run->{chrooted_urpmi}) { + my ($host) = $run->{chrooted_urpmi}{rooted_media} =~ m,(?:file|http|ftp)://([^/]*),; + my ($_name, $_aliases, $_addrtype, $_length, @addrs) = gethostbyname($host); + + my $ip = join('.', unpack('C4', $addrs[0])); + + $ip =~ /\d+\.\d+\.\d+\.\d+/ + or die "FATAL: could not resolve $host ip address"; + + $run->{chrooted_urpmi}{rooted_media} =~ s/$host/$ip/; + $run->{chrooted_media} = $run->{chrooted_urpmi}{rooted_media} . + "/$run->{distro}/$run->{my_arch}"; + + # Now squash all slashes that don't follow colon + $run->{chrooted_media} =~ s|(?<!:)/+|/|g; + + plog('DEBUG', "installation media: $run->{chrooted_media}"); + } + $self->{urpmi_media_options} .= + " --use-distrib $config->{repository}/$run->{distro}/$run->{my_arch}"; + + $self; +} + +sub set_command { + my ($self, $chroot_tmp) = @_; + $self->{urpmi_command} = "urpmi $self->{urpmi_options} $self->{urpmi_media_options} --root $chroot_tmp"; +} + +sub set_local_media { + my ($self, $local_media) = @_; + $self->{local_media} = $local_media; +} + +sub add_to_local_media { + my ($self, $chroot_tmp, $srpm, $luser) = @_; + my $local_media = $self->{local_media}; + + system("cp $chroot_tmp/home/$luser/rpm/RPMS/*/*.rpm $local_media &>/dev/null") and plog("ERROR: could not copy rpm files from $chroot_tmp/home/$luser/rpm/RPMS/ to $local_media ($!)"); + system("cp $chroot_tmp/home/$luser/rpm/SRPMS/$srpm $local_media &>/dev/null") and plog("ERROR: could not copy $srpm from $chroot_tmp/home/$luser/rpm/SRPMS/ to $local_media ($!)"); +} + +sub urpmi_command { + my ($self, $chroot_tmp, $_luser) = @_; + my $run = $self->{run}; + my $local_media = $self->{local_media}; + + #plog(3, "urpmi_command ($chroot_tmp user $luser)"); + if ($run->{chrooted_urpmi}) { + $self->{urpmi_command} = "urpmi $self->{urpmi_options} $self->{urpmi_media_options} --root $chroot_tmp "; + +# CM: commented out +# this was causing rpm database corruption problems and the packages +# are already installed +# +# if (!install_packages($self, 'chroot', $chroot_tmp, $local_spool, {}, 'configure', "[ADMIN] installation of urpmi and sudo failed in the chroot $run->{my_arch}", { maintainer => $config->{admin}, check => 1 }, 'urpmi', 'sudo')) { +# $run->{chrooted_urpmi} = 0; +# return +# } + + # Here should be added only the needed media for the given package + # main/release -> main/release + # main/testing -> main/release main/testing + # contrib/release -> contrib/release main/release + # contrib/testing -> contrib/testing contrib/release main/testing main/release + # non-free/release ... + # This is now done with an option in iurt2 --chrooted-urpmi -m media1 media2 -- media_url + + if ($run->{chrooted_urpmi}{media}) { + foreach my $m (@{$run->{chrooted_urpmi}{media}}) { + my $m_name = $m; + $m_name =~ s,/,_,g; + if (!add_media($self, $chroot_tmp, $m_name, + "$m_name $run->{chrooted_media}/media/$m")) { + $run->{chrooted_urpmi} = 0; + return; + } + } + } else { + if (!add_media($self, $chroot_tmp, 'Main', "--distrib $run->{chrooted_media}")) { + if (!add_media($self, $chroot_tmp, 'Main', "--wget --distrib $run->{chrooted_media}")) { + $run->{chrooted_urpmi} = 0; + return; + } + } + } + + if (-d "$local_media/hdlist.cz") { + mkdir("$chroot_tmp/iurt_media/"); + opendir my $dir, $local_media; + my $next; + foreach my $f (readdir $dir) { + $f =~ /(\.rpm|^hdlist.cz)$/ or next; + if (!link "$local_media/$f", "$chroot_tmp/iurt_media") { + if (!copy "$local_media/$f", "$chroot_tmp/iurt_media") { + plog("ERROR: could not copy file $local_media/$f to $chroot_tmp/iurt_media"); + $next = 1; + last; + } + } + } + next if $next; + add_media($self, $chroot_tmp, 'iurt_group', "iurt_group file:///iurt_media") or next; + } + + $self->{urpmi_command} = "chroot $chroot_tmp urpmi $self->{urpmi_options} "; + return 1; + } else { + $self->{urpmi_command} = "urpmi $self->{urpmi_options} $self->{urpmi_media_options} --root $chroot_tmp"; + } +} + +sub check_media_added { + my ($chroot, $media) = @_; + my $medias = `sudo chroot $chroot urpmq --list-media 2>&1`; + print "MEDIA $medias ($media)\n"; + $medias =~ /$media/m; +} + +sub add_media { + my ($self, $chroot, $regexp, $media) = @_; + my $run = $self->{run}; + my $config = $self->{config}; + my $cache = $run->{cache}; + + plog("add chroot media: $run->{chrooted_media}"); + + if (!perform_command("sudo chroot $chroot urpmi.addmedia --probe-hdlist $media", + $run, $config, $cache, + mail => $config->{admin}, + timeout => 300, + freq => 1, + retry => 2, + debug_mail => $run->{debug})) { + } + if (!check_media_added($chroot, $regexp)) { + plog('ERR', "ERROR iurt could not add media into the chroot"); + return; + } + 1; +} + +sub add_packages { + my ($self, $chroot, $_user, @packages) = @_; + my $run = $self->{run}; + my $config = $self->{config}; + my $cache = $run->{cache}; + if (!perform_command("sudo $self->{urpmi_command} @packages", + $run, $config, $cache, + timeout => 300, + freq => 1, + retry => 2, + error_ok => [ 11 ], + debug_mail => $run->{debug}, + error_regexp => 'cannot be installed', + wait_regexp => { + 'is needed by' => sub { + plog("WARNING: rpm database seems corrupted, retrying"); + system("sudo chroot $chroot rm -rf /var/lib/rpm/__db* &> /dev/null"); + 1; + }, + 'database locked' => sub { + plog("WARNING: urpmi database locked, waiting..."); + sleep 30; + $self->{wait_limit}++; + if ($self->{wait_limit} > 10) { + $self->{wait_limit} = 0; + system(qq(sudo pkill -9 urpmi &>/dev/null)); + return; + } + 1; + } },)) { + plog("ERROR: could not install @packages inside $chroot"); + return 0; + } + 1; +} + +sub get_local_provides { + my ($self) = @_; + my $run = $self->{run}; + my $program_name = $run->{program_name}; + my $local_media = $self->{local_media}; + + opendir my $dir, $local_media; + plog(1, "get local provides ($local_media)"); + require URPM; + my $urpm = new URPM; + foreach my $d (readdir $dir) { + $d =~ /\.src\.rpm$/ and next; + $d =~ /\.rpm$/ or next; + my $id = $urpm->parse_rpm("$local_media/$d"); + my $pkg = $urpm->{depslist}[$id]; + plog(3, "$program_name: checking $d provides"); + foreach ($pkg->provides, $pkg->files) { + plog(3, "$program_name: adding $_ as provides of $d"); + $run->{local_provides}{$_} = $d; + } + } + 1; +} + +sub get_build_requires { + my ($self, $union_id, $luser) = @_; + my $run = $self->{run}; + my $config = $self->{config}; + my $cache = $run->{cache}; + + $run->{todo_requires} = {}; + plog("get_build_requires"); + + my ($u_id, $chroot_tmp) = create_temp_chroot($run, $config, $cache, $union_id, $run->{chroot_tmp}, $run->{chroot_tar}) or return; + add_local_user($chroot_tmp, $run, $config, $luser, $run->{uid}) or return; + $union_id = $u_id; + + my $urpm = new URPM; + foreach my $p (@{$run->{todo}}) { + my ($dir, $srpm, $s) = @$p; + recreate_srpm($self, $run, $config, $chroot_tmp, $dir, $srpm, $run->{user}) or return; + $s or next; + my $id = $urpm->parse_rpm("$dir/$srpm"); + my $pkg = $urpm->{depslist}[$id]; + foreach ($pkg->requires) { + plog(3, "adding $_ as requires of $srpm"); + $run->{todo_requires}{$_} = $srpm; + } + } + 1; +} + +sub order_packages { + my ($self, $union_id, $provides, $luser) = @_; + my $run = $self->{run}; + my @packages = @{$run->{todo}}; + my $move; + + plog(1, "order_packages"); + get_local_provides($self) or return; + if (!$run->{todo_requires}) { + get_build_requires($self, $union_id, $luser) or return; + } + my %visit; + my %status; + do { + $move = 0; + foreach my $p (@packages) { + my ($_dir, $rpm, $status) = @$p; + defined $status{$rpm} && $status{$rpm} == 0 and next; + plog("checking packages $rpm"); + foreach my $r (@{$run->{todo_requires}{$rpm}}) { + plog("checking requires $r"); + if (!$run->{local_provides}{$r}) { + if ($provides->{$r}) { + $status = 1; + } else { + $status = 0; + } + } elsif ($visit{$rpm}{$r}) { + # to evit loops + $status = 0; + } elsif ($run->{done}{$rpm} && $run->{done}{$provides->{$r}}) { + if ($run->{done}{$rpm} < $run->{done}{$provides->{$r}}) { + $move = 1; + $status = $status{$provides->{$r}} + 1; + } else { + $status = 0; + } + } elsif ($status < $status{$provides->{$r}}) { + $move = 1; + $status = $status{$provides->{$r}} + 1; + } + $visit{$rpm}{$r} = 1; + } + $status{$rpm} = $status; + $p->[2] = $status; + } + } while $move; + $run->{todo} = [ sort { $a->[2] <=> $b->[2] } @packages ]; + if ($run->{verbose}) { + foreach (@packages) { + plog("order_packages $_->[1]"); + } + } + @packages; +} + +sub wait_urpmi { + my ($self) = @_; + my $run = $self->{run}; + + plog("WARNING: urpmi database locked, waiting...") if $run->{debug}; + sleep 30; + $self->{wait_limit}++; + if ($self->{wait_limit} > 8) { + $self->{wait_limit} = 0; system(qq(sudo pkill -9 urpmi &>/dev/null)); + } +} + +sub install_packages_old { + my ($self, $local_spool, $srpm, $log, $error, @packages) = @_; + my $run = $self->{run}; + my $config = $self->{config}; + my $cache = $run->{cache}; + my $log_spool = "$local_spool/log/$srpm/"; + -d $log_spool or mkdir $log_spool; + if (!perform_command("sudo $self->{urpmi_command} @packages", + $run, $config, $cache, + # mail => $maintainer, + error => $error, + hash => "${log}_$srpm", + srpm => $srpm, + timeout => 600, + retry => 2, + debug_mail => $run->{debug}, + freq => 1, + wait_regexp => { 'database locked' => \&wait_urpmi }, + error_regexp => 'unable to access', + log => $log_spool)) { + $cache->{failure}{$srpm} = 1; + $run->{status}{$srpm} = 'binary_test_failure'; + return 0; + } + 1; +} + +sub install_packages { + my ($self, $title, $chroot_tmp, $local_spool, $pack_provide, $log, $error, $opt, @packages) = @_; + + my $maintainer = $opt->{maintainer}; + my $run = $self->{run}; + my $config = $self->{config}; + my $cache = $run->{cache}; + my $program_name = $run->{program_name}; + my $ok; + my @to_install; + + plog('DEBUG', "installing @packages"); + + if ($run->{chrooted_urpmi}) { + @to_install = map { s/$chroot_tmp//; $_ } @packages; + } else { + push @to_install, @packages; + } + + @to_install or return 1; + + (my $log_dirname = $title) =~ s/.*:(.*)\.src.rpm/$1/; + + my $log_spool = "$local_spool/log/$log_dirname/"; + + mkdir $log_spool; + + my $try_urpmi = 1; + my @rpm = grep { !/\.src\.rpm$/ } @to_install; + + return 1 if ($opt->{check} && -f "$chroot_tmp/bin/rpm" && @rpm && !system("sudo chroot $chroot_tmp rpm -q @to_install")); + + if ($try_urpmi) { + foreach my $try ( + [ '', 'using urpmi' ], + [ '', 'rebuild rpm base and retry', '_retry' ], + [ ' --allow-nodeps', 'retrying with nodeps' , '_nodeps' ], + [ ' --no-install', 'using rpm directly', '_rpm' ] + ) { + my ($opt, $msg, $suf) = @$try; + + plog('INFO', "install dependencies: $msg"); + my $unsatisfied; + + if (!perform_command( + "sudo $self->{urpmi_command} $opt @to_install", + $run, $config, $cache, + error => $error, + logname => "${log}$suf", + hash => "${log}_$title$suf", + timeout => 600, + srpm => $title, + freq => 1, + #cc => $cc, + retry => 3, + debug_mail => $run->{debug}, + error_regexp => 'cannot be installed', + wait_regexp => { + 'database locked' => \&wait_urpmi, + 'is needed by' => sub { + plog('WARN', "WARNING: rpm database seems corrupted, retrying"); + system("sudo chroot $chroot_tmp rm -rf /var/lib/rpm/__db* &> /dev/null"); + 1; + }, + }, + log => $log_spool, + callback => sub { + my ($opt, $output) = @_; + plog('DEBUG', "calling callback for $opt->{hash}"); + +# 20060614 +# it seems the is needed urpmi error is due to something else (likely a +# database corruption error). +# my @missing_deps = $output =~ /(?:(\S+) is needed by )|(?:\(due to unsatisfied ([^[ ]*)(?: (.*)|\[(.*)\])?\))/g; +# + + my @missing_deps = $output =~ /([^ \n]+) \(due to unsatisfied ([^[ \n]*)(?: ([^\n]*)|\[([^\n]*)\])?\)/g; + + # as it seems that rpm db corruption is making urpmi + # returning false problem on deps installation, try + # to compile anyway + + @missing_deps or return 1; + $unsatisfied = 1; + + while (my $missing_package = shift @missing_deps) { + my $missing_deps = shift @missing_deps; + my $version = shift @missing_deps; + my $version2 = shift @missing_deps; + $version ||= $version2 || 0; + my $p = $pack_provide->{$missing_deps} || $missing_deps; + my ($missing_package_name, $first_maint); + if ($missing_package !~ /\.src$/) { + ($first_maint, $missing_package_name) = get_maint($run, $missing_package); + plog(5, "likely $missing_package_name need to be rebuilt ($first_maint)"); + } else { + $missing_package = ''; + } + + my ($other_maint) = get_maint($run, $p); + plog('FAIL', "missing dep: $missing_deps ($other_maint) missing_package $missing_package ($first_maint)"); + $run->{status}{$title} = 'missing_dep'; + foreach my $m ($first_maint, $other_maint) { # FIXME: (tv) this loop is useless !!! + if ($other_maint && $other_maint ne 'NOT_FOUND') { + $opt->{mail} = $config->{admin}; + #$opt->{mail} .= ", $other_maint"; + } + } + + if (!$opt->{mail}) { + $opt->{mail} = $config->{admin}; + } + + # remember what is needed, and do not try to + # recompile until it is available + + if ($missing_package) { + $opt->{error} = "[MISSING] $missing_deps, needed by $missing_package to build $title, is not available on $run->{my_arch} (rebuild $missing_package?)"; + $cache->{needed}{$title}{$missing_deps} = { package => $missing_package , version => $version, maint => $first_maint || $other_maint || $maintainer }; + } else { + $opt->{error} = "[MISSING] $missing_deps, needed to build $title, is not available on $run->{my_arch}"; + $cache->{needed}{$title}{$missing_deps} = { package => $missing_package , version => $version, maint => $maintainer || $other_maint }; + } + } + 0; + }, + )) { + if (!clean_process($run, "$self->{urpmi_command} $opt @to_install", $run->{verbose})) { + dump_cache_par($run); + die "FATAL $program_name: Could not have urpmi working !"; + } + $unsatisfied and last; + } else { + if (!@rpm || !system("sudo chroot $chroot_tmp rpm -q @rpm")) { + plog("installation successful"); + $ok = 1; + } + } + + if (-f "$chroot_tmp/bin/rpm") { + if (!$ok && system("sudo chroot $chroot_tmp rm -rf /var/lib/rpm/__db*; sudo chroot $chroot_tmp rpm --rebuilddb")) { + plog("ERROR: rebuilding rpm db failed, aborting ($!)"); + last; + } + if ($suf eq '_rpm') { + plog(1, "trying to install all the rpms in $chroot_tmp/var/cache/urpmi/rpms/ manually"); + if (!system("sudo chroot $chroot_tmp rpm -Uvh --force --nodeps /var/cache/urpmi/rpms/*.rpm")) { + $ok = 1; + last; + } else { + $ok = 0; + } + } + } + last if $ok == 1; + } + } + if (!-f "$chroot_tmp/bin/rpm" || @rpm && system("sudo chroot $chroot_tmp rpm -q @to_install")) { + plog(1, "ERROR: urpmi is not working, doing it manually"); + my $root = "$config->{repository}/$run->{distro}/$run->{my_arch}"; + my $depslist = "$root/media/media_info/depslist.ordered"; + if (-f $depslist) { + my $distrib = $self->{distrib}; + if (!$distrib) { + $distrib = MDV::Distribconf::Build->new($root); + plog(3, "getting media config from $root"); + if (!$distrib->loadtree) { + plog(1, "ERROR: $root does not seem to be a distribution tree\n"); + return; + } + $distrib->parse_mediacfg; + foreach my $media ($distrib->listmedia) { + $media =~ /(SRPMS|debug_)/ and next; + my $path = $distrib->getfullpath($media, 'path'); + opendir my $rpmdh, $path; + foreach my $rpm (readdir $rpmdh) { + if ($rpm =~ /^(.*)-([^-]+)-([^-]+)\.([^.]+)\.rpm/) { + $distrib->{file}{"$1-$2-$3.$4"} = "$path/$rpm"; + } + } + } + } + $self->{distrib} = $distrib; + plog(3, "using $depslist to resolve dependencies"); + open my $depsfh, $depslist; + my %packages; + my @deps; + my $i; + my @install; + my @pack; + while (<$depsfh>) { + my ($pack, $_size, @d) = split ' '; + $pack =~ s/:\d+$//; + push @deps, \@d; + my ($name, $version, $release, $arch) = $pack =~ /(.*)-([^-]+)-([^-]+)\.([^.]+)$/; + $pack[$i] = $pack; + $packages{$pack} ||= $i; + if ($arch ne 'src' && !$packages{$name}) { + $packages{$name} = $i; + $packages{"$name-$version"} = $i; + $packages{"$name-$version-$release"} = $i; + } + $i++; + } + plog(4, "$i packages found"); + my %done; + # rpm -root $chroot -qa does not work + if (-f "$chroot_tmp/bin/rpm") { + my $qa = `sudo chroot $chroot_tmp rpm -qa --qf "\%{name}-\%{version}-\%{release}.\%{arch}\n"`; + foreach my $rpm (split "\n", $qa) { + plog(6, "$rpm already installed"); + $done{$rpm} = 1; + } + } + foreach my $p (@to_install) { + my $pa = $pack[$packages{$p}]; + $done{$pa} and next; + my $f = $distrib->{file}{$pa}; + if ($f) { + push @install, $pa; + } else { + plog(1, "ERROR: main package $p is not present in the repository"); + return 0; + } + } + my $dok; + while (!$dok) { + $dok = 1; + foreach my $p (@install) { + $done{$p} and next; + $done{$p} = 1; + plog(5, "adding deps for $p (", join(', ', @{$deps[$packages{$p}]}, ")")); + foreach my $d (@{$deps[$packages{$p}]}) { + plog("$d (pack $pack[$d]) done $done{$d} done pack $done{$pack[$d]}"); + $done{$d} and next; + $done{$pack[$d]} and next; + $done{$d} = 1; + if ($d =~ /\d+/) { + my $f = $distrib->{file}{$pack[$d]}; + if ($f) { + $dok = 1; + plog(5, "adding $pack[$d]"); + push @install, $pack[$d]; + } else { + plog(2, "ERROR: deps for $p, $pack[$d] ($d) is not present in the repository"); + } + } elsif ($d =~ /\|/) { + my $done; + foreach my $a (split '\|', $d) { + my $f = $distrib->{file}{$pack[$a]}; + if ($f) { + $done = 1; + if (!$done{$pack[$a]}) { + $dok = 1; + plog(5, "adding $pack[$a]"); + push @install, $pack[$a]; + $done{$pack[$a]} = 1; + } + last; + } else { + plog(2, "ERROR: alternate deps, $pack[$a] ($d) is not present in the repository, using alternative"); + } + } + if (!$done) { + plog(2, "ERROR: no alternatives present in the repository"); + } + } + } + } + } + my $rpms; + my %install_done; + # FIXME: (tv) this loop could be simplified with uniq() from MDK::Common: + # eg: $rpms = join(map { "$distrib->{file}{$_}" } uniq(@install)) + foreach my $rpm (@install) { + $install_done{$rpm} and next; + print "$program_name: will install $rpm ($distrib->{file}{$rpm})\n" if $run->{verbose} > 3; + $install_done{$rpm} = 1; + $rpms .= "$distrib->{file}{$rpm} "; + } + if ($rpms) { + return !system("sudo rpm --ignoresize --nosignature --root $chroot_tmp -Uvh $rpms"); + } + $ok = 1; + } + } + $ok; +} + +sub clean_urpmi_process { + my ($self) = @_; + my $run = $self->{run}; + my $program_name = $run->{program_name}; + if (!$run->{chrooted_urpmi}) { + my $match = $self->{urpmi_command} or return; + if (!clean_process($run, $match, $run->{verbose})) { + dump_cache_par($run); + die "FATAL $program_name: Could not have urpmi working !"; + } + } +} + +sub update_srpm { + my ($self, $dir, $rpm, $wrong_rpm) = @_; + my $run = $self->{run}; + my $cache = $run->{cache}; + my ($arch) = $rpm =~ /([^\.]+)\.rpm$/ or return 0; + my $srpm = $cache->{rpm_srpm}{$rpm}; + if (!$srpm) { + my $hdr = RPM4::Header->new("$dir/$rpm"); + $hdr or return 0; + $srpm = $hdr->queryformat('%{SOURCERPM}'); + $cache->{rpm_srpm}{$rpm} = $srpm; + } + $srpm = fix_srpm_name($cache, $srpm, $rpm, $wrong_rpm); + $arch, $srpm; +} + +sub fix_srpm_name { + my ($cache, $srpm, $rpm, $wrong_rpm) = @_; + my $old_srpm = $srpm; + if ($srpm =~ s/^lib64/lib/) { + push @$wrong_rpm, [ $old_srpm, $rpm ] if ref $wrong_rpm; + $cache->{rpm_srpm}{$rpm} = $srpm; + } + $srpm; +} + +sub recreate_srpm { + my ($_self, $run, $config, $chroot_tmp, $dir, $srpm, $luser, $b_retry) = @_; +# recreate a new srpm for buildarch condition in the spec file + my $program_name = $run->{program_name}; + my $cache = $run->{cache}; + my $with_flags = $run->{with_flags}; + + plog('NOTIFY', "recreate srpm: $srpm"); + + perform_command([ + sub { + my ($s, $d) = @_; + sudo($run, $config, '--cp', $s, $d) } , [ "$dir/$srpm", "$chroot_tmp/home/$luser/rpm/SRPMS/" ] ], + $run, $config, $cache, + type => 'perl', + mail => $config->{admin}, + error => "[REBUILD] cannot copy $srpm to $chroot_tmp", + debug_mail => $run->{debug}, + hash => "copy_$srpm") or return; + + my %opt = (mail => $config->{admin}, + error => "[REBUILD] cannot install $srpm in $chroot_tmp", + debug_mail => $run->{debug}, + hash => "install_$srpm", + retry => $b_retry, + callback => sub { + my ($opt, $output) = @_; + plog('DEBUG', "calling callback for $opt->{hash}"); + if ($output =~ /warning: (group|user) .* does not exist - using root|Header V3 DSA signature/i) { + return 1; + } elsif ($output =~ /user $luser does not exist|cannot write to \%sourcedir/) { + plog('WARN', "WARNING: chroot seems corrupted!"); + $opt->{error} = "[CHROOT] chroot is corrupted"; + $opt->{retry} ||= 1; + return; + } + 1; + }); + plog('DEBUG', "recreating src.rpm..."); + if (!perform_command(qq(sudo chroot $chroot_tmp su $luser -c "rpm -i /home/$luser/rpm/SRPMS/$srpm"), + $run, $config, $cache, %opt)) { + plog("ERROR: chrooting failed (retry $opt{retry}") if $run->{debug}; + if ($opt{retry}) { + check_build_chroot($run->{chroot_path}, $run->{chroot_tar}, $run, $config) or return; + return -1; + } + return; + } + + my $spec; + my $oldsrpm = "$chroot_tmp/home/$luser/rpm/SRPMS/$srpm"; + my $filelist = `rpm -qlp $oldsrpm`; + my ($name) = $srpm =~ /(?:.*:)?(.*)-[^-]+-[^-]+\.src\.rpm$/; + foreach my $file (split "\n", $filelist) { + if ($file =~ /(.*)\.spec/) { + if (!$spec) { + $spec = $file; + } elsif ($1 eq $name) { + $spec = $file; + } + } + } + # 20060515 This should not be necessairy any more if urpmi *.spec works, but it doesn't + # + my $ret = perform_command(qq(sudo chroot $chroot_tmp su $luser -c "rpm --nodeps -bs $with_flags /home/$luser/rpm/SPECS/$spec"), + $run, $config, $cache, + mail => $config->{admin}, + error => "[REBUILD] cannot create $srpm in $chroot_tmp", + debug_mail => $run->{debug}, + hash => "create_$srpm" + ); + + # Return if we can't regenerate srpm + # + return (0, ,) unless $ret; + + # CM: was: foreach my $file (readdir $dir) + # The above line returned entries in a strange order in my test + # system, such as + # .. + # cowsay-3.03-11mdv2007.1.src.rpm + # cowsay-3.03-11mdv2007.0.src.rpm + # . + # assigning '.' to $new_rpm. Now sorting the output. + + # we should better perform a rpm -qp -qf "%{name}-%{version}-%{release}.src.rpm" $spec + my $file; + my $stat; + foreach my $f (glob "$chroot_tmp/home/$luser/rpm/SRPMS/$name-*.src.rpm") { + my (@s) = stat $f; + if ($s[9] > $stat) { + $file = $f; + $stat = $s[9]; + } + } + my ($new_srpm) = basename($file); + my $prefix = get_package_prefix($srpm); + my $newfile = "$chroot_tmp/home/$luser/rpm/SRPMS/$prefix$new_srpm"; + if (-f $file && $newfile ne $file) { + if (-f $newfile) { + sudo($run, $config, '--rm', $newfile) or die "$program_name: could not delete $newfile ($!)"; + } + sudo($run, $config, '--ln', $file, $newfile) or die "$program_name: linking $file to $newfile failed ($!)"; + unlink $file; + unlink $oldsrpm if $oldsrpm ne $newfile; + } + plog('NOTIFY', "new srpm: $prefix$new_srpm"); + ($ret, "$prefix$new_srpm", $spec); +} + +1; |