summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgarciasuarez@mandriva.org>2004-08-12 09:31:49 +0000
committerRafael Garcia-Suarez <rgarciasuarez@mandriva.org>2004-08-12 09:31:49 +0000
commit96383ba7fe1fc97890f5d86e088caca3bcfc73c0 (patch)
treea649c3f74c185c0963a1d34643b2088299f190cf
parent3c9786002b9179fc49bd22b6b4d8eda0b277c6d1 (diff)
downloaddrakx-96383ba7fe1fc97890f5d86e088caca3bcfc73c0.tar
drakx-96383ba7fe1fc97890f5d86e088caca3bcfc73c0.tar.gz
drakx-96383ba7fe1fc97890f5d86e088caca3bcfc73c0.tar.bz2
drakx-96383ba7fe1fc97890f5d86e088caca3bcfc73c0.tar.xz
drakx-96383ba7fe1fc97890f5d86e088caca3bcfc73c0.zip
First stab at supporting several hdlists on a supplementary CD
-rw-r--r--perl-install/install_any.pm44
-rw-r--r--perl-install/pkgs.pm14
2 files changed, 32 insertions, 26 deletions
diff --git a/perl-install/install_any.pm b/perl-install/install_any.pm
index f6f94cf45..53f7f9419 100644
--- a/perl-install/install_any.pm
+++ b/perl-install/install_any.pm
@@ -396,26 +396,30 @@ sub setPackages {
mountCdrom("/mnt/cdrom", $cdrom);
log::l($@) if $@;
useMedium($medium_name);
- #- TODO probe for an hdlists file, and then look for
- #- all hdlists listed herein
- my $supplmedium = pkgs::psUsingHdlist(
- $o->{prefix}, # /mnt
- $suppl_method,
- $o->{packages},
- "hdlist$medium_name.cz",
- $medium_name,
- 'media/main',
- "Supplementary CD $medium_name",
- 1, # selected
- "/mnt/cdrom/media/main/media_info/hdlist$medium_name.cz",
- );
- if ($supplmedium) {
- log::l("read suppl hdlist on cdrom");
- $supplmedium->{prefix} = "removable://mnt/cdrom"; #- for install_urpmi
- $supplmedium->{selected} = 1;
- $supplmedium->{method} = 'cdrom';
- } else {
- log::l("no suppl hdlist");
+ #- probe for an hdlists file and then look for all hdlists listed herein
+ eval { pkgs::psUsingHdlists($o->{prefix}, $suppl_method, "/mnt/cdrom/media/media_info/hdlists", $o->{packages}) };
+ if ($@) {
+ #- no hdlists found on the suppl. CD
+ #- Look directly for a file media/main/hdlist1s.cz
+ my $supplmedium = pkgs::psUsingHdlist(
+ $o->{prefix}, # /mnt
+ $suppl_method,
+ $o->{packages},
+ "hdlist$medium_name.cz",
+ $medium_name,
+ 'media/main',
+ "Supplementary CD $medium_name",
+ 1, # selected
+ "/mnt/cdrom/media/main/media_info/hdlist$medium_name.cz",
+ );
+ if ($supplmedium) {
+ log::l("read suppl hdlist on cdrom");
+ $supplmedium->{prefix} = "removable://mnt/cdrom"; #- for install_urpmi
+ $supplmedium->{selected} = 1;
+ $supplmedium->{method} = 'cdrom';
+ } else {
+ log::l("no suppl hdlist");
+ }
}
}
} else {
diff --git a/perl-install/pkgs.pm b/perl-install/pkgs.pm
index 25cdd9237..4bfe1e39f 100644
--- a/perl-install/pkgs.pm
+++ b/perl-install/pkgs.pm
@@ -378,13 +378,15 @@ sub psUpdateHdlistsDeps {
}
sub psUsingHdlists {
- my ($prefix, $method) = @_;
- my $listf = install_any::getFile('media/media_info/hdlists') or die "no hdlists found";
- my $packages = new URPM;
+ my ($prefix, $method, $hdlistsfile, $packages) = @_;
+ my $listf = install_any::getFile($hdlistsfile || 'media/media_info/hdlists')
+ or die "no hdlists found";
my $suppl_CDs = 0;
-
- #- add additional fields used by DrakX.
- @$packages{qw(count mediums)} = (0, {});
+ if (!$packages) {
+ $packages = new URPM;
+ #- add additional fields used by DrakX.
+ @$packages{qw(count mediums)} = (0, {});
+ }
#- parse hdlists file.
my $medium_name = 1;
='n269' href='#n269'>269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
package diskdrake::hd_gtk; # $Id$

use diagnostics;
use strict;

use common;
use ugtk2 qw(:helpers :wrappers :create);
use partition_table qw(:types);
use partition_table::raw;
use detect_devices;
use diskdrake::interactive;
use run_program;
use loopback;
use devices;
use raid;
use any;
use log;
use fsedit;
use fs;

my ($width, $height, $minwidth) = (400, 50, 5);
my ($all_hds, $in, $do_force_reload, $current_kind, $current_entry, $update_all);
my ($w, @notebook, $done_button);

=begin


=head1 SYNOPSYS

struct {
  string name      # which is displayed in tab of the notebook
  bool no_auto     # wether the kind can disappear after creation
  string type      # one of { 'hd', 'raid', 'lvm', 'loopback', 'removable', 'nfs', 'smb' }
  hd | hd_lvm | part_raid[] | part_loopback[] | raw_hd[]  val

  # 
  widget main_box
  widget display_box
  widget action_box
  widget info_box
} current_kind

part current_entry

notebook current_kind[]

=cut

sub main {
    ($in, $all_hds, my $nowizard, $do_force_reload, my $interactive_help) = @_;

    @notebook = ();

    local $in->{grab} = 1;

    $w = ugtk2->new('DiskDrake');
    $::main_window = $w->{rwindow} if !$::isEmbedded && !$::isInstall;
    my $rc = "/usr/share/libDrakX/diskdrake.rc";
    -r $rc or $rc = dirname(__FILE__) . "/../diskdrake.rc";
    -r $rc or $rc = dirname(__FILE__) . "/../share/diskdrake.rc";
    Gtk2::Rc->parse($rc);

    # TODO
#    is_empty_array_ref($all_hds->{raids}) or raid::stopAll;
#    updateLoopback();

    gtkadd($w->{window},
	   gtkpack_(Gtk2::VBox->new(0,7),
		    0, filesystems_button_box(),
		    1, (my $notebook_widget = Gtk2::Notebook->new),
		    0, (my $per_kind_action_box = Gtk2::HBox->new(0,0)),
		    0, (my $general_action_box  = Gtk2::HBox->new(0,0)),
		   ),
	  );
    my $lock;
    $update_all = sub {
	$lock and return;
	$lock = 1;
	partition_table::assign_device_numbers($_) foreach fsedit::all_hds($all_hds);
	create_automatic_notebooks($notebook_widget);
	general_action_box($general_action_box, $nowizard, $interactive_help);
	per_kind_action_box($per_kind_action_box, $current_kind);
	current_kind_changed($in, $current_kind);
	current_entry_changed($current_kind, $current_entry);
	$lock = 0;
    };
    create_automatic_notebooks($notebook_widget);

    $notebook_widget->signal_connect(switch_page => sub {
	$current_kind = $notebook[$_[2]];
	$current_entry = '';
	$update_all->();
    });
    $w->sync;
    $done_button->grab_focus;
    $in->ask_okcancel(N("Read carefully!"), N("Please make a backup of your data first"), 1) or return
      if $::isStandalone;
    $in->ask_warn('', 
N("If you plan to use aboot, be careful to leave a free space (2048 sectors is enough)
at the beginning of the disk")) if arch() eq 'alpha' && !$::isEmbedded;

    $w->main;
}

sub try {
    my ($name, @args) = @_;
    my $f = $diskdrake::interactive::{$name} or die "unknown function $name";
    try_($name, \&$f, @args);
}
sub try_ {
    my ($name, $f, @args) = @_;

    fsedit::undo_prepare($all_hds) if $name ne 'Undo';

    my $v = eval { $f->($in, @args, $all_hds) };
    if (my $err = $@) {
	$in->ask_warn(N("Error"), formatError($err));
    }
    if ($v eq 'force_reload') {	
	$all_hds = $do_force_reload->();
    }

    $current_entry = '' if !diskdrake::interactive::is_part_existing($current_entry, $all_hds);
    $update_all->();

    Gtk2->main_quit if $v && member($name, 'Done', 'Wizard');
}

################################################################################
# generic: helpers
################################################################################
sub add_kind2notebook {
    my ($notebook_widget, $kind) = @_;
    die if $kind->{main_box};

    $kind->{display_box} = gtkset_size_request(Gtk2::HBox->new(0,0), $width, $height);
    $kind->{action_box} = gtkset_size_request(Gtk2::VBox->new(0,0), $::isStandalone ? 165 : 150, $::isEmbedded ? 150 : 180);
    $kind->{info_box} = Gtk2::VBox->new(0,0);
    $kind->{main_box} =
      gtkpack_(Gtk2::VBox->new(0,7),
	       0, $kind->{display_box},
	       1, gtkpack_(Gtk2::HBox->new(0,7),
			   0, $kind->{action_box},
			   1, $kind->{info_box}));
    ugtk2::add2notebook($notebook_widget, $kind->{name}, $kind->{main_box});
    push @notebook, $kind;
    $kind;
}

sub general_action_box {
    my ($box, $nowizard, $interactive_help) = @_;
    $_->destroy foreach $box->get_children;

    gtkadd($box, gtksignal_connect(Gtk2::Button->new(N("Help")), clicked => $interactive_help)) if $interactive_help;

    my @actions = (if_($::isInstall && !$nowizard, N_("Wizard")), 
		   diskdrake::interactive::general_possible_actions($in, $all_hds), 
		   N_("Done"));
    foreach my $s (@actions) {
	my $button = Gtk2::Button->new(translate($s));
	$done_button = $button if $s eq 'Done';
	gtkadd($box, gtksignal_connect($button, clicked => sub { try($s) }));
    }
}
sub per_kind_action_box {
    my ($box, $kind) = @_;
    $_->destroy foreach $box->get_children;

    $kind->{type} =~ /hd|lvm/ or return;

    foreach my $s (diskdrake::interactive::hd_possible_actions($in, kind2hd($kind), $all_hds)) {
	gtkadd($box, 
	       gtksignal_connect(Gtk2::Button->new(translate($s)),
				 clicked => sub { try($s, kind2hd($kind)) }));
    }
}
sub per_entry_action_box {
    my ($box, $kind, $entry) = @_;
    $_->destroy foreach $box->get_children;

    if ($entry) {
	my @buttons = map { 
	    my $s = $_;
	    my $w = Gtk2::Button->new(translate($s));
	    $w->signal_connect(clicked => sub { try($s, kind2hd($kind), $entry) });
	    $w;
	} diskdrake::interactive::part_possible_actions($in, kind2hd($kind), $entry, $all_hds);

	gtkadd($box, gtkadd(Gtk2::Frame->new(N("Choose action")),
			    create_scrolled_window(gtkpack__(Gtk2::VBox->new(0,0), @buttons)))) if @buttons;
    } else {
	my $txt = !$::isStandalone && fsedit::is_one_big_fat_or_NT($all_hds->{hds}) ?
N("You have one big Microsoft Windows partition.
I suggest you first resize that partition
(click on it, then click on \"Resize\")") : N("Please click on a partition");
	gtkpack($box, gtktext_insert(Gtk2::TextView->new, $txt));
    }
}

sub per_entry_info_box {
    my ($box, $kind, $entry) = @_;
    $_->destroy foreach $box->get_children;
    my $info;
    if ($entry) {
	$info = diskdrake::interactive::format_part_info(kind2hd($kind), $entry);
    } elsif ($kind->{type} =~ /hd|lvm/) {
	$info = diskdrake::interactive::format_hd_info($kind->{val});
    }
    gtkpack($box, gtkadd(Gtk2::Frame->new(N("Details")), gtkset_justify(Gtk2::Label->new($info), 'left')));
}

sub current_kind_changed {
    my ($_in, $kind) = @_;

    $_->destroy foreach $kind->{display_box}->get_children;

    my $v = $kind->{val};
    my @parts = 
      $kind->{type} eq 'raid' ? grep { $_ } @$v :
      $kind->{type} eq 'loopback' ? @$v : fsedit::get_fstab_and_holes($v);
    my $totalsectors = 
      $kind->{type} =~ /raid|loopback/ ? sum(map { $_->{size} } @parts) : $v->{totalsectors};
    create_buttons4partitions($kind, $totalsectors, @parts);
}

sub current_entry_changed {
    my ($kind, $entry) = @_;
    $current_entry = $entry;
    if ($kind) {
	per_entry_action_box($kind->{action_box}, $kind, $entry);
	per_entry_info_box($kind->{info_box}, $kind, $entry);
    }
}

sub create_automatic_notebooks {
    my ($notebook_widget) = @_;

    $_->{marked} = 0 foreach @notebook;
    my $may_add = sub {
	my ($kind) = @_;
	my @l = grep { $kind->{val} == $_->{val} } @notebook;
	@l > 1 and log::l("weird: create_automatic_notebooks");
	$kind = $l[0] || add_kind2notebook($notebook_widget, $kind);
	$kind->{marked} = 1;
    };
    $may_add->(hd2kind($_)) foreach @{$all_hds->{hds}};
    $may_add->(lvm2kind($_)) foreach @{$all_hds->{lvms}};
    $may_add->(raid2kind()) if any { $_ } @{$all_hds->{raids}};
    $may_add->(loopback2kind()) if @{$all_hds->{loopbacks}};

    @notebook = grep_index {
	my $b = $_->{marked} or $notebook_widget->remove_page($::i);
	$b;
    } @notebook;
    @notebook or die N("No hard drives found");
}

################################################################################
# parts: helpers
################################################################################
sub create_buttons4partitions {
    my ($kind, $totalsectors, @parts) = @_;

    $width = max($width, 0.9 * second($w->{window}->window->get_size)) if $w->{window}->window;

    my $ratio = $totalsectors ? ($width - @parts * $minwidth) / $totalsectors : 1;
    while (1) {
	my $totalwidth = sum(map { $_->{size} * $ratio + $minwidth } @parts);
	$totalwidth <= $width and last;
	$ratio /= $totalwidth / $width * 1.1;
    }

    foreach my $entry (@parts) {
	my $w = Gtk2::Button->new_with_label($entry->{mntpoint} || '') or die '';
	$w->signal_connect(focus_in_event     => sub { current_entry_changed($kind, $entry); $w->grab_focus }); #- grab_focus is needed because gtk2 is buggy. Forcing an expose event would be enough
	$w->signal_connect(button_press_event => sub { current_entry_changed($kind, $entry); $w->grab_focus }); #- grab_focus is needed because gtk2 is buggy. The creation of widgets causes the lost of the focus
	$w->signal_connect(key_press_event => sub {
	    my (undef, $event) = @_;
	    member('control-mask', @{$event->state}) or return; 
	    my $c = chr $event->keyval;

	    foreach my $s (diskdrake::interactive::part_possible_actions($in, kind2hd($kind), $entry, $all_hds)) {
		${{
		    Create => 'c', Delete => 'd', Format => 'f', 
		    Loopback => 'l', Resize => 'r', Type => 't', 
		    Mount => 'M', Unmount => 'u', 'Mount point' => 'm',
		    'Add to LVM' => 'L', 'Remove from LVM' => 'L', 
		    'Add to RAID' => 'R', 'Remove from RAID' => 'R',
		}}{$s} eq $c or next;

		try($s, kind2hd($kind), $entry);
		last;
	    }
	});
	$w->set_name("PART_" . pt_type2name($entry->{pt_type}));
	$w->set_size_request($entry->{size} * $ratio + $minwidth, 0);
	gtkpack__($kind->{display_box}, $w);
	$w->grab_focus if $current_entry && fsedit::are_same_partitions($current_entry, $entry);
    }
}


################################################################################
# disks: helpers
################################################################################
sub current_hd() { 
    $current_kind->{type} eq 'hd' or die 'current_hd called but $current_kind is not an hd';
    $current_kind->{val};
}
sub current_part() {
    current_hd();
    $current_entry;
}

sub kind2hd {
    my ($kind) = @_;
    $kind->{type} =~ /hd|lvm/ ? $kind->{val} : {}
}

sub hd2kind {
    my ($hd) = @_;
    { type => 'hd', name => $hd->{device}, val => $hd };
}

sub filesystems_button_box() {
    my @types = (N_("Ext2"), N_("Journalised FS"), N_("Swap"), arch() =~ /sparc/ ? N_("SunOS") : arch() eq "ppc" ? N_("HFS") : N_("Windows"),
		 N_("Other"), N_("Empty"));
    my %name2pt_type = (Ext2 => 0x83, 'Journalised FS' => 0x483, Swap => 0x82, Other => 1, "Windows" => 0xb, HFS => 0x402);

    gtkpack(Gtk2::HBox->new(0,0), 
	    N("Filesystem types:"),
	    map { my $w = Gtk2::Button->new(translate($_));
		  my $t = $name2pt_type{$_};
		  $w->signal_connect(clicked => sub { try_('', \&createOrChangeType, $t, current_hd(), current_part()) });
		  $w->can_focus(0);
		  $w->set_name($_); 
		  $w;
	    } @types);
}

sub createOrChangeType {
    my ($in, $pt_type, $hd, $part, $all_hds) = @_;

    $part ||= !fsedit::get_fstab($hd) && 
              { pt_type => 0, start => 1, size => $hd->{totalsectors} - 1 };
    $part or return;
    if ($pt_type == 1) {
	$in->ask_warn('', N("Use ``%s'' instead", $part->{pt_type} ? N("Type") : N("Create")));
    } elsif (!$pt_type) {
	$in->ask_warn('', N("Use ``%s'' instead", N("Delete"))) if $part->{pt_type};
    } elsif ($part->{pt_type}) {
	return if $pt_type == $part->{pt_type};
	$in->ask_warn('', isBusy($part) ? N("Use ``Unmount'' first") : N("Use ``%s'' instead", N("Type")));
    } else {
	$part->{pt_type} = $pt_type;
	diskdrake::interactive::Create($in, $hd, $part, $all_hds);
    }
}

################################################################################
# lvms: helpers
################################################################################
sub lvm2kind {
    my ($lvm) = @_;
    { type => 'lvm', name => $lvm->{VG_name}, val => $lvm };
}

################################################################################
# raids: helpers
################################################################################
sub raid2kind() {
    { type => 'raid', name => 'raid', val => $all_hds->{raids} };
}

################################################################################
# loopbacks: helpers
################################################################################
sub loopback2kind() {