diff options
-rw-r--r-- | .perl_checker | 1 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | t/helper.pm | 26 | ||||
-rw-r--r-- | t/superuser--addmedia.t | 22 | ||||
-rw-r--r-- | urpm.pm | 1 | ||||
-rw-r--r-- | urpm/cfg.pm | 63 | ||||
-rw-r--r-- | urpm/media.pm | 40 |
7 files changed, 151 insertions, 4 deletions
diff --git a/.perl_checker b/.perl_checker index 5f46df51..c97dff1e 100644 --- a/.perl_checker +++ b/.perl_checker @@ -17,3 +17,4 @@ Time::HiRes open encoding XML::LibXML::Reader +Config::IniFiles @@ -1,3 +1,5 @@ +- urpmi handles /etc/urpmi/media.d/*.cfg + as an alternative to using urpmi.addmedia - urpmi.update, urpmi.addmedia: o handle --virtual for remote media (a better name would be "auto-update", a la yum) diff --git a/t/helper.pm b/t/helper.pm index 870baa2b..edf787d3 100644 --- a/t/helper.pm +++ b/t/helper.pm @@ -7,6 +7,7 @@ our @EXPORT = qw(need_root_and_prepare urpmi_addmedia urpmi_removemedia urpmi_update urpm_cmd run_urpm_cmd urpmi_cmd urpmi test_urpmi_fail urpme urpmi_cfg set_urpmi_cfg_global_options + create_media_d_cfg media_d_cfg system_ system_should_fail rpm_is_jbj_version check_installed_fullnames check_installed_names check_nothing_installed @@ -101,6 +102,31 @@ sub set_urpmi_cfg_global_options { ok(urpm::cfg::dump_config(urpmi_cfg(), $config), 'set_urpmi_cfg_global_options'); } +sub media_d_dir { + "$::pwd/root/etc/urpmi/media.d"; +} +sub media_d_cfg { + my ($name) = @_; + media_d_dir() . "/$name.cfg"; +} +sub create_media_d_cfg { + my ($name, @l) = @_; + + system("install -d " . media_d_dir()); + my $cfg = media_d_cfg($name); + -e $cfg and die "$cfg already exists\n"; + open(my $F, '>', $cfg); + + my $cnt = 1; + foreach my $h (@l) { + my %h = %$h; + my $section = delete $h{conf_file__rel_media} || $cnt++; + print $F "[$section]\n"; + print $F "$_ = $h->{$_}\n" foreach keys %$h; + } +} + + sub system_ { my ($cmd) = @_; system($cmd); diff --git a/t/superuser--addmedia.t b/t/superuser--addmedia.t index 63b9fb34..f6701a3e 100644 --- a/t/superuser--addmedia.t +++ b/t/superuser--addmedia.t @@ -14,6 +14,9 @@ my $name3 = 'various3'; my @fields = qw(hdlist synthesis with_synthesis media_info_dir no-media-info list virtual ignore); +try_media_d_1(); +try_media_d_2(); + try_medium({}, ''); @@ -150,3 +153,22 @@ sub check_urpmi { urpmi(join(' ', @names)); check_installed_and_remove(@names); } + +sub try_media_d_1 { + create_media_d_cfg($name, { name => $name, url => "$::pwd/media/$name" }); + check_urpmi($name); + + create_media_d_cfg($name2, { name => $name2, url => "$::pwd/media/$name2" }); + check_urpmi($name2); + + ok(unlink media_d_cfg($name)); + ok(unlink media_d_cfg($name2)); +} +sub try_media_d_2 { + create_media_d_cfg($name, + { name => $name, url => "$::pwd/media/$name" }, + { name => $name2, url => "$::pwd/media/$name2" }); + check_urpmi($name, $name2); + + ok(unlink media_d_cfg($name)); +} @@ -123,6 +123,7 @@ sub set_files { my ($urpm, $urpmi_root) = @_; my %h = ( config => "$urpmi_root/etc/urpmi/urpmi.cfg", + configs_dir => "$urpmi_root/etc/urpmi/media.d", skiplist => prefer_rooted($urpmi_root, '/etc/urpmi/skip.list'), instlist => prefer_rooted($urpmi_root, '/etc/urpmi/inst.list'), prefer_list => prefer_rooted($urpmi_root, '/etc/urpmi/prefer.list'), diff --git a/urpm/cfg.pm b/urpm/cfg.pm index a1c24d3f..634a188d 100644 --- a/urpm/cfg.pm +++ b/urpm/cfg.pm @@ -252,6 +252,69 @@ sub dump_config_raw { 1; } +sub load_ini_config_file_raw { + my ($file, $b_norewrite) = @_; + + require Config::IniFiles; + my $cfg = Config::IniFiles->new('-file' => $file); + [ map { + my $section = $_; + my %h = map { + my $v = $cfg->val($section, $_); + $v = expand_line($v) if !$b_norewrite; + $_ => $v; + } $cfg->Parameters($section); + { conf_file__rel_media => $section, %h }; + } $cfg->Sections ]; +} + +sub write_ini_config { + my ($file, $blocks) = @_; + + if (@$blocks == 0) { + unlink $file; + return; + } + my $modified; + + require Config::IniFiles; + my $cfg = Config::IniFiles->new('-file' => $file); + if ($cfg) { + # remove dropped blocks + foreach (difference2([ $cfg->Sections ], [ map { $_->{name} } @$blocks ])) { + $cfg->DeleteSection($_); + $modified = 1; + } + } else { + $cfg = Config::IniFiles->new; + } + + my %uniq; + + foreach (@$blocks) { + my %h = %$_; + my $section = delete $h{conf_file__rel_media} || '_'; + $uniq{$section}++ or die "conflicting conf_file__rel_media value\n"; + + foreach (difference2([ $cfg->Parameters($section) ], [ keys %h ])) { + # remove those options which are no more wanted + $cfg->delval($section, $_); + $modified = 1; + } + foreach (keys %h) { + my $old_v = $cfg->getval($section, $_); + my $v = substitute_back($h{$_}, $old_v); + if ($old_v ne $v) { + $cfg->setval($section, $_, $v); + $modified = 1; + } + } + } + if ($modified) { + $cfg->RewriteConfig; + } +} + #- routines to handle mirror list location #- Default mirror list diff --git a/urpm/media.pm b/urpm/media.pm index ac66c3b2..0e056c63 100644 --- a/urpm/media.pm +++ b/urpm/media.pm @@ -11,6 +11,7 @@ use MDV::Distribconf; our @PER_MEDIA_OPT = qw( + conf_file__rel_media downloader ignore key-ids @@ -144,6 +145,7 @@ sub read_config { #- per-media options read_config_add_passwords($urpm, $config); + my @media; foreach my $m (@{$config->{media}}) { my $medium = _only_media_opts_read($m); @@ -154,9 +156,22 @@ sub read_config { $medium->{url} or $urpm->{error}("unable to find url in list file $medium->{name}, medium ignored"); } - add_existing_medium($urpm, $medium); + push @media, $medium; } + require File::Glob; + # we can't use perl's glob() because we allow spaces in filename + foreach my $conf_file (File::Glob::bsd_glob("$urpm->{configs_dir}/*.cfg")) { + $urpm->{debug} and $urpm->{debug}("parsing: $conf_file"); + my $conf = urpm::cfg::load_ini_config_file_raw($conf_file); + foreach my $medium (map { _only_media_opts_read($_) } @$conf) { + $medium->{conf_file} = $conf_file; + push @media, $medium; + } + } + + add_existing_medium($urpm, $_) foreach @media; + eval { require urpm::ldap; urpm::ldap::load_ldap_media($urpm) }; } @@ -172,7 +187,12 @@ sub check_existing_medium { N("unable to access list file of \"%s\", medium ignored", $medium->{name}); } elsif (!$medium->{ignore} && !-r any_synthesis($urpm, $medium)) { - $err = N("unable to access synthesis file of \"%s\", medium ignored", $medium->{name}); + if ($medium->{conf_file} && $< == 0) { + # no pb, we create on the fly + $medium->{force_auto_update} = 1; + } else { + $err = N("unable to access synthesis file of \"%s\", medium ignored", $medium->{name}); + } } if ($err) { $medium->{ignore} = 1; @@ -406,11 +426,16 @@ sub write_urpmi_cfg { #- avoid trashing exiting configuration if it wasn't loaded $urpm->{media} or return; + my %media_per_cfg; + foreach (grep { !$_->{external} } @{$urpm->{media}}) { + push @{$media_per_cfg{$_->{conf_file} || ''}}, _only_media_opts_write($_); + } + my $config = { #- global config options found in the config file, without the ones #- set from the command-line global => $urpm->{global_config}, - media => [ map { _only_media_opts_write($_) } grep { !$_->{external} } @{$urpm->{media}} ], + media => delete $media_per_cfg{''}, }; remove_passwords_and_write_private_netrc($urpm, $config); @@ -419,6 +444,13 @@ sub write_urpmi_cfg { $urpm->{log}(N("wrote config file [%s]", $urpm->{config})); + foreach my $conf_file (sort keys %media_per_cfg) { + urpm::cfg::write_ini_config($conf_file, $media_per_cfg{$conf_file}) + or $urpm->{fatal}(6, N("unable to write config file [%s]", $conf_file)); + + $urpm->{log}(N("wrote config file [%s]", $conf_file)); + } + #- everything should be synced now. delete $urpm->{modified}; } @@ -552,7 +584,7 @@ sub _auto_update_media { my $errors; foreach (grep { !$_->{ignore} && (!$options{update} || $_->{update}) && - _is_remote_virtual($_) } @{$urpm->{media} || []}) { + ($_->{force_auto_update} || _is_remote_virtual($_)) } @{$urpm->{media} || []}) { _update_medium($urpm, $_, %options) or $errors++; } !$errors; |