/[soft]/rpmdrake/trunk/rpmdrake.pm
ViewVC logotype

Contents of /rpmdrake/trunk/rpmdrake.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1030 - (show annotations) (download)
Thu Apr 28 18:34:00 2011 UTC (10 years, 5 months ago) by tv
File size: 33508 byte(s)
typo fix in comment
1 #*****************************************************************************
2 #
3 # Copyright (c) 2002 Guillaume Cottenceau
4 # Copyright (c) 2002-2007 Thierry Vignaud <tvignaud@mandriva.com>
5 # Copyright (c) 2003, 2004, 2005 MandrakeSoft SA
6 # Copyright (c) 2005, 2007 Mandriva SA
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License version 2, as
10 # published by the Free Software Foundation.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #
21 #*****************************************************************************
22 #
23 # $Id: rpmdrake.pm 267936 2010-04-26 16:40:21Z jvictor $
24
25 package rpmdrake;
26
27 use lib qw(/usr/lib/libDrakX);
28 use urpm::download ();
29 use urpm::prompt;
30 use urpm::media;
31
32 use MDK::Common;
33 use MDK::Common::System;
34 use urpm;
35 use urpm::cfg;
36 use URPM;
37 use URPM::Resolve;
38 use strict;
39 use c;
40 use POSIX qw(_exit);
41 use common;
42 use Locale::gettext;
43 use feature 'state';
44
45 our @ISA = qw(Exporter);
46 our $VERSION = '2.27';
47 our @EXPORT = qw(
48 $changelog_first_config
49 $compute_updates
50 $filter
51 $dont_show_selections
52 $ignore_debug_media
53 $mandrakeupdate_wanted_categories
54 $mandrivaupdate_height
55 $mandrivaupdate_width
56 $max_info_in_descr
57 $mode
58 $NVR_searches
59 $offered_to_add_sources
60 $rpmdrake_height
61 $rpmdrake_width
62 $tree_flat
63 $tree_mode
64 $use_regexp
65 $typical_width
66 $clean_cache
67 $auto_select
68 add_distrib_update_media
69 add_medium_and_check
70 but
71 but_
72 check_update_media_version
73 choose_mirror
74 distro_type
75 fatal_msg
76 getbanner
77 get_icon
78 interactive_list
79 interactive_list_
80 interactive_msg
81 interactive_packtable
82 myexit
83 readconf
84 remove_wait_msg
85 run_drakbug
86 show_urpm_progress
87 slow_func
88 slow_func_statusbar
89 statusbar_msg
90 statusbar_msg_remove
91 strip_first_underscore
92 update_sources
93 update_sources_check
94 update_sources_interactive
95 update_sources_noninteractive
96 wait_msg
97 warn_for_network_need
98 writeconf
99 );
100 our $typical_width = 280;
101
102 our $dont_show_selections;
103
104 # i18n: IMPORTANT: to get correct namespace (rpmdrake instead of libDrakX)
105 BEGIN { unshift @::textdomains, qw(rpmdrake urpmi rpm-summary-main rpm-summary-contrib rpm-summary-devel rpm-summary-non-free) }
106
107 use mygtk2 qw(gtknew);
108 use ugtk2 qw(:all);
109 ugtk2::add_icon_path('/usr/share/rpmdrake/icons');
110
111 Locale::gettext::bind_textdomain_codeset('rpmdrake', 'UTF8');
112
113 our $mandrake_release = cat_(
114 -e '/etc/mandrakelinux-release' ? '/etc/mandrakelinux-release' : '/etc/release'
115 ) || '';
116 chomp $mandrake_release;
117 our ($mdk_version) = $mandrake_release =~ /(\d+\.\d+)/;
118 our ($branded, %distrib);
119 $branded = -f '/etc/sysconfig/oem'
120 and %distrib = MDK::Common::System::distrib();
121 our $myname_update = $branded ? N("Software Update") : N("Mageia Update");
122
123 @rpmdrake::prompt::ISA = 'urpm::prompt';
124
125 sub rpmdrake::prompt::prompt {
126 my ($self) = @_;
127 my @answers;
128 my $d = ugtk2->new("", grab => 1, if_($::main_window, transient => $::main_window));
129 $d->{rwindow}->set_position('center_on_parent');
130 gtkadd(
131 $d->{window},
132 gtkpack(
133 Gtk2::VBox->new(0, 5),
134 Gtk2::WrappedLabel->new($self->{title}),
135 (map { gtkpack(
136 Gtk2::HBox->new(0, 5),
137 Gtk2::Label->new($self->{prompts}[$_]),
138 $answers[$_] = gtkset_visibility(gtkentry(), !$self->{hidden}[$_]),
139 ) } 0 .. $#{$self->{prompts}}),
140 gtksignal_connect(Gtk2::Button->new(N("Ok")), clicked => sub { Gtk2->main_quit }),
141 ),
142 );
143 $d->main;
144 map { $_->get_text } @answers;
145 }
146
147 $urpm::download::PROMPT_PROXY = new rpmdrake::prompt(
148 N("Please enter your credentials for accessing proxy\n"),
149 [ N("User name:"), N("Password:") ],
150 undef,
151 [ 0, 1 ],
152 );
153
154 sub myexit {
155 writeconf();
156 ugtk2::exit(undef, @_);
157 }
158
159 my ($root) = grep { $_->[2] == 0 } list_passwd();
160 $ENV{HOME} = $> == 0 ? $root->[7] : $ENV{HOME} || '/root';
161 $ENV{HOME} = $::env if $::env = $Rpmdrake::init::rpmdrake_options{env}[0];
162
163 our $configfile = "$ENV{HOME}/.rpmdrake";
164
165 #
166 # Configuration File Options
167 #
168
169 # clear download cache after successfull installation of packages
170 our $clean_cache;
171
172 # automatic select dependencies without user intervention
173 our $auto_select;
174
175 our ($changelog_first_config, $compute_updates, $filter, $max_info_in_descr, $mode, $NVR_searches, $tree_flat, $tree_mode, $use_regexp);
176 our ($mandrakeupdate_wanted_categories, $ignore_debug_media, $offered_to_add_sources, $no_confirmation);
177 our ($rpmdrake_height, $rpmdrake_width, $mandrivaupdate_height, $mandrivaupdate_width);
178
179 our %config = (
180 clean_cache => {
181 var => \$clean_cache,
182 default => [ 0 ]
183 },
184 auto_select => {
185 var => \$auto_select,
186 default => [ 0 ]
187 },
188 changelog_first_config => { var => \$changelog_first_config, default => [ 0 ] },
189 compute_updates => { var => \$compute_updates, default => [ 1 ] },
190 dont_show_selections => { var => \$dont_show_selections, default => [ $> ? 1 : 0 ] },
191 filter => { var => \$filter, default => [ 'all' ] },
192 ignore_debug_media => { var => \$ignore_debug_media, default => [ 0 ] },
193 mandrakeupdate_wanted_categories => { var => \$mandrakeupdate_wanted_categories, default => [ qw(security) ] },
194 mandrivaupdate_height => { var => \$mandrivaupdate_height, default => [ 0 ] },
195 mandrivaupdate_width => { var => \$mandrivaupdate_width, default => [ 0 ] },
196 max_info_in_descr => { var => \$max_info_in_descr, default => [] },
197 mode => { var => \$mode, default => [ 'by_group' ] },
198 NVR_searches => { var => \$NVR_searches, default => [ 0 ] },
199 'no-confirmation' => { var => \$no_confirmation, default => [ 0 ] },
200 offered_to_add_sources => { var => \$offered_to_add_sources, default => [ 0 ] },
201 rpmdrake_height => { var => \$rpmdrake_height, default => [ 0 ] },
202 rpmdrake_width => { var => \$rpmdrake_width, default => [ 0 ] },
203 tree_flat => { var => \$tree_flat, default => [ 0 ] },
204 tree_mode => { var => \$tree_mode, default => [ qw(gui_pkgs) ] },
205 use_regexp => { var => \$use_regexp, default => [ 0 ] },
206 );
207
208 sub readconf() {
209 ${$config{$_}{var}} = $config{$_}{default} foreach keys %config;
210 foreach my $l (cat_($configfile)) {
211 foreach (keys %config) {
212 ${$config{$_}{var}} = [ split ' ', $1 ] if $l =~ /^\Q$_\E(.*)/;
213 }
214 }
215 # special cases:
216 $::rpmdrake_options{'no-confirmation'} = $no_confirmation->[0] if !defined $::rpmdrake_options{'no-confirmation'};
217 $Rpmdrake::init::default_list_mode = $tree_mode->[0] if ref $tree_mode && !$Rpmdrake::init::overriding_config;
218 }
219
220 sub writeconf() {
221 return if $::env;
222 unlink $configfile;
223
224 # special case:
225 $no_confirmation->[0] = $::rpmdrake_options{'no-confirmation'};
226
227 output $configfile, map { "$_ " . (ref ${$config{$_}{var}} ? join(' ', @${$config{$_}{var}}) : ()) . "\n" } keys %config;
228 }
229
230 sub getbanner() {
231 $::MODE or return undef;
232 if (0) {
233 +{
234 remove => N("Software Packages Removal"),
235 update => N("Software Packages Update"),
236 install => N("Software Packages Installation"),
237 };
238 }
239 Gtk2::Banner->new($ugtk2::wm_icon, $::MODE eq 'update' ? N("Software Packages Update") : N("Software Management"));
240 }
241
242 # return value:
243 # - undef if if closed (aka really canceled)
244 # - 0 if if No/Cancel
245 # - 1 if if Yes/Ok
246 sub interactive_msg {
247 my ($title, $contents, %options) = @_;
248 $options{transient} ||= $::main_window if $::main_window;
249 local $::isEmbedded;
250 my $d = ugtk2->new($title, grab => 1, if_(exists $options{transient}, transient => $options{transient}));
251 $d->{rwindow}->set_position($options{transient} ? 'center_on_parent' : 'center_always');
252 if ($options{scroll}) {
253 $contents = ugtk2::markup_to_TextView_format($contents) if !ref $contents;
254 } else { #- because we'll use a WrappedLabel
255 $contents = formatAlaTeX($contents) if !ref $contents;
256 }
257 my $text_w;
258 my $button_yes;
259 gtkadd(
260 $d->{window},
261 gtkpack_(
262 Gtk2::VBox->new(0, 5),
263 1,
264 (
265 $options{scroll} ?
266 ($text_w = create_scrolled_window(gtktext_insert(Gtk2::TextView->new, $contents)))
267 : ($text_w = gtknew('WrappedLabel', text_markup => $contents))
268 ),
269 if_($options{widget}, 0, $options{widget}),
270 0,
271 gtkpack(
272 create_hbox(),
273 (
274 ref($options{yesno}) eq 'ARRAY' ? map {
275 my $label = $_;
276 gtksignal_connect(
277 $button_yes = Gtk2::Button->new($label),
278 clicked => sub { $d->{retval} = $label; Gtk2->main_quit }
279 );
280 } @{$options{yesno}}
281 : (
282 $options{yesno} ? (
283 gtksignal_connect(
284 Gtk2::Button->new($options{text}{no} || N("No")),
285 clicked => sub { $d->{retval} = 0; Gtk2->main_quit }
286 ),
287 gtksignal_connect(
288 $button_yes = Gtk2::Button->new($options{text}{yes} || N("Yes")),
289 clicked => sub { $d->{retval} = 1; Gtk2->main_quit }
290 ),
291 )
292 : gtksignal_connect(
293 $button_yes = Gtk2::Button->new(N("Ok")),
294 clicked => sub { Gtk2->main_quit }
295 )
296 )
297 )
298 )
299 )
300 );
301 $d->{window}->set_focus($button_yes);
302 $text_w->set_size_request($typical_width*2, $options{scroll} ? 300 : -1);
303 $d->main;
304 return $d->{retval};
305 }
306
307 sub interactive_packtable {
308 my ($title, $parent_window, $top_label, $lines, $action_buttons) = @_;
309
310 my $w = ugtk2->new($title, grab => 1, transient => $parent_window);
311 local $::main_window = $w->{real_window};
312 $w->{rwindow}->set_position($parent_window ? 'center_on_parent' : 'center');
313 my $packtable = create_packtable({}, @$lines);
314
315 gtkadd($w->{window},
316 gtkpack_(Gtk2::VBox->new(0, 5),
317 if_($top_label, 0, Gtk2::Label->new($top_label)),
318 1, create_scrolled_window($packtable),
319 0, gtkpack__(create_hbox(), @$action_buttons)));
320 my $preq = $packtable->size_request;
321 my ($xpreq, $ypreq) = ($preq->width, $preq->height);
322 my $wreq = $w->{rwindow}->size_request;
323 my ($xwreq, $ywreq) = ($wreq->width, $wreq->height);
324 $w->{rwindow}->set_default_size(max($typical_width, min($typical_width*2.5, $xpreq+$xwreq)),
325 max(200, min(450, $ypreq+$ywreq)));
326 $w->main;
327 }
328
329 sub interactive_list {
330 my ($title, $contents, $list, $callback, %options) = @_;
331 my $d = ugtk2->new($title, grab => 1, if_(exists $options{transient}, transient => $options{transient}));
332 $d->{rwindow}->set_position($options{transient} ? 'center_on_parent' : 'center_always');
333 my @radios = gtkradio('', @$list);
334 my $vbradios = $callback ? create_packtable(
335 {},
336 mapn {
337 my $n = $_[1];
338 [ $_[0],
339 gtksignal_connect(
340 Gtk2::Button->new(but(N("Info..."))),
341 clicked => sub { $callback->($n) },
342 ) ];
343 } \@radios, $list,
344 ) : gtkpack__(Gtk2::VBox->new(0, 0), @radios);
345 my $choice;
346 my $button_ok;
347 gtkadd(
348 $d->{window},
349 gtkpack__(
350 Gtk2::VBox->new(0,5),
351 Gtk2::Label->new($contents),
352 int(@$list) > 8 ? gtkset_size_request(create_scrolled_window($vbradios), 250, 320) : $vbradios,
353 gtkpack__(
354 create_hbox(),
355 if_(!$options{nocancel},
356 gtksignal_connect(
357 Gtk2::Button->new(N("Cancel")), clicked => sub { Gtk2->main_quit }),
358 ),
359 gtksignal_connect(
360 $button_ok=Gtk2::Button->new(N("Ok")), clicked => sub {
361 each_index { $_->get_active and $choice = $::i } @radios;
362 Gtk2->main_quit;
363 }
364 )
365 )
366 )
367 );
368 $d->{window}->set_focus($button_ok);
369 $d->main;
370 $choice;
371 }
372
373 sub interactive_list_ { interactive_list(@_, if_($::main_window, transient => $::main_window)) }
374
375 sub fatal_msg {
376 interactive_msg @_;
377 myexit -1;
378 }
379
380 sub wait_msg {
381 my ($msg, %options) = @_;
382 gtkflush();
383 $options{transient} ||= $::main_window if $::main_window;
384 local $::isEmbedded;
385 my $mainw = ugtk2->new(N("Please wait"), grab => 1, if_(exists $options{transient}, transient => $options{transient}));
386 $mainw->{real_window}->set_position($options{transient} ? 'center_on_parent' : 'center_always');
387 my $label = ref($msg) =~ /^Gtk/ ? $msg : Gtk2::WrappedLabel->new($msg);
388 gtkadd(
389 $mainw->{window},
390 gtkpack__(
391 gtkset_border_width(Gtk2::VBox->new(0, 5), 6),
392 $label,
393 if_(exists $options{widgets}, @{$options{widgets}}),
394 )
395 );
396 $mainw->sync;
397 gtkset_mousecursor_wait($mainw->{rwindow}->window) unless $options{no_wait_cursor};
398 $mainw->flush;
399 $mainw;
400 }
401
402 sub remove_wait_msg {
403 my $w = shift;
404 gtkset_mousecursor_normal($w->{rwindow}->window);
405 $w->destroy;
406 }
407
408 sub but { " $_[0] " }
409 sub but_ { " $_[0] " }
410
411 sub slow_func ($&) {
412 my ($param, $func) = @_;
413 if (ref($param) =~ /^Gtk/) {
414 gtkset_mousecursor_wait($param);
415 ugtk2::flush();
416 $func->();
417 gtkset_mousecursor_normal($param);
418 } else {
419 my $w = wait_msg($param);
420 $func->();
421 remove_wait_msg($w);
422 }
423 }
424
425 sub statusbar_msg {
426 unless ($::statusbar) { #- fallback if no status bar
427 if (defined &::wait_msg_) { goto &::wait_msg_ } else { goto &wait_msg }
428 }
429 my ($msg, $o_timeout) = @_;
430 #- always use the same context description for now
431 my $cx = $::statusbar->get_context_id("foo");
432 $::w and $::w->{rwindow} and gtkset_mousecursor_wait($::w->{rwindow}->window);
433 #- returns a msg_id to be passed optionnally to statusbar_msg_remove
434 my $id = $::statusbar->push($cx, $msg);
435 gtkflush();
436 Glib::Timeout->add(5000, sub { statusbar_msg_remove($id); 0 }) if $o_timeout;
437 $id;
438 }
439
440 sub statusbar_msg_remove {
441 my ($msg_id) = @_;
442 if (!$::statusbar || ref $msg_id) { #- fallback if no status bar
443 goto &remove_wait_msg;
444 }
445 my $cx = $::statusbar->get_context_id("foo");
446 if (defined $msg_id) {
447 $::statusbar->remove($cx, $msg_id);
448 } else {
449 $::statusbar->pop($cx);
450 }
451 $::w and $::w->{rwindow} and gtkset_mousecursor_normal($::w->{rwindow}->window);
452 }
453
454 sub slow_func_statusbar ($$&) {
455 my ($msg, $w, $func) = @_;
456 gtkset_mousecursor_wait($w->window);
457 my $msg_id = statusbar_msg($msg);
458 gtkflush();
459 $func->();
460 statusbar_msg_remove($msg_id);
461 gtkset_mousecursor_normal($w->window);
462 }
463
464 my %u2l = (
465 at => N_("Austria"),
466 au => N_("Australia"),
467 be => N_("Belgium"),
468 br => N_("Brazil"),
469 ca => N_("Canada"),
470 ch => N_("Switzerland"),
471 cr => N_("Costa Rica"),
472 cz => N_("Czech Republic"),
473 de => N_("Germany"),
474 dk => N_("Danmark"),
475 el => N_("Greece"),
476 es => N_("Spain"),
477 fi => N_("Finland"),
478 fr => N_("France"),
479 gr => N_("Greece"),
480 hu => N_("Hungary"),
481 il => N_("Israel"),
482 it => N_("Italy"),
483 jp => N_("Japan"),
484 ko => N_("Korea"),
485 nl => N_("Netherlands"),
486 no => N_("Norway"),
487 pl => N_("Poland"),
488 pt => N_("Portugal"),
489 ru => N_("Russia"),
490 se => N_("Sweden"),
491 sg => N_("Singapore"),
492 sk => N_("Slovakia"),
493 tw => N_("Taiwan"),
494 uk => N_("United Kingdom"),
495 cn => N_("China"),
496 com => N_("United States"),
497 org => N_("United States"),
498 net => N_("United States"),
499 edu => N_("United States"),
500 );
501 my $us = [ qw(com org net edu) ];
502 my %t2l = (
503 'America/\w+' => $us,
504 'Asia/Tel_Aviv' => [ qw(il ru it cz at de fr se) ],
505 'Asia/Tokyo' => [ qw(jp ko tw), @$us ],
506 'Asia/Seoul' => [ qw(ko jp tw), @$us ],
507 'Asia/Taipei' => [ qw(tw jp), @$us ],
508 'Asia/(Shanghai|Beijing)' => [ qw(cn tw sg), @$us ],
509 'Asia/Singapore' => [ qw(cn sg), @$us ],
510 'Atlantic/Reykjavik' => [ qw(uk no se fi dk), @$us, qw(nl de fr at cz it) ],
511 'Australia/\w+' => [ qw(au jp ko tw), @$us ],
512 'Brazil/\w+' => [ 'br', @$us ],
513 'Canada/\w+' => [ 'ca', @$us ],
514 'Europe/Amsterdam' => [ qw(nl be de at cz fr se dk it) ],
515 'Europe/Athens' => [ qw(gr pl cz de it nl at fr) ],
516 'Europe/Berlin' => [ qw(de be at nl cz it fr se) ],
517 'Europe/Brussels' => [ qw(be de nl fr cz at it se) ],
518 'Europe/Budapest' => [ qw(cz it at de fr nl se) ],
519 'Europe/Copenhagen' => [ qw(dk nl de be se at cz it) ],
520 'Europe/Dublin' => [ qw(uk fr be nl dk se cz it) ],
521 'Europe/Helsinki' => [ qw(fi se no nl be de fr at it) ],
522 'Europe/Istanbul' => [ qw(il ru it cz it at de fr nl se) ],
523 'Europe/Lisbon' => [ qw(pt es fr it cz at de se) ],
524 'Europe/London' => [ qw(uk fr be nl de at cz se it) ],
525 'Europe/Madrid' => [ qw(es fr pt it cz at de se) ],
526 'Europe/Moscow' => [ qw(ru de pl cz at se be fr it) ],
527 'Europe/Oslo' => [ qw(no se fi dk de be at cz it) ],
528 'Europe/Paris' => [ qw(fr be de at cz nl it se) ],
529 'Europe/Prague' => [ qw(cz it at de fr nl se) ],
530 'Europe/Rome' => [ qw(it fr cz de at nl se) ],
531 'Europe/Stockholm' => [ qw(se no dk fi nl de at cz fr it) ],
532 'Europe/Vienna' => [ qw(at de cz it fr nl se) ],
533 );
534
535 #- get distrib release number (2006.0, etc)
536 sub etc_version() {
537 (my $v) = split / /, cat_('/etc/version');
538 return $v;
539 }
540
541 #- returns the keyword describing the type of the distribution.
542 #- the parameter indicates whether we want base or update sources
543 sub distro_type {
544 my ($want_base_distro) = @_;
545 return 'cooker' if $mandrake_release =~ /cooker/i;
546 #- we can't use updates for community while official is not out (release ends in ".0")
547 if ($want_base_distro || $mandrake_release =~ /community/i && etc_version() =~ /\.0$/) {
548 return 'official' if $mandrake_release =~ /official|limited/i;
549 return 'community' if $mandrake_release =~ /community/i;
550 #- unknown: fallback to updates
551 }
552 return 'updates';
553 }
554
555 sub compat_arch_for_updates($) {
556 # FIXME: We prefer 64-bit packages to update on biarch platforms,
557 # since the system is populated with 64-bit packages anyway.
558 my ($arch) = @_;
559 return $arch =~ /x86_64|amd64/ if arch() eq 'x86_64';
560 MDK::Common::System::compat_arch($arch);
561 }
562
563 sub mirrors {
564 my ($urpm, $want_base_distro) = @_;
565 my $cachedir = $urpm->{cachedir} || '/root';
566 require mirror;
567 mirror::register_downloader(
568 sub {
569 my ($url) = @_;
570 my $file = $url;
571 $file =~ s!.*/!$cachedir/!;
572 unlink $file; # prevent "partial file" errors
573 before_leaving(sub { unlink $file });
574
575 my ($gurpm, $id, $canceled);
576 # display a message in statusbar (if availlable):
577 $::statusbar and $id = statusbar_msg(
578 $branded
579 ? N("Please wait, downloading mirror addresses.")
580 : N("Please wait, downloading mirror addresses from the Mageia website."),
581 0);
582 my $_clean_guard = before_leaving {
583 undef $gurpm;
584 $id and statusbar_msg_remove($id);
585 };
586
587 require Rpmdrake::gurpm;
588 require Rpmdrake::pkg;
589
590 my $res = urpm::download::sync_url($urpm, $url,
591 dir => $cachedir,
592 callback => sub {
593 $gurpm ||=
594 Rpmdrake::gurpm->new(N("Please wait"),
595 transient => $::main_window);
596 $canceled ||=
597 !Rpmdrake::pkg::download_callback($gurpm, @_);
598 gtkflush();
599 },
600 );
601 $res or die N("retrieval of [%s] failed", $file) . "\n";
602 return $canceled ? () : cat_($file);
603 });
604 my @mirrors = @{ mirror::list(common::parse_LDAP_namespace_structure(cat_('/etc/product.id')), 'distrib') || [] };
605 require timezone;
606 my $tz = ${timezone::read()}{timezone};
607 foreach my $mirror (@mirrors) {
608 my $goodness;
609 each_index { $_ = $u2l{$_} || $_; $_ eq $mirror->{country} and $goodness ||= 100-$::i } (map { if_($tz =~ /^$_$/, @{$t2l{$_}}) } keys %t2l), @$us;
610 $mirror->{goodness} = $goodness + rand();
611 $mirror->{country} = translate($mirror->{country});
612 }
613 unless (-x '/usr/bin/rsync') {
614 @mirrors = grep { $_->{url} !~ /^rsync:/ } @mirrors;
615 }
616 return sort { $b->{goodness} <=> $a->{goodness} } @mirrors;
617 }
618
619 sub warn_for_network_need {
620 my ($message, %options) = @_;
621 $message ||=
622 $branded
623 ? N("I need to access internet to get the mirror list.
624 Please check that your network is currently running.
625
626 Is it ok to continue?")
627 : N("I need to contact the Mageia website to get the mirror list.
628 Please check that your network is currently running.
629
630 Is it ok to continue?");
631 interactive_msg(N("Mirror choice"), $message, yesno => 1, %options) or return '';
632 }
633
634 sub choose_mirror {
635 my ($urpm, %options) = @_;
636 delete $options{message};
637 my @transient_options = exists $options{transient} ? (transient => $options{transient}) : ();
638 warn_for_network_need($options{message}, %options) or return;
639 my @mirrors = eval { mirrors($urpm, $options{want_base_distro}) };
640 my $error = $@;
641 if ($error) {
642 $error = "\n$error\n";
643 interactive_msg(N("Error during download"),
644 ($branded
645 ? N("There was an error downloading the mirror list:
646
647 %s
648 The network, or the website, may be unavailable.
649 Please try again later.", $error)
650 : N("There was an error downloading the mirror list:
651
652 %s
653 The network, or the Mageia website, may be unavailable.
654 Please try again later.", $error)), %options
655
656 );
657 return '';
658 }
659
660 !@mirrors and interactive_msg(N("No mirror"),
661 ($branded
662 ? N("I can't find any suitable mirror.")
663 : N("I can't find any suitable mirror.
664
665 There can be many reasons for this problem; the most frequent is
666 the case when the architecture of your processor is not supported
667 by Mageia Official Updates.")), %options
668 ), return '';
669
670 my $w = ugtk2->new(N("Mirror choice"), grab => 1, @transient_options);
671 $w->{rwindow}->set_position($options{transient} ? 'center_on_parent' : 'center_always');
672 my $tree_model = Gtk2::TreeStore->new("Glib::String");
673 my $tree = Gtk2::TreeView->new_with_model($tree_model);
674 $tree->get_selection->set_mode('browse');
675 $tree->append_column(Gtk2::TreeViewColumn->new_with_attributes(undef, Gtk2::CellRendererText->new, text => 0));
676 $tree->set_headers_visible(0);
677
678 gtkadd(
679 $w->{window},
680 gtkpack_(
681 Gtk2::VBox->new(0,5),
682 0, N("Please choose the desired mirror."),
683 1, create_scrolled_window($tree),
684 0, gtkpack(
685 create_hbox('edge'),
686 map {
687 my $retv = $_->[1];
688 gtksignal_connect(
689 Gtk2::Button->new(but($_->[0])),
690 clicked => sub {
691 if ($retv) {
692 my ($model, $iter) = $tree->get_selection->get_selected;
693 $model and $w->{retval} = { sel => $model->get($iter, 0) };
694 }
695 Gtk2->main_quit;
696 },
697 );
698 } [ N("Cancel"), 0 ], [ N("Ok"), 1 ]
699 ),
700 )
701 );
702 my %roots;
703 $tree_model->append_set($roots{$_->{country}} ||= $tree_model->append_set(undef, [ 0 => $_->{country} ]),
704 [ 0 => $_->{url} ]) foreach @mirrors;
705
706 $w->{window}->set_size_request(500, 400);
707 $w->{rwindow}->show_all;
708
709 my $path = Gtk2::TreePath->new_first;
710 $tree->expand_row($path, 0);
711 $path->down;
712 $tree->get_selection->select_path($path);
713
714 $w->main && return grep { $w->{retval}{sel} eq $_->{url} } @mirrors;
715 }
716
717 sub show_urpm_progress {
718 my ($label, $pb, $mode, $file, $percent, $total, $eta, $speed) = @_;
719 $file =~ s|([^:]*://[^/:\@]*:)[^/:\@]*(\@.*)|$1xxxx$2|; #- if needed...
720 state $medium;
721 if ($mode eq 'copy') {
722 $pb->set_fraction(0);
723 $label->set_label(N("Copying file for medium `%s'...", $file));
724 } elsif ($mode eq 'parse') {
725 $pb->set_fraction(0);
726 $label->set_label(N("Examining file of medium `%s'...", $file));
727 } elsif ($mode eq 'retrieve') {
728 $pb->set_fraction(0);
729 $label->set_label(N("Examining remote file of medium `%s'...", $file));
730 $medium = $file;
731 } elsif ($mode eq 'done') {
732 $pb->set_fraction(1.0);
733 $label->set_label($label->get_label . N(" done."));
734 $medium = undef;
735 } elsif ($mode eq 'failed') {
736 $pb->set_fraction(1.0);
737 $label->set_label($label->get_label . N(" failed!"));
738 $medium = undef;
739 } else {
740 # FIXME: we're displaying misplaced quotes such as "downloading `foobar from 'medium Main Updates'ยด"
741 $file = $medium && length($file) < 40 ? #-PO: We're downloading the said file from the said medium
742 N("%s from medium %s", basename($file), $medium)
743 : basename($file);
744 if ($mode eq 'start') {
745 $pb->set_fraction(0);
746 $label->set_label(N("Starting download of `%s'...", $file));
747 } elsif ($mode eq 'progress') {
748 if (defined $total && defined $eta) {
749 $pb->set_fraction($percent/100);
750 $label->set_label(N("Download of `%s'\ntime to go:%s, speed:%s", $file, $eta, $speed));
751 } else {
752 $pb->set_fraction($percent/100);
753 $label->set_label(N("Download of `%s'\nspeed:%s", $file, $speed));
754 }
755 }
756 }
757 Gtk2->main_iteration while Gtk2->events_pending;
758 }
759
760 sub update_sources {
761 my ($urpm, %options) = @_;
762 my $cancel = 0;
763 my $w; my $label; $w = wait_msg(
764 $label = Gtk2::Label->new(N("Please wait, updating media...")),
765 no_wait_cursor => 1,
766 widgets => [
767 my $pb = gtkset_size_request(Gtk2::ProgressBar->new, 300, -1),
768 gtkpack(
769 create_hbox(),
770 gtksignal_connect(
771 Gtk2::Button->new(N("Cancel")),
772 clicked => sub {
773 $cancel = 1;
774 $urpm->{error}->(N("Canceled"));
775 $w and $w->destroy;
776 },
777 ),
778 ),
779 ],
780 );
781 my @media; @media = @{$options{medialist}} if ref $options{medialist};
782 my $outerfatal = $urpm->{fatal};
783 local $urpm->{fatal} = sub { $w->destroy; $outerfatal->(@_) };
784 urpm::media::update_those_media($urpm, [ urpm::media::select_media_by_name($urpm, \@media) ],
785 %options, allow_failures => 1,
786 callback => sub {
787 $cancel and goto cancel_update;
788 my ($type, $media) = @_;
789 return if $type !~ /^(?:start|progress|end)$/ && @media && !member($media, @media);
790 if ($type eq 'failed') {
791 $urpm->{fatal}->(N("Error retrieving packages"),
792 N("It's impossible to retrieve the list of new packages from the media
793 `%s'. Either this update media is misconfigured, and in this case
794 you should use the Software Media Manager to remove it and re-add it in order
795 to reconfigure it, either it is currently unreachable and you should retry
796 later.",
797 $media));
798 } else {
799 show_urpm_progress($label, $pb, @_);
800 }
801 },
802 );
803 $w->destroy;
804 cancel_update:
805 }
806
807 sub update_sources_check {
808 my ($urpm, $options, $error_msg, @media) = @_;
809 my @error_msgs;
810 local $urpm->{fatal} = sub { push @error_msgs, $_[1]; goto fatal_error };
811 local $urpm->{error} = sub { push @error_msgs, $_[0] };
812 update_sources($urpm, %$options, noclean => 1, medialist => \@media);
813 fatal_error:
814 if (@error_msgs) {
815 interactive_msg(N("Error"), sprintf(translate($error_msg), join("\n", map { formatAlaTeX($_) } @error_msgs)), scroll => 1);
816 return 0;
817 }
818 return 1;
819 }
820
821 sub update_sources_interactive {
822 my ($urpm, %options) = @_;
823 my $w = ugtk2->new(N("Update media"), grab => 1, center => 1, %options);
824 $w->{rwindow}->set_position($options{transient} ? 'center_on_parent' : 'center_always');
825 my @buttons;
826 my @media = grep { ! $_->{ignore} } @{$urpm->{media}};
827 unless (@media) {
828 interactive_msg(N("Warning"), N("No active medium found. You must enable some media to be able to update them."));
829 return 0;
830 }
831 gtkadd(
832 $w->{window},
833 gtkpack_(
834 0, Gtk2::VBox->new(0,5),
835 0, Gtk2::Label->new(N("Select the media you wish to update:")),
836 1, gtknew('ScrolledWindow', height => 300, child =>
837 # FIXME: using a listview would be just better:
838 gtknew('VBox', spacing => 5, children_tight => [
839 @buttons = map {
840 Gtk2::CheckButton->new_with_label($_->{name});
841 } @media
842 ])
843 ),
844 0, Gtk2::HSeparator->new,
845 0, gtkpack(
846 create_hbox(),
847 gtksignal_connect(
848 Gtk2::Button->new(N("Cancel")),
849 clicked => sub { $w->{retval} = 0; Gtk2->main_quit },
850 ),
851 gtksignal_connect(
852 Gtk2::Button->new(N("Select all")),
853 clicked => sub { $_->set_active(1) foreach @buttons },
854 ),
855 gtksignal_connect(
856 Gtk2::Button->new(N("Update")),
857 clicked => sub {
858 $w->{retval} = any { $_->get_active } @buttons;
859 # list of media listed in the checkbox panel
860 my @buttonmedia = grep { !$_->{ignore} } @{$urpm->{media}};
861 @media = map_index { if_($_->get_active, $buttonmedia[$::i]{name}) } @buttons;
862 Gtk2->main_quit;
863 },
864 ),
865 )
866 )
867 );
868 if ($w->main) {
869 return update_sources_noninteractive($urpm, \@media, %options);
870 }
871 return 0;
872 }
873
874 sub update_sources_noninteractive {
875 my ($urpm, $media, %options) = @_;
876
877 urpm::media::select_media($urpm, @$media);
878 update_sources_check(
879 $urpm,
880 {},
881 N_("Unable to update medium; it will be automatically disabled.\n\nErrors:\n%s"),
882 @$media,
883 );
884 return 1;
885 }
886
887 sub add_medium_and_check {
888 my ($urpm, $options) = splice @_, 0, 2;
889 my @newnames = ($_[0]); #- names of added media
890 my $fatal_msg;
891 my @error_msgs;
892 local $urpm->{fatal} = sub { printf STDERR "Fatal: %s\n", $_[1]; $fatal_msg = $_[1]; goto fatal_error };
893 local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] };
894 if ($options->{distrib}) {
895 @newnames = urpm::media::add_distrib_media($urpm, @_);
896 } else {
897 urpm::media::add_medium($urpm, @_);
898 }
899 if (@error_msgs) {
900 interactive_msg(
901 N("Error"),
902 N("Unable to add medium, errors reported:\n\n%s",
903 join("\n", map { formatAlaTeX($_) } @error_msgs)) . "\n\n" . N("Medium: ") . "$_[0] ($_[1])",
904 scroll => 1,
905 );
906 return 0;
907 }
908
909 foreach my $name (@newnames) {
910 urpm::download::set_proxy_config($_, $options->{proxy}{$_}, $name) foreach keys %{$options->{proxy} || {}};
911 }
912
913 if (update_sources_check($urpm, $options, N_("Unable to add medium, errors reported:\n\n%s"), @newnames)) {
914 urpm::media::write_config($urpm);
915 $options->{proxy} and urpm::download::dump_proxy_config();
916 } else {
917 urpm::media::read_config($urpm);
918 return 0;
919 }
920
921 my %newnames; @newnames{@newnames} = ();
922 if (any { exists $newnames{$_->{name}} } @{$urpm->{media}}) {
923 return 1;
924 } else {
925 interactive_msg(N("Error"), N("Unable to create medium."));
926 return 0;
927 }
928
929 fatal_error:
930 interactive_msg(N("Failure when adding medium"),
931 N("There was a problem adding medium:\n\n%s", $fatal_msg));
932 return 0;
933 }
934
935 #- Check whether the default update media (added by installation)
936 #- matches the current mdk version
937 sub check_update_media_version {
938 my $urpm = shift;
939 foreach (@_) {
940 if ($_->{name} =~ /(\d+\.\d+).*\bftp\du\b/ && $1 ne $mdk_version) {
941 interactive_msg(
942 N("Warning"),
943 $branded
944 ? N("Your medium `%s', used for updates, does not match the version of %s you're running (%s).
945 It will be disabled.",
946 $_->{name}, $distrib{system}, $distrib{product})
947 : N("Your medium `%s', used for updates, does not match the version of Mageia you're running (%s).
948 It will be disabled.",
949 $_->{name}, $mdk_version)
950 );
951 $_->{ignore} = 1;
952 urpm::media::write_config($urpm) if -w $urpm->{config};
953 return 0;
954 }
955 }
956 1;
957 }
958
959 sub add_distrib_update_media {
960 my ($urpm, $mirror, %options) = @_;
961 #- ensure a unique medium name
962 my $medium_name = $rpmdrake::mandrake_release =~ /(\d+\.\d+) \((\w+)\)/ ? $2 . $1 . '-' : 'distrib';
963 my $initial_number = 1 + max map { $_->{name} =~ /\(\Q$medium_name\E(\d+)\b/ ? $1 : 0 } @{$urpm->{media}};
964 add_medium_and_check(
965 $urpm,
966 { nolock => 1, distrib => 1 },
967 $medium_name,
968 ($mirror ? $mirror->{url} : (undef, mirrorlist => '$MIRRORLIST')),
969 probe_with => 'synthesis', initial_number => $initial_number, %options,
970 usedistrib => 1,
971 );
972 }
973
974 sub open_help {
975 my ($mode) = @_;
976 use run_program;
977 run_program::raw({ detach => 1, as_user => 1 }, 'drakhelp', '--id', $mode ? "software-management-$mode" : 'software-management');
978 N("Help launched in background");
979 statusbar_msg(N("The help window has been started, it should appear shortly on your desktop."), 1);
980 }
981
982 sub run_drakbug {
983 my ($id) = @_;
984 run_program::raw({ detach => 1, as_user => 1 }, 'drakbug', '--report', $id);
985 }
986
987 mygtk2::add_icon_path('/usr/share/mcc/themes/default/');
988 sub get_icon {
989 my ($mcc_icon, $fallback_icon) = @_;
990 my $icon = eval { mygtk2::_find_imgfile($mcc_icon) };
991 $icon ||= eval { mygtk2::_find_imgfile($fallback_icon) };
992 $icon;
993 }
994
995 sub strip_first_underscore { join '', map { s/_//; $_ } @_ }
996
997 1;

  ViewVC Help
Powered by ViewVC 1.1.28