summaryrefslogtreecommitdiffstats
path: root/perl-install/do_pkgs.pm
blob: 8b56be26c494de964731759bc8b16e4c1b71c2bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
Diffstat (limited to 'perl-install/detect_devices.pm')
-rw-r--r--perl-install/detect_devices.pm6
1 files changed, 3 insertions, 3 deletions
diff --git a/perl-install/detect_devices.pm b/perl-install/detect_devices.pm
index 4aea403b8..1246fbdb3 100644
--- a/perl-install/detect_devices.pm
+++ b/perl-install/detect_devices.pm
@@ -587,12 +587,12 @@ sub stringlist() {
sub tryOpen($) {
my $F;
- sysopen $F, devices::make($_[0]), c::O_NONBLOCK() and $F;
+ sysopen($F, devices::make($_[0]), c::O_NONBLOCK()) && $F;
}
sub tryWrite($) {
my $F;
- sysopen $F, devices::make($_[0]), 1 | c::O_NONBLOCK() and $F;
+ sysopen($F, devices::make($_[0]), 1 | c::O_NONBLOCK()) && $F;
}
sub syslog() {
@@ -685,7 +685,7 @@ sub probeSerialDevices() {
sub probeSerial($) { $serialprobe{$_[0]} }
sub hasModem($) {
- $serialprobe{$_[0]} and $serialprobe{$_[0]}{CLASS} eq 'MODEM' and $serialprobe{$_[0]}{DESCRIPTION};
+ $serialprobe{$_[0]} && $serialprobe{$_[0]}{CLASS} eq 'MODEM' && $serialprobe{$_[0]}{DESCRIPTION};
}
sub hasMousePS2 {
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
package do_pkgs;

=head1 SYNOPSYS

B<do_pkgs> enables to install packages (through urpmi) from our tools.
It works both during installer and in standalone tools.


=head1 Functions

=over

=cut

=item do_pkgs($in)

Returns a new B<do_pkgs> object from a L<interactive> object.

=cut

sub do_pkgs {
    my ($in) = @_;
    ($::isInstall ? 'do_pkgs_during_install' : 'do_pkgs_standalone')->new($in);
}

################################################################################
package do_pkgs_common;
use common;

=item ensure_is_installed($do, $pkg, $o_file, $b_auto)

Makes sure that the $pkg package is installed.
If $o_file is provided, the already installed check is I<way> faster.
If $b_auto is set, (g)urpmi will not ask any questions.

=cut

sub ensure_is_installed {
    my ($do, $pkg, $o_file, $b_auto) = @_;

    if ($o_file ? -e "$::prefix$o_file" : $do->is_installed($pkg)) {
	return 1;
    }

	$do->in->ask_okcancel(N("Warning"), N("The package %s needs to be installed. Do you want to install it?", $pkg), 1) 
	  or return if !$b_auto && $do->in;

	if (!$do->install($pkg)) {
	    $do->in->ask_warn(N("Error"), N("Could not install the %s package!", $pkg)) if $do->in;
	    return;
	}

    if ($o_file && ! -e "$::prefix$o_file") {
	$do->in->ask_warn(N("Error"), N("Mandatory package %s is missing", $pkg)) if $do->in;
	return;
    }
    1;
}

=item ensure_are_installed($do, $pkgs, $b_auto)

Makes sure that the packages listed in $pkgs array ref are installed.
If $b_auto is set, (g)urpmi will not ask any questions.

It's quite costly, so it's better to use the B<ensure_files_are_installed> instead.

=cut

sub ensure_are_installed {
    my ($do, $pkgs, $b_auto) = @_;

    my @not_installed = difference2($pkgs, [ $do->are_installed(@$pkgs) ]) or return 1;

    $do->in->ask_okcancel(N("Warning"), N("The following packages need to be installed:\n") . join(', ', @not_installed), 1)
	  or return if !$b_auto && $do->in;

    if (!$do->install(@not_installed)) {
	if ($do->in) {
	    $do->in->ask_warn(N("Error"), N("Could not install the %s package!", $not_installed[0]));
	} else {
	    log::l("Could not install packages: " . join(' ', @not_installed));
	}
	return;
    }
    1;
}

=item ensure_binary_is_installed($do, $pkg, $binary, $b_auto)

Makes sure that the $pkg package is installed.
$binary is looked for in $PATH. If not found, the package is installed.
If $b_auto is set, (g)urpmi will not ask any questions.

=cut

sub ensure_binary_is_installed {
    my ($do, $pkg, $binary, $b_auto) = @_;

    if (!whereis_binary($binary, $::prefix)) {
	$do->in->ask_okcancel(N("Warning"), N("The package %s needs to be installed. Do you want to install it?", $pkg), 1) 
	  or return if !$b_auto && $do->in;
	if (!$do->install($pkg)) {
            $do->in->ask_warn(N("Error"), N("Could not install the %s package!", $pkg)) if $do->in;
	    return;
	}
    }
    if (!whereis_binary($binary, $::prefix)) {
        $do->in->ask_warn(N("Error"), N("Mandatory package %s is missing", $pkg)) if $do->in;
	return;
    }
    1;
}

sub _find_file {
    my ($file) = @_;
    if ($file =~ m!/!) {
	-e "$::prefix$file";
    } else {
	# assume it's a binary to search in $PATH:
	whereis_binary($file, $prefix);
    }
}

=item ensure_files_are_installed($do, $pkgs, $b_auto)

Takes a list of [ "package", "file" ] and installs package if file is not there.
If $b_auto is set, (g)urpmi will not ask any questions.

=cut

sub ensure_files_are_installed {
    my ($do, $pkgs, $b_auto) = @_;

    my @not_installed = map { my ($package, $file) = @$_; if_(!_find_file($file), $package) } @$pkgs;
    return 1 if !@not_installed;

    $do->in->ask_okcancel(N("Warning"), N("The following packages need to be installed:\n") . join(', ', @not_installed), 1)
	  or return if !$b_auto && $do->in;

    if (!$do->install(@not_installed)) {
	if ($do->in) {
	    $do->in->ask_warn(N("Error"), N("Could not install the %s package!", $not_installed[0]));
	} else {
	    log::l("Could not install packages: " . join(' ', @not_installed));
	}
	return;
    }
    1;
}

=item ensure_is_installed_if_available($do, $pkg, $file) = @_;

Install $pkg if $file is not present and if $pkg is actually known to urpmi.

=cut

sub ensure_is_installed_if_available {
    my ($do, $pkg, $file) = @_;
    if (-e "$::prefix$file" || $::testing) {
	1;
    } else {
        $do->what_provides($pkg) && $do->install($pkg);
    }
}

=item is_available($do, $name)

=item are_available($do, @names)

Returns name(s) of package(s) that are available (aka known to urpmi).
This is somewhat costly (needs to parse urpmi synthesis...)

=cut

sub is_available {
    my ($do, $name) = @_;
    $do->are_available($name);
}

=item is_installed($do, $name)

=item are_installed($do, @names)

Returns name(s) of package(s) that are already installed on the system.
This is less costly (needs to query RPM DB)

=cut

sub is_installed {
    my ($do, $name) = @_;
    $do->are_installed($name);
}

=item check_kernel_module_packages($do, $base_name)

Takes something like "C<ati-kernel>" and returns:

=over 4

=item * the various C<ati-kernel-3.Y.XX-ZZmga> available for the installed kernels

=item * C<dkms-ati> if available

=back

=cut

sub check_kernel_module_packages {
    my ($do, $base_name) = @_;
    
    require bootloader;
    my @test_rpms = (
	'dkms-' . $base_name,
	map { $base_name . '-kernel-' . bootloader::vmlinuz2version($_) } bootloader::installed_vmlinuz()
    );
    my @rpms = $do->are_available(@test_rpms);
    @rpms = $do->are_installed(@test_rpms) if !@rpms;
    @rpms or return;

    log::l("those kernel module packages can be installed: " . join(' ', @rpms));

    \@rpms;
}

################################################################################
package do_pkgs_during_install;
use run_program;
use common;

our @ISA = qw(do_pkgs_common);

=item new($type, $in)

Returns a C<do_pkg> object.

=cut

sub new {
    my ($type, $in) = @_;

    $in->isa('interactive') or undef $in;

    require install::pkgs;
    bless { in => $in, o => $::o }, $type;
}

sub in {
    my ($do) = @_;
    $do->{in};
}

sub install {
    my ($do, @l) = @_;
    log::l("do_pkgs_during_install::install");
    if ($::testing) {
	log::l("i would install packages " . join(' ', @l));
	1;
    } else {
	$do->{o}->pkg_install(@l);
	1; #- HACK, need better fix in install::steps::pkg_install()
    }
}

sub what_provides {
    my ($do, $name) = @_;
    map { $_->name } install::pkgs::packagesProviding($do->{o}{packages}, $name);
}

sub are_available {
    my ($do, @pkgs) = @_;
    grep { install::pkgs::packageByName($do->{o}{packages}, $_) } @pkgs;
}

sub are_installed {
    my ($do, @l) = @_;
    grep {
	my $p = install::pkgs::packageByName($do->{o}{packages}, $_);
	$p && $p->flag_available;
    } @l;
}

sub remove {
    my ($do, @l) = @_;

    @l = grep {
	my $p = install::pkgs::packageByName($do->{o}{packages}, $_);
	install::pkgs::unselectPackage($do->{o}{packages}, $p) if $p;
	$p;
    } @l;
    run_program::rooted($::prefix, 'rpm', '-e', @l);
}

sub remove_nodeps {
    my ($do, @l) = @_;

    @l = grep {
	my $p = install::pkgs::packageByName($do->{o}{packages}, $_);
	if ($p) {
	    $p->set_flag_requested(0);
	    $p->set_flag_required(0);
	}
	$p;
    } @l;
    run_program::rooted($::prefix, 'rpm', '-e', '--nodeps', @l);
}

################################################################################
package do_pkgs_standalone;
use run_program;
use common;
use log;
use feature qw(state);

our @ISA = qw(do_pkgs_common);

sub new {
    my ($type, $o_in) = @_;
    bless { in => $o_in }, $type;
}

sub in {
    my ($do) = @_;
    $do->{in};
}

sub install {
    my ($do, @l) = @_;

    return 1 if listlength(are_installed($do, @l)) == @l;

    if ($::testing) {
	log::l("i would install packages " . join(' ', @l));
	return 1;
    }

    my @options = ('--allow-medium-change', '--auto', '--no-verify-rpm', '--expect-install', @l);
    my $ret;
    if (check_for_xserver() && -x '/usr/bin/gurpmi') {
        $ret = system('gurpmi', @options) == 0;
    } else {
        my $_wait = $do->in && $do->in->wait_message(N("Please wait"), N("Installing packages..."));
        $do->in->suspend if $do->in;
        log::explanations("installing packages @l");
        $ret = system('urpmi', @options) == 0;
        $do->in->resume if $do->in;
    }
    $ret;
}

sub are_available {
    my ($_do, @pkgs) = @_;
    my %pkgs = map { $_ => 1 } @pkgs;

    require urpm::media;
    state $urpm;
    eval {
	if (!$urpm) {
	    $urpm = urpm->new;
	    $urpm->{log} = \&log::l;
	    urpm::media::configure($urpm, 
				   nocheck_access => 1,
				   no_skiplist => 1,
				   no_second_pass => 1);
	}
	map { $_->name } grep { $pkgs{$_->name} } @{$urpm->{depslist} || []};
    };
}

sub what_provides {
    my ($_do, $name) = @_;
    split('\|', chomp_(run_program::get_stdout('urpmq', $name)));
}

sub are_installed {
    my ($_do, @l) = @_;
    @l or return;

    my @l2;
    my $query_all = (any { /\*/ } @l) ? 'a' : '';
    run_program::run('/bin/rpm', '>', \@l2, '-q' . $query_all, '--qf', "%{name}\n", @l); #- do not care about the return value
    $query_all ? chomp_(@l2) : intersection(\@l, [ chomp_(@l2) ]); #- cannot return directly @l2 since it contains things like "package xxx is not installed"
}

sub remove {
    my ($do, @l) = @_;
    my $_wait = $do->in && $do->in->wait_message(N("Please wait"), N("Removing packages..."));
    $do->in->suspend if $do->in;
    log::explanations("removing packages @l");
    my $ret = system('rpm', '-e', @l) == 0;
    $do->in->resume if $do->in;
    $ret;
}

sub remove_nodeps {
    my ($do, @l) = @_;
    remove($do, '--nodeps', @l) == 0;
}

=back

=cut