summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perl-install/pkgs.pm784
1 files changed, 427 insertions, 357 deletions
diff --git a/perl-install/pkgs.pm b/perl-install/pkgs.pm
index 4ff05f593..af343b281 100644
--- a/perl-install/pkgs.pm
+++ b/perl-install/pkgs.pm
@@ -2,7 +2,7 @@ package pkgs; # $Id$
use diagnostics;
use strict;
-use vars qw(*LOG %compssListDesc @skip_list %by_lang @preferred $limitMinTrans $PKGS_SELECTED $PKGS_FORCE $PKGS_INSTALLED $PKGS_BASE $PKGS_SKIP $PKGS_UPGRADE);
+use vars qw(*LOG %compssListDesc @skip_list %by_lang @preferred $limitMinTrans);
use common qw(:common :file :functional);
use install_any;
@@ -92,13 +92,23 @@ autoirpm autoirpm-icons numlock
#- constant for small transaction.
$limitMinTrans = 8;
+#- constant for package accessor (via table).
+my $FILE = 0;
+my $FLAGS = 1;
+my $SIZE_DEPS = 2;
+my $MEDIUM = 3;
+my $PROVIDES = 4;
+my $VALUES = 5;
+my $HEADER = 6;
+my $INSTALLED_CUMUL_SIZE = 7;
+
#- constant for packing flags, see below.
-$PKGS_SELECTED = 0x00ffffff;
-$PKGS_FORCE = 0x01000000;
-$PKGS_INSTALLED = 0x02000000;
-$PKGS_BASE = 0x04000000;
-$PKGS_SKIP = 0x08000000;
-$PKGS_UPGRADE = 0x20000000;
+my $PKGS_SELECTED = 0x00ffffff;
+my $PKGS_FORCE = 0x01000000;
+my $PKGS_INSTALLED = 0x02000000;
+my $PKGS_BASE = 0x04000000;
+my $PKGS_SKIP = 0x08000000;
+my $PKGS_UPGRADE = 0x20000000;
#- package to ignore, typically in Application CD.
my %ignoreBadPkg = (
@@ -117,45 +127,52 @@ my %ignoreBadPkg = (
#- following flags : selected, force, installed, base, skip.
#- size and deps are grouped to save memory too and make a much
#- simpler and faster depslist reader, this gets (sizeDeps).
-sub packageHeaderFile { my ($pkg) = @_; $pkg->{file} }
-sub packageName { my ($pkg) = @_; $pkg->{file} =~ /([^\(]*)(?:\([^\)]*\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
-sub packageSpecificArch { my ($pkg) = @_; $pkg->{file} =~ /[^\(]*(?:\(([^\)]*)\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
-sub packageVersion { my ($pkg) = @_; $pkg->{file} =~ /.*-([^-]+)-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
-sub packageRelease { my ($pkg) = @_; $pkg->{file} =~ /.*-[^-]+-([^-]+)/ ? $1 : die "invalid file `$pkg->{file}'" }
+sub packageHeaderFile { $_[0]->[$FILE] }
+sub packageName { $_[0]->[$FILE] =~ /([^\(]*)(?:\([^\)]*\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$_[0]->[$FILE]'" }
+sub packageSpecificArch { $_[0]->[$FILE] =~ /[^\(]*(?:\(([^\)]*)\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$_[0]->[$FILE]'" }
+sub packageVersion { $_[0]->[$FILE] =~ /.*-([^-]+)-[^-]+/ ? $1 : die "invalid file `$_[0]->[$FILE]'" }
+sub packageRelease { $_[0]->[$FILE] =~ /.*-[^-]+-([^-]+)/ ? $1 : die "invalid file `$_[0]->[$FILE]'" }
+
+sub packageSize { to_int($_[0]->[$SIZE_DEPS]) }
+sub packageDepsId { split ' ', ($_[0]->[$SIZE_DEPS] =~ /^\d*\s*(.*)/)[0] }
+
+sub packageFlagSelected { $_[0]->[$FLAGS] & $PKGS_SELECTED }
+sub packageFlagForce { $_[0]->[$FLAGS] & $PKGS_FORCE }
+sub packageFlagInstalled { $_[0]->[$FLAGS] & $PKGS_INSTALLED }
+sub packageFlagBase { $_[0]->[$FLAGS] & $PKGS_BASE }
+sub packageFlagSkip { $_[0]->[$FLAGS] & $PKGS_SKIP }
+sub packageFlagUpgrade { $_[0]->[$FLAGS] & $PKGS_UPGRADE }
+
+sub packageSetFlagSelected { $_[0]->[$FLAGS] &= ~$PKGS_SELECTED; $_[0]->[$FLAGS] |= $_[1] & $PKGS_SELECTED; }
-sub packageSize { my ($pkg) = @_; to_int($pkg->{sizeDeps}) }
-sub packageDepsId { my ($pkg) = @_; split ' ', ($pkg->{sizeDeps} =~ /^\d*\s*(.*)/)[0] }
+sub packageSetFlagForce { $_[1] ? ($_[0]->[$FLAGS] |= $PKGS_FORCE) : ($_[0]->[$FLAGS] &= ~$PKGS_FORCE); }
+sub packageSetFlagInstalled { $_[1] ? ($_[0]->[$FLAGS] |= $PKGS_INSTALLED) : ($_[0]->[$FLAGS] &= ~$PKGS_INSTALLED); }
+sub packageSetFlagBase { $_[1] ? ($_[0]->[$FLAGS] |= $PKGS_BASE) : ($_[0]->[$FLAGS] &= ~$PKGS_BASE); }
+sub packageSetFlagSkip { $_[1] ? ($_[0]->[$FLAGS] |= $PKGS_SKIP) : ($_[0]->[$FLAGS] &= ~$PKGS_SKIP); }
+sub packageSetFlagUpgrade { $_[1] ? ($_[0]->[$FLAGS] |= $PKGS_UPGRADE) : ($_[0]->[$FLAGS] &= ~$PKGS_UPGRADE); }
-sub packageFlagSelected { my ($pkg) = @_; $pkg->{flags} & $PKGS_SELECTED }
-sub packageFlagForce { my ($pkg) = @_; $pkg->{flags} & $PKGS_FORCE }
-sub packageFlagInstalled { my ($pkg) = @_; $pkg->{flags} & $PKGS_INSTALLED }
-sub packageFlagBase { my ($pkg) = @_; $pkg->{flags} & $PKGS_BASE }
-sub packageFlagSkip { my ($pkg) = @_; $pkg->{flags} & $PKGS_SKIP }
-sub packageFlagUpgrade { my ($pkg) = @_; $pkg->{flags} & $PKGS_UPGRADE }
+sub packageMedium { $_[0]->[$MEDIUM] }
-sub packageSetFlagSelected { my ($pkg, $v) = @_; $pkg->{flags} &= ~$PKGS_SELECTED; $pkg->{flags} |= $v & $PKGS_SELECTED; }
+sub packageProvides { map { $_[0]->{depslist}[$_] || die "unkown package id $_" } unpack "s*", $_[1]->[$PROVIDES] }
-sub packageSetFlagForce { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_FORCE) : ($pkg->{flags} &= ~$PKGS_FORCE); }
-sub packageSetFlagInstalled { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_INSTALLED) : ($pkg->{flags} &= ~$PKGS_INSTALLED); }
-sub packageSetFlagBase { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_BASE) : ($pkg->{flags} &= ~$PKGS_BASE); }
-sub packageSetFlagSkip { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_SKIP) : ($pkg->{flags} &= ~$PKGS_SKIP); }
-sub packageSetFlagUpgrade { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_UPGRADE) : ($pkg->{flags} &= ~$PKGS_UPGRADE); }
+sub packageValues { [ unpack "s*", $_[0]->[$VALUES] ] }
+sub packageSetValues { $_[0]->[$VALUES] = pack "s*", @{$_[1]} }
-sub packageProvides { my ($pkg) = @_; @{$pkg->{provides} || []} }
+sub packageHeader { $_[0]->[$HEADER] }
+sub packageFreeHeader { c::headerFree(delete $_[0]->[$HEADER]) }
sub packageFile {
- my ($pkg) = @_;
- $pkg->{header} or die "packageFile: missing header";
- $pkg->{file} =~ /([^\(]*)(?:\([^\)]*\))?(-[^-]+-[^-]+)/;
- "$1$2." . c::headerGetEntry($pkg->{header}, 'arch') . ".rpm";
+ $_[0]->[$HEADER] or die "packageFile: missing header";
+ $_[0]->[$FILE] =~ /([^\(]*)(?:\([^\)]*\))?(-[^-]+-[^-]+)/;
+ "$1$2." . c::headerGetEntry($_[0]->[$HEADER], 'arch') . ".rpm";
}
-sub packageSelectedOrInstalled { my ($pkg) = @_; packageFlagSelected($pkg) || packageFlagInstalled($pkg) }
+sub packageSelectedOrInstalled { packageFlagSelected($_[0]) || packageFlagInstalled($_[0]) }
sub packageId {
my ($packages, $pkg) = @_;
my $i = 0;
- foreach (@{$packages->[1]}) { return $i if $pkg == $packages->[1][$i]; $i++ }
+ foreach (@{$packages->{depslist}}) { return $i if $pkg == $packages->{depslist}[$i]; $i++ }
return;
}
@@ -179,9 +196,9 @@ sub extractHeaders($$$) {
my $f = "$prefix/tmp/headers/". packageHeaderFile($_);
local *H;
open H, $f or log::l("unable to open header file $f: $!"), next;
- $_->{header} = c::headerRead(fileno H, 1) or log::l("unable to read header of package ". packageHeaderFile($_));
+ $_->[$HEADER] = c::headerRead(fileno H, 1) or log::l("unable to read header of package ". packageHeaderFile($_));
}
- @$pkgs = grep { $_->{header} } @$pkgs;
+ @$pkgs = grep { $_->[$HEADER] } @$pkgs;
}
#- size and correction size functions for packages.
@@ -208,8 +225,8 @@ sub invCorrectSize {
sub selectedSize {
my ($packages) = @_;
my $size = 0;
- foreach (values %{$packages->[0]}) {
- packageFlagSelected($_) && !packageFlagInstalled($_) and $size += packageSize($_) - ($_->{installedCumulSize} || 0);
+ foreach (values %{$packages->{names}}) {
+ packageFlagSelected($_) && !packageFlagInstalled($_) and $size += packageSize($_) - ($_->[$INSTALLED_CUMUL_SIZE] || 0);
}
$size;
}
@@ -222,34 +239,34 @@ sub correctedSelectedSize { correctSize(selectedSize($_[0]) / sqr(1024)) }
#- a list to search by id.
sub packageByName {
my ($packages, $name) = @_;
- $packages->[0]{$name} or log::l("unknown package `$name'") && undef;
+ $packages->{names}{$name} or log::l("unknown package `$name'") && undef;
}
sub packageById {
my ($packages, $id) = @_;
- $packages->[1][$id] or log::l("unknown package id $id") && undef;
+ $packages->{depslist}[$id] or log::l("unknown package id $id") && undef;
}
sub allPackages {
my ($packages) = @_;
my %skip_list; @skip_list{@skip_list} = ();
- grep { !exists $skip_list{packageName($_)} } values %{$packages->[0]};
+ grep { !exists $skip_list{packageName($_)} } values %{$packages->{names}};
}
sub packagesOfMedium {
my ($packages, $mediumName) = @_;
- my $medium = $packages->[2]{$mediumName};
- grep { $_->{medium} == $medium } @{$packages->[1]};
+ my $medium = $packages->{mediums}{$mediumName};
+ grep { $_->[$MEDIUM] == $medium } @{$packages->{depslist}};
}
sub packagesToInstall {
my ($packages) = @_;
- grep { $_->{medium}{selected} && packageFlagSelected($_) && !packageFlagInstalled($_) } values %{$packages->[0]};
+ grep { $_->[$MEDIUM]{selected} && packageFlagSelected($_) && !packageFlagInstalled($_) } values %{$packages->{names}};
}
sub allMediums {
my ($packages) = @_;
- keys %{$packages->[2]};
+ keys %{$packages->{mediums}};
}
sub mediumDescr {
my ($packages, $medium) = @_;
- $packages->[2]{$medium}{descr};
+ $packages->{mediums}{$medium}{descr};
}
#- selection, unselection of package.
@@ -262,10 +279,10 @@ sub selectPackage { #($$;$$$)
#- check for medium selection, if the medium has not been
#- selected, the package cannot be selected.
- $pkg->{medium}{selected} or return;
+ $pkg->[$MEDIUM]{selected} or return;
#- avoid infinite recursion (mainly against badly generated depslist.ordered).
- $check_recursion ||= {}; exists $check_recursion->{$pkg->{file}} and return; $check_recursion->{$pkg->{file}} = undef;
+ $check_recursion ||= {}; exists $check_recursion->{$pkg->[$FILE]} and return; $check_recursion->{$pkg->[$FILE]} = undef;
#- make sure base package are set even if already selected.
$base and packageSetFlagBase($pkg, 1);
@@ -317,7 +334,7 @@ sub unselectPackage($$;$) {
#- provides are closed and are taken into account to get possible
#- unselection of package (value false on otherOnly) or strict
#- unselection (value true on otherOnly).
- foreach my $provided ($pkg, packageProvides($pkg)) {
+ foreach my $provided ($pkg, packageProvides($packages, $pkg)) {
packageFlagBase($provided) and die "a provided package cannot be a base package";
if (packageFlagSelected($provided)) {
my $unselect_alone = 0;
@@ -363,7 +380,7 @@ sub setPackageSelection($$$) {
sub unselectAllPackages($) {
my ($packages) = @_;
- foreach (values %{$packages->[0]}) {
+ foreach (values %{$packages->{names}}) {
unless (packageFlagBase($_) || packageFlagUpgrade($_)) {
packageSetFlagSelected($_, 0);
}
@@ -371,7 +388,7 @@ sub unselectAllPackages($) {
}
sub unselectAllPackagesIncludingUpgradable($) {
my ($packages, $removeUpgradeFlag) = @_;
- foreach (values %{$packages->[0]}) {
+ foreach (values %{$packages->{names}}) {
unless (packageFlagBase($_)) {
packageSetFlagSelected($_, 0);
packageSetFlagUpgrade($_, 0);
@@ -381,7 +398,7 @@ sub unselectAllPackagesIncludingUpgradable($) {
sub skipSetWithProvides {
my ($packages, @l) = @_;
- packageSetFlagSkip($_, 1) foreach grep { $_ } map { $_, packageProvides($_) } @l;
+ packageSetFlagSkip($_, 1) foreach grep { $_ } map { $_, packageProvides($packages, $_) } @l;
}
sub psUpdateHdlistsDeps {
@@ -421,51 +438,46 @@ sub psUpdateHdlistsDeps {
sub psUsingHdlists {
my ($prefix, $method) = @_;
my $listf = install_any::getFile('Mandrake/base/hdlists') or die "no hdlists found";
- my @packages = ({}, [], {});
- my @hdlists;
+ my %packages = ( names => {}, depslist => [], mediums => {});
- #- parse hdlist.list file.
+ #- parse hdlists file.
my $medium = 1;
- local $_;
- while (<$listf>) {
+ foreach (<$listf>) {
chomp;
s/\s*#.*$//;
/^\s*$/ and next;
m/^\s*(hdlist\S*\.cz2?)\s+(\S+)\s*(.*)$/ or die "invalid hdlist description \"$_\" in hdlists file";
- push @hdlists, [ $1, $medium, $2, $3 ];
- ++$medium;
- }
-
- foreach (@hdlists) {
- my ($hdlist, $medium, $rpmsdir, $descr) = @$_;
#- make sure the first medium is always selected!
#- by default select all image.
- psUsingHdlist($prefix, $method, \@packages, $hdlist, $medium, $rpmsdir, $descr, 1);
+ psUsingHdlist($prefix, $method, \%packages, $1, $medium, $2, $3, 1);
+ ++$medium;
}
- log::l("psUsingHdlists read " . scalar keys(%{$packages[0]}) . " headers on " . scalar keys(%{$packages[2]}) . " hdlists");
+ log::l("psUsingHdlists read " . scalar keys(%{$packages{names}}) .
+ " headers on " . scalar keys(%{$packages{mediums}}) . " hdlists");
- \@packages;
+ \%packages;
}
sub psUsingHdlist {
my ($prefix, $method, $packages, $hdlist, $medium, $rpmsdir, $descr, $selected, $fhdlist) = @_;
+ my $fakemedium = $method . $medium;
+ log::l("trying to read $hdlist for medium $medium");
#- if the medium already exist, use it.
- $packages->[2]{$medium} and return;
-
- my $fakemedium = $method . $medium;
- my $m = $packages->[2]{$medium} = { hdlist => $hdlist,
- medium => $medium,
- rpmsdir => $rpmsdir, #- where is RPMS directory.
- descr => $descr,
- fakemedium => $fakemedium,
- min => scalar keys %{$packages->[0]},
- max => -1, #- will be updated after reading current hdlist.
- selected => $selected, #- default value is only CD1, it is really the minimal.
- };
+ $packages->{mediums}{$medium} and return;
+
+ my $m = $packages->{mediums}{$medium} = { hdlist => $hdlist,
+ medium => $medium,
+ rpmsdir => $rpmsdir, #- where is RPMS directory.
+ descr => $descr,
+ fakemedium => $fakemedium,
+ min => scalar keys %{$packages->{names}},
+ max => -1, #- will be updated after reading current hdlist.
+ selected => $selected, #- default value is only CD1, it is really the minimal.
+ };
#- copy hdlist file directly to $prefix/var/lib/urpmi, this will be used
#- for getting header of package during installation or after by urpmi.
@@ -482,18 +494,15 @@ sub psUsingHdlist {
chomp;
/^[dlf]\s+/ or next;
if (/^f\s+\d+\s+(.*)/) {
- my $pkg = { file => $1, #- rebuild filename according to header one
- flags => 0, #- flags
- medium => $m,
- };
+ my $pkg = [ (undef) x 8 ]; $pkg->[$FILE] = $1; $pkg->[$MEDIUM] = $m;
my $specific_arch = packageSpecificArch($pkg);
if (!$specific_arch || compat_arch($specific_arch)) {
- my $old_pkg = $packages->[0]{packageName($pkg)};
+ my $old_pkg = $packages->{names}{packageName($pkg)};
if ($old_pkg) {
if (packageVersion($pkg) eq packageVersion($old_pkg) && packageRelease($pkg) eq packageRelease($old_pkg)) {
if (better_arch($specific_arch, packageSpecificArch($old_pkg))) {
log::l("replacing old package with package $1 with better arch: $specific_arch");
- $packages->[0]{packageName($pkg)} = $pkg;
+ $packages->{names}{packageName($pkg)} = $pkg;
} else {
log::l("keeping old package against package $1 with worse arch");
}
@@ -501,7 +510,7 @@ sub psUsingHdlist {
log::l("ignoring package $1 already present in distribution with different version or release");
}
} else {
- $packages->[0]{packageName($pkg)} = $pkg;
+ $packages->{names}{packageName($pkg)} = $pkg;
}
} else {
log::l("ignoring package $1 with incompatible arch: $specific_arch");
@@ -513,7 +522,7 @@ sub psUsingHdlist {
close F or die "unable to parse $newf";
#- update maximal index.
- $m->{max} = scalar(keys %{$packages->[0]}) - 1;
+ $m->{max} = scalar(keys %{$packages->{names}}) - 1;
$m->{max} >= $m->{min} or die "nothing found while parsing $newf";
log::l("read " . ($m->{max} - $m->{min} + 1) . " headers in $hdlist");
1;
@@ -527,15 +536,15 @@ sub getOtherDeps($$) {
local $_;
while (<$f>) {
my ($name, $version, $release, $size, $deps) = /^(\S*)-([^-\s]+)-([^-\s]+)\s+(\d+)\s+(.*)/;
- my $pkg = $packages->[0]{$name};
+ my $pkg = $packages->{names}{$name};
$pkg or log::l("ignoring package $name-$version-$release in depslist is not in hdlist"), next;
$version eq packageVersion($pkg) and $release eq packageRelease($pkg)
or log::l("warning package $name-$version-$release in depslist mismatch version or release in hdlist ($version ne ",
packageVersion($pkg), " or $release ne ", packageRelease($pkg), ")"), next;
- my $index = scalar @{$packages->[1]};
- $index >= $pkg->{medium}{min} && $index <= $pkg->{medium}{max}
+ my $index = scalar @{$packages->{depslist}};
+ $index >= $pkg->[$MEDIUM]{min} && $index <= $pkg->[$MEDIUM]{max}
or log::l("ignoring package $name-$version-$release in depslist outside of hdlist indexation");
#- here we have to translate referenced deps by name to id.
@@ -546,13 +555,13 @@ sub getOtherDeps($$) {
map { packageByName($packages, $_) or do { log::l("unknown package $_ in depslist for closure"); undef } }
split /\s+/, $deps} = ();
- $pkg->{sizeDeps} = join " ", $size, keys %closuredeps;
+ $pkg->[$SIZE_DEPS] = join " ", $size, keys %closuredeps;
- push @{$packages->[1]}, $pkg;
+ push @{$packages->{depslist}}, $pkg;
}
#- check for same number of package in depslist and hdlists, avoid being to hard.
- scalar(keys %{$packages->[0]}) == scalar(@{$packages->[1]})
+ scalar(keys %{$packages->{names}}) == scalar(@{$packages->{depslist}})
or log::l("other depslist has not same package as hdlist file");
}
@@ -574,31 +583,32 @@ sub getDeps($) {
local $_;
while (<F>) {
my ($name, $version, $release, $sizeDeps) = /^(\S*)-([^-\s]+)-([^-\s]+)\s+(.*)/;
- my $pkg = $packages->[0]{$name};
+ my $pkg = $packages->{names}{$name};
$pkg or
log::l("ignoring $name-$version-$release in depslist is not in hdlist"), $mismatch = 1, next;
$version eq packageVersion($pkg) and $release eq packageRelease($pkg) or
log::l("ignoring $name-$version-$release in depslist mismatch version or release in hdlist ($version ne ", packageVersion($pkg), " or $release ne ", packageRelease($pkg), ")"), $mismatch = 1, next;
- $pkg->{sizeDeps} = $sizeDeps;
+ $pkg->[$SIZE_DEPS] = $sizeDeps;
#- check position of package in depslist according to precomputed
#- limit by hdlist, very strict :-)
#- above warning have chance to raise an exception here, but may help
#- for debugging.
- my $i = scalar @{$packages->[1]};
- $i >= $pkg->{medium}{min} && $i <= $pkg->{medium}{max} or $mismatch = 1;
+ my $i = scalar @{$packages->{depslist}};
+ $i >= $pkg->[$MEDIUM]{min} && $i <= $pkg->[$MEDIUM]{max} or $mismatch = 1;
#- package are already sorted in depslist to enable small transaction and multiple medium.
- push @{$packages->[1]}, $pkg;
+ push @{$packages->{depslist}}, $pkg;
}
#- check for mismatching package, it should breaj with above die unless depslist has too many errors!
$mismatch and die "depslist.ordered mismatch against hdlist files";
#- check for same number of package in depslist and hdlists.
- scalar(keys %{$packages->[0]}) == scalar(@{$packages->[1]}) or die "depslist.ordered has not same package as hdlist files";
+ scalar(keys %{$packages->{names}}) == scalar(@{$packages->{depslist}})
+ or die "depslist.ordered has not same package as hdlist files";
}
sub getProvides($) {
@@ -612,12 +622,16 @@ sub getProvides($) {
#- base package are not updated because they cannot be unselected,
#- this save certainly a lot of memory since most of them may be
#- needed by a large number of package.
-
- foreach my $pkg (@{$packages->[1]}) {
+ #- now using a packed of signed short, this means no more than 32768
+ #- packages can be managed by DrakX (currently about 2000).
+ my $i = 0;
+ foreach my $pkg (@{$packages->{depslist}}) {
packageFlagBase($pkg) and next;
- map { my $provided = $packages->[1][$_] or die "invalid package index $_";
- packageFlagBase($provided) or push @{$provided->{provides} ||= []}, $pkg;
- } map { split '\|' } grep { !/^NOTFOUND_/ } packageDepsId($pkg);
+ foreach (map { split '\|' } grep { !/^NOTFOUND_/ } packageDepsId($pkg)) {
+ my $provided = $packages->{depslist}[$_] or die "invalid package index $_";
+ packageFlagBase($provided) or $provided->[$PROVIDES] = pack "s*", (unpack "s*", $provided->[$PROVIDES]), $i;
+ }
+ ++$i;
}
}
@@ -638,7 +652,7 @@ sub readCompss {
$p = $1;
} else {
/(\S+)/;
- $packages->[0]{$1} or log::l("unknown package $1 in compss"), next;
+ $packages->{names}{$1} or log::l("unknown package $1 in compss"), next;
push @compss, "$p/$1";
}
}
@@ -655,15 +669,15 @@ sub readCompssList {
/^\s*$/ || /^#/ and next;
my ($name, @values) = split;
my $p = packageByName($packages, $name) or log::l("unknown entry $name (in compssList)"), next;
- $p->{values} = \@values;
+ $p->[$VALUES] = pack "s*", @values;
}
my %done;
foreach (@$langs) {
my $p = packageByName($packages, "locales-$_") or next;
- foreach ($p, @{$p->{provides} || []}, map { packageByName($packages, $_) } @{$by_lang{$_} || []}) {
+ foreach ($p, packageProvides($packages, $p), map { packageByName($packages, $_) } @{$by_lang{$_} || []}) {
next if !$_ || $done{$_}; $done{$_} = 1;
- $_->{values} = [ map { $_ + 90 } @{$_->{values} || [ (0) x @levels ]} ];
+ $_->[$VALUES] = pack "s*", map { $_ + 90 } ($_->[$VALUES] ? (unpack "s*", $_->[$VALUES]) : ((0) x @levels));
}
}
my $l = { map_index { $_ => $::i } @levels };
@@ -680,7 +694,7 @@ sub readCompssUsers {
my $map = sub {
$l or return;
- $_ = $packages->[0]{$_} or log::l("unknown package $_ (in compssUsers)") foreach @$l;
+ $_ = $packages->{names}{$_} or log::l("unknown package $_ (in compssUsers)") foreach @$l;
};
my $file = 'Mandrake/base/compssUsers';
my $f = $meta_class && install_any::getFile("$file.$meta_class") || install_any::getFile($file) or die "can't find $file";
@@ -715,13 +729,13 @@ sub setSelectedFromCompssList {
my @packages = allPackages($packages);
my @places = do {
#- special case for /^k/ aka kde stuff
- my @values = map { $_->{values}[$ind] } @packages;
+ my @values = map { (unpack "s*", $_->[$VALUES])[$ind] } @packages;
sort { $values[$b] <=> $values[$a] } 0 .. $#packages;
};
foreach (@places) {
my $p = $packages[$_];
next if packageFlagSkip($p);
- last if $p->{values}[$ind] < $min_level;
+ last if (unpack "s*", $p->[$VALUES])[$ind] < $min_level;
#- determine the packages that will be selected when
#- selecting $p. the packages are not selected.
@@ -731,11 +745,11 @@ sub setSelectedFromCompssList {
#- this enable an incremental total size.
my $old_nb = $nb;
foreach (grep { $newSelection{$_} } keys %newSelection) {
- $nb += packageSize($packages->[0]{$_});
+ $nb += packageSize($packages->{names}{$_});
}
if ($max_size && $nb > $max_size) {
$nb = $old_nb;
- $min_level = $p->{values}[$ind];
+ $min_level = (unpack "s*", $p->[$VALUES])[$ind];
last;
}
@@ -750,7 +764,7 @@ sub setSelectedFromCompssList {
#- just saves the selected packages, call setSelectedFromCompssList and restores the selected packages
sub saveSelected {
my ($packages) = @_;
- my @l = values %{$packages->[0]};
+ my @l = values %{$packages->{names}};
my @flags = map { pkgs::packageFlagSelected($_) } @l;
[ $packages, \@l, \@flags ];
}
@@ -761,7 +775,7 @@ sub restoreSelected {
sub init_db {
- my ($prefix, $isUpgrade) = @_;
+ my ($prefix) = @_;
my $f = "$prefix/root/install.log";
open(LOG, "> $f") ? log::l("opened $f") : log::l("Failed to open $f. No install log will be kept.");
@@ -773,13 +787,33 @@ sub init_db {
log::l("reading /usr/lib/rpm/rpmrc");
c::rpmReadConfigFiles() or die "can't read rpm config files";
log::l("\tdone");
+}
+
+sub rebuild_db_open_for_traversal {
+ my ($packages, $prefix) = @_;
+
+ log::l("reading /usr/lib/rpm/rpmrc");
+ c::rpmReadConfigFiles() or die "can't read rpm config files";
+ log::l("\tdone");
+
+ unless (exists $packages->{rebuild_db}) {
+ if (my $pid = fork()) {
+ waitpid $pid, 0;
+ ($? & 0xff00) and die "rebuilding of rpm database failed";
+ } else {
+ log::l("rebuilding rpm database");
+ c::rpmdbRebuild($prefix) and c::_exit(0);
- if ($isUpgrade) {
- log::l("rebuilding rpm database");
- c::rpmdbRebuild($prefix) or die "rebuilding of rpm database failed: ", c::rpmErrorString();
+ log::l("rebuilding of rpm database failed: ". c::rpmErrorString());
+ c::_exit(2);
+ }
+ $packages->{rebuild_db} = undef;
}
- #- seems no more necessary to rpmdbInit ?
- #c::rpmdbOpen($prefix) or die "creation of rpm database failed: ", c::rpmErrorString();
+
+ my $db = c::rpmdbOpenForTraversal($prefix) or die "unable to open $prefix/var/lib/rpm/Packages";
+ log::l("opened rpm database for examining existing packages");
+
+ $db;
}
sub done_db {
@@ -799,13 +833,7 @@ sub versionCompare($$) {
sub selectPackagesAlreadyInstalled {
my ($packages, $prefix) = @_;
-
- log::l("reading /usr/lib/rpm/rpmrc");
- c::rpmReadConfigFiles() or die "can't read rpm config files";
- log::l("\tdone");
-
- my $db = c::rpmdbOpenForTraversal($prefix) or die "unable to open $prefix/var/lib/rpm/packages.rpm";
- log::l("opened rpm database for examining existing packages");
+ my $db = rebuild_db_open_for_traversal($packages, $prefix);
#- this method has only one objectif, check the presence of packages
#- already installed and avoid installing them again. this is to be used
@@ -814,7 +842,7 @@ sub selectPackagesAlreadyInstalled {
#- is enough).
c::rpmdbTraverse($db, sub {
my ($header) = @_;
- my $p = $packages->[0]{c::headerGetEntry($header, 'name')};
+ my $p = $packages->{names}{c::headerGetEntry($header, 'name')};
if ($p) {
my $version_cmp = versionCompare(c::headerGetEntry($header, 'version'), packageVersion($p));
@@ -832,262 +860,304 @@ sub selectPackagesAlreadyInstalled {
sub selectPackagesToUpgrade($$$;$$) {
my ($packages, $prefix, $base, $toRemove, $toSave) = @_;
-
- log::l("reading /usr/lib/rpm/rpmrc");
- c::rpmReadConfigFiles() or die "can't read rpm config files";
- log::l("\tdone");
-
- my $db = c::rpmdbOpenForTraversal($prefix) or die "unable to open $prefix/var/lib/rpm/packages.rpm";
- log::l("opened rpm database for examining existing packages");
-
local $_; #- else perl complains on the map { ... } grep { ... } @...;
- #- used for package that are not correctly updated.
- #- should only be used when nothing else can be done correctly.
- my %upgradeNeedRemove = (
- 'libstdc++' => 1,
- 'compat-glibc' => 1,
- 'compat-libs' => 1,
- );
-
- #- these package are not named as ours, need to be translated before working.
- #- a version may follow to setup a constraint 'installed version greater than'.
- my %otherPackageToRename = (
- 'qt' => [ 'qt2', '2.0' ],
- 'qt1x' => [ 'qt' ],
- );
- #- generel purpose for forcing upgrade of package whatever version is.
- my %packageNeedUpgrade = (
- 'lilo' => 1, #- this package has been misnamed in 7.0.
- );
-
- #- help removing package which may have different release numbering
- my %toRemove; map { $toRemove{$_} = 1 } @{$toRemove || []};
-
- #- help searching package to upgrade in regard to already installed files.
- my %installedFilesForUpgrade;
-
- #- make a subprocess here for reading filelist, this is important
- #- not to waste a lot of memory for the main program which will fork
- #- latter for each transaction.
- local (*INPUT, *OUTPUT_CHILD); pipe INPUT, OUTPUT_CHILD;
- local (*INPUT_CHILD, *OUTPUT); pipe INPUT_CHILD, OUTPUT;
+ local (*UPGRADE_INPUT, *UPGRADE_OUTPUT); pipe UPGRADE_INPUT, UPGRADE_OUTPUT;
if (my $pid = fork()) {
- close INPUT_CHILD;
- close OUTPUT_CHILD;
- select((select(OUTPUT), $| = 1)[0]);
-
- #- internal reading from interactive mode of parsehdlist.
- my $ask_child = sub {
- my ($name, $tag) = @_;
- my @list;
- print OUTPUT "$name:$tag\n";
-
- local $_;
- while (<INPUT>) {
- chomp;
- /^\s*$/ and last;
- push @list, $_;
+ @{$toRemove || []} = (); #- reset this one.
+
+ close UPGRADE_OUTPUT;
+ while (<UPGRADE_INPUT>) {
+ chomp;
+ my ($action, $name) = /^([\w\d]*):(.*)/;
+ for ($action) {
+ /remove/ and do { push @$toRemove, $name; next };
+ /keepfiles/ and do { push @$toSave, $name; next };
+
+ my $p = $packages->{names}{$name} or die "unable to find package ($name)";
+ /^\d*$/ and do { $p->[$INSTALLED_CUMUL_SIZE] = $action; next };
+ /installed/ and do { packageSetFlagInstalled($p, 1); next };
+ /select/ and do { selectPackage($packages, $p); next };
+
+ die "unknown action ($action)";
+ }
+ }
+ close UPGRADE_INPUT;
+ waitpid $pid, 0;
+ } else {
+ close UPGRADE_INPUT;
+
+ my $db = rebuild_db_open_for_traversal($packages, $prefix);
+ #- used for package that are not correctly updated.
+ #- should only be used when nothing else can be done correctly.
+ my %upgradeNeedRemove = (
+ 'libstdc++' => 1,
+ 'compat-glibc' => 1,
+ 'compat-libs' => 1,
+ );
+
+ #- these package are not named as ours, need to be translated before working.
+ #- a version may follow to setup a constraint 'installed version greater than'.
+ my %otherPackageToRename = (
+ 'qt' => [ 'qt2', '2.0' ],
+ 'qt1x' => [ 'qt' ],
+ );
+ #- generel purpose for forcing upgrade of package whatever version is.
+ my %packageNeedUpgrade = (
+ 'lilo' => 1, #- this package has been misnamed in 7.0.
+ );
+
+ #- help removing package which may have different release numbering
+ my %toRemove; map { $toRemove{$_} = 1 } @{$toRemove || []};
+
+ #- help searching package to upgrade in regard to already installed files.
+ my %installedFilesForUpgrade;
+
+ #- help keeping memory by this set of package that have been obsoleted.
+ my %obsoletedPackages;
+
+ #- make a subprocess here for reading filelist, this is important
+ #- not to waste a lot of memory for the main program which will fork
+ #- latter for each transaction.
+ local (*INPUT, *OUTPUT_CHILD); pipe INPUT, OUTPUT_CHILD;
+ local (*INPUT_CHILD, *OUTPUT); pipe INPUT_CHILD, OUTPUT;
+ if (my $pid = fork()) {
+ close INPUT_CHILD;
+ close OUTPUT_CHILD;
+ select((select(OUTPUT), $| = 1)[0]);
+
+ #- internal reading from interactive mode of parsehdlist.
+ #- takes a code to call with the line read, this avoid allocating
+ #- memory for that.
+ my $ask_child = sub {
+ my ($name, $tag, $code) = @_;
+ $code or die "no callback code for parsehdlist output";
+ print OUTPUT "$name:$tag\n";
+
+ local $_;
+ while (<INPUT>) {
+ chomp;
+ /^\s*$/ and last;
+ $code->($_);
+ }
+ };
+
+ #- select packages which obseletes other package, obselete package are not removed,
+ #- should we remove them ? this could be dangerous !
+ foreach (values %{$packages->{names}}) {
+ my $p = $_;
+
+ #- TODO take into account version number and flags (that's why regexp :-)
+ $ask_child->(packageName($p), "obsoletes", sub {
+ if ($_[0] =~ /^(\S*)/ && c::rpmdbNameTraverse($db, $1) > 0) {
+ log::l("selecting " . packageName($p) . " by selection on obsoletes");
+ $obsoletedPackages{$1} = undef;
+ selectPackage($packages, $p);
+ }
+ });
}
- @list;
- };
-
- #- mark all files which are not in /etc/rc.d/ for packages which are already installed but which
- #- are not in the packages list to upgrade.
- #- the 'installed' property will make a package unable to be selected, look at select.
- c::rpmdbTraverse($db, sub {
- my ($header) = @_;
- my $otherPackage = (c::headerGetEntry($header, 'release') !~ /mdk\w*$/ &&
- (c::headerGetEntry($header, 'name'). '-' .
- c::headerGetEntry($header, 'version'). '-' .
- c::headerGetEntry($header, 'release')));
- my $renaming = $otherPackage && $otherPackageToRename{c::headerGetEntry($header, 'name')};
- my $name = $renaming &&
- (!$renaming->[1] || versionCompare(c::headerGetEntry($header, 'version'), $renaming->[1]) >= 0) &&
- $renaming->[0];
- $name and $packageNeedUpgrade{$name} = 1; #- keep in mind to force upgrading this package.
- my $p = $packages->[0]{$name || c::headerGetEntry($header, 'name')};
-
- if ($p) {
- my $version_cmp = versionCompare(c::headerGetEntry($header, 'version'), packageVersion($p));
- my $version_rel_test = $version_cmp > 0 || $version_cmp == 0 &&
- versionCompare(c::headerGetEntry($header, 'release'), packageRelease($p)) >= 0;
- if ($version_rel_test) { #- by default, package selecting are upgrade whatever version is !
- if ($otherPackage && $version_cmp <= 0) {
- log::l("force upgrading $otherPackage since it will not be updated otherwise");
- } else {
- packageSetFlagInstalled($p, 1);
+ #- mark all files which are not in /etc/rc.d/ for packages which are already installed but which
+ #- are not in the packages list to upgrade.
+ #- the 'installed' property will make a package unable to be selected, look at select.
+ c::rpmdbTraverse($db, sub {
+ my ($header) = @_;
+ my $otherPackage = (c::headerGetEntry($header, 'release') !~ /mdk\w*$/ &&
+ (c::headerGetEntry($header, 'name'). '-' .
+ c::headerGetEntry($header, 'version'). '-' .
+ c::headerGetEntry($header, 'release')));
+ my $renaming = $otherPackage && $otherPackageToRename{c::headerGetEntry($header, 'name')};
+ my $name = $renaming &&
+ (!$renaming->[1] || versionCompare(c::headerGetEntry($header, 'version'),
+ $renaming->[1]) >= 0) && $renaming->[0];
+ $name and $packageNeedUpgrade{$name} = 1; #- keep in mind to force upgrading this package.
+ my $p = $packages->{names}{$name || c::headerGetEntry($header, 'name')};
+
+ if ($p) {
+ my $version_cmp = versionCompare(c::headerGetEntry($header, 'version'), packageVersion($p));
+ my $version_rel_test = $version_cmp > 0 || $version_cmp == 0 &&
+ versionCompare(c::headerGetEntry($header, 'release'), packageRelease($p)) >= 0;
+ if ($version_rel_test) { #- by default, package selecting are upgrade whatever version is !
+ if ($otherPackage && $version_cmp <= 0) {
+ log::l("force upgrading $otherPackage since it will not be updated otherwise");
+ } else {
+ #- let the parent known this installed package.
+ print UPGRADE_OUTPUT "installed:" . packageName($p) . "\n";
+ packageSetFlagInstalled($p, 1);
+ }
+ } elsif ($upgradeNeedRemove{packageName($p)}) {
+ my $otherPackage = (c::headerGetEntry($header, 'name'). '-' .
+ c::headerGetEntry($header, 'version'). '-' .
+ c::headerGetEntry($header, 'release'));
+ log::l("removing $otherPackage since it will not upgrade correctly!");
+ $toRemove{$otherPackage} = 1; #- force removing for theses other packages, select our.
}
- } elsif ($upgradeNeedRemove{packageName($p)}) {
- my $otherPackage = (c::headerGetEntry($header, 'name'). '-' .
- c::headerGetEntry($header, 'version'). '-' .
- c::headerGetEntry($header, 'release'));
- log::l("removing $otherPackage since it will not upgrade correctly!");
- $toRemove{$otherPackage} = 1; #- force removing for theses other packages, select our.
- }
- } else {
- my @files = c::headerGetEntry($header, 'filenames');
- @installedFilesForUpgrade{grep { ($_ !~ m|^/etc/rc.d/| &&
- ! -d "$prefix/$_" && ! -l "$prefix/$_") } @files} = ();
- }
- });
-
- #- find new packages to upgrade.
- foreach (values %{$packages->[0]}) {
- my $p = $_;
- my $skipThis = 0;
- my $count = c::rpmdbNameTraverse($db, packageName($p), sub {
- my ($header) = @_;
- $skipThis ||= packageFlagInstalled($p);
- });
-
- #- skip if not installed (package not found in current install).
- $skipThis ||= ($count == 0);
-
- #- make sure to upgrade package that have to be upgraded.
- $packageNeedUpgrade{packageName($p)} and $skipThis = 0;
-
- #- select the package if it is already installed with a lower version or simply not installed.
- unless ($skipThis) {
- my $cumulSize;
-
- selectPackage($packages, $p);
-
- #- keep in mind installed files which are not being updated. doing this costs in
- #- execution time but use less memory, else hash all installed files and unhash
- #- all file for package marked for upgrade.
- c::rpmdbNameTraverse($db, packageName($p), sub {
- my ($header) = @_;
- $cumulSize += c::headerGetEntry($header, 'size'); #- all these will be deleted on upgrade.
+ } else {
+ if (! exists $obsoletedPackages{$name || c::headerGetEntry($header, 'name')}) {
my @files = c::headerGetEntry($header, 'filenames');
@installedFilesForUpgrade{grep { ($_ !~ m|^/etc/rc.d/| &&
! -d "$prefix/$_" && ! -l "$prefix/$_") } @files} = ();
- });
+ }
+ }
+ });
- map { delete $installedFilesForUpgrade{$_} } grep { $_ !~ m|^/etc/rc.d/| } $ask_child->(packageName($p), "files");
+ #- find new packages to upgrade.
+ foreach (values %{$packages->{names}}) {
+ my $p = $_;
+ my $skipThis = 0;
+ my $count = c::rpmdbNameTraverse($db, packageName($p), sub {
+ my ($header) = @_;
+ $skipThis ||= packageFlagInstalled($p);
+ });
- #- keep in mind the cumul size of installed package since they will be deleted
- #- on upgrade.
- $p->{installedCumulSize} = $cumulSize;
- }
- }
+ #- skip if not installed (package not found in current install).
+ $skipThis ||= ($count == 0);
- #- unmark all files for all packages marked for upgrade. it may not have been done above
- #- since some packages may have been selected by depsList.
- foreach (values %{$packages->[0]}) {
- my $p = $_;
+ #- make sure to upgrade package that have to be upgraded.
+ $packageNeedUpgrade{packageName($p)} and $skipThis = 0;
+
+ #- select the package if it is already installed with a lower version or simply not installed.
+ unless ($skipThis) {
+ my $cumulSize;
+
+ selectPackage($packages, $p);
+
+ #- keep in mind installed files which are not being updated. doing this costs in
+ #- execution time but use less memory, else hash all installed files and unhash
+ #- all file for package marked for upgrade.
+ c::rpmdbNameTraverse($db, packageName($p), sub {
+ my ($header) = @_;
+ $cumulSize += c::headerGetEntry($header, 'size');
+ my @files = c::headerGetEntry($header, 'filenames');
+ @installedFilesForUpgrade{grep { ($_ !~ m|^/etc/rc.d/| &&
+ ! -d "$prefix/$_" && ! -l "$prefix/$_") } @files} = ();
+ });
- if (packageFlagSelected($p)) {
- map { delete $installedFilesForUpgrade{$_} } grep { $_ !~ m|^/etc/rc.d/| } $ask_child->(packageName($p), "files");
+ $ask_child->(packageName($p), "files", sub {
+ delete $installedFilesForUpgrade{$_[0]};
+ });
+
+ #- keep in mind the cumul size of installed package since they will be deleted
+ #- on upgrade.
+ print UPGRADE_OUTPUT "$cumulSize:" . packageName($p) . "\n";
+ }
}
- }
- #- select packages which contains marked files, then unmark on selection.
- #- a special case can be made here, the selection is done only for packages
- #- requiring locales if the locales are selected.
- #- another special case are for devel packages where fixes over the time has
- #- made some files moving between the normal package and its devel couterpart.
- #- if only one file is affected, no devel package is selected.
- foreach (values %{$packages->[0]}) {
- my $p = $_;
+ #- unmark all files for all packages marked for upgrade. it may not have been done above
+ #- since some packages may have been selected by depsList.
+ foreach (values %{$packages->{names}}) {
+ my $p = $_;
- unless (packageFlagSelected($p)) {
- my $toSelect = 0;
- map { if (exists $installedFilesForUpgrade{$_}) {
- ++$toSelect if ! -d "$prefix/$_" && ! -l "$prefix/$_"; delete $installedFilesForUpgrade{$_} }
- } grep { $_ !~ m|^/etc/rc.d/| } $ask_child->(packageName($p), "files");
- if ($toSelect) {
- if ($toSelect <= 1 && packageName($p) =~ /-devel/) {
- log::l("avoid selecting " . packageName($p) . " as not enough files will be updated");
- } else {
- #- default case is assumed to allow upgrade.
- my @deps = map { my $p = $packages->[1][$_];
- $p && packageName($p) =~ /locales-/ ? ($p) : () } packageDepsId($p);
- if (@deps == 0 || @deps > 0 && (grep { !packageFlagSelected($_) } @deps) == 0) {
- log::l("selecting " . packageName($p) . " by selection on files");
- selectPackage($packages, $p);
+ if (packageFlagSelected($p)) {
+ $ask_child->(packageName($p), "files", sub {
+ delete $installedFilesForUpgrade{$_[0]};
+ });
+ }
+ }
+
+ #- select packages which contains marked files, then unmark on selection.
+ #- a special case can be made here, the selection is done only for packages
+ #- requiring locales if the locales are selected.
+ #- another special case are for devel packages where fixes over the time has
+ #- made some files moving between the normal package and its devel couterpart.
+ #- if only one file is affected, no devel package is selected.
+ foreach (values %{$packages->{names}}) {
+ my $p = $_;
+
+ unless (packageFlagSelected($p)) {
+ my $toSelect = 0;
+ $ask_child->(packageName($p), "files", sub {
+ if ($_[0] !~ m|^/etc/rc.d/| && exists $installedFilesForUpgrade{$_[0]}) {
+ ++$toSelect if ! -d "$prefix/$_[0]" && ! -l "$prefix/$_[0]";
+ delete $installedFilesForUpgrade{$_[0]};
+ }
+ });
+ if ($toSelect) {
+ if ($toSelect <= 1 && packageName($p) =~ /-devel/) {
+ log::l("avoid selecting " . packageName($p) . " as not enough files will be updated");
} else {
- log::l("avoid selecting " . packageName($p) . " as its locales language is not already selected");
+ #- default case is assumed to allow upgrade.
+ my @deps = map { my $p = $packages->{depslist}[$_];
+ $p && packageName($p) =~ /locales-/ ? ($p) : () } packageDepsId($p);
+ if (@deps == 0 || @deps > 0 && (grep { !packageFlagSelected($_) } @deps) == 0) {
+ log::l("selecting " . packageName($p) . " by selection on files");
+ selectPackage($packages, $p);
+ } else {
+ log::l("avoid selecting " . packageName($p) . " as its locales language is not already selected");
+ }
}
}
}
}
- }
- #- clean memory...
- %installedFilesForUpgrade = ();
+ #- clean memory...
+ %installedFilesForUpgrade = ();
- #- select packages which obseletes other package, obselete package are not removed,
- #- should we remove them ? this could be dangerous !
- foreach (values %{$packages->[0]}) {
+ #- no need to still use the child as this point, we can let him to terminate.
+ close OUTPUT;
+ close INPUT;
+ waitpid $pid, 0;
+ } else {
+ close INPUT;
+ close OUTPUT;
+ open STDIN, "<&INPUT_CHILD";
+ open STDOUT, ">&OUTPUT_CHILD";
+ exec "parsehdlist", "--interactive", map { "/tmp/$_->{hdlist}" } values %{$packages->{mediums}};
+ c::_exit(1);
+ }
+
+ #- let the parent known about what we found here!
+ foreach (values %{$packages->{names}}) {
my $p = $_;
- #- TODO take into account version number and flags (that's why regexp :-)
- foreach (map { /^(\S*)/ ? ($1) : () } $ask_child->(packageName($p), "obsoletes")) {
- if (c::rpmdbNameTraverse($db, $_) > 0) {
- log::l("selecting " . packageName($p) . " by selection on obsoletes");
- selectPackage($packages, $p);
- }
- }
+ print UPGRADE_OUTPUT "select:" . packageName($p) . "\n" if packageFlagSelected($p);
}
- #- no need to still use the child as this point, we can let him to terminate.
- close OUTPUT;
- close INPUT;
- waitpid $pid, 0;
- } else {
- close INPUT;
- close OUTPUT;
- open STDIN, "<&INPUT_CHILD";
- open STDOUT, ">&OUTPUT_CHILD";
- exec "parsehdlist", "--interactive", map { "/tmp/$_->{hdlist}" } values %{$packages->[2]};
- c::_exit(1);
+ #- clean false value on toRemove.
+ delete $toRemove{''};
+
+ #- get filenames that should be saved for packages to remove.
+ #- typically config files, but it may broke for packages that
+ #- are very old when compabilty has been broken.
+ #- but new version may saved to .rpmnew so it not so hard !
+ if ($toSave && keys %toRemove) {
+ c::rpmdbTraverse($db, sub {
+ my ($header) = @_;
+ my $otherPackage = (c::headerGetEntry($header, 'name'). '-' .
+ c::headerGetEntry($header, 'version'). '-' .
+ c::headerGetEntry($header, 'release'));
+ if ($toRemove{$otherPackage}) {
+ print UPGRADE_OUTPUT "remove:$otherPackage\n";
+ if (packageFlagBase($packages->{names}{c::headerGetEntry($header, 'name')})) {
+ delete $toRemove{$otherPackage}; #- keep it selected, but force upgrade.
+ } else {
+ my @files = c::headerGetEntry($header, 'filenames');
+ my @flags = c::headerGetEntry($header, 'fileflags');
+ for my $i (0..$#flags) {
+ if ($flags[$i] & c::RPMFILE_CONFIG()) {
+ print UPGRADE_OUTPUT "keepfiles:$files[$i]\n" unless $files[$i] =~ /kdelnk/;
+ }
+ }
+ }
+ }
+ });
+ }
+
+ #- close db, job finished !
+ c::rpmdbClose($db);
+ log::l("done selecting packages to upgrade");
+
+ close UPGRADE_OUTPUT;
+ c::_exit(0);
}
#- keep a track of packages that are been selected for being upgraded,
- #- these packages should not be unselected.
- foreach (values %{$packages->[0]}) {
+ #- these packages should not be unselected (unless expertise)
+ foreach (values %{$packages->{names}}) {
my $p = $_;
packageSetFlagUpgrade($p, 1) if packageFlagSelected($p);
}
-
- #- clean false value on toRemove.
- delete $toRemove{''};
-
- #- get filenames that should be saved for packages to remove.
- #- typically config files, but it may broke for packages that
- #- are very old when compabilty has been broken.
- #- but new version may saved to .rpmnew so it not so hard !
- if ($toSave && keys %toRemove) {
- c::rpmdbTraverse($db, sub {
- my ($header) = @_;
- my $otherPackage = (c::headerGetEntry($header, 'name'). '-' .
- c::headerGetEntry($header, 'version'). '-' .
- c::headerGetEntry($header, 'release'));
- if ($toRemove{$otherPackage}) {
- if (packageFlagBase($packages->[0]{c::headerGetEntry($header, 'name')})) {
- delete $toRemove{$otherPackage}; #- keep it selected, but force upgrade.
- } else {
- my @files = c::headerGetEntry($header, 'filenames');
- my @flags = c::headerGetEntry($header, 'fileflags');
- for my $i (0..$#flags) {
- if ($flags[$i] & c::RPMFILE_CONFIG()) {
- push @$toSave, $files[$i] unless $files[$i] =~ /kdelnk/; #- avoid doublons for KDE.
- }
- }
- }
- }
- });
- }
-
- #- close db, job finished !
- c::rpmdbClose($db);
- log::l("done selecting packages to upgrade");
-
- #- update external copy with local one.
- @{$toRemove || []} = keys %toRemove;
}
sub allowedToUpgrade { $_[0] !~ /^(kernel|kernel-secure|kernel-smp|kernel-linus|hackkernel)$/ }
@@ -1127,8 +1197,8 @@ sub install($$$;$$) {
my $callbackOpen = sub {
my $p = $packages{$_[0]};
my $f = packageFile($p);
- print LOG "$f $p->{medium}{descr}\n";
- my $fd = install_any::getFile($f, $p->{medium}{descr});
+ print LOG "$f $p->[$MEDIUM]{descr}\n";
+ my $fd = install_any::getFile($f, $p->[$MEDIUM]{descr});
$fd ? fileno $fd : -1;
};
my $callbackClose = sub { packageSetFlagInstalled(delete $packages{$_[0]}, 1) };
@@ -1159,7 +1229,7 @@ sub install($$$;$$) {
while ($i <= $media->{$medium}{max} && ($i < $min || scalar @transToInstall < $limitMinTrans)) {
my $dep = $packages{packageName($depOrder->[$i++])} or next;
- if ($dep->{medium}{selected}) {
+ if ($dep->[$MEDIUM]{selected}) {
push @transToInstall, $dep;
foreach (map { split '\|' } packageDepsId($dep)) {
$min < $_ and $min = $_;
@@ -1186,7 +1256,7 @@ sub install($$$;$$) {
#- reset file descriptor open for main process but
#- make sure error trying to change from hdlist are
#- trown from main process too.
- install_any::getFile(packageFile($transToInstall[0]), $transToInstall[0]{medium}{descr});
+ install_any::getFile(packageFile($transToInstall[0]), $transToInstall[0][$MEDIUM]{descr});
#- and make sure there are no staling open file descriptor too!
install_any::getFile('XXX');
@@ -1228,7 +1298,7 @@ sub install($$$;$$) {
my $trans = c::rpmtransCreateSet($db, $prefix);
log::l("opened rpm database for transaction of ". scalar @transToInstall ." new packages, still $nb after that to do");
- c::rpmtransAddPackage($trans, $_->{header}, packageName($_), $isUpgrade && allowedToUpgrade(packageName($_)))
+ c::rpmtransAddPackage($trans, $_->[$HEADER], packageName($_), $isUpgrade && allowedToUpgrade(packageName($_)))
foreach @transToInstall;
c::rpmdepOrder($trans) or
@@ -1264,15 +1334,15 @@ sub install($$$;$$) {
close OUTPUT;
c::_exit(0);
}
- c::headerFree(delete $_->{header}) foreach @transToInstall;
+ packageFreeHeader($_) foreach @transToInstall;
cleanHeaders($prefix);
- if (my @badpkgs = grep { !packageFlagInstalled($_) && $_->{medium}{selected} && !exists($ignoreBadPkg{packageName($_)}) } @transToInstall) {
+ if (my @badpkgs = grep { !packageFlagInstalled($_) && $_->[$MEDIUM]{selected} && !exists($ignoreBadPkg{packageName($_)}) } @transToInstall) {
foreach (@badpkgs) {
- log::l("bad package $_->{file}");
+ log::l("bad package $_->[$FILE]");
packageSetFlagSelected($_, 0);
}
- cdie ("error installing package list: " . join(", ", map { $_->{file} } @badpkgs));
+ cdie ("error installing package list: " . join(", ", map { $_->[$FILE] } @badpkgs));
}
} while ($nb > 0 && !$pkgs::cancel_install);