mirror of
https://github.com/webmin/webmin.git
synced 2026-08-23 23:40:29 +01:00
This PR adds DNF 4 and DNF 5 versionlock support to Package Updates, including listing, holding, unholding, and explicitly updating held packages. DNF 4 requires the versionlock plugin to be installed, while DNF 5 supports versionlock natively. Hold controls are shown only when the versionlock command is available. It also previews DNF transactions before confirmation so users can see which packages will be installed or updated in the table, similar to APT.
240 lines
7.2 KiB
Perl
Executable File
240 lines
7.2 KiB
Perl
Executable File
#!/usr/local/bin/perl
|
|
# Update selected packages
|
|
|
|
require './package-updates-lib.pl';
|
|
&ReadParse();
|
|
if ($in{'redir'}) {
|
|
$redir = $in{'redir'};
|
|
$redirdesc = $in{'redirdesc'};
|
|
}
|
|
elsif ($in{'redirdesc'}) {
|
|
$redir = $ENV{'HTTP_REFERER'};
|
|
$redirdesc = $in{'redirdesc'};
|
|
}
|
|
else {
|
|
$redir = "index.cgi?mode=".&urlize($in{'mode'}).
|
|
"&search=".&urlize($in{'search'});
|
|
$redirdesc = $text{'index_return'};
|
|
$redir = $redir =~ /tab=/ ? $redir :
|
|
$redir =~ /\?/ ? "$redir&tab=pkgs" : "$redir?tab=pkgs";
|
|
}
|
|
|
|
$hold_action = $in{'hold'} ? 1 : $in{'unhold'} ? 0 : undef;
|
|
if (defined($hold_action)) {
|
|
# Hold or unhold selected packages
|
|
&supports_package_holds() || &error($text{'hold_enotsupported'});
|
|
@holdpkgs = split(/\0/, $in{'u'});
|
|
@holdpkgs || &error($text{'hold_enone'});
|
|
@current = &list_current(1);
|
|
%current = map { $_->{'name'}."/".$_->{'system'}, 1 } @current;
|
|
@held = &list_package_holds();
|
|
@holdnames = ( );
|
|
foreach $ps (@holdpkgs) {
|
|
($p, $s) = split(/\//, $ps, 2);
|
|
$current{$p."/".$s} || &error(&text('hold_enotinstalled', $p));
|
|
$s eq $software::update_system ||
|
|
&error(&text('hold_esystem', $p));
|
|
if (!$hold_action && !&package_is_held($p, \@held)) {
|
|
&error(&text('hold_enotheld', $p));
|
|
}
|
|
push(@holdnames, $p);
|
|
}
|
|
@holdnames = &unique(@holdnames);
|
|
$err = &update_package_holds(\@holdnames, $hold_action);
|
|
&error(&text($hold_action ? 'hold_efailed' : 'unhold_efailed', $err))
|
|
if ($err);
|
|
&flush_package_caches();
|
|
$logaction = $hold_action ? 'hold' : 'unhold';
|
|
&webmin_log($logaction, "packages", scalar(@holdnames),
|
|
{ 'packages' => \@holdnames });
|
|
&redirect("index.cgi?mode=".&urlize($in{'mode'}).
|
|
"&search=".&urlize($in{'search'}));
|
|
}
|
|
elsif ($in{'refresh'} || $in{'refresh_top'}) {
|
|
&ui_print_unbuffered_header(undef, $text{'refresh_title'}, "");
|
|
|
|
# Clear all caches
|
|
print $text{'refresh_clearing'},"<br>\n";
|
|
&flush_package_caches();
|
|
&clear_repository_cache();
|
|
print $text{'refresh_done'},"<p>\n";
|
|
|
|
# Force re-fetch
|
|
print $text{'refresh_available'},"<br>\n";
|
|
@avail = &list_possible_updates();
|
|
print &text('refresh_done3', scalar(@avail)),"<p>\n";
|
|
|
|
&webmin_log("refresh");
|
|
&ui_print_footer($redir, $redirdesc);
|
|
}
|
|
else {
|
|
# Upgrade some packages
|
|
my @pkgs = split(/\0/, $in{'u'});
|
|
@pkgs || &error($text{'update_enone'});
|
|
$allow_held = 0;
|
|
if ($in{'mode'} eq 'held') {
|
|
# Only Held updates can override a hold for one transaction.
|
|
&supports_package_holds() || &error($text{'hold_enotsupported'});
|
|
@held = &list_package_holds();
|
|
foreach $ps (@pkgs) {
|
|
($p, $s) = split(/\//, $ps, 2);
|
|
$s eq $software::update_system &&
|
|
&package_is_held($p, \@held) ||
|
|
&error(&text('update_enotheld', $p));
|
|
}
|
|
$allow_held = 1;
|
|
}
|
|
$install_flags = $allow_held ? &software::update_system_hold_flags() :
|
|
$in{'flags'};
|
|
&ui_print_unbuffered_header(undef,
|
|
$in{'mode'} eq 'new' ? $text{'update_title2'} : $text{'update_title'}, "");
|
|
|
|
# Save this CGI from being killed by a webmin or apache upgrade
|
|
$SIG{'TERM'} = 'IGNORE';
|
|
$SIG{'PIPE'} = 'IGNORE';
|
|
|
|
# Work out what will be done, if possible
|
|
@ops = ( );
|
|
if (!$in{'confirm'}) {
|
|
print $text{'update_ops'},"<p>\n";
|
|
@pkgnames = ( );
|
|
foreach my $ps (@pkgs) {
|
|
($p, $s) = split(/\//, $ps);
|
|
push(@pkgnames, $p);
|
|
}
|
|
@ops = &list_package_operations(join(" ", @pkgnames), $s,
|
|
$install_flags);
|
|
&error($text{'update_enoheldops'}) if (!@ops && $allow_held);
|
|
}
|
|
|
|
if (@ops) {
|
|
# Ask first
|
|
my $getconfform = sub {
|
|
my ($bottom) = @_;
|
|
my $bottom_sel;
|
|
$bottom_sel = 'data-outside-of-viewport'
|
|
if ($bottom);
|
|
my $confform = &ui_form_start("update.cgi", "post", undef, $bottom_sel);
|
|
$confform .= &ui_hidden("mode", $in{'mode'});
|
|
$confform .= &ui_hidden("search", $in{'search'});
|
|
$confform .= &ui_hidden("redir", $in{'redir'});
|
|
$confform .= &ui_hidden("redirdesc", $in{'redirdesc'});
|
|
foreach $ps (@pkgs) {
|
|
$confform .= &ui_hidden("u", $ps);
|
|
}
|
|
$confform .= &ui_alert_box($text{'update_heldnote'},
|
|
'warn', undef, undef, '')
|
|
if ($allow_held && !$bottom);
|
|
$confform .= &text('update_rusure', scalar(@ops)),"<p>\n"
|
|
if (!$bottom);
|
|
$confform .= &ui_form_end([ [ "confirm",
|
|
$allow_held ? $text{'update_confirmheld'} :
|
|
$text{'update_confirm'} ] ]);
|
|
};
|
|
print &$getconfform();
|
|
|
|
# Show table of all depends
|
|
@current = &list_current(1);
|
|
print &ui_columns_start([ $text{'index_name'},
|
|
$text{'update_oldver'},
|
|
$text{'update_newver'},
|
|
$text{'index_desc'},
|
|
], 100);
|
|
foreach $p (@ops) {
|
|
($c) = grep { $_->{'name'} eq $p->{'name'} &&
|
|
$_->{'system'} eq $p->{'system'} } @current;
|
|
if (!$c && !@avail) {
|
|
# Only get available if needed
|
|
@avail = &list_available(0);
|
|
}
|
|
($a) = grep { $_->{'name'} eq $p->{'name'} &&
|
|
$_->{'system'} eq $p->{'system'} } @avail;
|
|
print &ui_columns_row([
|
|
$p->{'name'},
|
|
$c ? $c->{'version'}
|
|
: "<i>$text{'update_none'}</i>",
|
|
$p->{'version'},
|
|
$c ? $c->{'desc'} :
|
|
$a ? $a->{'desc'} : '',
|
|
]);
|
|
}
|
|
print &ui_columns_end();
|
|
print &$getconfform(1), &ui_hide_outside_of_viewport();
|
|
}
|
|
else {
|
|
# Check if a reboot was required before
|
|
$reboot_before = &check_reboot_required();
|
|
|
|
# Do it
|
|
$msg = $in{'mode'} eq 'new' ? 'update_pkg2' : 'update_pkg';
|
|
&start_update_progress([ map { (split(/\//, $_))[0] } @pkgs ]);
|
|
if ($config{'update_multiple'} && @pkgs > 1) {
|
|
# Update all packages at once
|
|
@pkgnames = ( );
|
|
foreach my $ps (@pkgs) {
|
|
($p, $s) = split(/\//, $ps);
|
|
push(@pkgnames, $p);
|
|
$pkgsystem ||= $s;
|
|
}
|
|
print &text($msg, "<tt>".&html_escape(join(" ", @pkgnames))."</tt>"),
|
|
"<br>\n";
|
|
print "<ul data-package-updates='1'>\n";
|
|
@got = &package_install_multiple(
|
|
\@pkgnames, $pkgsystem, $in{'mode'} eq 'new', $install_flags);
|
|
print "</ul><br>\n";
|
|
}
|
|
else {
|
|
# Do them one by one in a loop
|
|
foreach my $ps (@pkgs) {
|
|
($p, $s) = split(/\//, $ps);
|
|
next if ($donedep{$p});
|
|
print &text($msg, "<tt>@{[&html_escape($p)]}</tt>"),"<br>\n";
|
|
print "<ul data-package-updates='2'>\n";
|
|
@pgot = &package_install(
|
|
$p, $s, $in{'mode'} eq 'new', $install_flags);
|
|
foreach $g (@pgot) {
|
|
$donedep{$g}++;
|
|
}
|
|
push(@got, @pgot);
|
|
print "</ul><br>\n";
|
|
}
|
|
}
|
|
if (@got) {
|
|
print &text('update_ok', scalar(@got)),"<p>\n";
|
|
}
|
|
else {
|
|
print $text{'update_failed'},"<p>\n";
|
|
}
|
|
&end_update_progress(\@pkgs);
|
|
|
|
# Refresh collected package info
|
|
print $text{'refresh_available'},"<br>\n";
|
|
if (&foreign_check("system-status")) {
|
|
&foreign_require("system-status");
|
|
&system_status::refresh_possible_packages(\@got);
|
|
}
|
|
|
|
# Refresh collected package info
|
|
if (&foreign_check("virtual-server") && @got) {
|
|
&foreign_require("virtual-server");
|
|
&virtual_server::refresh_possible_packages(\@got);
|
|
}
|
|
print $text{'refresh_done'},"<p>\n";
|
|
# Check if a reboot is required now
|
|
if (!$reboot_before && &check_reboot_required() &&
|
|
&foreign_check("init")) {
|
|
print &ui_form_start(
|
|
"@{[&get_webprefix()]}/init/reboot.cgi");
|
|
print &ui_hidden("confirm", 1);
|
|
print "<b>",$text{'update_rebootdesc'},"</b><p>\n";
|
|
print &ui_form_end(
|
|
[ [ undef, $text{'update_reboot'} ] ]);
|
|
}
|
|
|
|
&webmin_log("update", "packages", scalar(@got),
|
|
{ 'got' => \@got });
|
|
}
|
|
|
|
&ui_print_footer($redir, $redirdesc);
|
|
}
|