软件管理

在这一窗口中,您可以选择各种用于管理软件的工具。请点击下方的链接来了解更多信息。

软件管理(安装和移除软件)

rpmdrake

rpmdrake 介绍

此工具[1]也叫 drakrpm,是用于安装、卸载和升级软件包的程序,也是 URPMI 的图形化用户界面。每次启动时,它都会从 Mageia 官方服务器上下载在线软件包列表(即“媒体”),并在有可用更新时提示您。您可以使用筛选功能来显示特定类型的软件包,如仅显示已安装的软件(默认设置),或者仅显示可用更新。除了查看已安装的软件包,您也可以用名称、摘要或完整描述中的内容,以及软件包中的文件名来搜索您想要的软件。

若要使用此功能,您需要使用 “配置媒体”一节 来配置仓库。

重要

在安装系统时,系统使用预设的仓库(通常是 DVD 或 CD)作为安装的媒体。如果您保留这一媒体,每当您需要安装软件包时都会看到如下通知:

。为了避免此类情形的发生,在您可以方便地连接到互联网的情况下,最好将这一媒体移除,并用在线仓库来取代它:“配置媒体”一节

此外,在线仓库的优势还有:仓库总是保持最新状态。包含更多软件包,并且可以用于更新部分软件。

界面的主要内容

  1. 软件包类型筛选

    此筛选器用于显示特定类型的软件包。您首次启动管理器时,将只显示含有图形化界面的应用程序。您可以将其设置为显示所有软件包及其库和依赖;或者只显示软件包组,如应用程序、更新或来自新版 Mageia 的后向移植软件包。

    警告

    默认的筛选条件适用于 Linux 或 Mageia 新手,即不希望使用命令行或特别专业的工具。不过既然您读到了此内容,说明您有兴趣进一步了解 Mageia,所以我们建议您将筛选条件设为“所有”。

  2. 软件包状态筛选:

    此筛选器可用于控制显示已安装的软件包、未安装的软件包或所有软件包。

  3. 搜索模式:

    点击此图标,可以在软件包名称、摘要、完整描述或文件名中进行搜索。

  4. “查找”框:

    在这里输入一个或多个关键词。如果您希望使用一个以上的关键词,请用“|”将它们分隔开来。例如,要搜索“mplayer”和“xine”,您可以输入“mplayer | xine”。

  5. 清除所有:

    此图标用于清空“查找”框中的关键词。

  6. 分类列表

    此侧边栏将所有应用和软件包分组排列显示。

  7. 描述窗格

    此窗格中显示了软件包名称、概要和完整描述,其中包括了所选软件包的有用信息。有关软件包的详细情况、软件包中的文件和维护者对软件包所作更改也会显示在这里。

状态栏

当您设置了筛选条件后,您可以从分类列表(区域 6 所示)或根据名称/摘要/描述(区域 4 所示)来查找所需软件。系统将根据软件包的安装/升级状态来显示您所查询的软件包列表和所选媒体,以及相应的状态标记。若要改变软件状态,请勾选或取消勾选软件名掐案的复选框,然后点击应用

表 1. 

图标图例
此软件包已安装
此软件包将被安装
此软件包无法被更改
此软件包是一个更新包
此软件包将被卸载


上述截图中的示例:

  • 当您取消勾选 digikam(绿色箭头标记说明它目前已被安装),状态图标将会变为红色箭头;当您点击应用后系统会将 digikam 卸载。

  • 当您勾选了 qdigidoc(尚未安装),状态图标会变为橙色的向下箭头;当您点击应用后系统会安装 qdigidoc。

依赖关系

部分软件包需要其他软件包(如工具或库,它们被称为“依赖”)来工作。在这种情况下,Rpmdrake 将显示一个通知窗口,提示您是否允许或阻止安装所选依赖,或者显示更多信息(见上)。当所需库可以由多个软件包提供时,rpmdrake 也会显示可用的候选软件包,并允许您查看更多细节和选择要安装的软件包。

软件包更新

MageiaUpdate 或 drakrpm-update

您可以在 Mageia 控制中心的 软件管理选项卡中找到此工具[2]

注意

若要使用 MageiaUpdate,您需要将仓库配置为 drakrpm-editmedia 并将部分媒体选定为更新媒体。如果您尚未进行设置,程序会提示您进行设置。

启动该工具后,它将会扫描已安装的软件包,并列出仓库中可以更新的软件包。默认情况下,会自动选择所有可更新的软件包以便自动下载和安装。请点击更新按钮进行更新。

点击某个软件包后,您可以在窗口底部看到更多的信息。标题前的 > 表示您可以点击它来展开更多内容。

注意

当有可用的更新时,系统托盘中将会通过红色的图标来提示您。只需点击它并输入用户密码就可以更新系统。

配置更新频率

mgaapplet-config

此工具[3]可以在 Mageia 控制中心的软件管理选项卡中找到。您也可以通过右键单击系统托盘中的红色图标并选择更新配置来启动它。

第一个滑块可以设置 Mageia 检查更新的频率;第二个滑块可以设置在系统启动后延迟多长时间再检查更新。复选框用于设置当 Mageia 发布新版本时,是否提示您更新。

配置媒体

drakrpm-edit-media

重要

安装后的第一步是添加软件源(也叫仓库、媒体或镜像)。也就是说,您需要选择用于安装和更新软件包/应用程序的媒体资源(参见下面对添加按钮的说明)。

注意

如果您使用光盘(DVD 或 CD)或 USB 设备来安装或升级 Mageia,系统会默认添加一项使用光盘媒体的软件源。为了避免您在安装新软件包时需要插入光盘,您应当将该软件源(媒体类型为 CD-Rom)禁用。

注意

您的系统可能是 32 位(即 i586)或 64 位(即 x86_64)架构的,但部分软件包与架构无关,它们叫做 noarch 软件包。这些软件包在镜像中不属于独立的文件夹,而同时存在于 i586 和 x86_64 媒体中。

您可以在 Mageia 控制中心的 软件管理选项卡中找到此工具[4]

软件源选择列表

已启用:

被勾选的媒体将用于安装软件包。在使用“测试”和“调试”类型的媒体时请小心,它们可能会使得系统运行不稳定。

用于更新:

被勾选的媒体将用于更新软件包,必须将它们启用。请只选择名称中包含“Update”的媒体。出于安全考虑,您无法使用此工具修改这一列,而必须以 root 身份打开终端并输入 drakrpm-edit-media --expert

媒体:

显示媒体名称。Mageia 官方仓库中的最终发行版的软件源至少有三个:

  • Core,包含大多数由 Mageia 支持的程序。

  • Nonfree,包含非自由软件。

  • Tainted,包含在部分国家受专利保护的自由软件。

    每个媒体中都有四个子类:

  • 发行,包含了此版本的 Mageia 发行时所提供的软件包。

  • 更新,此版本的 Mageia 发行后软件更新,一般包含了安全和漏洞修复。即便您的网络速度可能很慢,也请务必启用该媒体。

  • 后向移植,包含了从新版 Mageia (Cauldron)移植过来的软件。

  • 测试,用于临时测试软件更新,使得错误报告者和 QA 团队能确定软件缺陷已被修复。

右侧按钮

移除

要移除一个媒体,请点击它,然后点击移除按钮。我们建议您移除用于安装(例如:CD 或 DVD)的媒体,因为它已被包含在 Core 媒体中。

编辑

对所选选媒体进行设置(URL、下载器和代理)。

添加

添加网络上可用的官方仓库,这些仓库仅包含安全且经过测试的软件。点击“添加”按钮可以将镜像列表添加到您的配置中,系统会自动选择距离您最近的服务器并用于安装和升级。如果您需要使用某个特定的镜像,请从“文件”下拉菜单中选择“添加特定媒体镜像”。

上下箭头

改变列表顺序。当 Drakrpm 查找软件包时,会根据列表中的顺序依次进行搜索,并选择第一个符合发行编号的软件包进行安装;当版本号不匹配时,将使用最新版本的软件包。因此,如果可能的话,请将最快的软件仓库移动到列表顶部。

菜单

文件 -> 更新

将会弹出媒体列表对话框。请选择您希望更新的媒体,然后点击更新按钮。

文件 -> 添加特定媒体镜像

如果您对当前的镜像不满意,如该镜像太慢或不可用,您可以选择其他镜像。请点击所有当前的媒体,然后点击移除来将它们删除。然后点击文件 -> 添加特定媒体镜像,并选择“仅更新”或“完整集合”(如果您不了解,请选择完整资源集合)并点击来接受更改。之后将会弹出此窗口:

您可以在左侧看到一个国家及地区列表,请从中选择距离您最近的地点并点击 > 符号,然后选择可用的镜像。之后,点击确定

文件 -> 添加自定义媒体

您也可以添加一个不被 Mageia 支持的媒体(如第三方媒体)。将会弹出一个新窗口:

请选择媒体类型,然后设置媒体名称(可以为任意内容)以及 URL(或路径)。

选项 -> 全局选项

此选项允许您选择何时“检验要安装的 RPM”(一直或从不)、下载器(curl、wget 或 aria2)和用于软件包信息的下载策略(按需(默认)、仅升级、一直或从不)。

选项 -> 管理密钥

为了确保高度的安全,系统使用数字密钥来认证媒体。您可以对每个媒体启用或禁用密钥。在弹出的窗口中,您可以选择一个媒体,然后点击添加来启用一个新密钥;或选择一个密钥,然后点击移除来禁用该密钥。

警告

请小心操作,因为它涉及到系统安全问题

选项 -> 代理

如果您需要使用代理服务器来访问互联网,您可以在这里进行配置。您只需要设置代理主机名;如果需要的话,也可以设置用户名密码

有关配置媒体的更多信息,请见the Mageia Wiki page



[1] 您可通过以 root 用户在命令行输入 rpmdrake 来启动该工具。

[2] 您可通过以 root 用户在命令行输入 MageiaUpdatedrakrpm-update 来启动该工具。

[3] 您可通过以 root 用户在命令行输入 mgaapplet-config 来启动该工具。

[4] 您可通过以 root 用户在命令行输入 drakrpm-edit-media 启动该工具。


CC BY-SA 3.0
Uploaded on 02/07/2019
loading table of contents...
lass="hl opt">::rpmdragora; use urpm; use urpm::lock; use urpm::install; use urpm::signature; use urpm::get_pkgs; use urpm::select; use urpm::main_loop; use urpm::args qw(); use urpm::util; use Carp; my $loc = ManaTools::rpmdragora::locale(); use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( $priority_up_alread_warned download_callback extract_header find_installed_version get_pkgs perform_installation perform_removal run_rpm sort_packages ); our $priority_up_alread_warned; sub sort_packages_biarch { sort { my ($na, $aa) = $a =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; my ($nb, $ab) = $b =~ /^(.*-[^-]+-[^-]+)\.([^.-]+)$/; !defined($na) ? (!defined($nb) ? 0 : 1) : (!defined($nb) ? -1 : $na cmp $nb || ($ab =~ /64$/) <=> ($aa =~ /64$/)); } @_; } sub sort_packages_monoarch { sort { uc($a) cmp uc($b) } @_; } *sort_packages = MDK::Common::System::arch() =~ /x86_64/ ? \&sort_packages_biarch : \&sort_packages_monoarch; sub run_rpm { foreach (qw(LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION LC_ALL)) { local $ENV{$_} = $ENV{$_} . '.UTF-8' if $ENV{$_} && $ENV{$_} !~ /UTF-8/; } my @l = map { ensure_utf8($_); $_ } ManaTools::Shared::RunProgram::get_stdout(@_); wantarray() ? @l : join('', @l); } sub extract_header { my ($pkg, $urpm, $xml_info, $o_installed_version) = @_; my %fields = ( info => 'description', files => 'files', changelog => 'changelog', ); # already extracted: return if $pkg->{$fields{$xml_info}}; my $p = $pkg->{pkg}; if (!$p) { warn ">> ghost package '$pkg' has no URPM object!!!\n"; return; } my $name = $p->fullname; # fix extracting info for SRPMS and RPM GPG keys: $name =~ s!\.src!!; if ($p->flag_installed && !$p->flag_upgrade) { my @files = map { MDK::Common::Various::chomp_($_) } run_rpm("rpm -ql $name"); MDK::Common::DataStructure::add2hash($pkg, { files => [ @files ? @files : $loc->N("(none)") ], description => rpm_description(scalar(run_rpm("rpm -q --qf '%{description}' $name"))), changelog => format_changelog_string($o_installed_version, scalar(run_rpm("rpm -q --changelog $name"))) }); } else { my $medium = pkg2medium($p, $urpm); my ($local_source, %xml_info_pkgs, $bar_id); my $_statusbar_clean_guard = MDK::Common::Func::before_leaving { $bar_id and statusbar_msg_remove($bar_id) }; my $dir = urpm::file_from_local_url($medium->{url}); print "p->filename: ". $p->filename."\n"; $local_source = "$dir/" . $p->filename if $dir; print "local_source: " . ($local_source ? $local_source : "") . "\n"; if ($local_source && -e $local_source) { $bar_id = statusbar_msg($loc->N("Getting information from %s...", $dir), 0); $urpm->{log}("getting information from rpms from $dir"); } else { my $gurpm; $bar_id = statusbar_msg($loc->N("Getting '%s' from XML meta-data...", $xml_info), 0); my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; if (my $xml_info_file = eval { urpm::media::any_xml_info($urpm, $medium, $xml_info, undef, sub { $gurpm ||= ManaTools::Rpmdragora::gurpm->new( text => $loc->N("Please wait"), ); download_callback($gurpm, @_) or goto header_non_available; }) }) { require urpm::xml_info; require urpm::xml_info_pkg; $urpm->{log}("getting information from $xml_info_file"); my %nodes = eval { urpm::xml_info::get_nodes($xml_info, $xml_info_file, [ $name ]) }; goto header_non_available if $@; MDK::Common::DataStructure::put_in_hash($xml_info_pkgs{$name} ||= {}, $nodes{$name}); } else { if ($xml_info eq 'info') { $urpm->{info}($loc->N("No xml info for medium \"%s\", only partial result for package %s", $medium->{name}, $name)); } else { $urpm->{error}($loc->N("No xml info for medium \"%s\", unable to return any result for package %s", $medium->{name}, $name)); } } } #- even if non-root, search for a header in the global cachedir if ($local_source && -s $local_source) { $p->update_header($local_source) or do { warn "Warning, could not extract header for $name from $medium!"; goto header_non_available; }; my @files = $p->files; @files = $loc->N("(none)") if !@files; MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($p->description), files => \@files, url => $p->url, changelog => format_changelog_changelogs($o_installed_version, $p->changelogs) }); $p->pack_header; # needed in order to call methods on objects outside ->traverse } elsif ($xml_info_pkgs{$name}) { if ($xml_info eq 'info') { MDK::Common::DataStructure::add2hash($pkg, { description => rpm_description($xml_info_pkgs{$name}{description}), url => $xml_info_pkgs{$name}{url} }); } elsif ($xml_info eq 'files') { my @files = map { MDK::Common::Various::chomp_($loc->to_utf8($_)) } split("\n", $xml_info_pkgs{$name}{files}); MDK::Common::DataStructure::add2hash($pkg, { files => scalar(@files) ? \@files : [ $loc->N("(none)") ] }); } elsif ($xml_info eq 'changelog') { MDK::Common::DataStructure::add2hash($pkg, { changelog => format_changelog_changelogs($o_installed_version, @{$xml_info_pkgs{$name}{changelogs}}) }); } } else { goto header_non_available; } return; header_non_available: MDK::Common::DataStructure::add2hash($pkg, { summary => $p->summary || $loc->N("(Not available)"), description => undef }); } } sub find_installed_version { my ($p) = @_; my $version = $loc->N("(none)"); open_rpm_db()->traverse_tag_find('name', $p->name, sub { $version = $_[0]->EVR; return ($version ? 1 : 0) }) if $p; return $version; } my $canceled; sub download_callback { my ($gurpm, $mode, $file, $percent, $total, $eta, $speed) = @_; $canceled = 0; if ($mode eq 'start') { $gurpm->label($loc->N("Downloading package `%s'...", urpm::util::basename($file))); # $gurpm->validate_cancel(but($loc->N("Cancel")), sub { $canceled = 1 }); } elsif ($mode eq 'progress') { $gurpm->label( join("\n", $loc->N("Downloading package `%s'...", urpm::util::basename($file)), (defined $total && defined $eta ? $loc->N(" %s%% of %s completed, ETA = %s, speed = %s", $percent, $total, $eta, $speed) : $loc->N(" %s%% completed, speed = %s", $percent, $speed) ) =~ /^\s*(.*)/ ), ); #$gurpm->progress($percenti/100); $gurpm->progress(ceil($percent)); } elsif ($mode eq 'end') { $gurpm->progress(100); # $gurpm->invalidate_cancel; } !$canceled; } # -=-=-=---=-=-=---=-=-=-- install packages -=-=-=---=-=-=---=-=-=- my (@update_medias, $is_update_media_already_asked); sub warn_about_media { my ($w, %options) = @_; return 0 if $::MODE ne 'update'; return 0 if $::rpmdragora_options{'no-media-update'}; # we use our own instance of the urpmi db in order not to mess up with skip-list managment (#31092): # and no need to fully configure urpmi since we may have to do it again anyway because of new media: my $urpm = fast_open_urpmi_db(); my $_lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); # build media list: @update_medias = get_update_medias($urpm); # do not update again media after installing/removing some packages: $::rpmdragora_options{'no-media-update'} ||= 1; if (@update_medias > 0) { if (!$options{skip_updating_mu} && !$is_update_media_already_asked) { $is_update_media_already_asked = 1; if (!$::rpmdragora_options{'no-confirmation'}) { my $choice = interactive_msg($loc->N("Confirmation"), $loc->N("I need to contact the mirror to get latest update packages. Please check that your network is currently running. Is it ok to continue?" ), yesno => 1, dont_ask_again => 1, # TODO widget => gtknew('CheckButton', text => $loc->N("Do not ask me next time"), # active_ref => \$::rpmdragora_options{'no-confirmation'} # ) ); $::rpmdragora_options{'no-confirmation'} = $choice->{dont_ask_again}; return(-1) if !$choice->{value}; } writeconf(); urpm::media::select_media($urpm, map { $_->{name} } @update_medias); update_sources($urpm, noclean => 1, medialist => [ map { $_->{name} } @update_medias ]); } } else { if (MDK::Common::Func::any { $_->{update} } @{$urpm->{media}}) { interactive_msg($loc->N("Already existing update media"), $loc->N("You already have at least one update medium configured, but all of them are currently disabled. You should run the Software Media Manager to enable at least one (check it in the \"%s\" column). Then, restart \"%s\".", $loc->N("Enabled"), $ManaTools::rpmdragora::myname_update)); return (-1); } my ($mirror) = choose_mirror($urpm, transient => $w->{real_window} || $::main_window, message => join("\n\n", $loc->N("You have no configured update media. MageiaUpdate cannot operate without any update media."), $loc->N("I need to contact the Mageia website to get the mirror list. Please check that your network is currently running. Is it ok to continue?"), ), ); my $m = ref($mirror) ? $mirror->{url} : ''; $m or interactive_msg($loc->N("How to choose manually your mirror"), $loc->N("You may also choose your desired mirror manually: to do so, launch the Software Media Manager, and then add a `Security updates' medium. Then, restart %s.", $ManaTools::rpmdragora::myname_update)), return (-1); add_distrib_update_media($urpm, $mirror, only_updates => 0); } return 0; } sub get_parallel_group() { $::rpmdragora_options{parallel} ? $::rpmdragora_options{parallel}[0] : undef; } my ($count, $level, $limit, $new_stage, $prev_stage, $total); sub init_progress_bar { my ($urpm) = @_; undef $_ foreach $count, $prev_stage, $new_stage, $limit; $level = 5; $total = @{$urpm->{depslist}}; } sub reset_pbar_count { undef $prev_stage; $count = 0; $limit = $_[0]; } sub update_pbar { my ($gurpm) = @_; return if !$total; # don't die if there's no source $count++; $new_stage = $level+($limit-$level)*$count/$total; $prev_stage = 0 if(!defined($prev_stage)); if ($prev_stage + 1 < $new_stage) { $prev_stage = $new_stage; $gurpm->progress(ceil($new_stage)); } } sub get_installed_packages { my ($urpm, $db, $all_pkgs, $gurpm) = @_; $urpm->{global_config}{'prohibit-remove'} = '' if(!defined($urpm->{global_config}{'prohibit-remove'})); my @base = ("basesystem", split /,\s*/, $urpm->{global_config}{'prohibit-remove'}); my (%base, %basepackages, @installed_pkgs, @processed_base); reset_pbar_count(33); while (defined(local $_ = shift @base)) { exists $basepackages{$_} and next; $db->traverse_tag(m|^/| ? 'path' : 'whatprovides', [ $_ ], sub { update_pbar($gurpm); my $name = $_[0]->fullname; # workaround looping in URPM: return if MDK::Common::DataStructure::member($name, @processed_base); push @processed_base, $name; push @{$basepackages{$_}}, $name; push @base, $_[0]->requires_nosense; }); } foreach (values %basepackages) { my $n = @$_; #- count number of times it's provided foreach (@$_) { $base{$_} = \$n; } } # costly: $db->traverse(sub { my ($pkg) = @_; update_pbar($gurpm); my $fullname = urpm_name($pkg); return if $fullname =~ /@/; $all_pkgs->{$fullname} = { pkg => $pkg, urpm_name => $fullname, } if !($all_pkgs->{$fullname} && $all_pkgs->{$fullname}{description}); if (my $name = $base{$fullname}) { $all_pkgs->{$fullname}{base} = \$name; $pkg->set_flag_base(1) if $$name == 1; } push @installed_pkgs, $fullname; $pkg->set_flag_installed; $pkg->pack_header; # needed in order to call methods on objects outside ->traverse }); @installed_pkgs; } urpm::select::add_packages_to_priority_upgrade_list('rpmdragora', 'perl-Glib', 'perl-Gtk2'); my ($priority_state, $priority_requested); our $need_restart; our $probe_only_for_updates; sub get_updates_list { my ($urpm, $db, $state, $requested, $requested_list, $requested_strict, $all_pkgs, %limit_preselect) = @_; $urpm->request_packages_to_upgrade( $db, $state, $requested, %limit_preselect ); my %common_opts = ( callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, priority_upgrade => $urpm->{options}{'priority-upgrade'} || '', ); if ($urpm->{options}{'priority-upgrade'}) { $need_restart = urpm::select::resolve_priority_upgrades_after_auto_select($urpm, $db, $state, $requested, %common_opts); } # list of updates (including those matching /etc/urpmi/skip.list): @$requested_list = sort map { my $name = urpm_name($_); $all_pkgs->{$name} = { pkg => $_ }; $name; } @{$urpm->{depslist}}[keys %$requested]; # list of pure updates (w/o those matching /etc/urpmi/skip.list but with their deps): if ($probe_only_for_updates && !$need_restart) { @$requested_strict = sort map { urpm_name($_); } $urpm->resolve_requested($db, $state, $requested, callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices); if (my @l = grep { $state->{selected}{$_->id} } urpm::select::_priority_upgrade_pkgs($urpm, $urpm->{options}{'priority-upgrade'})) { if (!$need_restart) { $need_restart = urpm::select::_resolve_priority_upgrades($urpm, $db, $state, $state->{selected}, \@l, %common_opts); } } } if ($need_restart) { $requested_strict = [ map { scalar $_->fullname } @{$urpm->{depslist}}[keys %{$state->{selected}}] ]; # drop non priority updates: @$requested_list = (); } # list updates including skiped ones + their deps in MageiaUpdate: @$requested_list = MDK::Common::DataStructure::uniq(@$requested_list, @$requested_strict); # do not pre select updates in rpmdragora: @$requested_strict = () if !$probe_only_for_updates; } sub get_pkgs { my (%options) = @_; my $w = $::main_window; myexit (-1) if (warn_about_media($w, %options) == -1); my $gurpm = ManaTools::Rpmdragora::gurpm->new( text => $loc->N("Please wait"), ); my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; my $urpm = open_urpmi_db(update => $probe_only_for_updates && !is_it_a_devel_distro()); my $_drop_lock = MDK::Common::Func::before_leaving { undef $urpm->{lock} }; $priority_up_alread_warned = 0; # update media list in case warn_about_media() added some: @update_medias = get_update_medias($urpm); $gurpm->label($loc->N("Reading updates description")); #- parse the description file my $update_descr = urpm::get_updates_description($urpm, @update_medias); $gurpm->progress(100); my $_unused = $loc->N("Please wait, finding available packages..."); # # find out installed packages: init_progress_bar($urpm); $gurpm->label($loc->N("Please wait, listing base packages...")); $gurpm->progress(ceil($level)); my $db = eval { open_rpm_db() }; if (my $err = $@) { interactive_msg($loc->N("Error"), $loc->N("A fatal error occurred: %s.", $err)); return; } my $sig_handler = sub { undef $db; exit 3 }; local $SIG{INT} = $sig_handler; local $SIG{QUIT} = $sig_handler; $gurpm->label($loc->N("Please wait, finding installed packages...")); $level = 33; $gurpm->progress(ceil($level)); reset_pbar_count(66); my (@installed_pkgs, %all_pkgs); if (!$probe_only_for_updates) { @installed_pkgs = get_installed_packages($urpm, $db, \%all_pkgs, $gurpm); } if (my $group = get_parallel_group()) { urpm::media::configure($urpm, parallel => $group); } # find out availlable packages: $urpm->{state} = {}; $gurpm->label($loc->N("Please wait, finding available packages...")); $level = 66; $gurpm->progress(ceil($level)); check_update_media_version($urpm, @update_medias); my $requested = {}; my $state = {}; my (@requested, @requested_strict); if ($compute_updates->[0] || $::MODE eq 'update') { my %filter; if ($options{pure_updates}) { # limit to packages from update-media (dependencies can still come from other media) %filter = (idlist => [ map { $_->{start} .. $_->{end} } @update_medias ]); } get_updates_list($urpm, $db, $state, $requested, \@requested, \@requested_strict, \%all_pkgs, %filter); } if ($need_restart) { $priority_state = $state; $priority_requested = $requested; } else { ($priority_state, $priority_requested) = (); } if (!$probe_only_for_updates) { $urpm->compute_installed_flags($db); # TODO/FIXME: not for updates $urpm->{depslist}[$_]->set_flag_installed foreach keys %$requested; #- pretend it's installed } $urpm->{rpmdragora_state} = $state; #- Don't forget it $level = 70; $gurpm->progress(ceil($level)); my %l; reset_pbar_count(100); foreach my $pkg (@{$urpm->{depslist}}) { update_pbar($gurpm); $pkg->flag_upgrade or next; my $key = $pkg->name . $pkg->arch; $l{$key} = $pkg if !$l{$key} || $l{$key}->compare_pkg($pkg); } my @installable_pkgs = map { my $n = $_->fullname; $all_pkgs{$n} = { pkg => $_ }; $n } values %l; undef %l; my @inactive_backports; my @active_backports; my @backport_medias = get_backport_media($urpm); foreach my $medium (@backport_medias) { update_pbar($gurpm); # The 'searchmedia' flag differentiates inactive backport medias # (because that option was passed to urpm::media::configure to # temporarily enable them) my $backports = $medium->{searchmedia} ? \@inactive_backports : \@active_backports; if (defined($medium->{start}) || defined($medium->{end})) { foreach my $pkg_id ($medium->{start} .. $medium->{end}) { next if !$pkg_id; my $pkg = $urpm->{depslist}[$pkg_id]; $pkg->flag_upgrade or next; my $name = $pkg->fullname; push @$backports, $name; $all_pkgs{$name} = { pkg => $pkg, is_backport => 1 }; } } } my @updates = @requested; # selecting updates by default but skipped ones (MageiaUpdate only): foreach (@requested_strict) { $all_pkgs{$_}{selected} = 1; } # urpmi only care about the first medium where it found the package, # so there's no need to list the same package several time: @installable_pkgs = MDK::Common::DataStructure::uniq(MDK::Common::DataStructure::difference2(\@installable_pkgs, \@updates)); my @meta_pkgs = grep { /^task-|^basesystem/ } keys %all_pkgs; my $pkg_list = File::ShareDir::dist_file(ManaTools::Shared::distName(), 'modules/rpmdragora/gui.lst'); my @gui_pkgs = map { chomp; $_ } MDK::Common::File::cat_($pkg_list); $DB::single = 1; # add meta packages to GUI packages list (which expect basic names not fullnames): push @gui_pkgs, map { (split_fullname($_))[0] } @meta_pkgs; +{ urpm => $urpm, all_pkgs => \%all_pkgs, installed => \@installed_pkgs, installable => \@installable_pkgs, updates => \@updates, meta_pkgs => \@meta_pkgs, gui_pkgs => [ grep { my $p = $all_pkgs{$_}{pkg}; $p && MDK::Common::DataStructure::member(($p->fullname)[0], @gui_pkgs) } keys %all_pkgs ], update_descr => $update_descr, backports => [ @inactive_backports, @active_backports ], inactive_backports => \@inactive_backports }; } sub _display_READMEs_if_needed { my $urpm = shift; return if !$urpm->{readmes}; my %Readmes = %{$urpm->{readmes}}; return if ! scalar keys %Readmes; my $appTitle = yui::YUI::app()->applicationTitle(); ## set new title to get it in dialog yui::YUI::app()->setApplicationTitle($loc->N("Upgrade information")); my $factory = yui::YUI::widgetFactory; ## | [msg-label] | ## | | ## | pkg-list | ## | | ## | info on selected pkg |(1) ## | | ## | [ok] | #### # (1) info on pkg list: # selected package readmi.urpmi my $dialog = $factory->createPopupDialog; my $vbox = $factory->createVBox( $dialog ); my $msgBox = $factory->createLabel($vbox, $loc->N("These packages come with upgrade information"), 1); my $tree = $factory->createTree($vbox, $loc->N("Select a package")); $factory->createVSpacing($vbox, 1); my $infoBox = $factory->createRichText($vbox, "", 0); $tree->setWeight($yui::YD_HORIZ, 2); $infoBox->setWeight($yui::YD_HORIZ, 4); $tree->setWeight($yui::YD_VERT, 10); $infoBox->setWeight($yui::YD_VERT, 10); $factory->createVSpacing($vbox, 1); my $hbox = $factory->createHBox( $vbox ); my $align = $factory->createHCenter($hbox); my $okButton = $factory->createPushButton($align, $loc->N("&Ok")); $okButton->setDefaultButton(1); # adding packages to the list my $itemColl = new yui::YItemCollection; foreach my $f (sort keys %Readmes) { my $item = new yui::YTreeItem ("$Readmes{$f}"); my $child = new yui::YTreeItem ($item, "$f"); $child->DISOWN(); $itemColl->push($item); $item->DISOWN(); } $tree->addItems($itemColl); $tree->setImmediateMode(1); while(1) { my $event = $dialog->waitForEvent(); my $eventType = $event->eventType(); #event type checking if ($eventType == $yui::YEvent::CancelEvent) { last; } elsif ($eventType == $yui::YEvent::WidgetEvent) { ### widget my $widget = $event->widget(); if ($widget == $tree) { my $content = ""; my $item = $tree->selectedItem(); if ($item && !$item->hasChildren()) { my $filename = $tree->currentItem()->label(); $content = scalar MDK::Common::File::cat_($filename); $content = $loc->N("(none)") if !$content; # should not happen ensure_utf8($content); $content =~ s/\n/<br>/g; } $infoBox->setValue($content); } elsif ($widget == $okButton) { last; } } } destroy $dialog; # restore original title yui::YUI::app()->setApplicationTitle($appTitle) if $appTitle; return; } sub perform_parallel_install { my ($urpm, $group, $w, $statusbar_msg_id) = @_; my @pkgs = map { MDK::Common::Func::if_($_->flag_requested, urpm_name($_)) } @{$urpm->{depslist}}; my @error_msgs; my $res = !ManaTools::Shared::RunProgram::run('urpmi', '2>', \@error_msgs, '-v', '--X', '--parallel', $group, @pkgs); if ($res) { $$statusbar_msg_id = statusbar_msg( #$loc->N("Everything installed successfully"), $loc->N("All requested packages were installed successfully."), ); } else { interactive_msg( $loc->N("Problem during installation"), $loc->N("There was a problem during the installation:\n\n%s", join("\n", @error_msgs)), scroll => 1, ); } open_rpm_db('force_sync'); $w->set_sensitive(1); return 0; } sub perform_installation { #- (partially) duplicated from /usr/sbin/urpmi :-( my ($urpm, $pkgs) = @_; my @error_msgs; my $statusbar_msg_id; my $gurpm; local $urpm->{fatal} = sub { my $fatal_msg = $_[1]; printf STDERR "Fatal: %s\n", $fatal_msg; undef $gurpm; interactive_msg($loc->N("Installation failed"), $loc->N("There was a problem during the installation:\n\n%s", $fatal_msg)); goto return_with_exit_code; }; local $urpm->{error} = sub { printf STDERR "Error: %s\n", $_[0]; push @error_msgs, $_[0] }; my $w = $::main_window; #$w->set_sensitive(0); #my $_restore_sensitive = MDK::Common::Func::before_leaving { $w->set_sensitive(1) }; # my $_flush_guard = Gtk2::GUI_Update_Guard->new; if (my $group = get_parallel_group()) { return perform_parallel_install($urpm, $group, $w, \$statusbar_msg_id); } my ($lock, $rpm_lock); if (!$::env) { $lock = urpm::lock::urpmi_db($urpm, undef, wait => $urpm->{options}{wait_lock}); $rpm_lock = urpm::lock::rpm_db($urpm, 'exclusive'); } my $state = $priority_state || $probe_only_for_updates ? { } : $urpm->{rpmdragora_state}; my $bar_id = statusbar_msg($loc->N("Checking validity of requested packages..."), 0); # FIXME: THIS SET flag_requested on all packages!!!! # select packages to install / enssure selected pkg set is consistant: my %saved_flags; my $requested = { map { $saved_flags{$_->id} = $_->flag_requested; $_->id => undef; } grep { $_->flag_selected } @{$urpm->{depslist}} }; # NOTE: original code did not manage priority_upgrade anyway # _priority_upgrade_pkgs needs a string and split gives a warning for an undef value. urpm::select::resolve_dependencies( $urpm, $state, $requested, rpmdb => $::env && "$::env/rpmdb.cz", callback_choices => \&ManaTools::Rpmdragora::gui::callback_choices, priority_upgrade => '', ); statusbar_msg_remove($bar_id); my ($local_sources, $blist) = urpm::get_pkgs::selected2local_and_blists($urpm, $state->{selected}); if (!$local_sources && (!$blist || !@$blist)) { interactive_msg( $loc->N("Unable to get source packages."), $loc->N("Unable to get source packages, sorry. %s", @error_msgs ? $loc->N("\n\nError(s) reported:\n%s", join("\n", @error_msgs)) : ''), scroll => 1, ); goto return_with_exit_code; } my @to_install = @{$urpm->{depslist}}[keys %{$state->{selected}}]; my @pkgs = map { scalar($_->fullname) } sort(grep { $_->flag_selected } @to_install); @{$urpm->{ask_remove}} = sort(urpm::select::removed_packages($urpm->{state})); my @to_remove = map { MDK::Common::Func::if_($pkgs->{$_}{selected} && !$pkgs->{$_}{pkg}->flag_upgrade, $pkgs->{$_}{urpm_name}) } keys %$pkgs; my $r = format_list(map { scalar(urpm::select::translate_why_removed_one($urpm, $urpm->{state}, $_)) } @to_remove); my ($size, $filesize) = $urpm->selected_size_filesize($state); my $install_count = int(@pkgs); my $to_install = $install_count == 0 ? '' : ($priority_state ? '<b>' . $loc->N("Rpmdragora or one of its priority dependencies needs to be updated first. Rpmdragora will then restart.") . '</b>' . "\n\n" : '') . ($loc->P("The following package is going to be installed:", "The following %d packages are going to be installed:", $install_count, $install_count) . "\n\n" . format_list(map { s!.*/!!; $_ } @pkgs)); my $remove_count = scalar(@to_remove); interactive_msg(($to_install ? $loc->N("Confirmation") : $loc->N("Some packages need to be removed")), join("\n\n", ($r ? (!$to_install ? ($loc->P("Remove one package?", "Remove %d packages?", $remove_count, $remove_count), $r) : (($remove_count == 1 ? $loc->N("The following package has to be removed for others to be upgraded:") : $loc->N("The following packages have to be removed for others to be upgraded:")), $r), MDK::Common::Func::if_($to_install, $to_install)) : $to_install), format_size($size), format_filesize($filesize), $loc->N("Is it ok to continue?")), scroll => 1, yesno => 1, min_size => {lines => 18},) or return 1; my $_umount_guard = MDK::Common::Func::before_leaving { urpm::removable::try_umounting_removables($urpm) }; # select packages to uninstall for !update mode: perform_removal($urpm, { map { $_ => $pkgs->{$_} } @to_remove }) if !$probe_only_for_updates; $gurpm = ManaTools::Rpmdragora::gurpm->new( text => $loc->N("Please wait"), title => $loc->N("Initializing..."), ); # my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; my $something_installed; if (@to_install && $::rpmdragora_options{auto_orphans}) { urpm::orphans::compute_future_unrequested_orphans($urpm, $state); if (my @orphans = map { scalar $_->fullname } @{$state->{orphans_to_remove}}) { interactive_msg($loc->N("Orphan packages"), $loc->P("The following orphan package will be removed.", "The following orphan packages will be removed.", scalar(@orphans)) . "\n" . urpm::orphans::add_leading_spaces(join("\n", @orphans) . "\n"), scroll => 1); } } urpm::orphans::mark_as_requested($urpm, $state, 0); my ($progress, $total, @rpms_upgrade); my $transaction; my ($progress_nb, $transaction_progress_nb, $remaining, $done) = (0, 0, 0 ,0); my $callback_inst = sub { my ($urpm, $type, $id, $subtype, $amount, $total) = @_; my $pkg = defined $id ? $urpm->{depslist}[$id] : undef; if ($subtype eq 'start') { if ($type eq 'trans') { print($loc->N("Preparing package installation...") . "\n"); $gurpm->label($loc->N("Preparing package installation...")); } elsif (defined $pkg) { $something_installed = 1; $gurpm->label($loc->N("Installing package `%s' (%d/%d)...", $pkg->name, ++$transaction_progress_nb, scalar(@{$transaction->{upgrade}})) . "\n" . $loc->N("Total: %d/%d", ++$progress_nb, $install_count)); print($loc->N("Installing package `%s' (%d/%d)...", $pkg->name, $transaction_progress_nb, scalar(@{$transaction->{upgrade}})) . "\n" . $loc->N("Total: %d/%d", $progress_nb, $install_count) . "\n"); } } elsif ($subtype eq 'progress') { $gurpm->progress($total ? ceil(($amount/$total)*100) : 100); # print("Progress: ".($total ? ($amount/$total)*100 : 100)."\n"); } }; # FIXME: sometimes state is lost: my @ask_unselect = urpm::select::unselected_packages($state); # fix flags for orphan computing: foreach (keys %{$state->{selected}}) { my $pkg = $urpm->{depslist}[$_]; $pkg->set_flag_requested($saved_flags{$pkg->id}); } my $exit_code = urpm::main_loop::run($urpm, $state, 1, \@ask_unselect, { completed => sub { # explicitly destroy the progress window when it's over; we may # have sg to display before returning (errors, rpmnew/rpmsave, ...): undef $gurpm; undef $lock; undef $rpm_lock; }, inst => $callback_inst, trans => $callback_inst, ask_yes_or_no => sub { # handle 'allow-force' and 'allow-nodeps' options: my ($title, $msg) = @_; local $::main_window = $gurpm->{real_window}; interactive_msg($title, $msg, yesno => 1, scroll => 1, ); }, message => sub { my ($title, $message) = @_; interactive_msg($title, $message, scroll => 1); }, # cancel installation when 'cancel' button is pressed: trans_log => sub { download_callback($gurpm, @_) or goto return_with_exit_code }, post_extract => sub { my ($set, $transaction_sources, $transaction_sources_install) = @_; $transaction = $set; $transaction_progress_nb = 0; $done += grep { !/\.src\.rpm$/ } values %$transaction_sources; #updates $total = keys(%$transaction_sources_install) + keys %$transaction_sources; push @rpms_upgrade, keys %$transaction_sources; $done += grep { !/\.src\.rpm$/ } values %$transaction_sources_install; # installs }, pre_removable => sub { # Gtk2::GUI_Update_Guard->new use of alarm() kill us when # running system(), thus making DVD being ejected and printing # wrong error messages (#30463) local $SIG{ALRM} = sub { die "ALARM" }; $remaining = alarm(0); }, post_removable => sub { alarm $remaining }, copy_removable => sub { my ($medium) = @_; interactive_msg( $loc->N("Change medium"), $loc->N("Please insert the medium named \"%s\"", $medium), yesno => 1, text => { no => $loc->N("Cancel"), yes => $loc->N("Ok") }, ); }, pre_check_sig => sub { $gurpm->label($loc->N("Verifying package signatures...")) }, check_sig => sub { $gurpm->progress(ceil(++$progress/$total)*100) }, bad_signature => sub { my ($msg, $msg2) = @_; local $::main_window = $gurpm->{real_window}; $msg =~ s/:$/\n\n/m; # FIXME: to be fixed in urpmi after 2008.0 interactive_msg( $loc->N("Warning"), "$msg\n\n$msg2", yesno => 1, MDK::Common::Func::if_(10 < ($msg =~ tr/\n/\n/), scroll => 1), ); }, post_download => sub { $canceled and goto return_with_exit_code; # $gurpm->invalidate_cancel_forever; }, need_restart => sub { my ($need_restart_formatted) = @_; # FIXME: offer to restart the system interactive_msg($loc->N("Warning"), join("\n", values %$need_restart_formatted), scroll => 1); }, trans_error_summary => sub { my ($nok, $errors) = @_; interactive_msg( $loc->N("Problem during installation"), MDK::Common::Func::if_($nok, $loc->N("%d installation transactions failed", $nok) . "\n\n") . $loc->N("There was a problem during the installation:\n\n%s", join("\n\n", @$errors, @error_msgs)), scroll => 1, ); }, need_restart => sub { my ($need_restart_formatted) = @_; interactive_msg($loc->N("Warning"), join("\n\n", values %$need_restart_formatted)); }, success_summary => sub { if (!($done || @to_remove)) { interactive_msg($loc->N("Error"), $loc->N("Unrecoverable error: no package found for installation, sorry.")); return; } my $id = statusbar_msg($loc->N("Inspecting configuration files..."), 0); my %pkg2rpmnew; foreach my $id (@rpms_upgrade) { my $pkg = $urpm->{depslist}[$id]; next if $pkg->arch eq 'src'; $pkg2rpmnew{$pkg->fullname} = [ grep { (-r "$_.rpmnew" || -r "$_.rpmsave") && !ignore_rpmnew($_) } $pkg->conf_files ]; } statusbar_msg_remove($id); rpmnew_dialog($loc->N("The installation is finished; everything was installed correctly. Some configuration files were created as `.rpmnew' or `.rpmsave', you may now inspect some in order to take actions:"), %pkg2rpmnew) and statusbar_msg($loc->N("All requested packages were installed successfully."), 1); statusbar_msg($loc->N("Looking for \"README\" files..."), 1); _display_READMEs_if_needed($urpm); }, already_installed_or_not_installable => sub { my ($msg1, $msg2) = @_; my $msg = join("\n", @$msg1, @$msg2); return if !$msg; # workaround missing state interactive_msg($loc->N("Error"), $msg); }, }, ); #- restart rpmdragora if needed, keep command line for that. if ($need_restart && !$exit_code) { Sys::Syslog::syslog('info|local1', "restarting rpmdragora"); #- it seems to work correctly with exec instead of system, provided we stop timers #- added --previous-priority-upgrade to allow checking if yet if #- priority-upgrade list has changed. and make sure we don't uselessly restart my @argv = ('--previous-priority-upgrade=' . $urpm->{options}{'priority-upgrade'}, grep { !/^--no-priority-upgrade$|--previous-priority-upgrade=/ } @ManaTools::Rpmdragora::init::ARGV_copy); # remove "--emmbedded <id>" from argv: my $i = 0; foreach (@argv) { splice @argv, $i, 2 if /^--embedded$/; $i++; } alarm(0); # reMDK::Common::DataStructure::member not to ask again questions and the like: writeconf(); my $err = yui::YUI::app()->runInTerminal(join(" ", $0, @argv, " --ncurses")); if ($err == -1) { exec($0, @argv); } destroy $::main_window if $::main_window; exit(0); } my $_s1 = $loc->N("RPM transaction %d/%d", 0, 0); my $_s2 = $loc->N("Unselect all"); my $_s3 = $loc->N("Details"); statusbar_msg_remove($statusbar_msg_id); #- XXX maybe remove this if ($exit_code == 0 && !$::rpmdragora_options{auto_orphans}) { if (urpm::orphans::check_unrequested_orphans_after_auto_select($urpm)) { if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { interactive_msg($loc->N("Orphan packages"), $msg, scroll => 1); } } } return_with_exit_code: return !($something_installed || scalar(@to_remove)); } # -=-=-=---=-=-=---=-=-=-- remove packages -=-=-=---=-=-=---=-=-=- sub perform_removal { my ($urpm, $pkgs) = @_; my @toremove = map { MDK::Common::Func::if_($pkgs->{$_}{selected}, $pkgs->{$_}{urpm_name}) } keys %$pkgs; return if !@toremove; my $gurpm = ManaTools::Rpmdragora::gurpm->new( text => $loc->N("Please wait") ); my $_gurpm_clean_guard = MDK::Common::Func::before_leaving { undef $gurpm }; my $may_be_orphans = 1; urpm::orphans::unrequested_orphans_after_remove($urpm, \@toremove) or $may_be_orphans = 0; my $progress = -1; local $urpm->{log} = sub { my $str = $_[0]; print $str; $progress++; return if $progress <= 0; # skip first "creating transaction..." message $gurpm->label($str); # display "removing package %s" $gurpm->progress(ceil(min(99, scalar($progress/@toremove)*100))); #gtkflush(); }; my @results; slow_func_statusbar( $loc->N("Please wait, removing packages..."), $::main_window, sub { @results = $::rpmdragora_options{parallel} ? urpm::parallel::remove($urpm, \@toremove) : urpm::install::install($urpm, \@toremove, {}, {}, callback_report_uninst => sub { $gurpm->label($_[0]) }, ); open_rpm_db('force_sync'); }, ); if (@results) { interactive_msg( $loc->N("Problem during removal"), $loc->N("There was a problem during the removal of packages:\n\n%s", join("\n", @results)), MDK::Common::Func::if_(@results > 1, scroll => 1), ); return 1; } else { if ($may_be_orphans && !$::rpmdragora_options{auto_orphans}) { if (my $msg = urpm::orphans::get_now_orphans_gui_msg($urpm)) { interactive_msg($loc->N("Information"), $msg, scroll => 1); } } return 0; } } 1;