diff options
author | Angelo Naselli <anaselli@linux.it> | 2015-03-16 19:20:40 +0100 |
---|---|---|
committer | Angelo Naselli <anaselli@linux.it> | 2015-03-16 19:20:40 +0100 |
commit | b4e446c21e299af0441ec44db7a86334980b77c2 (patch) | |
tree | ea17c359431cb9e10aeed60346cb7b5a2c7af19d /lib/ManaTools/rpmdragora.pm | |
parent | fc9772f1f03684e8dab50ff77d2c46c5e0309c7b (diff) | |
download | manatools-b4e446c21e299af0441ec44db7a86334980b77c2.tar manatools-b4e446c21e299af0441ec44db7a86334980b77c2.tar.gz manatools-b4e446c21e299af0441ec44db7a86334980b77c2.tar.bz2 manatools-b4e446c21e299af0441ec44db7a86334980b77c2.tar.xz manatools-b4e446c21e299af0441ec44db7a86334980b77c2.zip |
Moved the tree accordingly
Diffstat (limited to 'lib/ManaTools/rpmdragora.pm')
-rw-r--r-- | lib/ManaTools/rpmdragora.pm | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/lib/ManaTools/rpmdragora.pm b/lib/ManaTools/rpmdragora.pm new file mode 100644 index 00000000..ecdf06ff --- /dev/null +++ b/lib/ManaTools/rpmdragora.pm @@ -0,0 +1,1165 @@ +# vim: set et ts=4 sw=4: +#***************************************************************************** +# +# Copyright (c) 2002 Guillaume Cottenceau +# Copyright (c) 2002-2007 Thierry Vignaud <tvignaud@mandriva.com> +# Copyright (c) 2003, 2004, 2005 MandrakeSoft SA +# Copyright (c) 2005, 2007 Mandriva SA +# Copyright (c) 2013 - 2015 Matteo Pasotti <matteo.pasotti@gmail.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +#***************************************************************************** +# +# $Id: rpmdragora.pm 267936 2010-04-26 16:40:21Z jvictor $ + +package ManaTools::rpmdragora; +use warnings::register; + +use urpm; +use urpm::cfg; +use urpm::mirrors; +use urpm::download (); +use urpm::prompt; +use urpm::media; + +# quick fix for mirror.pm +use lib qw(/usr/lib/libDrakX); + +use MDK::Common; +use MDK::Common::System; +use MDK::Common::String; +use MDK::Common::Func; +use MDK::Common::File qw(basename cat_ output); +use URPM; +use URPM::Resolve; +use strict; +use POSIX qw(_exit); + +use feature 'state'; + +use ManaTools::Shared; +use ManaTools::Shared::Locales; +use ManaTools::Shared::GUI; + +use Carp; + +our @ISA = qw(Exporter); +our @EXPORT = qw( + $changelog_first_config + $compute_updates + $filter + $dont_show_selections + $ignore_debug_media + $mandrakeupdate_wanted_categories + $mandrivaupdate_height + $mandrivaupdate_width + $max_info_in_descr + $mode + $NVR_searches + $offered_to_add_sources + $rpmdragora_height + $rpmdragora_width + $tree_flat + $tree_mode + $use_regexp + $typical_width + $clean_cache + $auto_select + locale + add_distrib_update_media + add_medium_and_check + but + but_ + check_update_media_version + choose_mirror + distro_type + fatal_msg + getbanner + get_icon + interactive_list + interactive_list_ + interactive_msg + myexit + readconf + remove_wait_msg + run_drakbug + show_urpm_progress + slow_func + slow_func_statusbar + statusbar_msg + statusbar_msg_remove + strip_first_underscore + update_sources + update_sources_check + update_sources_interactive + update_sources_noninteractive + wait_msg + warn_for_network_need + writeconf +); +our $typical_width = 280; + +our $dont_show_selections; + +# i18n: IMPORTANT: to get correct namespace (rpmdragora instead of libDrakX) +BEGIN { unshift @::textdomains, qw(rpmdragora urpmi rpm-summary-main rpm-summary-contrib rpm-summary-devel rpm-summary-non-free) } + +use yui; +use Glib; +#ugtk2::add_icon_path('/usr/share/rpmdragora/icons'); + +# Locale::gettext::bind_textdomain_codeset('rpmdragora', 'UTF8'); +my $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake');; + +our $mageia_release = MDK::Common::File::cat_( + -e '/etc/mageia-release' ? '/etc/mageia-release' : '/etc/release' +) || ''; +chomp $mageia_release; +our ($distro_version) = $mageia_release =~ /(\d+\.\d+)/; +our ($branded, %distrib); +$branded = -f '/etc/sysconfig/oem' + and %distrib = MDK::Common::System::distrib(); +our $myname_update = $branded ? $loc->N_("Software Update") : $loc->N_("Mageia Update"); + +@rpmdragora::prompt::ISA = 'urpm::prompt'; + + +sub locale() { + + if (!defined($loc)) { + $loc = ManaTools::Shared::Locales->new(domain_name => 'rpmdrake'); + } + + return $loc; +} + +sub rpmdragora::prompt::prompt { + my ($self) = @_; + my @answers; + my $d = ugtk2->new("", grab => 1, if_($::main_window, transient => $::main_window)); + $d->{rwindow}->set_position('center_on_parent'); + gtkadd( + $d->{window}, + gtkpack( + Gtk2::VBox->new(0, 5), + Gtk2::WrappedLabel->new($self->{title}), + (map { gtkpack( + Gtk2::HBox->new(0, 5), + Gtk2::Label->new($self->{prompts}[$_]), + $answers[$_] = gtkset_visibility(gtkentry(), !$self->{hidden}[$_]), + ) } 0 .. $#{$self->{prompts}}), + gtksignal_connect(Gtk2::Button->new($loc->N("Ok")), clicked => sub { Gtk2->main_quit }), + ), + ); + $d->main; + map { $_->get_text } @answers; +} + +$urpm::download::PROMPT_PROXY = new rpmdragora::prompt( + $loc->N_("Please enter your credentials for accessing proxy\n"), + [ $loc->N_("User name:"), $loc->N_("Password:") ], + undef, + [ 0, 1 ], +); + +sub myexit { + writeconf(); + destroy $::main_window if $::main_window; + exit @_; +} + +my ($root) = grep { $_->[2] == 0 } list_passwd(); +$ENV{HOME} = $> == 0 ? $root->[7] : $ENV{HOME} || '/root'; +$ENV{HOME} = $::env if $::env = $ManaTools::Rpmdragora::init::rpmdragora_options{env}[0]; + +our $configfile = "$ENV{HOME}/.rpmdragora"; + +# +# Configuration File Options +# + +# clear download cache after successfull installation of packages +our $clean_cache; + +# automatic select dependencies without user intervention +our $auto_select; + +our ($changelog_first_config, $compute_updates, $filter, $max_info_in_descr, $mode, $NVR_searches, $tree_flat, $tree_mode, $use_regexp); +our ($mandrakeupdate_wanted_categories, $ignore_debug_media, $offered_to_add_sources, $no_confirmation); +our ($rpmdragora_height, $rpmdragora_width, $mandrivaupdate_height, $mandrivaupdate_width); + +our %config = ( + clean_cache => { + var => \$clean_cache, + default => [ 0 ] + }, + auto_select => { + var => \$auto_select, + default => [ 0 ] + }, + changelog_first_config => { var => \$changelog_first_config, default => [ 0 ] }, + compute_updates => { var => \$compute_updates, default => [ 1 ] }, + dont_show_selections => { var => \$dont_show_selections, default => [ $> ? 1 : 0 ] }, + filter => { var => \$filter, default => [ 'all' ] }, + ignore_debug_media => { var => \$ignore_debug_media, default => [ 0 ] }, + mandrakeupdate_wanted_categories => { var => \$mandrakeupdate_wanted_categories, default => [ qw(security) ] }, + mandrivaupdate_height => { var => \$mandrivaupdate_height, default => [ 0 ] }, + mandrivaupdate_width => { var => \$mandrivaupdate_width, default => [ 0 ] }, + max_info_in_descr => { var => \$max_info_in_descr, default => [] }, + mode => { var => \$mode, default => [ 'by_group' ] }, + NVR_searches => { var => \$NVR_searches, default => [ 0 ] }, + 'no-confirmation' => { var => \$no_confirmation, default => [ 0 ] }, + offered_to_add_sources => { var => \$offered_to_add_sources, default => [ 0 ] }, + rpmdragora_height => { var => \$rpmdragora_height, default => [ 0 ] }, + rpmdragora_width => { var => \$rpmdragora_width, default => [ 0 ] }, + tree_flat => { var => \$tree_flat, default => [ 0 ] }, + tree_mode => { var => \$tree_mode, default => [ qw(gui_pkgs) ] }, + use_regexp => { var => \$use_regexp, default => [ 0 ] }, +); + +sub readconf() { + ${$config{$_}{var}} = $config{$_}{default} foreach keys %config; + foreach my $l (MDK::Common::File::cat_($configfile)) { + my ($key, @values) = split ' ', $l; + ${$config{$key}{var}} = \@values if scalar @values; + } + # special cases: + $::rpmdragora_options{'no-confirmation'} = $no_confirmation->[0] if !defined $::rpmdragora_options{'no-confirmation'}; + $ManaTools::Rpmdragora::init::default_list_mode = $tree_mode->[0] if ref $tree_mode && !$ManaTools::Rpmdragora::init::overriding_config; +} + +sub writeconf() { + return if $::env; + unlink $configfile; + + # special case: + $no_confirmation->[0] = $::rpmdragora_options{'no-confirmation'}; + my @config_content = map { "$_ " . (ref ${$config{$_}{var}} ? join(' ', @${$config{$_}{var}}) : '') . "\n" } sort keys %config; + MDK::Common::File::output($configfile, @config_content); + print "writeconf done!\n"; +} + +sub getbanner() { + $::MODE or return undef; + if (0) { + +{ + remove => $loc->N("Software Packages Removal"), + update => $loc->N("Software Packages Update"), + install => $loc->N("Software Packages Installation"), + }; + } +# Gtk2::Banner->new($ugtk2::wm_icon, $::MODE eq 'update' ? $loc->N("Software Packages Update") : $loc->N("Software Management")); +} + + +#============================================================= + +=head2 interactive_msg + +=head3 INPUT + + $title: dialog title + $contents: dialog text + %options: optional HASH containing { + scroll => Rich Text with scroll bar used + yesno => dialog with "yes" and "no" buttons (deafult yes) + dont_ask_again => add a checkbox with "dont ask again text" + main_dialog => create a main dialog instead of a popup one + min_size => {columns => X, lines => Y} for minimum dialog size, + } + +=head3 OUTPUT + + retval: if dont_ask_again HASH reference containig { + value => 1 yes (or ok) pressed, 0 no pressed + dont_ask_again => 1 if checked + } + or if dont_ask_again is not passed: + 1 yes (or ok) pressed, 0 no pressed + +=head3 DESCRIPTION + + This function shows a dialog with contents text and return the button + pressed (1 ok or yes), optionally returns the checkbox value if dont_ask_again is + passed. + If min_size is passed a minimum dialog size is set (default is 75x6) see libyui + createMinSize documenatation for explanation. + +=cut + +#============================================================= +sub interactive_msg { + my ($title, $contents, %options) = @_; + + my $retVal = 0; + + my $info; + + if ($options{scroll}) { + ## richtext needs <br> instead of '\n' + $contents =~ s/\n/<br>/g; + } + + my $oldTitle = yui::YUI::app()->applicationTitle(); + yui::YUI::app()->setApplicationTitle($title); + + my $factory = yui::YUI::widgetFactory; + my $dlg = $options{main_dialog} ? + $factory->createMainDialog() : + $factory->createPopupDialog(); + my $columns = $options{min_size}->{columns} || 75; + my $lines = $options{min_size}->{lines} || 6; + my $minSize = $factory->createMinSize( $dlg, $columns, $lines); + my $vbox = $factory->createVBox( $minSize ); + my $midhbox = $factory->createHBox($vbox); + ## app description + my $toprightvbox = $factory->createVBox($midhbox); + $toprightvbox->setWeight($yui::YD_HORIZ, 5); + $factory->createSpacing($toprightvbox,$yui::YD_HORIZ, 0, 5.0); + $factory->createRichText($toprightvbox, $contents, !$options{scroll}); + $factory->createSpacing($toprightvbox, $yui::YD_HORIZ, 0, 5.0); + + if ($options{dont_ask_again}){ + my $hbox = $factory->createHBox($vbox); + my $align = $factory->createRight($hbox); + $info->{checkbox} = $factory->createCheckBox($align, $loc->N("Do not ask me next time")); + } + + my $bottomhbox = $factory->createHBox($vbox); + if ($options{yesno}) { + my $alignRight = $factory->createRight($bottomhbox); + my $buttonBox = $factory->createHBox($alignRight); + + $info->{B1} = $factory->createPushButton($buttonBox, $options{text}{yes} || $loc->N("Yes")); + $info->{B2} = $factory->createPushButton($buttonBox, $options{text}{no} || $loc->N("No")); + } + else { + $info->{B1} = $factory->createPushButton($bottomhbox, $loc->N("Ok")); + } + + $dlg->setDefaultButton($info->{B1}); + + while (1) { + my $event = $dlg->waitForEvent(); + my $eventType = $event->eventType(); + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + $retVal = 1; ##default value + last; + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + + if ($info->{B1} && $widget == $info->{B1}) { + $retVal = 1; + last; + } + elsif ($info->{B2} && $widget == $info->{B2}) { + last; + } + } + } + + if ($info->{checkbox}) { + my $value = $retVal; + $retVal = undef; + $retVal->{value} = $value; + $retVal->{dont_ask_again} = $info->{checkbox}->isChecked(); + } + + $dlg->destroy(); + yui::YUI::app()->setApplicationTitle($oldTitle); + + return $retVal; +} + +sub interactive_list { + my ($title, $contents, $list, $callback, %options) = @_; + + my $factory = yui::YUI::widgetFactory; + my $mainw = $factory->createPopupDialog(); + my $vbox = $factory->createVBox($mainw); + my $lbltitle = $factory->createLabel($vbox, $loc->N("Dependencies")); + my $left = $factory->createLeft($factory->createHBox($vbox)); + my $radiobuttongroup = $factory->createRadioButtonGroup($left); + my $rbbox = $factory->createVBox($radiobuttongroup); + foreach my $item (@$list) { + my $radiobutton = $factory->createRadioButton($rbbox,$item); + if ($item eq $list->[0]) { + # select first by default + $radiobutton->setValue(1); + } + $radiobutton->setNotify(0); + $radiobuttongroup->addRadioButton($radiobutton); + } + my $submitButton = $factory->createIconButton($vbox,"", $loc->N("OK")); + my $choice; + + while(1) { + my $event = $mainw->waitForEvent(); + my $eventType = $event->eventType(); + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + $mainw->destroy(); + last; + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + + if($widget == $submitButton) { + # NOTE if for any reason radio button is not checked let's take the first package + $choice = $radiobuttongroup->currentButton() ? $radiobuttongroup->currentButton()->label() : $list->[0]; + $choice =~s/\&//g; + last; + } + } + } + $mainw->destroy(); + return $choice; +} + +sub interactive_list_ { interactive_list(@_, if_($::main_window, transient => $::main_window)) } + +sub fatal_msg { + interactive_msg @_; + myexit -1; +} + +sub wait_msg { + my $msg = shift; + + my $label = $msg ? $msg : $loc->N("Please wait"); + + my $factory = yui::YUI::widgetFactory; + my $mainw = $factory->createPopupDialog(); + my $vbox = $factory->createVBox($mainw); + my $title = $factory->createLabel($vbox, $label); + #$mainw->recalcLayout(); + #$mainw->doneMultipleChanges(); + $mainw->waitForEvent(10); + $mainw->pollEvent(); + #$mainw->recalcLayout(); + #$mainw->doneMultipleChanges(); + yui::YUI::app()->busyCursor(); + + $mainw; +} + +sub remove_wait_msg { + my $w = shift; + #gtkset_mousecursor_normal($w->{rwindow}->window); + $w->destroy; + yui::YUI::app()->normalCursor(); +} + +sub but { " $_[0] " } +sub but_ { " $_[0] " } + +#============================================================= + +=head2 slow_func + +=head3 INPUT + + $func: function to be executed with a busy cursor or waiting + dialog + $msg: message to be shown in ncurses waiting dialog (if any) + +=head3 DESCRIPTION + + This function executes a given function with a busy cursor set + in graphical environment, or with a waiting dialog if in ncurses + text mode + +=cut + +#============================================================= +sub slow_func (&) { + my ($func, $msg) = @_; + + my $retval = 1; + # NOTE busy cursor is not implemented in yui-ncurses + # but we can avoid a waiting dialog in Gtk and QT + if (yui::YUI::app()->isTextMode()) { + my $w = wait_msg($msg); + $retval = $func->(); + remove_wait_msg($w) + } + else { + yui::YUI::app()->busyCursor(); + $retval = $func->(); + yui::YUI::app()->normalCursor(); + } + return $retval; +} + +sub statusbar_msg { + my ($msg, $o_timeout) = @_; + + unless ($::statusbar) { #- fallback if no status bar + return wait_msg($msg); + } + + $::statusbar->setLabel($msg); + #- always use the same context description for now + #my $cx = $::statusbar->get_context_id("foo"); + #$::w and $::w->{rwindow} and gtkset_mousecursor_wait($::w->{rwindow}->window); + #- returns a msg_id to be passed optionnally to statusbar_msg_remove + #my $id = $::statusbar->push($cx, $msg); + #gtkflush(); + #Glib::Timeout->add(5000, sub { statusbar_msg_remove($id); 0 }) if $o_timeout; + $::statusbar->setTimeout ( 5000 ); + Glib::Timeout->add(5000, sub { statusbar_msg_remove(); 0 }) if $o_timeout; + #$id; + return 1; +} + +sub statusbar_msg_remove { + if (!$::statusbar) { #- fallback if no status bar + my $id = shift; + return remove_wait_msg($id);; + } + my ($msg_id) = @_; + #my $cx = $::statusbar->get_context_id("foo"); + #if (defined $msg_id) { + #$::statusbar->remove($cx, $msg_id); + #} else { + #$::statusbar->pop($cx); + #} + #$::w and $::w->{rwindow} and gtkset_mousecursor_normal($::w->{rwindow}->window); + $::statusbar->setLabel(""); +} + +sub slow_func_statusbar ($$&) { + my ($msg, $w, $func) = @_; + yui::YUI::app()->busyCursor(); + + my $msg_id = statusbar_msg($msg); + $func->(); + statusbar_msg_remove($msg_id); + + yui::YUI::app()->normalCursor(); +} + +my %u2l = ( + ar => $loc->N_("Argentina"), + at => $loc->N_("Austria"), + au => $loc->N_("Australia"), + by => $loc->N_("Belarus"), + be => $loc->N_("Belgium"), + br => $loc->N_("Brazil"), + gb => $loc->N_("Britain"), + ca => $loc->N_("Canada"), + ch => $loc->N_("Switzerland"), + cr => $loc->N_("Costa Rica"), + cz => $loc->N_("Czech Republic"), + de => $loc->N_("Germany"), + dk => $loc->N_("Danmark"), + ec => $loc->N_("Ecuador"), + el => $loc->N_("Greece"), + es => $loc->N_("Spain"), + fi => $loc->N_("Finland"), + fr => $loc->N_("France"), + gr => $loc->N_("Greece"), + hu => $loc->N_("Hungary"), + id => $loc->N_("Indonesia"), + il => $loc->N_("Israel"), + it => $loc->N_("Italy"), + jp => $loc->N_("Japan"), + ko => $loc->N_("Korea"), + nl => $loc->N_("Netherlands"), + no => $loc->N_("Norway"), + pl => $loc->N_("Poland"), + pt => $loc->N_("Portugal"), + ru => $loc->N_("Russia"), + se => $loc->N_("Sweden"), + sg => $loc->N_("Singapore"), + sk => $loc->N_("Slovakia"), + za => $loc->N_("South Africa"), + tw => $loc->N_("Taiwan"), + th => $loc->N_("Thailand"), + tr => $loc->N_("Turkey"), + uk => $loc->N_("United Kingdom"), + cn => $loc->N_("China"), + us => $loc->N_("United States"), + com => $loc->N_("United States"), + org => $loc->N_("United States"), + net => $loc->N_("United States"), + edu => $loc->N_("United States"), +); +my $us = [ qw(us com org net edu) ]; +my %t2l = ( + 'America/\w+' => $us, + 'Asia/Tel_Aviv' => [ qw(il ru it cz at de fr se) ], + 'Asia/Tokyo' => [ qw(jp ko tw), @$us ], + 'Asia/Seoul' => [ qw(ko jp tw), @$us ], + 'Asia/Taipei' => [ qw(tw jp), @$us ], + 'Asia/(Shanghai|Beijing)' => [ qw(cn tw sg), @$us ], + 'Asia/Singapore' => [ qw(cn sg), @$us ], + 'Atlantic/Reykjavik' => [ qw(gb uk no se fi dk), @$us, qw(nl de fr at cz it) ], + 'Australia/\w+' => [ qw(au jp ko tw), @$us ], + 'Brazil/\w+' => [ 'br', @$us ], + 'Canada/\w+' => [ 'ca', @$us ], + 'Europe/Amsterdam' => [ qw(nl be de at cz fr se dk it) ], + 'Europe/Athens' => [ qw(gr pl cz de it nl at fr) ], + 'Europe/Berlin' => [ qw(de be at nl cz it fr se) ], + 'Europe/Brussels' => [ qw(be de nl fr cz at it se) ], + 'Europe/Budapest' => [ qw(cz it at de fr nl se) ], + 'Europe/Copenhagen' => [ qw(dk nl de be se at cz it) ], + 'Europe/Dublin' => [ qw(gb uk fr be nl dk se cz it) ], + 'Europe/Helsinki' => [ qw(fi se no nl be de fr at it) ], + 'Europe/Istanbul' => [ qw(il ru it cz it at de fr nl se) ], + 'Europe/Lisbon' => [ qw(pt es fr it cz at de se) ], + 'Europe/London' => [ qw(gb uk fr be nl de at cz se it) ], + 'Europe/Madrid' => [ qw(es fr pt it cz at de se) ], + 'Europe/Moscow' => [ qw(ru de pl cz at se be fr it) ], + 'Europe/Oslo' => [ qw(no se fi dk de be at cz it) ], + 'Europe/Paris' => [ qw(fr be de at cz nl it se) ], + 'Europe/Prague' => [ qw(cz it at de fr nl se) ], + 'Europe/Rome' => [ qw(it fr cz de at nl se) ], + 'Europe/Stockholm' => [ qw(se no dk fi nl de at cz fr it) ], + 'Europe/Vienna' => [ qw(at de cz it fr nl se) ], +); + +#- get distrib release number (2006.0, etc) +sub etc_version() { + (my $v) = split / /, MDK::Common::File::cat_('/etc/version'); + return $v; +} + +#- returns the keyword describing the type of the distribution. +#- the parameter indicates whether we want base or update sources +sub distro_type { + my ($want_base_distro) = @_; + return 'cauldron' if $mageia_release =~ /cauldron/i; + #- we can't use updates for community while official is not out (release ends in ".0") + if ($want_base_distro || $mageia_release =~ /community/i && etc_version() =~ /\.0$/) { + return 'official' if $mageia_release =~ /official|limited/i; + return 'community' if $mageia_release =~ /community/i; + #- unknown: fallback to updates + } + return 'updates'; +} + +sub compat_arch_for_updates($) { + # FIXME: We prefer 64-bit packages to update on biarch platforms, + # since the system is populated with 64-bit packages anyway. + my ($arch) = @_; + return $arch =~ /x86_64|amd64/ if arch() eq 'x86_64'; + MDK::Common::System::compat_arch($arch); +} + +sub add_medium_and_check { + my ($urpm, $options) = splice @_, 0, 2; + my @newnames = ($_[0]); #- names of added media + my $fatal_msg; + my @error_msgs; + local $urpm->{fatal} = sub { printf STDERR "Fatal: %s\n", $_[1]; $fatal_msg = $_[1]; goto fatal_error }; + local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; + if ($options->{distrib}) { + @newnames = urpm::media::add_distrib_media($urpm, @_); + } else { + urpm::media::add_medium($urpm, @_); + } + if (@error_msgs) { + interactive_msg( + $loc->N("Error"), + $loc->N("Unable to add medium, errors reported:\n\n%s", + join("\n", map { MDK::Common::String::formatAlaTeX($_) } @error_msgs)) . "\n\n" . $loc->N("Medium: ") . "$_[0] ($_[1])", + scroll => 1, + ); + return 0; + } + + foreach my $name (@newnames) { + urpm::download::set_proxy_config($_, $options->{proxy}{$_}, $name) foreach keys %{$options->{proxy} || {}}; + } + + if (update_sources_check($urpm, $options, $loc->N_("Unable to add medium, errors reported:\n\n%s"), @newnames)) { + urpm::media::write_config($urpm); + $options->{proxy} and urpm::download::dump_proxy_config(); + } else { + urpm::media::read_config($urpm, 0); + return 0; + } + + my %newnames; @newnames{@newnames} = (); + if (any { exists $newnames{$_->{name}} } @{$urpm->{media}}) { + return 1; + } else { + interactive_msg($loc->N("Error"), $loc->N("Unable to create medium.")); + return 0; + } + + fatal_error: + interactive_msg($loc->N("Failure when adding medium"), + $loc->N("There was a problem adding medium:\n\n%s", $fatal_msg)); + return 0; +} + +sub update_sources_check { + my ($urpm, $options, $error_msg, @media) = @_; + my @error_msgs; + local $urpm->{fatal} = sub { push @error_msgs, $_[1]; goto fatal_error }; + local $urpm->{error} = sub { push @error_msgs, $_[0] }; + update_sources($urpm, %$options, noclean => 1, medialist => \@media); + fatal_error: + if (@error_msgs) { + interactive_msg($loc->N("Error"), $loc->N($error_msg, join("\n", map { formatAlaTeX($_) } @error_msgs)), scroll => 1); + return 0; + } + return 1; +} + +sub update_sources { + my ($urpm, %options) = @_; + my $cancel = 0; + + + my $factory = yui::YUI::widgetFactory; + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("rpmdragora")); + + my $dlg = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dlg, 80, 5 ); + my $vbox = $factory->createVBox($minSize); + my $hbox = $factory->createHBox($factory->createLeft($vbox)); + my $label = $factory->createRichText($hbox, $loc->N("Please wait, updating media..."), 1 ); + $label->setWeight($yui::YD_HORIZ, 1); + $label->setWeight($yui::YD_VERT, 1); + + my $pb = $factory->createProgressBar( $vbox, ""); + $pb->setValue(0); + # NOTE urpm::media::update_those_media seems not to say anything + # when downloads and tests md5sum + # a fake event (timeout 10 msec) allow to draw the waiting + # dialog + $dlg->waitForEvent(10); + $dlg->pollEvent(); + + my @media; @media = @{$options{medialist}} if ref $options{medialist}; + my $outerfatal = $urpm->{fatal}; + local $urpm->{fatal} = sub { $outerfatal->(@_) }; + urpm::media::update_those_media($urpm, [ urpm::media::select_media_by_name($urpm, \@media) ], + %options, allow_failures => 1, + callback => sub { + $cancel and goto cancel_update; + my ($type, $media) = @_; + goto cancel_update if $type !~ /^(?:start|progress|end)$/ && @media && !member($media, @media); + if ($type eq 'failed') { + $urpm->{fatal}->($loc->N("Error retrieving packages"), +$loc->N("It's impossible to retrieve the list of new packages from the media +`%s'. Either this update media is misconfigured, and in this case +you should use the Software Media Manager to remove it and re-add it in order +to reconfigure it, either it is currently unreachable and you should retry +later.", + $media)); + } else { + show_urpm_progress($label, $pb, @_); + $dlg->pollEvent(); + } + }, + ); + + $pb->setValue(100); + $dlg->waitForEvent(10); + $dlg->pollEvent(); + +cancel_update: + $dlg->destroy(); +} + +sub show_urpm_progress { + my ($label, $pb, $mode, $file, $percent, $total, $eta, $speed) = @_; + $file =~ s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; #- if needed... + state $medium; + + if ($mode eq 'copy') { + $pb->setValue(0); + $label->setValue($loc->N("Copying file for medium `%s'...", $file)); + } elsif ($mode eq 'parse') { + $pb->setValue(0); + $label->setValue($loc->N("Examining file of medium `%s'...", $file)); + } elsif ($mode eq 'retrieve') { + $pb->setValue(0); + $label->setValue($loc->N("Examining remote file of medium `%s'...", $file)); + $medium = $file; + } elsif ($mode eq 'done') { + $pb->setValue(100); + $label->setValue($label->value() . $loc->N(" done.")); + $medium = undef; + } elsif ($mode eq 'failed') { + $pb->setValue(100); + $label->setValue($label->value() . $loc->N(" failed!")); + $medium = undef; + } else { + # FIXME: we're displaying misplaced quotes such as "downloading `foobar from 'medium Main Updates'ยด" + $file = $medium && length($file) < 40 ? #-PO: We're downloading the said file from the said medium + $loc->N("%s from medium %s", basename($file), $medium) + : basename($file); + if ($mode eq 'start') { + $pb->setValue(0); + $label->setValue($loc->N("Starting download of `%s'...", $file)); + } elsif ($mode eq 'progress') { + if (defined $total && defined $eta) { + $pb->setValue($percent); + $label->setValue($loc->N("Download of `%s'\ntime to go:%s, speed:%s", $file, $eta, $speed)); + } else { + $pb->setValue($percent); + $label->setValue($loc->N("Download of `%s'\nspeed:%s", $file, $speed)); + } + } + } +} + + +sub update_sources_interactive { + my ($urpm, %options) = @_; + + my @media = grep { ! $_->{ignore} } @{$urpm->{media}}; + unless (@media) { + interactive_msg($loc->N("Warning"), $loc->N("No active medium found. You must enable some media to be able to update them.")); + return 0; + } + + my $appTitle = yui::YUI::app()->applicationTitle(); + + ## set new title to get it in dialog + yui::YUI::app()->setApplicationTitle($loc->N("Update media")); + + my $retVal = 0; + my $mageiaPlugin = "mga"; + my $factory = yui::YUI::widgetFactory; + my $mgaFactory = yui::YExternalWidgets::externalWidgetFactory($mageiaPlugin); + $mgaFactory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($mgaFactory); + + my $dialog = $factory->createPopupDialog(); + my $minSize = $factory->createMinSize( $dialog, 60, 15 ); + my $vbox = $factory->createVBox($minSize); + + my $yTableHeader = new yui::YTableHeader(); + $yTableHeader->addColumn("", $yui::YAlignBegin); + $yTableHeader->addColumn($loc->N("Media"), $yui::YAlignBegin); + + my $mediaTable = $mgaFactory->createCBTable($vbox, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn); + + my $itemCollection = new yui::YItemCollection; + foreach (@media) { + my $item = new yui::YCBTableItem($_->{name}); + $item->setLabel($_->{name}); + $itemCollection->push($item); + $item->DISOWN(); + } + $mediaTable->addItems($itemCollection); + + # dialog buttons + $factory->createVSpacing($vbox, 1.0); + ## Window push buttons + my $hbox = $factory->createHBox( $vbox ); + + my $cancelButton = $factory->createPushButton($hbox, $loc->N("Cancel") ); + my $selectButton = $factory->createPushButton($hbox, $loc->N("Select all") ); + my $updateButton = $factory->createPushButton($hbox, $loc->N("Update") ); + + while(1) { + my $event = $dialog->waitForEvent(); + my $eventType = $event->eventType(); + + #event type checking + if ($eventType == $yui::YEvent::CancelEvent) { + last; + } + elsif ($eventType == $yui::YEvent::WidgetEvent) { + # widget selected + my $widget = $event->widget(); + my $wEvent = yui::toYWidgetEvent($event); + + if ($widget == $cancelButton) { + last; + } + elsif ($widget == $selectButton) { + yui::YUI::app()->busyCursor(); + yui::YUI::ui()->blockEvents(); + $dialog->startMultipleChanges(); + for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { + my $item = $mediaTable->YItemIteratorToYItem($it); + if ($item) { + $mediaTable->checkItem($item, 1); + # NOTE for some reasons it is never == $mediaTable->itemsEnd() + if ($item->index() == $mediaTable->itemsCount()-1) { + last; + } + } + $it = $mediaTable->nextItem($it); + } + $dialog->recalcLayout(); + $dialog->doneMultipleChanges(); + yui::YUI::ui()->unblockEvents(); + yui::YUI::app()->normalCursor(); + + } + elsif ($widget == $updateButton) { + yui::YUI::app()->busyCursor(); + my @checked_media; + for (my $it = $mediaTable->itemsBegin(); $it != $mediaTable->itemsEnd(); ) { + my $item = $mediaTable->YItemIteratorToYItem($it); + $item = $mediaTable->toCBYTableItem($item); + if ($item) { + if ($item->checked()) { + push @checked_media, $item->label(); + } + # NOTE for some reasons it is never == $mediaTable->itemsEnd() + if ($item->index() == $mediaTable->itemsCount()-1) { + last; + } + } + $it = $mediaTable->nextItem($it); + } + + $retVal = update_sources_noninteractive($urpm, \@checked_media, %options); + yui::YUI::app()->normalCursor(); + last; + } + } + } + + $dialog->destroy(); + + #restore old application title + yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; + + return $retVal; +} + +sub update_sources_noninteractive { + my ($urpm, $media, %options) = @_; + + urpm::media::select_media_by_name($urpm, $media); + update_sources_check( + $urpm, + {}, + $loc->N_("Unable to update medium; it will be automatically disabled.\n\nErrors:\n%s"), + @$media, + ); + return 1; +} + +sub add_distrib_update_media { + my ($urpm, $mirror, %options) = @_; + #- ensure a unique medium name + my $medium_name = $ManaTools::rpmdragora::mageia_release =~ /(\d+\.\d+) \((\w+)\)/ ? $2 . $1 . '-' : 'distrib'; + my $initial_number = 1 + max map { $_->{name} =~ /\(\Q$medium_name\E(\d+)\b/ ? $1 : 0 } @{$urpm->{media}}; + add_medium_and_check( + $urpm, + { nolock => 1, distrib => 1 }, + $medium_name, + ($mirror ? $mirror->{url} : (undef, mirrorlist => '$MIRRORLIST')), + probe_with => 'synthesis', initial_number => $initial_number, %options, + usedistrib => 1, + ); +} + +sub warn_for_network_need { + my ($message, %options) = @_; + $message ||= + $branded + ? $loc->N("I need to access internet to get the mirror list. +Please check that your network is currently running. + +Is it ok to continue?") + : $loc->N("I need to contact the Mageia website to get the mirror list. +Please check that your network is currently running. + +Is it ok to continue?"); + interactive_msg($loc->N("Mirror choice"), $message, yesno => 1, %options) or return ''; +} + +sub choose_mirror { + my ($urpm, %options) = @_; + delete $options{message}; + my @transient_options = exists $options{transient} ? (transient => $options{transient}) : (); + warn_for_network_need($options{message}, %options) or return; + my @mirrors = eval { mirrors($urpm, $options{want_base_distro}) }; + my $error = $@; + if ($error) { + $error = "\n$error\n"; + interactive_msg($loc->N("Error during download"), + ($branded + ? $loc->N("There was an error downloading the mirror list:\n%s\n +The network, or the website, may be unavailable. +Please try again later.", $error) + : $loc->N("There was an error downloading the mirror list:\n%s\n +The network, or the Mageia website, may be unavailable. +Please try again later.", $error)), %options + ); + return ''; + } + + !@mirrors and interactive_msg($loc->N("No mirror"), + ($branded + ? $loc->N("I can't find any suitable mirror.") + : $loc->N("I can't find any suitable mirror.\n +There can be many reasons for this problem; the most frequent is +the case when the architecture of your processor is not supported +by Mageia Official Updates.")), %options + ), return ''; + + my @mirrorlist = map {$_->{country} . "|" . $_->{url}} @mirrors; + + my $sh_gui = ManaTools::Shared::GUI->new(); + my $mirror = $sh_gui->ask_fromTreeList({title => $loc->N("Mirror choice"), + header => $loc->N("Please choose the desired mirror."), + default_button => 1, + item_separator => "|", + default_item => $mirrors[0]->{url}, + skip_path => 1, + list => \@mirrorlist } + ); + + return $mirror ? { url => $mirror} : undef; + +} + + + + + + + +#- Check whether the default update media (added by installation) +#- matches the current mdk version +sub check_update_media_version { + my $urpm = shift; + foreach (@_) { + if ($_->{name} =~ /(\d+\.\d+).*\bftp\du\b/ && $1 ne $distro_version) { + interactive_msg( + $loc->N("Warning"), + $branded + ? $loc->N("Your medium `%s', used for updates, does not match the version of %s you're running (%s). +It will be disabled.", + $_->{name}, $distrib{system}, $distrib{product}) + : $loc->N("Your medium `%s', used for updates, does not match the version of Mageia you're running (%s). +It will be disabled.", + $_->{name}, $distro_version) + ); + $_->{ignore} = 1; + urpm::media::write_config($urpm) if -w $urpm->{config}; + return 0; + } + } + 1; +} + + + +sub mirrors { + my ($urpm, $want_base_distro) = @_; + my $cachedir = $urpm->{cachedir} || '/root'; + require mirror; + mirror::register_downloader( + sub { + my ($url) = @_; + my $file = $url; + $file =~ s!.*/!$cachedir/!; + unlink $file; # prevent "partial file" errors + MDK::Common::Func::before_leaving(sub { unlink $file }); + + my ($gurpm, $id, $canceled); + # display a message in statusbar (if availlable): + $::statusbar and $id = statusbar_msg( + $branded + ? $loc->N("Please wait, downloading mirror addresses.") + : $loc->N("Please wait, downloading mirror addresses from the Mageia website."), + 0); + my $_clean_guard = MDK::Common::Func::before_leaving { + undef $gurpm; + $id and statusbar_msg_remove($id); + }; + + require ManaTools::Rpmdragora::gurpm; + require ManaTools::Rpmdragora::pkg; + + my $res = urpm::download::sync_url($urpm, $url, + dir => $cachedir, + callback => sub { + $gurpm ||= + ManaTools::Rpmdragora::gurpm->new( + text => $loc->N("Please wait"), + ); + $canceled ||= + !ManaTools::Rpmdragora::pkg::download_callback($gurpm, @_); + $gurpm->flush(); + }, + ); + $res or die $loc->N("retrieval of [%s] failed", $file) . "\n"; + return $canceled ? () : MDK::Common::File::cat_($file); + }); + my @mirrors = @{ mirror::list(urpm::mirrors::parse_LDAP_namespace_structure(MDK::Common::File::cat_('/etc/product.id')), 'distrib') || [] }; + + require ManaTools::Shared::TimeZone; + my $tzo = ManaTools::Shared::TimeZone->new(); + my $tz = $tzo->readConfiguration()->{ZONE}; + foreach my $mirror (@mirrors) { + my $goodness = 0; + my $pri_mirr = defined ($t2l{$tz}) ? $t2l{$tz} : $us; + my $ind = 0; + foreach (@{$pri_mirr}) { + if (($_ eq lc($mirror->{zone})) || ($_ eq lc($mirror->{country}))) { + $goodness = scalar(@{$pri_mirr}) - $ind; + } + $ind ++; + } + + $mirror->{goodness} = $goodness + rand(); + $mirror->{country} = $u2l{lc($mirror->{country})} ? $loc->N($u2l{lc($mirror->{country})}) : $mirror->{country}; + } + unless (-x '/usr/bin/rsync') { + @mirrors = grep { $_->{url} !~ /^rsync:/ } @mirrors; + } + return sort { $b->{goodness} <=> $a->{goodness} } @mirrors; +} + + + + + +sub open_help { + my ($mode) = @_; + require ManaTools::Shared::RunProgram; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $mode ? "software-management-$mode" : 'software-management'); + my $_s = $loc->N("Help launched in background"); + statusbar_msg($loc->N("The help window has been started, it should appear shortly on your desktop."), 1); +} + +sub run_drakbug { + my ($id) = @_; + require ManaTools::Shared::RunProgram; + ManaTools::Shared::RunProgram::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', $id); +} + +#mygtk2::add_icon_path('/usr/share/mcc/themes/default/'); +sub get_icon { + my ($mcc_icon, $fallback_icon) = @_; + my $icon = eval { mygtk2::_find_imgfile($mcc_icon) }; + $icon ||= eval { mygtk2::_find_imgfile($fallback_icon) }; + $icon; +} + +sub strip_first_underscore { join '', map { s/_//; $_ } @_ } + +1; |