summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--urpm.pm213
1 files changed, 200 insertions, 13 deletions
diff --git a/urpm.pm b/urpm.pm
index bd35a4b2..cef92dee 100644
--- a/urpm.pm
+++ b/urpm.pm
@@ -3,7 +3,7 @@ package urpm;
use strict;
use vars qw($VERSION @ISA);
-$VERSION = '1.30';
+$VERSION = '1.40';
=head1 NAME
@@ -61,6 +61,7 @@ sub new {
provides => "/var/lib/urpmi/provides",
compss => "/var/lib/urpmi/compss",
statedir => "/var/lib/urpmi",
+ cachedir => "/var/cache/urpmi",
media => undef,
params => new rpmtools,
@@ -362,6 +363,10 @@ sub select_media {
#- update urpmi database regarding the current configuration.
#- take care of modification and try some trick to bypass
#- computational of base files.
+#- allow options :
+#- all -> all medium are rebuilded
+#- force -> try to force rebuilding from rpms files.
+#- noclean -> keep header directory cleaned.
sub update_media {
my ($urpm, %options) = @_; #- do not trust existing hdlist and try to recompute them.
@@ -374,7 +379,7 @@ sub update_media {
foreach my $medium (@{$urpm->{media}}) {
#- take care of modified medium only or all if all have to be recomputed.
$medium->{ignore} and next;
- $options{all} || $medium->{modified} or next;
+ $medium->{modified} ||= $options{all} or next;
#- list of rpm files for this medium, only available for local medium where
#- the source hdlist is not used (use force).
@@ -389,9 +394,23 @@ sub update_media {
#- if the source hdlist is present and we are not forcing using rpms file
if (!$options{force} && $medium->{with_hdlist} && -e "$dir/$medium->{with_hdlist}") {
- system("cp", "-f", "$dir/$medium->{with_hdlist}", "$urpm->{statedir}/.$medium->{hdlist}");
- -s "$urpm->{statedir}/.$medium->{hdlist}"
+ unlink "$urpm->{cachedir}/partial/$medium->{hdlist}";
+ system("cp", "-a", "$dir/$medium->{with_hdlist}", "$urpm->{cachedir}/partial/$medium->{hdlist}");
+
+ -s "$urpm->{cachedir}/partial/$medium->{hdlist}"
or $error = 1, $urpm->{error}("copy of [$dir/$medium->{with_hdlist}] failed");
+
+ #- check if the file are equals...
+ unless ($error) {
+ my @sstat = stat "$urpm->{cachedir}/partial/$medium->{hdlist}";
+ my @lstat = stat "$urpm->{statedir}/$medium->{hdlist}";
+ if ($sstat[7] == $lstat[7] && $sstat[9] == $lstat[9]) {
+ #- the two files are considered equal here, the medium is so not modified.
+ $medium->{modified} = 0;
+ unlink "$urpm->{cachedir}/partial/$medium->{hdlist}";
+ next;
+ }
+ }
} else {
#- try to find rpm files, use recursive method, added additional
#- / after dir to make sure it will be taken into account if this
@@ -401,15 +420,39 @@ sub update_media {
#- check files contains something good!
if (@files > 0) {
#- we need to rebuild from rpm files the hdlist.
- $urpm->{params}->build_hdlist("$urpm->{statedir}/.$medium->{hdlist}", @files);
+ eval {
+ $urpm->{log}("building hdlist [$urpm->{cachedir}/partial/$medium->{hdlist}]");
+ $urpm->{params}->build_hdlist($options{noclean}, "$urpm->{cachedir}/headers",
+ "$urpm->{cachedir}/partial/$medium->{hdlist}", @files);
+ };
+ $@ and $error = 1, $urpm->{error}("unable to build hdlist: $@");
} else {
$error = 1;
$urpm->{error}("no rpm files found from [$dir/]");
}
}
} else {
- system("wget", "-O", "$urpm->{statedir}/.$medium->{hdlist}", "$medium->{url}/$medium->{with_hdlist}");
+ my $basename = $medium->{with_hdlist} =~ /^.*\/([^\/]*)$/ && $1;
+
+ #- try to sync (copy if needed) local copy after restored the previous one.
+ unlink "$urpm->{cachedir}/partial/$basename";
+ $options{force} or
+ system("cp", "-a", "$urpm->{statedir}/$medium->{hdlist}", "$urpm->{cachedir}/partial/$basename");
+ system("wget", "-NP", "$urpm->{cachedir}/partial", "$medium->{url}/$medium->{with_hdlist}");
$? == 0 or $error = 1, $urpm->{error}("wget of [<source_url>/$medium->{with_hdlist}] failed (maybe wget is missing?)");
+ unless ($error) {
+ my @sstat = stat "$urpm->{cachedir}/partial/$basename";
+ my @lstat = stat "$urpm->{statedir}/$medium->{hdlist}";
+ if ($sstat[7] == $lstat[7] && $sstat[9] == $lstat[9]) {
+ #- the two files are considered equal here, the medium is so not modified.
+ $medium->{modified} = 0;
+ unlink "$urpm->{cachedir}/partial/$basename";
+ next;
+ }
+
+ #- the file are different, update local copy.
+ rename "$urpm->{cachedir}/partial/$basename", "$urpm->{cachedir}/partial/$medium->{hdlist}";
+ }
}
#- build list file according to hdlist used.
@@ -417,7 +460,7 @@ sub update_media {
unless ($error) {
local *LIST;
my $mask = umask 077;
- open LIST, ">$urpm->{statedir}/.$medium->{list}"
+ open LIST, ">$urpm->{cachedir}/partial/$medium->{list}"
or $error = 1, $urpm->{error}("unable to write list file of \"$medium->{name}\"");
umask $mask;
if (@files) {
@@ -426,7 +469,7 @@ sub update_media {
}
} else {
local (*F, $_);
- open F, "parsehdlist '$urpm->{statedir}/.$medium->{hdlist}' |";
+ open F, "parsehdlist '$urpm->{cachedir}/partial/$medium->{hdlist}' |";
while (<F>) {
print LIST "$medium->{url}/$_";
}
@@ -435,14 +478,14 @@ sub update_media {
close LIST;
#- check if at least something has been written into list file.
- -s "$urpm->{statedir}/.$medium->{list}"
+ -s "$urpm->{cachedir}/partial/$medium->{list}"
or $error = 1, $urpm->{error}("nothing written in list file for \"$medium->{name}\"");
}
if ($error) {
#- an error has occured for updating the medium, we have to remove tempory files.
- unlink "$urpm->{statedir}/.$medium->{hdlist}";
- unlink "$urpm->{statedir}/.$medium->{list}";
+ unlink "$urpm->{cachedir}/partial/$medium->{hdlist}";
+ unlink "$urpm->{cachedir}/partial/$medium->{list}";
} else {
#- make sure to rebuild base files and clean medium modified state.
$medium->{modified} = 0;
@@ -451,8 +494,8 @@ sub update_media {
#- but use newly created file.
unlink "$urpm->{statedir}/$medium->{hdlist}";
unlink "$urpm->{statedir}/$medium->{list}";
- rename "$urpm->{statedir}/.$medium->{hdlist}", "$urpm->{statedir}/$medium->{hdlist}";
- rename "$urpm->{statedir}/.$medium->{list}", "$urpm->{statedir}/$medium->{list}";
+ rename "$urpm->{cachedir}/partial/$medium->{hdlist}", "$urpm->{statedir}/$medium->{hdlist}";
+ rename "$urpm->{cachedir}/partial/$medium->{list}", "$urpm->{statedir}/$medium->{list}";
}
}
@@ -832,5 +875,149 @@ sub filter_packages_to_upgrade {
$packages;
}
+#- select source for package selected.
+#- according to keys given in the packages hash.
+#- return a list of list containing the source description for each rpm,
+#- match exactly the number of medium registered, ignored medium always
+#- have a null list.
+sub get_source_packages {
+ my ($urpm, $packages) = @_;
+ my ($error, @local_sources, @list, %select);
+ local (*D, *F, $_);
+
+ #- examine the local repository, which is trusted.
+ opendir D, "$urpm->{cachedir}/rpms";
+ while (defined($_ = readdir D)) {
+ if (/([^\/]*)-([^-]*)-([^-]*)\.([^\.]*)\.rpm/) {
+ my $pkg = $urpm->{params}{info}{$1};
+
+ #- check version, release and id selected.
+ #- TODO arch is not checked at this point.
+ $pkg->{version} cmp $2 && $pkg->{release} cmp $3 or next;
+ exists $packages->{$pkg->{id}} or next;
+
+ #- make sure only the first matching is taken...
+ exists $select{$pkg->{id}} and next; $select{$pkg->{id}} = undef;
+
+ #- we have found one source for id.
+ push @local_sources, "$urpm->{cachedir}/rpms/$1-$2-$3.$4.rpm";
+ } else {
+ $error = 1;
+ $urpm->{error}("unable to determine rpms cache directory $urpm->{cachedir}/rpms");
+ }
+ }
+ closedir D;
+
+ #- examine each medium to search for packages.
+ foreach my $medium (@{$urpm->{media} || []}) {
+ my @sources;
+
+ if (-r "$urpm->{statedir}/$medium->{hdlist}" && -r "$urpm->{statedir}/$medium->{list}" && !$medium->{ignore}) {
+ open F, "$urpm->{statedir}/$medium->{list}";
+ while (<F>) {
+ if (/(.*)\/([^\/]*)-([^-]*)-([^-]*)\.([^\.]*)\.rpm/) {
+ my $pkg = $urpm->{params}{info}{$2};
+
+ #- check version, release and id selected.
+ #- TODO arch is not checked at this point.
+ $pkg->{version} cmp $3 && $pkg->{release} cmp $4 or next;
+ exists $packages->{$pkg->{id}} or next;
+
+ #- make sure only the first matching is taken...
+ exists $select{$pkg->{id}} and next; $select{$pkg->{id}} = undef;
+
+ #- we have found one source for id.
+ push @sources, "$1/$2-$3-$4.$5.rpm";
+ } else {
+ $error = 1;
+ $urpm->{error}("unable to parse correctly $urpm->{statedir}/$medium->{list}");
+ last;
+ }
+ }
+ close F;
+ }
+ push @list, \@sources;
+ }
+
+ #- examine package list to see if a package has not been found.
+ foreach (keys %$packages) {
+ exists $select{$_} and next;
+
+ #- error found as a package has not be selected.
+ $error = 1;
+
+ #- try to find which one.
+ my $pkg = $urpm->{params}{depslist}[$_];
+ if ($pkg) {
+ $urpm->{error}("internal error for selecting unknown package for id=$_");
+ } else {
+ $urpm->{error}("package $pkg->{name}-$pkg->{version}-$pkg->{release} is not found");
+ }
+ }
+
+ $error ? () : ( \@local_sources, \@list );
+}
+
+#- upload package that may need to be uploaded.
+#- make sure header are available in the appropriate directory.
+#- change location to find the right package in the local
+#- filesystem for only one transaction.
+#- try to mount/eject removable media here.
+#- return a hash saying if a package has been uploaded or is local.
+sub upload_packages_for_install {
+ my ($urpm, $local_sources, $list) = @_;
+
+ #- make sure everything is correct on input...
+ @{$urpm->{media}} == @$list or return;
+
+ #- removable media have to be examined to keep mounted the one that has
+ #- more package than other (size is better ?).
+ my %removables;
+ foreach (0..$#$list) {
+ @{$list->[$_]} || $urpm->{media}[$_]{removable} or next;
+ push @{$removables{$urpm->{media}[$_]{removable}} ||= []}, $_;
+ }
+ foreach (keys %removables) {
+ #- here we have only removable device.
+ #- if more than one media use this device, we have to sort
+ #- needed package to copy first the needed rpms files.
+ if (@{$removables{$_}} > 1) {
+ my @sorted_media = sort { @{$list->[$a]} <=> @{$list->[$b]} } @{$removables{$_}};
+
+ #- mount all except the biggest one.
+ foreach (@sorted_media[0 .. $#sorted_media-1]) {
+ my $medium = $urpm->{media}[$_];
+ if (my ($prefix, $dir) = $medium->{url} =~ /^(removable_.*?|file):\/(.*)/) {
+ #- the directory given does not exist or may be accessible
+ #- by mounting some other. try to figure out these directory and
+ #- mount everything necessary.
+ $urpm->try_mounting($dir);
+
+ #- TODO to cut... and ask if correct to the user
+ system("cp", "-a", map { /^(removable_.*?|file):\/(.*)/ && $1 } @{$list->[$_]}, "$urpm->{cachedir}/rpms");
+ } else {
+ #- we have a removable device that is not removable, well...
+ $urpm->{error}("incoherent medium \"$medium->{name}\" marked removable but not really");
+ }
+ }
+ #- now mount the last one...
+ $removables{$_} = [ $sorted_media[-1] ];
+ }
+
+ #- mount the removable device, only one or the important one.
+ my $i = $removables{$_}[0];
+ if (my ($prefix, $dir) = $urpm->{media}[$i]{url} =~ /^(removable_.*?|file):\/(.*)/) {
+ $urpm->try_mounting($dir);
+ system("cp", "-a", map { /^(removable_.*?|file):\/(.*)/ && $1 } @{$list->[$i]}, "$urpm->{cachedir}/rpms");
+ } else {
+ #- we have a removable device that is not removable, well...
+ $urpm->{error}("incoherent medium \"$urpm->{media}[$i]{name}\" marked removable but not really");
+ }
+ }
+
+ #- get back all ftp and http accessible rpms file into the local cache.
+ #- TODO
+}
+
1;