summaryrefslogtreecommitdiffstats
path: root/perl_checker.src/perl_checker.ml
blob: 52eaaf57685a0af539da2a3cad85cda587d62b56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
open Types
open Common
open Tree
open Global_checks

let search_basedir file_name nb =
  let dir = Filename.dirname file_name in
  let config = Config_file.read dir in
  let nb = some_or config.Config_file.basedir nb in
  updir dir nb

let basedir = ref ""
let set_basedir state package =
  if !basedir = "" then
    let nb = List.length (split_at2 ':'':' package.package_name) - 1 in
    let dir = search_basedir package.file_name nb in
    lpush Tree.use_lib dir ;
    Config_file.read_any dir 1 ;
    read_packages_from_cache state dir ;
    if !Flags.verbose then print_endline_flush ("basedir is " ^ dir);
    basedir := dir

let mtime f = int_of_float ((Unix.stat f).Unix.st_mtime)

let rec parse_file from_basedir state file =
  try
    if !Flags.verbose then print_endline_flush ("checking " ^ file) ;
    let build_time = int_of_float (Unix.time()) in
    let command = 
      match !Flags.expand_tabs with
      | Some width -> "expand -t " ^ string_of_int width
      | None -> "cat" in
    let channel = Unix.open_process_in (Printf.sprintf "%s \"%s\"" command file) in
    let lexbuf = Lexing.from_channel channel in
    try
      Info.start_a_new_file file ;
      let tokens = Lexer.get_token Lexer.token lexbuf in
      let _ = Unix.close_process_in channel in
      let t = Parser_helper.parse_tokens Parser.prog tokens (Some lexbuf) in
      let packages = get_global_info_from_package from_basedir build_time t in
      let required_packages =
	collect (fun package ->
	  get_vars_declaration state.global_vars_declared package ;
	  Global_checks.add_package_to_state state package ;
	  set_basedir state package ;
	  package.required_packages
        ) packages in
      required_packages, state
    with Failure s -> (
      print_endline_flush s ;
      exit 1
     )
  with 
  | Not_found -> internal_error "runaway Not_found"

and parse_package_if_needed state (package_name, pos) =
  if List.mem package_name !Config_file.ignored_packages then [], state else
  let splitted = split_at2 ':'':' package_name in
  let rel_file = String.concat "/" splitted ^ ".pm" in

  (*print_endline_flush ("wondering about " ^ package_name) ;*)
  try
    let dir = findfile (Build.fake_packages_dir :: !use_lib) rel_file in
    let file = dir ^ "/" ^ rel_file in
    Config_file.read_any (Filename.dirname file) (List.length splitted) ;
    let already_done =
      try
	let pkg = Hashtbl.find state.per_package package_name in
	if pkg.from_cache then
	  if pkg.build_time > mtime file then (
	    Hashtbl.replace state.per_package package_name { pkg with from_cache = false };
	    (*print_endline_flush (package_name ^ " wants " ^ String.concat " " (List.map fst pkg.required_packages)) ; *)
	    Some pkg.required_packages
	  ) else (
	    if !Flags.verbose then print_endline_flush (Printf.sprintf "cached version of %s is outdated, re-parsing" file);
	    Hashtbl.remove state.per_package package_name ; (* so that check on file name below doesn't need to check from_cache *)
	    None
	  )
	else Some []
      with Not_found -> None in
    match already_done with
    | Some required_packages -> required_packages, state
    | None ->
	if hashtbl_exists (fun _ pkg -> pkg.file_name = file) state.per_package
	then [], state (* already seen, it happens when many files have the same package_name *)
	else parse_file (dir = !basedir) state file
  with Not_found -> 
    warn_with_pos pos (Printf.sprintf "can't find package %s" package_name) ;
    [], state

let rec parse_required_packages state = function
  | [] -> state
  | e :: l ->
      let el, state = parse_package_if_needed state e in
      parse_required_packages state (el @ l)


let parse_options =
  let args_r = ref [] in
  let restrict_to_files = ref false in

  let pot_file = ref "" in
  let generate_pot_chosen file =
    Flags.generate_pot := true ;
    Flags.expand_tabs := None ;
    pot_file := file
  in
  let options = [
    "-v", Arg.Set Flags.verbose, "  be verbose" ;
    "-q", Arg.Set Flags.quiet, "  be quiet" ;
    "-t", Arg.Int (fun i -> Flags.expand_tabs := Some i), "  set the tabulation width (default is 8)" ;
    "--check-unused", Arg.Set Flags.check_unused_global_vars, "  check unused global functions & variables" ;
    "--restrict-to-files", Arg.Set restrict_to_files, "  only display warnings concerning the file(s) given on command line" ;
    "--no-cache", Arg.Set Flags.no_cache, "  do not use cache" ;
    "--generate-pot", Arg.String generate_pot_chosen, "" ;
  ] in
  let usage = "Usage: perl_checker [-v] [-q] <files>\nOptions are:" in
  Arg.parse options (lpush args_r) usage;

  let files = if !args_r = [] then ["../t.pl"] else !args_r in

  let required_packages, state = collect_withenv (parse_file true) (default_state()) files in
  let required_packages = uniq_ (fun (a,_) (b,_) -> a = b) required_packages in

  if !Flags.generate_pot then Parser_helper.generate_pot !pot_file else (

  if !restrict_to_files then Common.print_endline_flush_quiet := true ;
  let state = parse_required_packages state required_packages in
  if !restrict_to_files then Common.print_endline_flush_quiet := false ;

  let state = arrange_global_vars_declared state in

  write_packages_cache state !basedir ;

  let state = Global_checks.get_methods_available state in

  let l = List.map snd (hashtbl_to_list state.per_package) in
  let l = List.filter (fun pkg -> not pkg.from_cache && pkg.from_basedir) l in
  (* HACK: skip ignored_packages. Some package may have appeared in ignored_packages due to the xs bootstrap hack *)
  let l = List.filter (fun pkg -> not (List.mem pkg.package_name !Config_file.ignored_packages)) l in

  let l = if !restrict_to_files then List.filter (fun pkg -> List.mem pkg.file_name files) l else l in

  List.iter (Global_checks.check_tree state) l;
  if !Flags.check_unused_global_vars then List.iter Global_checks.check_unused_vars l 
  )
span class="hl kwb">$o->{mouse} : $o->{mouse}{alternate_install}; install_gtk::createXconf($f, @$mouse{"XMOUSETYPE", "device"}, $o->{mouse}{wacom}[0], $Driver); push @options, if_(!$::globetrotter, '-kb'), '-allowMouseOpenFail', '-xf86config', $f if arch() !~ /^sparc/; push @options, 'tty7', '-dpms', '-s', '240'; #- old weird servers: Xsun push @options, '-fp', '/usr/X11R6/lib/X11/fonts:unscaled' if $server =~ /Xsun/; } if (!fork()) { c::setsid(); exec $server, @options or c::_exit(1); } #- wait for the server to start foreach (1..5) { sleep 1; last if fuzzy_pidofs(qr/\b$server\b/); log::l("$server still not running, trying again"); } my $nb; foreach (1..60) { log::l("Server died"), return 0 if !fuzzy_pidofs(qr/\b$server\b/); $nb++ if xf86misc::main::Xtest($wanted_DISPLAY); if ($nb > 2) { #- one succeeded test is not enough :-( $ugtk2::force_focus = 1; log::l("AFAIK X server is up"); return 1; } sleep 1; } log::l("Timeout!!"); 0; }; my @servers = qw(Driver:fbdev); #-) if ($::testing) { @servers = 'Xnest'; } elsif (arch() eq "alpha") { require Xconfig::card; my ($card) = Xconfig::card::probe(); Xconfig::card::add_to_card__using_Cards($card, $card->{type}) if $card && $card->{type}; @servers = $card->{server} || "TGA"; #-@servers = qw(SVGA 3DLabs TGA) } elsif (arch() =~ /^sparc/) { local $_ = cat_("/proc/fb"); if (/Mach64/) { @servers = qw(Mach64); } elsif (/Permedia2/) { @servers = qw(3DLabs); } else { @servers = qw(Xsun24); } } elsif (arch() =~ /ia64|x86_64/) { require Xconfig::card; my ($card) = Xconfig::card::probe(); @servers = map { if_($_, "Driver:$_") } $card && $card->{Driver}, 'fbdev'; } if (($::move || $::globetrotter) && !$::testing) { require move; require run_program; move::automatic_xconf($o); run_program::run('/sbin/service', 'xfs', 'start'); @servers = $::globetrotter ? qw(Driver:fbdev) : qw(X_move); } foreach (@servers) { log::l("Trying with server $_"); my $dir = "/usr/X11R6/bin"; my ($prog, $Driver) = /Driver:(.*)/ ? ('Xorg', $1) : /Xsun|Xnest|^X_move$/ ? $_ : "XF86_$_"; unless (-x "$dir/$prog") { unlink $_ foreach glob_("$dir/X*"); install_any::getAndSaveFile("install/stage2/live$dir/$prog", "$dir/$prog") or die "failed to get server $prog: $!"; chmod 0755, "$dir/$prog"; } if (/FB/i) { !$o->{vga16} && $o->{allowFB} or next; $o->{allowFB} = &$launchX($prog, $Driver) #- keep in mind FB is used. and goto OK; } else { $o->{vga16} = 1 if /VGA16/; &$launchX($prog, $Driver) and goto OK; } $::move and print("can't launch graphical mode :(\n"), c::_exit(1); } return undef; } OK: $ENV{DISPLAY} = $wanted_DISPLAY; install_gtk::init_gtk($o); install_gtk::init_sizes(); install_gtk::install_theme($o); install_gtk::create_logo_window($o); install_gtk::create_steps_window($o); $ugtk2::grab = 1; $ugtk2::force_center_at_pos = [ $::rootwidth - $::windowwidth, $::logoheight, $::windowwidth, $::windowheight ]; $o = (bless {}, ref($type) || $type)->SUPER::new($o); $o->interactive::gtk::new; $o; } sub enteringStep { my ($o, $step) = @_; printf "Entering step `%s'\n", $o->{steps}{$step}{text}; $o->SUPER::enteringStep($step); install_gtk::update_steps_position($o); # install_gtk::create_help_window($o); #- HACK: without this it doesn't work (reaches step doPartitionDisks then fail) } sub leavingStep { my ($o, $step) = @_; $o->SUPER::leavingStep($step); } sub charsetChanged { my ($o) = @_; Gtk2->set_locale; install_gtk::load_font($o); install_gtk::create_steps_window($o); } #-###################################################################################### #- Steps Functions #-###################################################################################### sub selectLanguage { my ($o, $first_time) = @_; $o->SUPER::selectLanguage; $o->ask_warn('', formatAlaTeX(N("Your system is low on resources. You may have some problem installing Mandrakelinux. If that occurs, you can try a text install instead. For this, press `F1' when booting on CDROM, then enter `text'."))) if $first_time && availableRamMB() < 70; # 70MB } #------------------------------------------------------------------------------ sub selectMouse { my ($o, $force) = @_; my %old = %{$o->{mouse}}; $o->SUPER::selectMouse($force) or return; my $mouse = $o->{mouse}; $mouse->{type} eq 'none' || $old{type} eq $mouse->{type} && $old{name} eq $mouse->{name} && $old{device} eq $mouse->{device} && !$force and return; while (1) { my $x_protocol_changed = mouse::change_mouse_live($mouse, \%old); mouse::test_mouse_install($mouse, $x_protocol_changed) and return; %old = %$mouse; $o->SUPER::selectMouse(1); $mouse = $o->{mouse}; } } sub reallyChooseGroups { my ($o, $size_to_display, $individual, $_compssUsers) = @_; my $w = ugtk2->new(''); my $tips = Gtk2::Tooltips->new; my $w_size = Gtk2::Label->new(&$size_to_display); my $entry = sub { my ($e) = @_; my $text = translate($e->{label}); my $help = translate($e->{descr}); my $check = Gtk2::CheckButton->new($text); $check->set_active($e->{selected}); $check->signal_connect(clicked => sub { $e->{selected} = $check->get_active; $w_size->set_label(&$size_to_display); }); gtkset_tip($tips, $check, $help); $check; }; #- when restarting this step, it might be necessary to reload the compssUsers.pl (bug 11558). kludgy. if (!ref $o->{gtk_display_compssUsers}) { install_any::load_rate_files($o) } gtkadd($w->{window}, gtkpack_($w->create_box_with_title(N("Package Group Selection")), 1, $o->{gtk_display_compssUsers}->($entry), 1, '', 0, gtkadd(Gtk2::HBox->new(0, 0), gtksignal_connect(Gtk2::Button->new(N("Help")), clicked => $o->interactive_help_sub_display_id('choosePackages')), $w_size, if_($individual, do { my $check = Gtk2::CheckButton->new(N("Individual package selection")); $check->set_active($$individual); $check->signal_connect(clicked => sub { $$individual = $check->get_active }); $check; }), gtksignal_connect(Gtk2::Button->new(N("Next")), clicked => sub { Gtk2->main_quit }), ), ), ); $w->main; 1; } sub choosePackagesTree { my ($o, $packages, $o_limit_medium) = @_; my $available = install_any::getAvailableSpace($o); my $availableCorrected = pkgs::invCorrectSize($available / sqr(1024)) * sqr(1024); my $common; $common = { get_status => sub { my $size = pkgs::selectedSize($packages); N("Total size: %d / %d MB", pkgs::correctSize($size / sqr(1024)), $available / sqr(1024)); }, node_state => sub { my $p = pkgs::packageByName($packages, $_[0]) or return; pkgs::packageMedium($packages, $p)->{selected} or return; $p->arch eq 'src' and return; $p->flag_base and return 'base'; $p->flag_installed && !$p->flag_upgrade and return 'installed'; $p->flag_selected and return 'selected'; return 'unselected'; }, build_tree => sub { my ($add_node, $flat) = @_; if ($flat) { foreach (sort map { $_->name } grep { !$o_limit_medium || pkgs::packageMedium($packages, $_) == $o_limit_medium } grep { $_ && $_->arch ne 'src' } @{$packages->{depslist}}) { $add_node->($_, undef); } } else { foreach my $root (@{$o->{compssUsers}}) { my (@firstchoice, @others); my %fl = map { $_ => 1 } @{$root->{flags}}; foreach my $p (@{$packages->{depslist}}) { !$o_limit_medium || pkgs::packageMedium($packages, $p) == $o_limit_medium or next; my @flags = $p->rflags; next if !($p->rate && any { any { !/^!/ && $fl{$_} } split('\|\|') } @flags); $p->rate >= 3 ? push(@firstchoice, $p->name) : push(@others, $p->name); } my $root2 = translate($root->{path}) . '|' . translate($root->{label}); $add_node->($_, $root2) foreach sort @firstchoice; $add_node->($_, $root2 . '|' . N("Other")) foreach sort @others; } } }, get_info => sub { my $p = pkgs::packageByName($packages, $_[0]) or return ''; pkgs::extractHeaders($o->{prefix}, [$p], $packages->{mediums}); my $imp = translate($pkgs::compssListDesc{$p->flag_base ? 5 : $p->rate}); my $tag = { 'foreground' => 'royalblue3' }; $@ ? N("Bad package") : [ [ N("Name: "), $tag ], [ $p->name . "\n" ], [ N("Version: "), $tag ], [ $p->version . '-' . $p->release . "\n" ], [ N("Size: "), $tag ], [ N("%d KB\n", $p->size / 1024) ], if_($imp, [ N("Importance: "), $tag ], [ "$imp\n" ]), [ "\n" ], [ formatLines(c::from_utf8($p->description)) ] ]; }, toggle_nodes => sub { my $set_state = shift @_; my $isSelection = 0; my %l = map { my $p = pkgs::packageByName($packages, $_); $isSelection ||= !$p->flag_selected; $p->id => 1 } @_; my $state = $packages->{state} ||= {}; my @l = $isSelection ? $packages->resolve_requested($packages->{rpmdb}, $state, \%l, callback_choices => \&pkgs::packageCallbackChoices) : $packages->disable_selected($packages->{rpmdb}, $state, map { $packages->{depslist}[$_] } keys %l); my $size = pkgs::selectedSize($packages); my $error; if (!@l) { #- no package can be selected or unselected. my @ask_unselect = grep { $state->{rejected}{$_}{backtrack} && exists $l{$packages->search($_, strict_fullname => 1)->id} } keys %{$state->{rejected} || {}}; #- extend to closure (to given more detailed and not absurd reason). my %ask_unselect; while (@ask_unselect > keys %ask_unselect) { @ask_unselect{@ask_unselect} = (); foreach (keys %ask_unselect) { foreach (keys %{$state->{rejected}{$_}{backtrack}{closure} || {}}) { next if exists $ask_unselect{$_}; push @ask_unselect, $_; } } } $error = [ N("You can't select/unselect this package"), formatList(20, map { my $rb = $state->{rejected}{$_}{backtrack}; my @froms = keys %{$rb->{closure} || {}}; my @unsatisfied = @{$rb->{unsatisfied} || []}; my $s = join ", ", ((map { N("due to missing %s", $_) } @froms), (map { N("due to unsatisfied %s", $_) } @unsatisfied), $rb->{promote} && !$rb->{keep} ? N("trying to promote %s", join(", ", @{$rb->{promote}})) : @{[]}, $rb->{keep} ? N("in order to keep %s", join(", ", @{$rb->{keep}})) : @{[]}, ); $_ . ($s ? " ($s)" : ''); } sort @ask_unselect) ]; } elsif (pkgs::correctSize($size / sqr(1024)) > $available / sqr(1024)) { $error = N("You can't select this package as there is not enough space left to install it"); } elsif (@l > @_ && $common->{state}{auto_deps}) { $o->ask_okcancel('', [ $isSelection ? N("The following packages are going to be installed") : N("The following packages are going to be removed"), formatList(20, sort(map { $_->name } @l)) ], 1) or $error = ''; #- defined } if (defined $error) { $o->ask_warn('', $error) if $error; #- disable selection (or unselection). $isSelection ? $packages->disable_selected($packages->{rpmdb}, $state, @l) : $packages->resolve_requested($packages->{rpmdb}, $state, { map { $_->id => 1 } @l }); } else { #- keep the changes, update visible state. foreach (@l) { $set_state->($_->name, $_->flag_selected ? 'selected' : 'unselected'); } } }, grep_allowed_to_toggle => sub { grep { my $p = pkgs::packageByName($packages, $_); $p && !$p->flag_base } @_; }, grep_unselected => sub { grep { !pkgs::packageByName($packages, $_)->flag_selected } @_; }, check_interactive_to_toggle => sub { my $p = pkgs::packageByName($packages, $_[0]) or return; if ($p->flag_base) { $o->ask_warn('', N("This is a mandatory package, it can't be unselected")); } elsif ($p->flag_installed && !$p->flag_upgrade) { $o->ask_warn('', N("You can't unselect this package. It is already installed")); } elsif ($p->flag_selected && $p->flag_installed) { if ($::expert) { $o->ask_yesorno('', N("This package must be upgraded.\nAre you sure you want to deselect it?")) or return; return 1; } else { $o->ask_warn('', N("You can't unselect this package. It must be upgraded")); } } else { return 1 } return; }, auto_deps => N("Show automatically selected packages"), interactive_help_id => 'choosePackagesTree', ok => N("Install"), cancel => N("Previous"), icons => [ { icon => 'floppy', help => N("Load/Save on floppy"), wait_message => N("Updating package selection"), code => sub { $o->loadSavePackagesOnFloppy($packages); 1 }, }, if_(0, { icon => 'feather', help => N("Minimal install"), code => sub { install_any::unselectMostPackages($o); pkgs::setSelectedFromCompssList($packages, { SYSTEM => 1 }, 4, $availableCorrected); 1; } }), ], state => { auto_deps => 1, flat => $o_limit_medium, }, }; $o->ask_browse_tree_info('', N("Choose the packages you want to install"), $common); } #------------------------------------------------------------------------------ sub beforeInstallPackages { my ($o) = @_; $o->SUPER::beforeInstallPackages; install_any::copy_advertising($o); } #------------------------------------------------------------------------------ sub installPackages { my ($o, $packages) = @_; my ($current_total_size, $last_size, $nb, $total_size, $start_time, $last_dtime, $_trans_progress_total); my $w = ugtk2->new(N("Installing")); $w->sync; my $text = Gtk2::Label->new; my ($advertising, $change_time, $i); my $show_advertising if 0; $show_advertising = to_bool(@install_any::advertising_images) if !defined $show_advertising; my ($msg, $msg_time_remaining) = map { Gtk2::Label->new($_) } '', N("Estimating"); my ($progress, $progress_total) = map { Gtk2::ProgressBar->new } (1..2); gtkadd($w->{window}, my $box = Gtk2::VBox->new(0,10)); $box->pack_end(gtkshow(gtkpack(Gtk2::VBox->new(0,5), $msg, $progress, create_packtable({}, [N("Time remaining "), $msg_time_remaining], ), $text, $progress_total, gtkadd(create_hbox(), my $cancel = Gtk2::Button->new(N("Cancel")), my $details = Gtk2::Button->new(''), ), )), 0, 1, 0); $details->hide if !@install_any::advertising_images; $w->sync; $msg->set_label(N("Please wait, preparing installation...")); foreach ($cancel, $details) { gtkset_mousecursor_normal($_->window); } my $advertize = sub { my ($update) = @_; @install_any::advertising_images or return; foreach ($msg, $progress, $text) { $show_advertising ? $_->hide : $_->show; } $details->set_label($show_advertising ? N("Details") : N("No details")); gtkdestroy($advertising) if $advertising; if ($show_advertising && $update) { $change_time = time(); my $f = $install_any::advertising_images[$i++ % @install_any::advertising_images]; log::l("advertising $f"); my $pl = $f; $pl =~ s/\.png$/.pl/; my $icon_name = $f; $icon_name =~ s/\.png$/_icon.png/; my ($draw_text, $width, $height, $border, $y_start, @text); -e $pl and $draw_text = 1; eval(cat_($pl)) if $draw_text; my $pix = gtkcreate_pixbuf($f); my $darea = Gtk2::DrawingArea->new; gtkpack($box, $advertising = !$draw_text ? gtkcreate_img($f) : gtksignal_connect(gtkset_size_request($darea, $width, $height), expose_event => sub { my (undef, undef, $dx, $dy) = $darea->allocation->values; $darea->window->draw_rectangle($darea->style->bg_gc('active'), 1, 0, 0, $dx, $dy); $pix->render_to_drawable($darea->window, $darea->style->bg_gc('normal'), 0, 0, ($dx-$width)/2, 0, $width, $height, 'none', 0, 0); my @lines = wrap_paragraph([ @text ], $darea, $border, $width); foreach my $line (@lines) { my $layout = $darea->create_pango_layout($line->{text}); my $draw_lay = sub { my ($gc, $decx) = @_; $darea->window->draw_layout($gc, $line->{'x'} + $decx, $y_start + $line->{'y'}, $layout); }; $draw_lay->($darea->style->black_gc, 0); $line->{options}{bold} and $draw_lay->($darea->style->black_gc, 1); } })); } else { $advertising = undef; } }; $cancel->signal_connect(clicked => sub { $pkgs::cancel_install = 1 }); $details->signal_connect(clicked => sub { invbool \$show_advertising; $advertize->(1); }); $advertize->(0); my $oldInstallCallback = \&pkgs::installCallback; local *pkgs::installCallback = sub { my ($data, $type, $id, $subtype, $amount, $total) = @_; if ($type eq 'user' && $subtype eq 'install') { #- $amount and $total are used to return number of package and total size. $nb = $amount; $total_size = $total; $current_total_size = 0; $start_time = time(); $msg->set_label(N("%d packages", $nb)); $w->flush; } elsif ($type eq 'inst' && $subtype eq 'start') { $progress->set_fraction(0); my $p = $data->{depslist}[$id]; $msg->set_label(N("Installing package %s", $p->name)); $current_total_size += $last_size; $last_size = $p->size; $text->set_label((split /\n/, c::from_utf8($p->summary))[0] || ''); $advertize->(1) if $show_advertising && $total_size > 20_000_000 && time() - $change_time > 20; $w->flush; } elsif ($type eq 'inst' && $subtype eq 'progress') { $progress->set_fraction($total ? $amount / $total : 0); my $dtime = time() - $start_time; my $ratio = $total_size == 0 ? 0 : pkgs::size2time($current_total_size + $amount, $total_size) / pkgs::size2time($total_size, $total_size); $ratio >= 1 and $ratio = 1; my $total_time = $ratio ? $dtime / $ratio : time(); $progress_total->set_fraction($ratio); if ($dtime != $last_dtime && $current_total_size > 80_000_000) { $msg_time_remaining->set_label(formatTime(10 * round(max($total_time - $dtime, 0) / 10) + 10)); $last_dtime = $dtime; } $w->flush; } else { goto $oldInstallCallback } }; #- the modification is not local as the box should be living for other package installation. undef *install_any::changeMedium; *install_any::changeMedium = sub { my ($method, $medium) = @_; #- if not using a cdrom medium or an iso image, always abort. return if !install_any::method_allows_medium_change($method); my $name = pkgs::mediumDescr($o->{packages}, $medium); local $| = 1; print "\a"; my $time = time(); my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept"); if ($method =~ /-iso$/) { $r = install_any::changeIso($name); } else { $r &&= $o->ask_okcancel('', N("Change your Cd-Rom! Please insert the Cd-Rom labelled \"%s\" in your drive and press Ok when done. If you don't have it, press Cancel to avoid installation from this Cd-Rom.", $name), 1); } #- add the elapsed time (otherwise the predicted time will be rubbish) $start_time += time() - $time; return $r; }; my $install_result; catch_cdie { $install_result = $o->install_steps::installPackages($packages) } sub { log::l("catch_cdie: $@"); my $time = time(); if ($@ =~ /^error ordering package list: (.*)/) { $o->ask_yesorno('', [ N("There was an error ordering packages:"), $1, N("Go on anyway?") ], 1) and return 1; ${$_[0]} = "already displayed"; } elsif ($@ =~ /^error installing package list: (.*)/) { $o->ask_yesorno('', [ N("There was an error installing packages:"), $1, N("Go on anyway?") ], 1) and return 1; ${$_[0]} = "already displayed"; } $w->destroy; #- add the elapsed time (otherwise the predicted time will be rubbish) $start_time += time() - $time; 0; }; if ($pkgs::cancel_install) { $pkgs::cancel_install = 0; die 'already displayed'; } $w->destroy; $install_result; } sub summary_prompt { my ($o, $l, $check_complete) = @_; my $w = ugtk2->new(''); my $set_entry_labels; my @table; my $group; foreach my $e (@$l) { if ($group ne $e->{group}) { $group = $e->{group}; push @table, [ gtkpack__(Gtk2::HBox->new(0, 0), $group), '' ]; } $e->{widget} = Gtk2::Label->new; $e->{widget}->set_property(wrap => 1); $e->{widget}->set_size_request($::real_windowwidth * 0.72, -1); push @table, [], [ gtkpack__(Gtk2::HBox->new(0, 30), '', $e->{widget}), gtksignal_connect(Gtk2::Button->new(N("Configure")), clicked => sub { $w->{rwindow}->hide; $e->{clicked}(); $w->{rwindow}->show; $set_entry_labels->(); }) ]; } $set_entry_labels = sub { foreach (@$l) { my $t = $_->{val}() || '<span foreground="red">' . N("not configured") . '</span>'; $t =~ s/&/&amp;/g; $_->{widget}->set_markup($_->{label} . ' - ' . $t); } }; $set_entry_labels->(); my $help_sub = $o->interactive_help_sub_display_id('summary'); gtkadd($w->{window}, gtkpack_(Gtk2::VBox->new(0,5), 1, create_scrolled_window(create_packtable({ mcc => 1 }, @table)), 0, $w->create_okcancel(undef, '', '', if_($help_sub, [ N("Help"), $help_sub, 1 ])) )); $w->main($check_complete); } 1;