diff options
Diffstat (limited to 'perl-install/install/steps_interactive.pm')
-rw-r--r-- | perl-install/install/steps_interactive.pm | 1158 |
1 files changed, 1158 insertions, 0 deletions
diff --git a/perl-install/install/steps_interactive.pm b/perl-install/install/steps_interactive.pm new file mode 100644 index 000000000..55985e01a --- /dev/null +++ b/perl-install/install/steps_interactive.pm @@ -0,0 +1,1158 @@ +package install::steps_interactive; + + +use strict; +use feature 'state'; + +our @ISA = qw(install::steps); + + +#-###################################################################################### +#- misc imports +#-###################################################################################### +use common; +use partition_table; +use fs::type; +use fs::partitioning; +use fs::partitioning_wizard; +use install::steps; +use install::interactive; +use install::any; +use messages; +use detect_devices; +use run_program; +use devices; +use fsedit; +use mouse; +use modules; +use modules::interactive; +use lang; +use keyboard; +use any; +use log; + +#-###################################################################################### +#- In/Out Steps Functions +#-###################################################################################### +sub errorInStep { + my ($o, $err) = @_; + $err = ugtk3::escape_text_for_TextView_markup_format($err) if $o->isa('install::steps_gtk'); + $o->ask_warn(N("Error"), [ N("An error occurred"), formatError($err) ]); +} + +sub kill_action { + my ($o) = @_; + $o->kill; +} + +#-###################################################################################### +#- Steps Functions +#-###################################################################################### +#------------------------------------------------------------------------------ + +sub acceptLicense { + my ($o) = @_; + return if $o->{useless_thing_accepted}; + + any::acceptLicense($o); +} + +sub selectLanguage { + my ($o) = @_; + + any::selectLanguage_install($o, $o->{locale}); + install::steps::selectLanguage($o); + + if ($o->isa('interactive::gtk')) { + $o->ask_warn('', formatAlaTeX( +"If you see this message it is because you chose a language for +which DrakX does not include a translation yet; however the fact +that it is listed means there is some support for it anyway. + +That is, once GNU/Linux will be installed, you will be able to at +least read and write in that language; and possibly more (various +fonts, spell checkers, various programs translated etc. that +varies from language to language).")) if $o->{locale}{lang} !~ /^en/ && !lang::load_mo(); + } else { + #- no need to have this in po since it is never translated + $o->ask_warn('', "The characters of your language cannot be displayed in console, +so the messages will be displayed in english during installation") if $ENV{LANGUAGE} eq 'C'; + } +} + +#------------------------------------------------------------------------------ +sub selectKeyboard { + my ($o, $clicked) = @_; + + my $from_usb = keyboard::from_usb(); + my $l = keyboard::lang2keyboards(lang::langs($o->{locale}{langs})); + + if ($clicked || !($from_usb || @$l && $l->[0][1] >= 90) || listlength(lang::langs($o->{locale}{langs})) > 1) { + add2hash($o->{keyboard}, $from_usb); + my @best = uniq(grep { $_ } $from_usb && $from_usb->{KEYBOARD}, $o->{keyboard}{KEYBOARD}, + map { $_->[0] } @$l); + @best = () if @best == 1; + + my $format = sub { translate(keyboard::KEYBOARD2text($_[0])) }; + my $other; + my $ext_keyboard = my $KEYBOARD = $o->{keyboard}{KEYBOARD}; + $o->ask_from_( + { title => N("Keyboard"), + interactive_help_id => 'selectKeyboard', + advanced_label => N("More"), + }, + [ + { label => N("Please choose your keyboard layout"), title => 1 }, + if_(@best, { val => \$KEYBOARD, type => 'list', format => $format, sort => 1, + list => [ @best ], changed => sub { $other = 0 } }), + if_(@best, + { label => N("Here is the full list of available keyboards:"), title => 1, advanced => 1 }), + { val => \$ext_keyboard, type => 'list', format => $format, changed => sub { $other = 1 }, + list => [ difference2([ keyboard::KEYBOARDs() ], \@best) ], advanced => @best > 1 } + ]); + $o->{keyboard}{KEYBOARD} = !@best || $other ? $ext_keyboard : $KEYBOARD; + delete $o->{keyboard}{unsafe}; + } + keyboard::group_toggle_choose($o, $o->{keyboard}) or goto &selectKeyboard; + install::steps::selectKeyboard($o); + if ($::isRestore) { + require MDV::Snapshot::Restore; + MDV::Snapshot::Restore::main($o); + $o->exit; + } +} + +#------------------------------------------------------------------------------ +sub selectInstallClass { + my ($o) = @_; + + return if $::isRestore; + + my @l = install::any::find_root_parts($o->{fstab}, $::prefix); + # Don't list other archs as ugrading between archs is not supported + my $arch = arch() =~ /i.86/ ? $MDK::Common::System::compat_arch{arch()} : arch(); + # Offer to upgrade only same arch and not mdv-2011+: + @l = grep { $_->{arch} eq $arch && $_->{version} !~ /201[1-9]/ } @l; + if (@l) { + _try_to_upgrade($o, @l); + } +} + +sub _try_to_upgrade { + my ($o, @l) = @_; + log::l("proposing to upgrade partitions " . join(" ", map { $_->{part} && $_->{part}{device} } @l)); + + my @releases = uniq(map { "$_->{release} $_->{version}" } @l); + if (@releases != @l) { + #- same release name so adding the device to differentiate them: + $_->{release} .= " ($_->{part}{device})" foreach @l; + } + + askInstallClass: + my $p; + $o->ask_from_({ title => N("Install/Upgrade"), + interactive_help_id => 'selectInstallClass', + }, + [ + { label => N("Is this an install or an upgrade?"), title => 1 }, + { val => \$p, + list => [ @l, N_("_: This is a noun:\nInstall") ], + type => 'list', + format => sub { ref($_[0]) ? N("Upgrade %s", "$_[0]->{release} $_[0]->{version}") : translate($_[0]) } + } ]); + if (ref $p) { + _check_unsafe_upgrade_and_warn($o, $p->{part}) or $p = undef; + } + + if (ref $p) { + _prepare_upgrade($o, $p); + } +} + +sub _prepare_upgrade { + my ($o, $p) = @_; + if ($p->{part}) { + log::l("choosing to upgrade partition $p->{part}{device}"); + $o->{migrate_device_names} = install::any::use_root_part($o->{all_hds}, $p->{part}, $o); + } + + #- handle encrypted partitions (esp. /home) + foreach (grep { $_->{mntpoint} } @{$o->{fstab}}) { + my ($options, $_unknown) = fs::mount_options::unpack($_); + $options->{encrypted} or next; + $o->ask_from_({ focus_first => 1 }, + [ { label => N("Encryption key for %s", $_->{mntpoint}), + hidden => 1, val => \$_->{encrypt_key} } ]); + } + + $o->{previous_release} = $p; + $o->{isUpgrade} = (find { $p->{release_file} =~ /$_/ } 'mageia', 'mandriva', 'mandrake', 'conectiva', 'redhat') || 'unknown'; + $o->{upgrade_by_removing_pkgs_matching} ||= { + conectiva => 'cl', + redhat => '.', #- everything! + }->{$o->{isUpgrade}}; + log::l("upgrading $o->{isUpgrade} distribution" . ($o->{upgrade_by_removing_pkgs_matching} ? " (upgrade_by_removing_pkgs_matching $o->{upgrade_by_removing_pkgs_matching})" : '')); +} + +sub _check_unsafe_upgrade_and_warn { + my ($o, $part) = @_; + !_is_unsafe_upgrade($part) || _warn_unsafe_upgrade($o); +} + +sub _is_unsafe_upgrade { + my ($part) = @_; + + my $r = run_program::get_stdout('dumpe2fs', devices::make($part->{device})); + my $block_size = $r =~ /^Block size:\s*(\d+)/m && $1; + log::l("block_size $block_size"); + $block_size == 1024; +} + +sub _warn_unsafe_upgrade { + my ($o) = @_; + + log::l("_warn_unsafe_upgrade"); + + my @choices = ( + N_("Cancel installation, reboot system"), + N_("New Installation"), + N_("Upgrade previous installation (not recommended)"), + ); + + my $choice; + $o->ask_from_({ messages => N("Installer has detected that your installed Linux system could not +safely be upgraded to %s. + +New installation replacing your previous one is recommended. + +Warning : you should backup all your personal data before choosing \"New +Installation\".", '%s') }, + [ { val => \$choice, type => 'list', list => \@choices, format => \&translate } ]); + + log::l("_warn_unsafe_upgrade: got $choice"); + + if ($choice eq $choices[0]) { + any::reboot(); + } elsif ($choice eq $choices[1]) { + undef; + } else { + 1; + } +} + +#------------------------------------------------------------------------------ +sub selectMouse { + my ($o, $force) = @_; + + $force || $o->{mouse}{unsafe} or return; + + mouse::select($o, $o->{mouse}) or return; + + if ($o->{mouse}{device} eq "input/mice") { + modules::interactive::load_category($o, $o->{modules_conf}, 'bus/usb', 1, 0); + eval { + modules::load('usbhid'); + }; + } +} +#------------------------------------------------------------------------------ +sub setupSCSI { + my ($o) = @_; + + install::any::configure_pcmcia($o); + { + my $_w = $o->wait_message(N("CD/DVD"), N("Configuring CD/DVD")); + modules::load(modules::category2modules('disk/cdrom')); + } + modules::interactive::load_category($o, $o->{modules_conf}, 'bus/firewire', 1); + + my $have_non_scsi = detect_devices::hds(); #- at_least_one scsi device if we have no disks + modules::interactive::load_category($o, $o->{modules_conf}, 'disk/card_reader|ide|scsi|hardware_raid|sata|firewire|virtual', 1, !$have_non_scsi); + modules::interactive::load_category($o, $o->{modules_conf}, 'disk/card_reader|ide|scsi|hardware_raid|sata|firewire|virtual') if !detect_devices::hds(); #- we really want a disk! + + install::interactive::tellAboutProprietaryModules($o); + + install::any::getHds($o, $o); +} + +#------------------------------------------------------------------------------ +sub doPartitionDisks { + my ($o) = @_; + + if (!$o->{isUpgrade}) { + fs::partitioning_wizard::main($o, $o->{all_hds}, $o->{fstab}, $o->{manualFstab}, $o->{partitions}, $o->{partitioning}, $::local_install); + } +} + +#------------------------------------------------------------------------------ +sub rebootNeeded { + my ($o) = @_; + fs::partitioning_wizard::warn_reboot_needed($o); + install::steps::rebootNeeded($o); +} + +#------------------------------------------------------------------------------ +sub choosePartitionsToFormat { + my ($o) = @_; + fs::partitioning::choose_partitions_to_format($o, $o->{fstab}); +} + +sub formatMountPartitions { + my ($o, $_fstab) = @_; + fs::partitioning::format_mount_partitions($o, $o->{all_hds}, $o->{fstab}); +} + +#------------------------------------------------------------------------------ +#- group by CD +sub ask_deselect_media__copy_on_disk { + my ($o, $hdlists, $o_copy_rpms_on_disk) = @_; + + log::l("ask_deselect_media__copy_on_disk"); + + my @names = uniq(map { $_->{name} } @$hdlists); + my %selection = map { $_ => 1 } @names; + + $o->ask_from_({ messages => formatAlaTeX(N("The following installation media have been found. +If you want to skip some of them, you can unselect them now.")) }, + [ (map { { type => 'bool', text => $_, val => \$selection{$_}, + if_($_ eq $names[0], disabled => sub { 1 }), + } } @names), + if_($o_copy_rpms_on_disk, + { type => 'label', val => \(formatAlaTeX(N("You have the option to copy the contents of the CDs onto the hard disk drive before installation. +It will then continue from the hard disk drive and the packages will remain available once the system is fully installed."))) }, + { type => 'bool', text => N("Copy whole CDs"), val => $o_copy_rpms_on_disk }, + ), + ]); + $_->{ignore} = !$selection{$_->{name}} foreach @$hdlists; + log::l("keeping media " . join ',', map { $_->{rpmsdir} } grep { !$_->{ignore} } @$hdlists); +} + +sub while_suspending_time { + my ($o, $f) = @_; + + my $time = time(); + + my $r = $f->(); + + #- add the elapsed time (otherwise the predicted time will be rubbish) + $o->{install_start_time} += time() - $time; + + $r; +} + +# nb: $file can be a directory +sub ask_change_cd { + my ($o, $medium) = @_; + + while_suspending_time($o, sub { ask_change_cd_($o, $medium) }); +} + +sub ask_change_cd_ { + my ($o, $medium) = @_; + + local $::isWizard = 0; # make button name match text, aka being "cancel" rather than "previous" + $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 do not have it, press Cancel to avoid installation from this Cd-Rom.", $medium), 1) or return; + +} + +sub selectSupplMedia { + my ($o) = @_; + install::any::selectSupplMedia($o); +} + +#------------------------------------------------------------------------------ +sub choosePackages { + my ($o) = @_; + + require pkgs; + add2hash_($o, { compssListLevel => pkgs::rpmsrate_rate_default() }); + + my $w = $o->wait_message('', N("Looking for available packages...")); + my $availableC = install::steps::choosePackages($o, pkgs::rpmsrate_rate_max()); + + require install::pkgs; + + my $min_size = install::pkgs::selectedSize($o->{packages}); + undef $w; + if ($min_size >= $availableC) { + my $msg = N("Your system does not have enough space left for installation or upgrade (%dMB > %dMB)", + $min_size / sqr(1024), $availableC / sqr(1024)); + log::l($msg); + $o->ask_warn('', $msg); + install::steps::rebootNeeded($o); + } + + my ($individual, $chooseGroups); + + if (!$o->{isUpgrade}) { + my $tasks_ok = install::pkgs::packageByName($o->{packages}, 'task-plasma-minimal') && + install::pkgs::packageByName($o->{packages}, 'task-gnome-minimal'); + if ($tasks_ok && $availableC >= 2_500_000_000) { + _chooseDesktop($o, $o->{rpmsrate_flags_chosen}, \$chooseGroups); + } else { + $tasks_ok ? log::l("not asking for desktop since not enough place") : + log::l("not asking for desktop since kde and gnome are not available on media (useful for mini iso)"); + $chooseGroups = 1; + } + } + + chooseGroups: + $o->chooseGroups($o->{packages}, $o->{compssUsers}, \$individual) if $chooseGroups; + + ($o->{packages_}{ind}) = + install::pkgs::setSelectedFromCompssList($o->{packages}, $o->{rpmsrate_flags_chosen}, $o->{compssListLevel}, $availableC); + + $o->choosePackagesTree($o->{packages}) or goto chooseGroups if $individual; + + install::any::warnAboutRemovedPackages($o, $o->{packages}); +} + +sub choosePackagesTree { + my ($o, $packages, $o_limit_to_medium) = @_; + + $o->ask_many_from_list('', N("Choose the packages you want to install"), + { + list => [ grep { !$o_limit_to_medium || install::pkgs::packageMedium($packages, $_) == $o_limit_to_medium } + @{$packages->{depslist}} ], + value => \&URPM::Package::flag_selected, + label => \&URPM::Package::name, + sort => 1, + }); +} + +sub loadSavePackagesOnFloppy { + my ($o, $packages) = @_; + $o->ask_from('', +N("Please choose load or save package selection. +The format is the same as auto_install generated files."), + [ { val => \ (my $choice), list => [ N_("Load"), N_("Save") ], format => \&translate, type => 'list' } ]) or return; + + if ($choice eq 'Load') { + while (1) { + log::l("load package selection"); + my ($_h, $fh) = install::any::media_browser($o, '', 'package_list.pl') or return; + my $O = eval { install::any::loadO(undef, $fh) }; + if ($@) { + $o->ask_okcancel('', N("Bad file")) or return; + } else { + install::any::unselectMostPackages($o); + install::pkgs::select_by_package_names($packages, $O->{default_packages} || []); + return 1; + } + } + } else { + log::l("save package selection"); + install::any::g_default_packages($o); + } +} + +sub _chooseDesktop { + my ($o, $rpmsrate_flags_chosen, $chooseGroups) = @_; + + my @l = group_by2( + PLASMA => N("Plasma"), + GNOME => N("GNOME"), + Custom => N("Custom"), + ); + my $title = N("Desktop Selection"); + my $message = N("You can choose your workstation desktop profile."); + + my $default_choice = (find { $rpmsrate_flags_chosen->{"CAT_" . $_->[0]} } @l) || $l[0]; + my $choice = $default_choice; + if ($o->isa('interactive::gtk')) { + # perl_checker: require install::steps_gtk + $choice = install::steps_gtk::reallyChooseDesktop($o, $title, $message, \@l, $default_choice); + } else { + $o->ask_from_({ title => $title, message => $message }, [ + { val => \$choice, list => \@l, type => 'list', format => sub { $_[0][1] } }, + ]); + } + my $desktop = $choice->[0]; + log::l("chosen Desktop: $desktop"); + my @desktops = ('PLASMA', 'GNOME'); + if (member($desktop, @desktops)) { + my ($want, $dontwant) = ($desktop, grep { $desktop ne $_ } @desktops); + $rpmsrate_flags_chosen->{"CAT_$want"} = 1; + $rpmsrate_flags_chosen->{"CAT_$dontwant"} = 0; + my @flags = map_each { if_($::b, $::a) } %$rpmsrate_flags_chosen; + log::l("flags ", join(' ', sort @flags)); + install::any::unselectMostPackages($o); + } else { + $$chooseGroups = 1; + } +} + +sub chooseGroups { + my ($o, $packages, $compssUsers, $individual) = @_; + + my $w = $o->wait_message('', N("Looking for available packages...")); + + #- for all groups available, determine package which belongs to each one. + #- this will enable getting the size of each groups more quickly due to + #- limitation of current implementation. + #- use an empty state for each one (no flag update should be propagated). + + my $b = install::pkgs::saveSelected($packages); + install::any::unselectMostPackages($o); + install::pkgs::setSelectedFromCompssList($packages, { CAT_SYSTEM => 1 }, $o->{compssListLevel}, 0); + my $system_size = install::pkgs::selectedSize($packages); + my ($sizes, $pkgs) = install::pkgs::computeGroupSize($packages, $o->{compssListLevel}); + install::pkgs::restoreSelected($b); + log::l("system_size: $system_size"); + + my %stable_flags = grep_each { $::b } %{$o->{rpmsrate_flags_chosen}}; + delete $stable_flags{"CAT_$_"} foreach map { @{$_->{flags}} } @{$o->{compssUsers}}; + + undef $w; + + my $compute_size = sub { + my %pkgs; + my %flags = %stable_flags; @flags{@_} = (); + my $total_size; + A: while (my ($k, $size) = each %$sizes) { + Or: foreach (split "\t", $k) { + foreach (split "&&") { + exists $flags{$_} or next Or; + } + $total_size += $size; + $pkgs{$_} = 1 foreach @{$pkgs->{$k}}; + next A; + } + } + log::l("computed size $total_size (flags " . join(' ', keys %flags) . ")"); + log::l("chooseGroups: ", join(" ", sort keys %pkgs)); + + int $total_size; + }; + + my ($size, $unselect_all); + my $available_size = install::any::getAvailableSpace($o) / sqr(1024); + my $size_to_display = sub { + my $lsize = $system_size + $compute_size->(map { "CAT_$_" } map { @{$_->{flags}} } grep { $_->{selected} } @$compssUsers); + + #- if a profile is deselected, deselect everything (easier than deselecting the profile packages) + $unselect_all ||= $size > $lsize; + $size = $lsize; + N("Total size: %d / %d MB", install::pkgs::correctSize($size / sqr(1024)), $available_size); + }; + + while (1) { + if ($available_size < 200) { + # too small to choose anything. Defaulting to no group chosen + $_->{selected} = 0 foreach @$compssUsers; + last; + } + + $o->reallyChooseGroups($size_to_display, $individual, $compssUsers) or return; + + last if $::testing || install::pkgs::correctSize($size / sqr(1024)) < $available_size || every { !$_->{selected} } @$compssUsers; + + $o->ask_warn('', N("Selected size is larger than available space")); + } + install::any::set_rpmsrate_category_flags($o, $compssUsers); + + log::l("compssUsersChoice selected: ", join(', ', map { qq("$_->{path}|$_->{label}") } grep { $_->{selected} } @$compssUsers)); + + if (!$o->{isUpgrade}) { + #- do not try to deselect package (by default no groups are selected). + install::any::unselectMostPackages($o) if $unselect_all; + + #- if no group have been chosen, ask for using base system only, or no X, or normal. + if (!any { $_->{selected} } @$compssUsers) { + offer_minimal_options($o) or goto &chooseGroups; + } + } + 1; +} + +sub offer_minimal_options { + my ($o) = @_; + my $docs = !$o->{excludedocs}; + state $minimal; + my $recommends = !$o->{no_recommends}; + + $o->ask_from_({ title => N("Type of install"), + message => N("You have not selected any group of packages. +Please choose the minimal installation you want:"), + interactive_help_id => 'minimal-install' + }, + [ + { val => \$o->{rpmsrate_flags_chosen}{CAT_X}, type => 'bool', text => N("With X"), disabled => sub { $minimal } }, + { val => \$recommends, type => 'bool', text => N("Install recommended packages"), disabled => sub { $minimal } }, + { val => \$docs, type => 'bool', text => N("With basic documentation (recommended!)"), disabled => sub { $minimal } }, + { val => \$minimal, type => 'bool', text => N("Truly minimal install (especially no urpmi)") }, + ], + ) or return 0; + + if ($minimal) { + $o->{rpmsrate_flags_chosen}{CAT_X} = $docs = $recommends = 0; + $o->{rpmsrate_flags_chosen}{CAT_SYSTEM} = 0; + } + $o->{excludedocs} = !$docs; + $o->{rpmsrate_flags_chosen}{CAT_MINIMAL_DOCS} = $docs; + $o->{no_recommends} = !$recommends; + $o->{compssListLevel} = pkgs::rpmsrate_rate_max() if !$recommends; + log::l("install settings: no_recommends=$o->{no_recommends}, excludedocs=$o->{excludedocs}, really_minimal_install=$minimal"); + + install::any::unselectMostPackages($o); + 1; +} + +sub reallyChooseGroups { + my ($o, $size_to_display, $individual, $compssUsers) = @_; + + my $size_text = &$size_to_display; + + my ($path, $all); + $o->ask_from_({ messages => N("Package Group Selection"), + interactive_help_id => 'choosePackageGroups', + }, [ + { val => \$size_text, type => 'label' }, {}, + (map { + my $old = $path; + $path = $_->{path}; + if_($old ne $path, { val => translate($path) }), + { + val => \$_->{selected}, + type => 'bool', + disabled => sub { $all }, + text => translate($_->{label}), + help => translate($_->{descr}), + changed => sub { $size_text = &$size_to_display }, + }; + } @$compssUsers), + if_($individual, { text => N("Individual package selection"), val => $individual, advanced => 1, type => 'bool' }), + ]); + + if ($all) { + $_->{selected} = 1 foreach @$compssUsers; + } + 1; +} + +sub beforeInstallPackages { + my ($o) = @_; + my $_w = $o->{isUpgrade} && $o->wait_message('', N("Preparing upgrade...")); + $o->SUPER::beforeInstallPackages; +} + +#------------------------------------------------------------------------------ +sub installPackages { + my ($o) = @_; + my ($current, $total) = (0, 0); + + my ($_w, $wait_message) = $o->wait_message_with_progress_bar(N("Installing")); + $wait_message->(N("Preparing installation"), 0, 100); #- beware, interactive::curses::wait_message_with_progress_bar need to create the Dialog::Progress here because in installCallback we are chrooted + + local *install::steps::installCallback = sub { + my ($packages, $type, $id, $subtype, $_amount, $total_) = @_; + if ($type eq 'user' && $subtype eq 'install') { + $total = $total_; + } elsif ($type eq 'inst' && $subtype eq 'start') { + my $p = $packages->{depslist}[$id]; + $wait_message->(N("Installing package %s", $p->name), $current, $total); + $current += $p->size; + } + }; + + my $install_result; + catch_cdie { $install_result = $o->install::steps::installPackages('interactive') } + sub { installPackages__handle_error($o, $_[0]) }; + + if ($install::pkgs::cancel_install) { + $install::pkgs::cancel_install = 0; + die "setstep choosePackages\n"; + } + $install_result; +} + +sub installPackages__handle_error { + my ($o, $err_ref) = @_; + + log::l("catch_cdie: $$err_ref"); + my $time = time(); + my $go_on; + if ($$err_ref =~ /^error ordering package list: (.*)/) { + $go_on = $o->ask_yesorno('', [ + N("There was an error ordering packages:"), $1, N("Go on anyway?") ], 1); + } elsif ($$err_ref =~ /^error installing package list: (\S+)\s*(.*)/) { + my ($pkg_name, $medium_name) = ($1, $2); + my @choices = ( + [ 'retry', N("Retry") ], + [ 'skip_one', N("Skip this package") ], + [ 'disable_media', N("Skip all packages from medium \"%s\"", $medium_name) ], + [ '', N("Go back to media and packages selection") ], + ); + my $choice; + $o->ask_from_({ messages => N("There was an error installing package %s.", $pkg_name) }, + [ { val => \$choice, type => 'list', list => \@choices, format => sub { $_[0][1] } } ]); + $go_on = $choice->[0]; + } + if ($go_on) { + #- add the elapsed time (otherwise the predicted time will be rubbish) + $o->{install_start_time} += time() - $time; + $go_on; + } else { + $o->{askmedia} = 1; + $$err_ref = "already displayed"; + 0; + } +} + + +sub afterInstallPackages($) { + my ($o) = @_; + local $o->{pop_wait_messages} = 1; + my $_w = $o->wait_message(N("Post-install configuration"), N("Post-install configuration")); + $o->SUPER::afterInstallPackages; +} + +sub updatemodules { + my ($o, $dev, $rel_dir) = @_; + + $o->ask_okcancel('', N("Please ensure the Update Modules media is in drive %s", $dev), 1) or return; + $o->SUPER::updatemodules($dev, $rel_dir); +} + +#------------------------------------------------------------------------------ +sub configureNetwork { + my ($o) = @_; + #- don't overwrite configuration in a network install + if (!install::any::is_network_install($o)) { + require network::network; + network::network::easy_dhcp($o->{net}, $o->{modules_conf}); + } + $o->SUPER::configureNetwork; +} + +#------------------------------------------------------------------------------ +sub installUpdates { + my ($o) = @_; + $o->{updates} ||= {}; + + $o->hasNetwork or return; + + if (install::any::is_network_install($o) && + find { $_->{update} } install::media::allMediums($o->{packages})) { + log::l("installUpdates: skipping since updates were already available during install"); + return; + } + + $o->ask_yesorno_({ title => N("Updates"), messages => formatAlaTeX( +N("You now have the opportunity to setup online media.") . "\n\n" . +N("This allows to install security updates.") . "\n\n" . +N("To setup those media, you will need to have a working Internet +connection. + +Do you want to setup the update media?")), + interactive_help_id => 'installUpdates', + }, 1) or do { + log::l("installUpdates: skipping since user say no to media setup"); + return; + }; + + my $urpmi_options = { mirror_url => '$MIRRORLIST', downloader => $o->{options}{downloader} }; + + try_again: + #- bring all interface up for installing updates packages. + install::interactive::upNetwork($o); + + any::ask_mirror_and_downloader($o, $urpmi_options); + + if (!any::urpmi_set_downloader($o, $o->{packages}, $urpmi_options->{downloader})) { + log::l("installUpdates: failed to change urpmi downloader"); + local $::isWizard = 0; # make button names "ok" and "cancel", not "next" and "previous" + if ($o->ask_okcancel(N("Warning"), + N("That downloader could not be installed") . "\n" . N("Retry?"))) { + goto try_again; + } else { + return 0; + } + } + + if ($urpmi_options->{mirror_url} ne '$MIRRORLIST') { + $urpmi_options->{mirror_url} = any::ask_mirror($o, 'distrib', $urpmi_options->{mirror_url}); + } + + install::pkgs::clean_rpmdb_shared_regions(); + if (any::urpmi_add_all_media($o, $o->{previous_release}, $urpmi_options->{mirror_url})) { + log::l("installUpdates: successfully added media"); + } else { + log::l("installUpdates: failed to add media"); + local $::isWizard = 0; # make button names "ok" and "cancel", not "next" and "previous" + if ($o->ask_okcancel(N("Warning"), + N("Failure when adding medium") . "\n" . N("Retry?"))) { + goto try_again; + } else { + return 0; + } + } + + $o->ask_yesorno_({ title => N("Updates"), messages => formatAlaTeX( +N("You now have the opportunity to download updated packages. These packages +have been updated after the distribution was released. They may +contain security or bug fixes. + +To download these packages, you will need to have a working Internet +connection. + +Do you want to install the updates?")), + interactive_help_id => 'installUpdates', + }, 1) or do { + log::l("installUpdates: skipping since user say no to updates"); + return; + }; + + my $binary = find { whereis_binary($_, $::prefix) } if_(check_for_xserver(), 'gurpmi2'), 'urpmi' or return; + my $log_file = '/root/drakx/updates.log'; + run_program::raw({ root => $::prefix, timeout => 'never' }, $binary, '>>', $log_file, '2>>', $log_file, '--auto-select'); + + install::pkgs::clean_rpmdb_shared_regions(); + + #- not downing network, even PPP. We don't care much since it is the end of install :) +} + + +#------------------------------------------------------------------------------ +sub configureTimezone { + my ($o, $clicked) = @_; + + any::configure_timezone($o, $o->{timezone}, $clicked) or return; + + install::steps::configureTimezone($o); + 1; +} + +#------------------------------------------------------------------------------ +sub configureServices { + my ($o, $clicked) = @_; + require services; + $o->{services} = services::ask($o) if $clicked; + install::steps::configureServices($o); +} + + +sub summaryBefore { + my ($o) = @_; + + install::any::preConfigureTimezone($o); + #- get back network configuration. + require network::network; + eval { + network::network::read_net_conf($o->{net}); + }; + log::l("summaryBefore: network configuration: ", formatError($@)) if $@; +} + +sub summary_prompt { + my ($o, $l, $check_complete) = @_; + + foreach (@$l) { + my $val = $_->{val}; + ($_->{format}, $_->{val}) = (sub { $val && $val->() || N("not configured") }, ''); + } + + $o->ask_from_({ + messages => N("Summary"), + interactive_help_id => 'summary', + cancel => '', + callbacks => { complete => sub { !$check_complete->() } }, + }, $l); +} + +sub summary { + my ($o) = @_; + + my @l; + + my $timezone_manually_set; + push @l, { + group => N("System"), + label => N("Timezone"), + val => sub { $o->{timezone}{timezone} }, + clicked => sub { $timezone_manually_set = $o->configureTimezone(1) || $timezone_manually_set }, + }; + push @l, { + group => N("System"), + label => N("Country / Region"), + val => sub { lang::c2name($o->{locale}{country}) }, + clicked => sub { + any::selectCountry($o, $o->{locale}) or return; + + my $pkg_locale = lang::locale_to_main_locale(lang::getlocale_for_country($o->{locale}{lang}, $o->{locale}{country})); + my @pkgs = URPM::packages_providing($o->{packages}, "locales-$pkg_locale"); + $o->pkg_install(map { $_->name } @pkgs) if @pkgs; + + lang::write_and_install($o->{locale}, $o->do_pkgs); + if (!$timezone_manually_set && !$o->{isUpgrade}) { + delete $o->{timezone}; + install::any::preConfigureTimezone($o); #- now we can precise the timezone thanks to the country + } + }, + }; + local $o->{bootloader}{boot} = 'ESP' if is_uefi(); + push @l, { + group => N("System"), + label => N("Bootloader"), + val => sub { + + $o->{bootloader}{boot} ? + #-PO: example: grub2-graphic on /dev/sda1 + N("%s on %s", $o->{bootloader}{method}, $o->{bootloader}{boot}) : N("None"); + }, + if_(is_uefi(), tip => N("EFI System Partition")), + clicked => sub { + any::setupBootloader($o, $o->{bootloader}, $o->{all_hds}, $o->{fstab}, $o->{security}) or return; + }, + } if !$::local_install; + + push @l, { + group => N("System"), + label => N("User management"), + clicked => sub { + if (my $u = any::ask_user($o, $o->{users}, $o->{security}, needauser => 1)) { + #- getpwnam, getgrnam, getgrid works + symlinkf("$::prefix/etc/passwd", '/etc/passwd'); + symlinkf("$::prefix/etc/group", '/etc/group'); + any::add_users([$u], $o->{authentication}); + } + }, + }; + + push @l, { + group => N("System"), + label => N("Services"), + val => sub { + require services; + my ($l, $activated) = services::services(); + N("%d activated for %d registered", int(@$activated), int(@$l)); + }, + clicked => sub { + require services; + $o->{services} = services::ask($o) and services::doit($o, $o->{services}); + }, + }; + + push @l, { + group => N("Hardware"), + label => N("Keyboard"), + val => sub { $o->{keyboard} && translate(keyboard::keyboard2text($o->{keyboard})) }, + clicked => sub { $o->selectKeyboard(1) }, + } if !$o->{match_all_hardware}; + + push @l, { + group => N("Hardware"), + label => N("Mouse"), + val => sub { translate($o->{mouse}{type}) . ' ' . translate($o->{mouse}{name}) }, + clicked => sub { selectMouse($o, 1); mouse::write($o->do_pkgs, $o->{mouse}) }, + } if !$o->{match_all_hardware}; + + + my @sound_cards = $o->{match_all_hardware} ? () : detect_devices::getSoundDevices(); + + my $sound_index = 0; + foreach my $device (@sound_cards) { + $device->{sound_slot_index} = $sound_index; + push @l, { + group => N("Hardware"), + label => N("Sound card"), + val => sub { + $device->{driver} && modules::module2description($device->{driver}) || $device->{description}; + }, + clicked => sub { + require harddrake::sound; + harddrake::sound::config($o, $o->{modules_conf}, $device); + }, + }; + $sound_index++; + } + + push @l, { + group => N("Hardware"), + label => N("Graphical interface"), + val => sub { $o->{raw_X} ? Xconfig::various::to_string($o->{raw_X}) : '' }, + clicked => sub { configureX($o, 'expert') }, + } if !$o->{match_all_hardware}; + + push @l, { + group => N("Network & Internet"), + label => N("Network"), + val => sub { $o->{net}{type} }, + format => sub { $_[0] =~ s/.*:://; $_[0] }, + clicked => sub { + require network::netconnect; + network::netconnect::real_main($o->{net}, $o, $o->{modules_conf}); + }, + } if !$o->{match_all_hardware}; + + $o->{miscellaneous} ||= {}; + push @l, { + group => N("Network & Internet"), + label => N("Proxies"), + val => sub { $o->{miscellaneous}{http_proxy} || $o->{miscellaneous}{ftp_proxy} ? N("configured") : N("not configured") }, + clicked => sub { + require network::network; + network::network::miscellaneous_choose($o, $o->{miscellaneous}); + network::network::proxy_configure($o->{miscellaneous}) if !$::testing; + }, + } if !$o->{match_all_hardware}; + + push @l, { + group => N("Security"), + label => N("Security Level"), + val => sub { + require security::level; + security::level::to_string($o->{security}); + }, + clicked => sub { + require security::level; + my $security = $o->{security}; + set_sec_level: + if (security::level::level_choose($o, \$security, \$o->{security_user})) { + check_security_level($o, $security) or goto set_sec_level; + $o->{security} = $security; + install::any::set_security($o); + } + }, + } if -x "$::prefix/usr/sbin/msec"; + # FIXME: install msec if needed instead + + push @l, { + group => N("Security"), + label => N("Firewall"), + val => sub { + require network::shorewall; + my $shorewall = network::shorewall::read(); + $shorewall && !$shorewall->{disabled} ? N("activated") : N("disabled"); + }, + clicked => sub { + require network::drakfirewall; + if (my @rc = network::drakfirewall::main($o, $o->{security} < 1)) { + $o->{firewall_ports} = !$rc[0] && $rc[1]; + } + }, + } if detect_devices::get_net_interfaces(); + + my $check_complete = sub { + return 1 if $o->{match_all_hardware}; + require install::pkgs; + my $p = install::pkgs::packageByName($o->{packages}, 'task-x11'); + $o->{raw_X} || !$::testing && $p && !$p->flag_installed || + $o->ask_yesorno('', N("You have not configured X. Are you sure you really want this?")); + }; + + $o->summary_prompt(\@l, $check_complete); + + any::installBootloader($o, $o->{bootloader}, $o->{all_hds}) if !$::local_install; + install::steps::configureTimezone($o) if !$timezone_manually_set; #- do not forget it. +} + +#------------------------------------------------------------------------------ +#-setRootPassword_addUser +#------------------------------------------------------------------------------ +sub setRootPassword_addUser { + my ($o) = @_; + $o->{users} ||= []; + + my $sup = $o->{superuser} ||= {}; + $sup->{password2} ||= $sup->{password} ||= ""; + + any::ask_user_and_root($o, $sup, $o->{users}, $o->{security}); + + install::steps::setRootPassword($o); + install::steps::addUser($o); +} + +#------------------------------------------------------------------------------ +sub setupBootloaderBefore { + my ($o) = @_; + local $o->{pop_wait_messages} = 1; + my $_w = $o->wait_message(N("Please wait"), + #-PO: This is NOT the boot loader (just the kernel initrds)!!!! + N("Preparing initial startup program...") . "\n" . + N("Be patient, this may take a while...") + ); + $o->SUPER::setupBootloaderBefore; +} + +#------------------------------------------------------------------------------ +sub setupBootloader { + my ($o) = @_; + { + any::setupBootloader_simple($o, $o->{bootloader}, $o->{all_hds}, $o->{fstab}, $o->{security}) or return; + } +} + +sub check_security_level { + my ($o, $security) = @_; + if ($security > 3 && find { $_->{fs_type} eq 'vfat' } @{$o->{fstab}}) { + $o->ask_okcancel('', N("In this security level, access to the files in the Windows partition is restricted to the administrator.")) or return 0; + } + return 1; +} + +sub miscellaneous { + my ($o, $_clicked) = @_; + + install::steps::miscellaneous($o); +} + +#------------------------------------------------------------------------------ +sub configureX { + my ($o, $expert) = @_; + + install::steps::configureXBefore($o); + symlink "$::prefix/etc/gtk", "/etc/gtk"; + + require Xconfig::main; + my ($raw_X) = Xconfig::main::configure_everything_or_configure_chooser($o, install::any::X_options_from_o($o), !$expert, $o->{keyboard}, $o->{mouse}); + if ($raw_X) { + $o->{raw_X} = $raw_X; + install::steps::configureXAfter($o); + } +} + +#------------------------------------------------------------------------------ +sub generateAutoInstFloppy { + my ($o, $replay) = @_; + my $img = install::any::getAndSaveAutoInstallFloppies($o, $replay) or return; + + my $floppy = detect_devices::floppy(); + $o->ask_okcancel('', N("Insert a blank floppy in drive %s", $floppy), 1) or return; + + my $_w = $o->wait_message('', N("Creating auto install floppy...")); + require install::commands; + install::commands::dd("if=$img", 'of=' . devices::make($floppy)); + common::sync(); +} + +#------------------------------------------------------------------------------ +sub exitInstall { + my ($o, $alldone) = @_; + + return $o->{step} = '' if !$alldone && !$o->ask_yesorno(N("Warning"), +N("Some steps are not completed. + +Do you really want to quit now?"), 0); + + install::steps::exitInstall($o); + + $o->exit unless $alldone; + + $o->ask_from_no_check( + { + title => N("Congratulations"), + messages => formatAlaTeX(messages::install_completed()), + interactive_help_id => 'exitInstall', + ok => $::local_install ? N("Quit") : N("Reboot"), + }, []) if $alldone; +} + + +#-###################################################################################### +#- Misc Steps Functions +#-###################################################################################### + +1; |