home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
clients
/
update_proposal.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
14KB
|
480 lines
/**
* Module: update_proposal.ycp
*
* Author: Arvin Schnell <arvin@suse.de>
*
* Purpose: Let user choose update settings.
*
* $Id: update_proposal.ycp 34238 2006-11-10 09:18:34Z locilka $
*/
{
textdomain "update";
import "HTML";
import "Update";
import "Packages";
import "PackageCallbacks";
import "SpaceCalculation";
import "Installation";
import "Kernel";
import "Popup";
import "ProductFeatures";
import "Product";
import "FileUtils";
import "Label";
string func = (string) WFM::Args(0);
map param = (map) WFM::Args(1);
map <string, any> ret = $[];
boolean rpm_db_existency_checked_already = false;
// bugzilla #148105
// Check the current RPM Database if exists
//
// RPM DB found -> return true
// RPM DB not found & skipped -> return true
// RPM DB not found & aborted -> return false
//
boolean CheckRPMDBforExistency () {
y2milestone ("Checking the current RPM Database in '%1'...", Installation::destdir);
// at least one must be there, the second one is for RPM v3
list <string> rpm_db_files = [ "/var/lib/rpm/Packages", "/var/lib/rpm/packages.rpm" ];
boolean ret = false;
boolean file_found_or_error_skipped = false;
while (! file_found_or_error_skipped) {
foreach (string check_file, rpm_db_files, {
if (Installation::destdir != "/")
check_file = sformat("%1%2", Installation::destdir, check_file);
if (FileUtils::Exists (check_file)) {
y2milestone ("RPM Database '%1' found", check_file);
ret = true;
file_found_or_error_skipped = true;
break;
}
});
// file not found
if (! ret) {
y2error ("None of files %1 exist in '%2'",
rpm_db_files, Installation::destdir
);
string missing_files = "";
foreach (string check_file, rpm_db_files, {
if (Installation::destdir != "/")
check_file = sformat("%1%2", Installation::destdir, check_file);
missing_files = missing_files + "\n" + check_file;
});
UI::OpenDialog (
`opt(`decorated),
`VBox (
// popup error
`Label (
// part of error popup message
_("Cannot read the current RPM Database.") + "\n\n" +
// part of error popup message, %1 stands for newline-separated list of files
sformat (_("None of these files exist:%1"), missing_files) + "\n\n"
),
`HBox (
`PushButton (`id(`abort), Label::AbortButton()),
`PushButton (`id(`retry), Label::RetryButton())
// disabled button - bugzilla #148105, comments #22 - #28
// `PushButton (`id(`ignore), Label::IgnoreButton())
)
)
);
any ui_r = UI::UserInput();
if (ui_r == `cancel || ui_r == `abort) {
ret = false;
file_found_or_error_skipped = true;
y2milestone ("Check failed, returning error.");
} else if (ui_r == `retry) {
file_found_or_error_skipped = false;
y2milestone ("Trying again...");
//} else if (ui_r == `ignore) {
// ret = true;
// file_found_or_error_skipped = true;
// y2warning ("Skipping missing RPM Database, problems might occur...");
} else {
file_found_or_error_skipped = false;
y2error ("Unexpected return: %1", ui_r);
}
UI::CloseDialog();
}
}
y2milestone ("CheckRPMDBforExistency - returning: %1", ret);
return ret;
}
define void SelectKernelPackages () {
list <list> provides = Pkg::PkgQueryProvides ("kernel");
y2milestone ("provides: %1", provides);
list <list> kernels = filter (list l, provides, {
return l[1]:`NONE == `BOTH || l[1]:`NONE == l[2]:`NONE;
});
if (size (kernels) != 1)
y2error ("not exactly one package provides tag kernel");
string selected_kernel = kernels[0,0]:"none";
list<string> recom_kernel = Kernel::ComputePackages ();
y2milestone ("Selected kernel: %1, recommended kernel: %2",
selected_kernel, recom_kernel);
list<string> kernel_packs = Kernel::ComputePackages ();
boolean kernel_refresh_needed = false;
foreach (string p, kernel_packs, {
if (! Pkg::IsProvided (p))
{
kernel_refresh_needed = true;
y2milestone ("Package %1 is not installed - forcing kernel update", p);
}
});
if (kernel_refresh_needed)
{
foreach (string p, kernel_packs, {
Pkg::PkgInstall (p);
});
}
}
define void init_stuff ()
{
// initialize package manager
if (true)
{
UI::OpenDialog (`opt(`decorated),
// intermediate popup while initializing internal packagemanagement
`Label(_("Reading package information. One moment please...")));
Packages::Init (true);
UI::CloseDialog();
}
// initialize target
if (true)
{
PackageCallbacks::SetConvertDBCallbacks ();
Pkg::TargetInit (Installation::destdir, false);
Update::GetProductName ();
}
// connect target with package manager
if (!Update::did_init1)
{
Update::did_init1 = true;
if (size (Pkg::ResolvableProperties ("", `pattern, "")) > 0)
{
y2milestone ("No base selection found, but patterns found...");
Packages::using_patterns = true;
}
list<string> restore = [];
list<map<string,any> > selected = Pkg::ResolvableProperties ("", `product, "");
foreach (map<string,any> s, selected, {
restore = add (restore, s["name"]:"");
});
Pkg::PkgApplReset ();
foreach (string res, restore, {
Pkg::ResolvableInstall (res, `product);
});
if (! Update::onlyUpdateInstalled)
{
if (Packages::using_patterns)
{
Update::SetDesktopPattern ();
}
else
{
Update::ProposeSelection ();
}
}
if (Update::onlyUpdateInstalled) // just consider already installed packages
{
Pkg::SetSelection (""); // -> don't select any additional selections
}
else if (Packages::using_patterns)
{
if (! ProductFeatures::GetBooleanFeature ("software",
"only_update_installed"))
{
foreach (string pat, Product::patterns, {
y2milestone("Pre-select pattern %1", pat);
Pkg::ResolvableInstall( pat, `pattern );
});
}
}
else // update selections too
{
Pkg::SetSelection (Update::selected_selection); // -> set the base selection (minimal, default, ....)
if (!Update::manual_interaction)
{
// now compare installed (old) selections against available (new) selections
// and set all selections which are installed (old) and available (new)
// as 'to be installed' -> UI will show "to be updated" for these selections
list<string> available_addons = Pkg::GetSelections (`available, "");
list<string> installed_addons = Pkg::GetSelections (`installed, "");
foreach (string installed, installed_addons,
{
if (contains (available_addons, installed)) // we have a newer selection for an installed one
{
Pkg::SetSelection (installed); // update this selection too (selection solving included)
}
});
}
}
Packages::SelectProduct();
Pkg::ActivateSelections (); // now go through all selected selections and select their packages
map<symbol, integer> update_sum
= Pkg::PkgUpdateAll (Update::deleteOldPackages);
y2milestone ("Update summary: %1", update_sum);
Update::unknown_packages = update_sum[`ProblemListSze]:0;
SelectKernelPackages ();
list<string> sys_patterns = Packages::ComputeSystemPatternList ();
foreach (string pat, sys_patterns, {
Pkg::ResolvableInstall (pat, `pattern);
});
if (Pkg::PkgSolve (!Update::onlyUpdateInstalled))
Update::solve_errors = 0;
else
Update::solve_errors = Pkg::PkgSolveErrors ();
}
// check product compatibility
if (! (Update::ProductsCompatible () || Update::products_incompatible))
{
if (Popup::ContinueCancel (
// continue-cancel popup
_("The installed product is not compatible with the product
on the installation media. If you try to update using the
current installation media, the system may not start or
some applications may not run properly.")))
{
Update::IgnoreProductCompatibility ();
}
else
{
Update::products_incompatible = true;
}
}
// Pkg::GetPackages()
// `installed all installed packages
// `selected returns all selected but not yet installed packages
// `available returns all available packages (from the installation source)
// `removed all packages selected for removal
// recreate the update summary
list<string> installed = Pkg::GetPackages (`installed, true);
list<string> selected = Pkg::GetPackages (`selected, true);
list<string> removed = Pkg::GetPackages (`removed, true);
integer cnt_installed = size (installed);
integer cnt_selected = size (selected);
integer cnt_removed = size (removed);
y2milestone ("Selected: %1, Installed: %2, Removed: %3", cnt_selected, cnt_installed, cnt_removed);
y2milestone("Removed: %1", removed);
map<string,boolean> installed_m = listmap (string p, installed, {
return $[ p : true ];
});
map<string,boolean> selected_m = listmap (string p, selected, {
return $[ p : true ];
});
// packages that are both 'installed' && 'selected'
Update::packages_to_update = size (filter (string p, selected, {
return haskey (installed_m, p);
}));
// packages that are 'selected' but not 'installed'
Update::packages_to_install = cnt_selected - Update::packages_to_update;
// packages that are 'removed' but not 'selected again'
Update::packages_to_remove = size (filter (string p, removed, {
return ! haskey (selected_m, p);
}));
y2milestone("Update statistics: Updated: %1, Installed: %2, Removed: %3",
Update::packages_to_update, Update::packages_to_install, Update::packages_to_remove);
}
if ( func == "MakeProposal" )
{
boolean force_reset = param["force_reset" ]:false;
boolean language_changed = param["language_changed"]:false;
// call some function that makes a proposal here:
//
// DummyMod::MakeProposal( force_reset );
if (force_reset)
{
Update::Reset ();
Packages::Reset ([`product]);
Update::did_init1 = false;
rpm_db_existency_checked_already = false;
}
// bugzilla #148105
if (! rpm_db_existency_checked_already) {
rpm_db_existency_checked_already = true;
// if it doesn't exist, user can still confirm to continue
// packager will then suggest some set of packages
if (! CheckRPMDBforExistency()) {
return $[
// error message in proposal
"warning" : _("Cannot read the current RPM Database."),
"warning_level" : `fatal,
"raw_proposal" : [],
];
}
}
// Fill return map
init_stuff ();
if (Update::products_incompatible)
{
return $[
// error message in proposal
"warning" : _("The installed product is not compatible with the product on the installatin media."),
"warning_level" : `fatal,
"raw_proposal" : [],
];
}
if (true)
{
list available_base_selections = Update::GetBaseSelections ();
if ((! Packages::using_patterns) && size (available_base_selections) == 0)
{
y2error ("No base selections available");
// Can't find any software data, probably a installation media error
// error message
return $[ "warning" : _("Cannot read package data from installation media. Media error?"),
"warning_level" : `blocker,
"raw_proposal" : [] ];
}
}
if (Update::disallow_upgrade)
{
if (false) // FIXME
{
// proposal error
return $[ "warning" : _("Updating to another version is not supported from the running system."),
"warning_level" : `fatal,
"raw_proposal" : [] ];
}
}
list<string> tmp = [];
tmp = Update::SelectedProducts ();
// summary text (%1 is package selection)
// tmp = add (tmp, sformat (_("Update to %1"), Update::updateVersion["nameandversion"]:"?"));
if (Update::onlyUpdateInstalled)
{
// Proposal for backup during update
tmp = add (tmp, _("Only Update Installed Packages"));
}
else
{
if (Packages::using_patterns)
{
list<map<string,any> > patterns = Pkg::ResolvableProperties ("", `pattern, "");
patterns = filter (map<string,any> p, patterns, {
return p["status"]:nil == `selected && p["user_visible"]:true && p["summary"]:p["name"]:"" != "";
});
// proposal string
tmp = add (tmp, _("Update Based on Patterns"));
foreach (map<string,any> p, patterns, {
tmp = add (tmp, "+ " + p["summary"]:p["name"]:"");
});
}
else
{
map selection_data = Pkg::SelectionData (Update::selected_selection);
string selection_summary = selection_data["summary"]:"error";
// Proposal for selection during update
tmp = add (tmp, sformat (_("Update Based on Selection \"%1\""),
selection_summary));
}
}
// recalculate the disk space usage data
SpaceCalculation::GetPartitionInfo();
if (Update::deleteOldPackages)
{
// Proposal for backup during update
tmp = add (tmp, _("Delete Old Packages"));
}
ret = $[ "preformatted_proposal" :
HTML::List (tmp)
];
}
else if ( func == "AskUser" )
{
boolean has_next = param["has_next"]:false;
// call some function that displays a user dialog
// or a sequence of dialogs here:
//
// sequence = DummyMod::AskUser( has_next );
symbol result = (symbol) WFM::CallFunction ("inst_update", [true, has_next]);
if (result == `next)
{
Update::did_init1 = false;
}
// Fill return map
ret = $[ "workflow_sequence" : result ];
}
else if ( func == "Description" )
{
// Fill return map.
//
// Static values do just nicely here, no need to call a function.
ret =
$[
// this is a heading
"rich_text_title" : _("Update Options"),
// this is a menu entry
"menu_title" : _("&Update Options"),
"id" : "update_stuff"
];
}
return ret;
}