home *** CD-ROM | disk | FTP | other *** search
- /**
- * 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;
- }
-