| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package urpm::install; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 | 1 |  |  | 1 |  | 1634 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 53 |  | 
| 5 | 1 |  |  | 1 |  | 28 | use urpm; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | use urpm::msg; | 
| 7 |  |  |  |  |  |  | use urpm::util qw(cat_utf8 member); | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | =head1 NAME | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | urpm::install - Package installation transaction routines for urpmi | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | =over | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =cut | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # size of the installation progress bar | 
| 23 |  |  |  |  |  |  | my $progress_size = 45; | 
| 24 |  |  |  |  |  |  | if (-t *STDOUT) { | 
| 25 |  |  |  |  |  |  | eval { | 
| 26 |  |  |  |  |  |  | require Term::ReadKey; | 
| 27 |  |  |  |  |  |  | ($progress_size) = Term::ReadKey::GetTerminalSize(); | 
| 28 |  |  |  |  |  |  | $progress_size -= 35; | 
| 29 |  |  |  |  |  |  | $progress_size < 5 and $progress_size = 5; | 
| 30 |  |  |  |  |  |  | }; | 
| 31 |  |  |  |  |  |  | } | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | sub _hash_intersect_list { | 
| 35 |  |  |  |  |  |  | my ($h, $l) = @_; | 
| 36 |  |  |  |  |  |  | my %h; | 
| 37 |  |  |  |  |  |  | foreach (@$l) { | 
| 38 |  |  |  |  |  |  | exists $h->{$_} and $h{$_} = $h->{$_}; | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  | \%h; | 
| 41 |  |  |  |  |  |  | } | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | =item prepare_transaction($set, $blists, $sources) | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | =cut | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | sub prepare_transaction { | 
| 49 |  |  |  |  |  |  | my ($set, $blists, $sources) = @_; | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | my @blists_subset = map { | 
| 52 |  |  |  |  |  |  | +{ %$_, pkgs => _hash_intersect_list($_->{pkgs}, $set->{upgrade}) }; | 
| 53 |  |  |  |  |  |  | } @$blists; | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | \@blists_subset, _hash_intersect_list($sources, $set->{upgrade}); | 
| 56 |  |  |  |  |  |  | } | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | sub build_transaction_set_ { | 
| 59 |  |  |  |  |  |  | my ($urpm, $state, %options) = @_; | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | if ($urpm->{parallel_handler} || !$options{split_length} || | 
| 62 |  |  |  |  |  |  | keys %{$state->{selected}} < $options{split_level}) { | 
| 63 |  |  |  |  |  |  | #- build simplest transaction (no split). | 
| 64 |  |  |  |  |  |  | $urpm->build_transaction_set(undef, $state, split_length => 0); | 
| 65 |  |  |  |  |  |  | } else { | 
| 66 |  |  |  |  |  |  | my $db = urpm::db_open_or_die_($urpm); | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | my $sig_handler = sub { undef $db; exit 3 }; | 
| 69 |  |  |  |  |  |  | local $SIG{INT} = $sig_handler; | 
| 70 |  |  |  |  |  |  | local $SIG{QUIT} = $sig_handler; | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | #- build transaction set... | 
| 73 |  |  |  |  |  |  | $urpm->build_transaction_set($db, $state, split_length => $options{split_length}, keep => $options{keep}); | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | sub transaction_set_to_string { | 
| 78 |  |  |  |  |  |  | my ($urpm, $set) = @_; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | my $format_list = sub { int(@_) . '=' . join(',', @_) }; | 
| 81 |  |  |  |  |  |  | map { | 
| 82 |  |  |  |  |  |  | sprintf('remove=%s update=%s', | 
| 83 |  |  |  |  |  |  | $format_list->(@{$_->{remove} || []}), | 
| 84 |  |  |  |  |  |  | $format_list->(map { $urpm->{depslist}[$_]->name } @{$_->{upgrade} || []})); | 
| 85 |  |  |  |  |  |  | } @$set; | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | =item install_logger($urpm, $type, $id, $subtype, $amount, $total) | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | Standard logger for transactions | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | See L for parameters | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | =cut | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | # install logger callback | 
| 97 |  |  |  |  |  |  | my ($erase_logger, $index, $total_pkg, $uninst_count, $current_pkg); | 
| 98 |  |  |  |  |  |  | sub install_logger { | 
| 99 |  |  |  |  |  |  | my ($urpm, $type, undef, $subtype, $amount, $total) = @_; | 
| 100 |  |  |  |  |  |  | local $| = 1; | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | if ($subtype eq 'start') { | 
| 103 |  |  |  |  |  |  | $urpm->{logger_progress} = 0; | 
| 104 |  |  |  |  |  |  | if ($type eq 'trans') { | 
| 105 |  |  |  |  |  |  | $total_pkg = $urpm->{nb_install}; | 
| 106 |  |  |  |  |  |  | $urpm->{logger_count} ||= 0; | 
| 107 |  |  |  |  |  |  | $uninst_count = 0; | 
| 108 |  |  |  |  |  |  | my $p = N("Preparing..."); | 
| 109 |  |  |  |  |  |  | print $p, " " x (33 - length $p); | 
| 110 |  |  |  |  |  |  | } else { | 
| 111 |  |  |  |  |  |  | my $pname; | 
| 112 |  |  |  |  |  |  | my $cnt; | 
| 113 |  |  |  |  |  |  | if ($type eq 'uninst') { | 
| 114 |  |  |  |  |  |  | $total_pkg = $urpm->{trans}->NElements - $index if !$uninst_count; | 
| 115 |  |  |  |  |  |  | $cnt = ++$uninst_count; | 
| 116 |  |  |  |  |  |  | $pname = N("removing %s", $current_pkg); | 
| 117 |  |  |  |  |  |  | $erase_logger->($urpm, undef, undef, $subtype); | 
| 118 |  |  |  |  |  |  | } else { | 
| 119 |  |  |  |  |  |  | $pname = $urpm->{trans}->Element_name($index); | 
| 120 |  |  |  |  |  |  | ++$urpm->{logger_count} if $pname; | 
| 121 |  |  |  |  |  |  | $cnt = $pname ? $urpm->{logger_count} : '-'; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  | my $s = sprintf("%9s: %-22s", $cnt . "/" . $total_pkg, $pname); | 
| 124 |  |  |  |  |  |  | print $s; | 
| 125 |  |  |  |  |  |  | $s =~ / $/ or printf "\n%9s  %-22s", '', ''; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  | } elsif ($subtype eq 'stop') { | 
| 128 |  |  |  |  |  |  | if ($urpm->{logger_progress} < $progress_size) { | 
| 129 |  |  |  |  |  |  | $urpm->{print}('#' x ($progress_size - $urpm->{logger_progress})); | 
| 130 |  |  |  |  |  |  | $urpm->{logger_progress} = 0; | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  | } elsif ($subtype eq 'progress') { | 
| 133 |  |  |  |  |  |  | my $new_progress = $total > 0 ? int($progress_size * $amount / $total) : $progress_size; | 
| 134 |  |  |  |  |  |  | if ($new_progress > $urpm->{logger_progress}) { | 
| 135 |  |  |  |  |  |  | print '#' x ($new_progress - $urpm->{logger_progress}); | 
| 136 |  |  |  |  |  |  | $urpm->{logger_progress} = $new_progress; | 
| 137 |  |  |  |  |  |  | $urpm->{logger_progress} == $progress_size and print "\n"; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | =item get_README_files($urpm, $trans, $pkg) | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | =cut | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | sub get_README_files { | 
| 147 |  |  |  |  |  |  | my ($urpm, $trans, $pkg) = @_; | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | foreach my $file ($pkg->doc_files) { | 
| 150 |  |  |  |  |  |  | my ($kind) = $file =~ m!/README([^/]*)\.urpmi$! or next; | 
| 151 |  |  |  |  |  |  | my $valid; | 
| 152 |  |  |  |  |  |  | if ($kind eq '') { | 
| 153 |  |  |  |  |  |  | $valid = 1; | 
| 154 |  |  |  |  |  |  | } elsif ($kind eq '.install' && !$pkg->flag_installed) { | 
| 155 |  |  |  |  |  |  | $valid = 1; | 
| 156 |  |  |  |  |  |  | } elsif ($kind =~ /(.*)\.(upgrade|update)$/ && $pkg->flag_installed) { | 
| 157 |  |  |  |  |  |  | if (!$1) { | 
| 158 |  |  |  |  |  |  | $valid = 1; | 
| 159 |  |  |  |  |  |  | } else { | 
| 160 |  |  |  |  |  |  | my $version = $1; | 
| 161 |  |  |  |  |  |  | foreach my $i (0 .. $trans->NElements - 1) { | 
| 162 |  |  |  |  |  |  | $trans->Element_name($i) eq $pkg->name or next; | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | # handle README.-.upgrade.urpmi: | 
| 165 |  |  |  |  |  |  | # the content is displayed when upgrading from rpm older than | 
| 166 |  |  |  |  |  |  | my $vr = $trans->Element_version($i) . '-' . $trans->Element_release($i); | 
| 167 |  |  |  |  |  |  | if (URPM::ranges_overlap("== $vr", "< $version")) { | 
| 168 |  |  |  |  |  |  | $valid = 1; | 
| 169 |  |  |  |  |  |  | last; | 
| 170 |  |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  | $valid and $urpm->{readmes}{$file} = $pkg->fullname; | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | sub options { | 
| 179 |  |  |  |  |  |  | my ($urpm) = @_; | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | ( | 
| 182 |  |  |  |  |  |  | excludepath => $urpm->{options}{excludepath}, | 
| 183 |  |  |  |  |  |  | excludedocs => $urpm->{options}{excludedocs}, | 
| 184 |  |  |  |  |  |  | post_clean_cache => $urpm->{options}{'post-clean'}, | 
| 185 |  |  |  |  |  |  | nosize => $urpm->{options}{ignoresize}, | 
| 186 |  |  |  |  |  |  | ignorearch => $urpm->{options}{ignorearch}, | 
| 187 |  |  |  |  |  |  | noscripts => $urpm->{options}{noscripts}, | 
| 188 |  |  |  |  |  |  | replacefiles => $urpm->{options}{replacefiles}, | 
| 189 |  |  |  |  |  |  | ); | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | sub _schedule_packages_for_erasing { | 
| 193 |  |  |  |  |  |  | my ($urpm, $trans, $remove) = @_; | 
| 194 |  |  |  |  |  |  | foreach (@$remove) { | 
| 195 |  |  |  |  |  |  | if ($trans->remove($_)) { | 
| 196 |  |  |  |  |  |  | $urpm->{debug} and $urpm->{debug}("trans: scheduling removal of $_"); | 
| 197 |  |  |  |  |  |  | } else { | 
| 198 |  |  |  |  |  |  | $urpm->{error}("unable to remove package " . $_); | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  | } | 
| 201 |  |  |  |  |  |  | } | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | sub _apply_delta_rpm { | 
| 204 |  |  |  |  |  |  | my ($urpm, $path, $mode, $pkg) = @_; | 
| 205 |  |  |  |  |  |  | my $true_rpm = urpm::sys::apply_delta_rpm($path, "$urpm->{cachedir}/rpms", $pkg); | 
| 206 |  |  |  |  |  |  | my $true_pkg; | 
| 207 |  |  |  |  |  |  | if ($true_rpm) { | 
| 208 |  |  |  |  |  |  | if (my ($id) = $urpm->parse_rpm($true_rpm)) { | 
| 209 |  |  |  |  |  |  | $true_pkg = defined $id && $urpm->{depslist}[$id]; | 
| 210 |  |  |  |  |  |  | $mode->{$id} = $true_rpm; | 
| 211 |  |  |  |  |  |  | } else { | 
| 212 |  |  |  |  |  |  | $urpm->{error}("Failed to parse $true_pkg"); | 
| 213 |  |  |  |  |  |  | } | 
| 214 |  |  |  |  |  |  | } else { | 
| 215 |  |  |  |  |  |  | $urpm->{error}(N("unable to extract rpm from delta-rpm package %s", $path)); | 
| 216 |  |  |  |  |  |  | } | 
| 217 |  |  |  |  |  |  | $true_rpm, $true_pkg; | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | sub _schedule_packages { | 
| 221 |  |  |  |  |  |  | my ($urpm, $trans, $install, $upgrade, %options) = @_; | 
| 222 |  |  |  |  |  |  | my $update = 0; | 
| 223 |  |  |  |  |  |  | my (@trans_pkgs, @produced_deltas); | 
| 224 |  |  |  |  |  |  | foreach my $mode ($install, $upgrade) { | 
| 225 |  |  |  |  |  |  | foreach (keys %$mode) { | 
| 226 |  |  |  |  |  |  | my $pkg = $urpm->{depslist}[$_]; | 
| 227 |  |  |  |  |  |  | $pkg->update_header($mode->{$_}, keep_all_tags => 1); | 
| 228 |  |  |  |  |  |  | my ($true_rpm, $true_pkg); | 
| 229 |  |  |  |  |  |  | if ($pkg->payload_format eq 'drpm') { #- handle deltarpms | 
| 230 |  |  |  |  |  |  | ($true_rpm, $true_pkg) = _apply_delta_rpm($urpm, $mode->{$_}, $mode, $pkg); | 
| 231 |  |  |  |  |  |  | push @produced_deltas, ($mode->{$_} = $true_rpm); #- fix path | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  | if ($trans->add($true_pkg || $pkg, update => $update, | 
| 234 |  |  |  |  |  |  | $options{excludepath} ? (excludepath => [ split /,/, $options{excludepath} ]) : ())) { | 
| 235 |  |  |  |  |  |  | $urpm->{debug} and $urpm->{debug}( | 
| 236 |  |  |  |  |  |  | sprintf('trans: scheduling %s of %s (id=%d, file=%s)', | 
| 237 |  |  |  |  |  |  | $update ? 'update' : 'install', | 
| 238 |  |  |  |  |  |  | scalar($pkg->fullname), $_, $mode->{$_})); | 
| 239 |  |  |  |  |  |  | push @trans_pkgs, $pkg; | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | } else { | 
| 242 |  |  |  |  |  |  | $urpm->{error}(N("unable to install package %s", $mode->{$_})); | 
| 243 |  |  |  |  |  |  | my $cachefile = "$urpm->{cachedir}/rpms/" . $pkg->filename; | 
| 244 |  |  |  |  |  |  | if (-e $cachefile) { | 
| 245 |  |  |  |  |  |  | $urpm->{error}(N("removing bad rpm (%s) from %s", $pkg->name, "$urpm->{cachedir}/rpms")); | 
| 246 |  |  |  |  |  |  | unlink $cachefile or $urpm->{fatal}(1, N("removing %s failed: %s", $cachefile, $!)); | 
| 247 |  |  |  |  |  |  | } | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  | ++$update; | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  | \@produced_deltas, @trans_pkgs; | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub _get_callbacks { | 
| 256 |  |  |  |  |  |  | my ($urpm, $db, $trans, $options, $install, $upgrade, $have_pkgs) = @_; | 
| 257 |  |  |  |  |  |  | $index = 0; | 
| 258 |  |  |  |  |  |  | my $fh; | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | my $is_test = $options->{test}; # fix circular reference | 
| 261 |  |  |  |  |  |  | #- assume default value for some parameter. | 
| 262 |  |  |  |  |  |  | $options->{delta} ||= 1000; | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | #- ensure perl does not create a circular reference below, otherwise all this won't be collected, | 
| 265 |  |  |  |  |  |  | #  and rpmdb won't be closed: | 
| 266 |  |  |  |  |  |  | my ($callback_open_helper, $callback_close_helper) = ($options->{callback_open_helper}, $options->{callback_close_helper}); | 
| 267 |  |  |  |  |  |  | $options->{callback_open} = sub { | 
| 268 |  |  |  |  |  |  | my ($_data, $_type, $id) = @_; | 
| 269 |  |  |  |  |  |  | $callback_open_helper and $callback_open_helper->(@_); | 
| 270 |  |  |  |  |  |  | $fh = urpm::sys::open_safe($urpm, '<', $install->{$id} || $upgrade->{$id}); | 
| 271 |  |  |  |  |  |  | $fh ? fileno $fh : undef; | 
| 272 |  |  |  |  |  |  | }; | 
| 273 |  |  |  |  |  |  | $options->{callback_close} = sub { | 
| 274 |  |  |  |  |  |  | my ($urpm, undef, $pkgid) = @_; | 
| 275 |  |  |  |  |  |  | return unless defined $pkgid; | 
| 276 |  |  |  |  |  |  | $callback_close_helper and $callback_close_helper->($db, @_); | 
| 277 |  |  |  |  |  |  | get_README_files($urpm, $trans, $urpm->{depslist}[$pkgid]) if !$is_test; | 
| 278 |  |  |  |  |  |  | close $fh if defined $fh; | 
| 279 |  |  |  |  |  |  | }; | 
| 280 |  |  |  |  |  |  |  | 
| 281 |  |  |  |  |  |  | #- ensure perl does not create a circular reference below, otherwise all this won't be collected, | 
| 282 |  |  |  |  |  |  | #  and rpmdb won't be closed | 
| 283 |  |  |  |  |  |  | my $verbose = $options->{verbose}; | 
| 284 |  |  |  |  |  |  | $erase_logger = sub { | 
| 285 |  |  |  |  |  |  | my ($urpm, undef, undef, $subtype) = @_; | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | if ($subtype eq 'start') { | 
| 288 |  |  |  |  |  |  | my $name = $trans->Element_name($index); | 
| 289 |  |  |  |  |  |  | my @previous = map { $trans->Element_name($_) } 0 .. ($index - 1); | 
| 290 |  |  |  |  |  |  | # looking at previous packages in transaction | 
| 291 |  |  |  |  |  |  | # we should be looking only at installed packages, but it should not give a different result | 
| 292 |  |  |  |  |  |  | if (member($name, @previous)) { | 
| 293 |  |  |  |  |  |  | $urpm->{log}("removing upgraded package $current_pkg"); | 
| 294 |  |  |  |  |  |  | } else { | 
| 295 |  |  |  |  |  |  | $urpm->{print}(N("removing package %s", $current_pkg)) if $verbose >= 0; | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  | } | 
| 298 |  |  |  |  |  |  | }; | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | $options->{callback_uninst} ||= $options->{verbose} >= 0 ? \&install_logger : $erase_logger; | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | $options->{callback_elem} ||= sub { | 
| 303 |  |  |  |  |  |  | my (undef, undef, undef, undef, $idx, undef) = @_; | 
| 304 |  |  |  |  |  |  | $index = $idx; | 
| 305 |  |  |  |  |  |  | $current_pkg = $trans->Element_fullname($idx); | 
| 306 |  |  |  |  |  |  | }; | 
| 307 |  |  |  |  |  |  | $options->{callback_error} ||= sub { | 
| 308 |  |  |  |  |  |  | my ($urpm, undef, undef, $subtype, undef, undef) = @_; | 
| 309 |  |  |  |  |  |  | $urpm->{error}("ERROR: '$subtype' failed for $current_pkg"); | 
| 310 |  |  |  |  |  |  | }; | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | if ($options->{verbose} >= 0 && $have_pkgs) { | 
| 313 |  |  |  |  |  |  | $options->{callback_inst}  ||= \&install_logger; | 
| 314 |  |  |  |  |  |  | $options->{callback_trans} ||= \&install_logger; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | =item install($urpm, $remove, $install, $upgrade, %options) | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | Install packages according to each hash (remove, install or upgrade). | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | options: | 
| 323 |  |  |  |  |  |  | test, excludepath, nodeps, noorder (unused), delta, | 
| 324 |  |  |  |  |  |  | callback_inst, callback_trans, callback_uninst, | 
| 325 |  |  |  |  |  |  | callback_open_helper, callback_close_helper, | 
| 326 |  |  |  |  |  |  | post_clean_cache, verbose | 
| 327 |  |  |  |  |  |  | (more options for trans->run) | 
| 328 |  |  |  |  |  |  | excludedocs, nosize, noscripts, oldpackage, replacepkgs, justdb, ignorearch | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | See L for callback parameters | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | =cut | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | #- side-effects: uses a $urpm->{readmes} | 
| 335 |  |  |  |  |  |  | sub install { | 
| 336 |  |  |  |  |  |  | my ($urpm, $remove, $install, $upgrade, %options) = @_; | 
| 337 |  |  |  |  |  |  | $options{translate_message} = 1; | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | my $db = urpm::db_open_or_die_($urpm, !$options{test}); #- open in read/write mode unless testing installation. | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | my $trans = $db->create_transaction; | 
| 342 |  |  |  |  |  |  | if ($trans) { | 
| 343 |  |  |  |  |  |  | my ($rm_count, $inst_count, $up_count) = (scalar(@{$remove || []}), scalar(values %$install), scalar(values %$upgrade)); | 
| 344 |  |  |  |  |  |  | sys_log("transaction on %s (remove=%d, install=%d, upgrade=%d)", $urpm->{root} || '/', $rm_count, $inst_count, $up_count); | 
| 345 |  |  |  |  |  |  | $urpm->{log}(N("created transaction for installing on %s (remove=%d, install=%d, upgrade=%d)", $urpm->{root} || '/', | 
| 346 |  |  |  |  |  |  | $rm_count, $inst_count, $up_count)); | 
| 347 |  |  |  |  |  |  | } else { | 
| 348 |  |  |  |  |  |  | return N("unable to create transaction"); | 
| 349 |  |  |  |  |  |  | } | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | $trans->set_script_fd($options{script_fd}) if $options{script_fd}; | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | my @errors; | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | _schedule_packages_for_erasing($urpm, $trans, $remove); | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | my ($produced_deltas, @trans_pkgs) = _schedule_packages($urpm, $trans, $install, $upgrade, %options); | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | if (!$options{nodeps} && (@errors = $trans->check(%options))) { | 
| 360 |  |  |  |  |  |  | } elsif (!$options{noorder} && (@errors = $trans->order(%options))) { | 
| 361 |  |  |  |  |  |  | } else { | 
| 362 |  |  |  |  |  |  | $urpm->{readmes} = {}; | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | _get_callbacks($urpm, $db, $trans, \%options, $install, $upgrade, scalar @trans_pkgs); | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | local $ENV{LD_PRELOAD}; # fix eatmydata & co | 
| 367 |  |  |  |  |  |  | local $urpm->{trans} = $trans; | 
| 368 |  |  |  |  |  |  | @errors = $trans->run($urpm, %options); | 
| 369 |  |  |  |  |  |  | delete $urpm->{trans}; | 
| 370 |  |  |  |  |  |  | undef $erase_logger; | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | #- don't clear cache if transaction failed. We might want to retry. | 
| 373 |  |  |  |  |  |  | if (!@errors && !$options{test} && $options{post_clean_cache}) { | 
| 374 |  |  |  |  |  |  | #- examine the local cache to delete packages which were part of this transaction | 
| 375 |  |  |  |  |  |  | my $cachedir = "$urpm->{cachedir}/rpms"; | 
| 376 |  |  |  |  |  |  | my @pkgs = grep { -e "$cachedir/$_" } map { $_->filename } @trans_pkgs; | 
| 377 |  |  |  |  |  |  | $urpm->{log}(N("removing installed rpms (%s) from %s", join(' ', @pkgs), $cachedir)) if @pkgs; | 
| 378 |  |  |  |  |  |  | foreach (@pkgs) { | 
| 379 |  |  |  |  |  |  | unlink "$cachedir/$_" or $urpm->{fatal}(1, N("removing %s failed: %s", $_, $!)); | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | if ($options{verbose} >= 0 && !$options{justdb}) { | 
| 384 |  |  |  |  |  |  | foreach (keys %{$urpm->{readmes}}) { | 
| 385 |  |  |  |  |  |  | $urpm->{print}("-" x 70 .  "\n" . | 
| 386 |  |  |  |  |  |  | N("More information on package %s", $urpm->{readmes}{$_})); | 
| 387 |  |  |  |  |  |  | $urpm->{print}(scalar cat_utf8(($urpm->{root} || '') . $_)); | 
| 388 |  |  |  |  |  |  | $urpm->{print}("-" x 70); | 
| 389 |  |  |  |  |  |  | } | 
| 390 |  |  |  |  |  |  | } | 
| 391 |  |  |  |  |  |  | } | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | unlink @$produced_deltas; | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | urpm::sys::may_clean_rpmdb_shared_regions($urpm, $options{test}); | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | # explicitely close the RPM DB (needed for drakx -- looks like refcount has hard work): | 
| 398 |  |  |  |  |  |  | undef $db; | 
| 399 |  |  |  |  |  |  | undef $trans; | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | @errors; | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | 1; | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | =back | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | =head1 COPYRIGHT | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | Copyright (C) 1999-2005 MandrakeSoft SA | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | Copyright (C) 2005-2010 Mandriva SA | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | Copyright (C) 2011-2017 Mageia | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | =cut |