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 / modules / Packages.ycp < prev    next >
Text File  |  2006-11-29  |  39KB  |  1,350 lines

  1. /**
  2.  * File:    Packages.ycp
  3.  * Package:    Package selections
  4.  * Authors:    Anas Nashif <nashif@suse.de>
  5.  *
  6.  * $Id: Packages.ycp 34552 2006-11-22 08:26:03Z lslezak $
  7.  */
  8.  
  9. {
  10.  
  11. module "Packages";
  12.  
  13. textdomain "packager";
  14.  
  15. import "AddOnProduct";
  16. import "Arch";
  17. import "Directory";
  18. import "InstURL";
  19. import "Kernel";
  20. import "Mode";
  21. import "Stage";
  22. import "Linuxrc";
  23. import "Language";
  24. import "ProductFeatures";
  25. import "ProductControl";
  26. import "Report";
  27. import "SlideShow";
  28. import "SpaceCalculation";
  29. import "String";
  30. import "Popup";
  31. import "Label";
  32. import "Wizard";
  33. import "DirInstall";
  34. import "PackageCallbacksInit";
  35. import "Product";
  36. import "DefaultDesktop";
  37. import "SourceDialogs";
  38.  
  39. /**
  40.  * Force full proposal routine next run
  41.  */
  42. boolean full_repropose = false;
  43.  
  44. /**
  45.  * Installation source has been initialized?
  46.  */
  47. boolean init_called = false;
  48.  
  49. /**
  50.  * Installation source initialization is WIP
  51.  */
  52. boolean init_in_progress = false;
  53.  
  54. /**
  55.  * Error which occurred during installation source initialization
  56.  */
  57. string init_error = nil;
  58.  
  59. // cache for the proposed summary
  60. map cached_proposal = nil;
  61. // the selection used for the cached proposal
  62. list<string> cached_proposal_packages = [];
  63. list<map> cached_proposal_patterns = [];
  64. list<map> cached_proposal_products = [];
  65. list<map> cached_proposal_patches = [];
  66. list<map> cached_proposal_selections = [];
  67. list<string> cached_proposal_languages = [];
  68.  
  69.     global boolean install_sources = false;    // Installing source packages ?
  70.     global integer timestamp = 0;        // last time of getting the target map
  71.  
  72.     global string metadir = "/yast-install";
  73.     global boolean metadir_used = false;    // true if meta data and inst-sys is in ramdisk
  74.  
  75.     global list<integer> theSources = [];        // id codes of sources in priority order
  76.     global list<string> theSourceDirectories = [];    // product directories on sources
  77.     global map<integer,integer> theSourceOrder = $[];    // installation order
  78.  
  79.     string servicepack_metadata = "/servicepack.tar.gz";
  80.  
  81.     // to remember if warning should occurre if switching base selection
  82.     global boolean base_selection_modified = false;
  83.  
  84.     global boolean base_selection_changed = false;
  85.  
  86.     // Local variables
  87.  
  88.  
  89.     string choosen_base_selection = "";
  90.  
  91.     // count of errors during packages solver
  92.     global integer solve_errors = 0;
  93.  
  94.     /**
  95.      * Packages to be selected when proposing the list
  96.      */
  97.     list<string> additional_packages = [];
  98.  
  99.     boolean system_packages_selected = false;
  100.  
  101. // DefaultDesktop::PrefferedWindowManager
  102. //    global string window_manager = nil;
  103.  
  104.     global boolean using_patterns = false;
  105.  
  106.     global string add_on_products_list = nil;
  107.  
  108.  
  109. // summary functions
  110.  
  111. /**
  112.  * List selected resolvables of specified kind
  113.  * @param what symbol specifying the kind of resolvables to select
  114.  * @param format string format string to print summaries in
  115.  * @return a list of selected resolvables
  116.  */
  117. global list<string> ListSelected (symbol what, string format) {
  118.     if (format == "" || format == nil)
  119.     format = "%1";
  120.     list<map<string,any> > selected = Pkg::ResolvableProperties ("", what, "");
  121.  
  122.     // ignore hidden patterns
  123.     if (what == `pattern)
  124.     {
  125.     selected = filter (map<string,any> r, selected, {
  126.         return r["user_visible"]:nil == true;
  127.     });
  128.     }
  129.  
  130.     selected = filter (map<string,any> r, selected, {
  131.     return r["status"]:nil == `selected;
  132.     });
  133.     list<string> ret = maplist (map<string,any> r, selected, {
  134.     string disp = r["summary"]:r["name"]:"";
  135.     return sformat (format, disp);
  136.     });
  137.     return ret;
  138. }
  139.  
  140. /**
  141.  * Count the total size of packages to be installed
  142.  * @return string formatted size of packages to be installed
  143.  */
  144. global string CountSizeToBeInstalled () {
  145.     integer sz = 0;
  146.     if (! Mode::installation () && !DirInstall::installing_into_dir )
  147.     {
  148.     list<string> packages = Pkg::GetPackages (`selected, true);
  149.     foreach (string p, packages, {
  150.         sz = sz + Pkg::PkgSize (p);
  151.     });
  152.     // convert into kB
  153.     sz = sz / 1024;
  154.     }
  155.     else // in case of fresh installation, disk is initially empty
  156.     {
  157.     map<string,list> du = Pkg::TargetGetDU ();
  158.     foreach (string mp, list usages, du, {
  159.         sz = sz + usages[2]:0 - usages[1]:0;
  160.     });
  161.     }
  162.     y2milestone ("Total size of packages to install (kB): %1", sz);
  163.     return String::FormatSizeWithPrecision (sz*1024, 1, true);
  164. }
  165.  
  166. /**
  167.  * Return information about suboptimal distribution if relevant
  168.  * @return string the information string or empty string
  169.  */
  170. global string InfoAboutSubOptimalDistribution () {
  171.     // warn about suboptimal distribution
  172.     // this depends on the kernel
  173.     string dp = (string) SCR::Read(.content.DISTPRODUCT);
  174.     if (dp==nil)
  175.     dp = "";
  176.  
  177.     if (ProductFeatures::GetBooleanFeature ("software",
  178.     "inform_about_suboptimal_distribution") &&
  179.     Arch::i386 () && issubstring(dp, "DVD"))
  180.     {
  181.     string tmp = (string) SCR::Read(.proc.cpuinfo.value."0"."flags");
  182.     list flags = (size (tmp) > 0) ? splitstring (tmp, " ") : [];
  183.  
  184.     // this depends on the cpu (lm = long mode)
  185.     if (contains (flags, "lm"))
  186.     {
  187.         // warning text
  188.         return _("Your computer is a 64-bit x86-64 system. However, you are trying to install a 32-bit distribution.");
  189.     }
  190.     }
  191.     return "";
  192. }
  193.  
  194. /**
  195.  * Return the summary output lines
  196.  * @param flags a list of flags, allowed are `product, `pattern, `selection,
  197.  *  `size, `desktop
  198.  * @return a list of the output lines
  199.  */
  200. global list<string> SummaryOutput (list<symbol> flags) {
  201.     list<string> output = [ InfoAboutSubOptimalDistribution () ];
  202.     if (contains (flags, `product))
  203.     output = (list<string>)merge (output, ListSelected (`product, ""));
  204.     if (contains (flags, `desktop))
  205.     output = (list<string>)add (output, DefaultDesktop::Description ());
  206.     if (contains (flags, `pattern))
  207.     output = (list<string>)
  208.         merge (output, ListSelected (`pattern, "+  %1"));
  209.     if (contains (flags, `selection))
  210.     output = (list<string>)
  211.         merge (output, ListSelected (`selection, "+  %1"));
  212.     if (contains (flags, `size))
  213.     output = (list<string>)add (output,
  214.         // part of summary, %1 is size of packages (in MB or GB)
  215.         sformat (_("Size of Packages to Install: %1"),
  216.         CountSizeToBeInstalled ()));
  217.  
  218.     output = filter (string o, output, {
  219.     return o != "" && o != nil;
  220.     });
  221.  
  222.     return output;
  223. }
  224.  
  225. /**
  226.  * Check if selected software fits on the partitions
  227.  * @param init boolean true if partition sizes have changed
  228.  * @return boolean true if selected software fits, false otherwise
  229.  */
  230. global boolean CheckDiskSize (boolean init) {
  231.     if (init)
  232.     {
  233.     y2milestone ("Resetting space calculation");
  234.     SpaceCalculation::GetPartitionInfo();
  235.     }
  236.     return SpaceCalculation::CheckDiskSize();
  237. }
  238.  
  239. /**
  240.  * Print the installatino proposal summary
  241.  * @param flags a list of symbols, see above
  242.  * @param boolean use_cache if true, use previous proposal if possible
  243.  * @returnu a map proposal summary
  244.  */
  245. global map Summary (list<symbol> flags, boolean use_cache) {
  246.     if (init_error != nil)
  247.     {
  248.     return $[
  249.         "warning" : init_error,
  250.         "warning_level" : `blocker,
  251.     ];
  252.     }
  253.     map ret = $[];
  254.  
  255.     if (! CheckDiskSize (! use_cache))
  256.     {
  257.     ret = $[
  258.         "warning" : ProductFeatures::GetFeature ("software","selection_type") == `fixed
  259.         // summary warning
  260.         ? _("Not enough disk space.")
  261.         // summary warning
  262.         : _("Not enough disk space. Remove some packages in the single selection."),
  263.         "warning_level" : Mode::update() ? `warning : `blocker,
  264.     ];
  265.     }
  266.     else
  267.     {
  268.     // check available free space (less than 5% and less than 1GB)
  269.     list<map> free_space = SpaceCalculation::CheckDiskFreeSpace(5, 1024*1024);
  270.  
  271.     if (size(free_space) > 0)
  272.     {
  273.         string warning = "";
  274.  
  275.         foreach(map df, free_space,
  276.         {
  277.             string partition = df["dir"]:"";
  278.             integer free_pct = df["free_percent"]:0;
  279.             integer free_kB = df["free_size"]:0;
  280.  
  281.             string w = sformat(_("Only %1 (%2%%) free space available on partition %3.<BR>"), String::FormatSize(free_kB*1024), free_pct, partition);
  282.  
  283.             warning = warning + w;
  284.         }
  285.         );
  286.  
  287.         if (warning != "")
  288.         {
  289.         ret["warning"] = warning;
  290.         ret["warning_level"] = `warning;
  291.         }
  292.     }
  293.     }
  294.  
  295.     ret["raw_proposal"] = SummaryOutput (flags);
  296.     return ret;
  297. }
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304. // proposal control functions
  305.  
  306. global void ForceFullRepropose () {
  307.     full_repropose = true;
  308. }
  309.  
  310. global boolean SelectProduct ();
  311.  
  312. /**
  313.  * Reset package selection, but keep objects of specified type
  314.  * @param keep a list of symbols specifying type of objects to be kept
  315.  */
  316. global void Reset (list<symbol> keep) {
  317.     list<map<string,any> > restore = [];
  318.     foreach (symbol type, keep, {
  319.     list<map<string,any> > selected = Pkg::ResolvableProperties ("", type, "");
  320.     foreach (map<string,any> s, selected, {
  321.         restore = add (restore, $[
  322.         "type" : type,
  323.         "name" : s["name"]:""
  324.         ]);
  325.     });
  326.     });
  327.     Pkg::PkgReset();
  328.     foreach (map<string,any> res, restore, {
  329.     Pkg::ResolvableInstall (res["name"]:"", (symbol)(res["type"]:nil));
  330.     });
  331.  
  332.     system_packages_selected = false;
  333. }
  334.  
  335. /**
  336.  * Initialize add-on products provided by the installation source
  337.  */
  338. global void InitializeAddOnProducts() {
  339.     if (Packages::add_on_products_list != nil)
  340.     {
  341.     y2milestone ("Found list of add-on products to preselect: %1", Packages::add_on_products_list);
  342.     Packages::SelectProduct ();
  343.     PackageCallbacksInit::SetMediaCallbacks();
  344.     AddOnProduct::AddPreselectedAddOnProducts (Packages::add_on_products_list);
  345.     Packages::add_on_products_list = nil; // do not select them any more
  346.     }
  347. }
  348.  
  349.  
  350.     /*-----------------------------------------------------------------------
  351.      * LOCALE FUNCTIONS
  352.      *-----------------------------------------------------------------------*/
  353.  
  354.     /**
  355.      * Add a package to list to be selected before proposal
  356.      * Can be called only before the installation proposal, later doesn't
  357.      * have any effect
  358.      * @param package string package to be selected
  359.      */
  360.     global void addAdditionalPackage(string package)
  361.     {
  362.     additional_packages = add (additional_packages, package);
  363.     }
  364.  
  365.     /**
  366.      * Compute architecture packages
  367.      * @return list(string)
  368.      */
  369.     define list<string> architecturePackages ()
  370.     {
  371.     list<string> packages = [];
  372.  
  373.     // remove unneeded / add needed packages for ppc
  374.     if (Arch::ppc ())
  375.     {
  376.         if (Arch::board_mac ())
  377.         {
  378.         packages = add (packages, "mouseemu");
  379.         }
  380.  
  381.         if (Arch::board_mac_new ()
  382.         || Arch::board_mac_old ())
  383.         {
  384.         string pmac_board = "";
  385.         list<map> pmac_compatible = (list<map>) SCR::Read(.probe.cpu);
  386.         foreach (map pmac_compatible_tmp, pmac_compatible, {
  387.             pmac_board = pmac_compatible_tmp["system"]:"";
  388.         });
  389.  
  390.         // install pbbuttonsd on PowerBooks and iMacs
  391.         if (issubstring (pmac_board, "PowerBook")
  392.             || issubstring (pmac_board, "PowerMac2,1")
  393.             || issubstring (pmac_board, "PowerMac2,2")
  394.             || issubstring (pmac_board, "PowerMac4,1")
  395.             || issubstring (pmac_board, "iMac,1"))
  396.         {
  397.             packages = add (packages, "pbbuttonsd");
  398.             packages = add (packages, "powerprefs");
  399.         }
  400.  
  401.         // mol is fun, and needs root access to kmem
  402.         packages = add (packages, "mol");
  403.         packages = add (packages, "sudo");
  404.         }
  405.  
  406.         if (Arch::ppc64 () && (Arch::board_chrp () || Arch::board_iseries ()))
  407.         {
  408.         packages = add (packages, "iprutils");
  409.         }
  410.     }
  411.  
  412.     if (Arch::ia64 ())
  413.     {
  414.         // install fpswa if the firmware has an older version
  415.         if (SCR::Execute(.target.bash, "/sbin/fpswa_check_version") != 0)
  416.         {
  417.         packages = add (packages, "fpswa");
  418.         }
  419.     }
  420.  
  421.     // add numactl on x86_64 with SMP
  422.     if (Arch::has_smp () && Arch::x86_64 ())
  423.     {
  424.         packages = add (packages, "numactl");
  425.         packages = add (packages, "irqbalance");
  426.     }
  427.  
  428.     return packages;
  429.     }
  430.  
  431.  
  432.     /**
  433.      * graphicPackages ()
  434.      * Compute graphic (x11) packages
  435.      * @return list(string)    list of rpm packages needed
  436.      */
  437.     define list<string> graphicPackages ()
  438.     {
  439.     list<string> packages = [];
  440.  
  441.     // don't setup graphics if running via serial console
  442.     if (!Linuxrc::serial_console ())
  443.     {
  444.         packages = [ "xorg-x11", "xorg-x11-server", "xorg-x11-server-glx",
  445.         "libusb", "sax2", "sax2-gui", "sax2-ident", "sax2-tools",
  446.         "sax2-libsax", "sax2-libsax-perl"];
  447.     }
  448.  
  449.     y2milestone ("X11 Packages to install: %1", packages);
  450.     return packages;
  451.     }
  452.  
  453.  
  454.     /**
  455.      * Compute special packages
  456.      * @return list(string)
  457.      */
  458.     define list<string> modePackages ()
  459.     {
  460.     list<string> packages = [];
  461.  
  462.     if (Linuxrc::vnc ())
  463.     {
  464.         packages = add (packages, "tightvnc");
  465.         packages = add (packages, "yast2-qt");
  466.         packages = add (packages, "xorg-x11");
  467.         packages = add (packages, "fvwm2");
  468.         packages = add (packages, "sax2-tools");
  469.     }
  470.  
  471.     if (Linuxrc::display_ip ())
  472.     {
  473.         packages = add (packages, "yast2-qt");
  474.         packages = add (packages, "xorg-x11");
  475.         packages = add (packages, "fvwm2");
  476.         packages = add (packages, "sax2-tools");
  477.     }
  478.  
  479.     if (Linuxrc::braille ())
  480.     {
  481.         packages = add (packages, "sbl");
  482.     }
  483.     y2milestone ("Installation mode packages: %1", packages);
  484.     return packages;
  485.     }
  486.  
  487.  
  488.     /**
  489.      * Compute special java packages
  490.      * @return list(string)
  491.      */
  492.     define list<string> javaPackages ()
  493.     {
  494.     if (!Arch::alpha ())
  495.         return [];
  496.  
  497.     list<string> packages = [];
  498.  
  499.     list cpus = (list) SCR::Read (.probe.cpu);
  500.     string model = cpus[0, "model"]:"EV4";
  501.     string cputype = substring (model, 2, 1);
  502.  
  503.     if ((cputype == "6") || (cputype == "7") || (cputype == "8"))
  504.     {
  505.         packages = ["cpml_ev6"];
  506.     }
  507.     else
  508.     {
  509.         packages = ["cpml_ev5"];
  510.     }
  511.     return packages;
  512.     }
  513.  
  514.  
  515.     /**
  516.      * Compute language dependant packages
  517.      * @return list(string)
  518.      */
  519.     define list<string> languagePackages ()
  520.     {
  521.     list<string> packages = [];
  522.     list<string> locales = Pkg::GetAdditionalLocales();
  523.     locales = prepend (locales, Pkg::GetLocale());
  524.     string transpac = "yast2-trans-";
  525.  
  526.     foreach (string loc, locales, {
  527.         if (Pkg::IsAvailable (transpac + loc))
  528.         packages = add (packages, transpac + loc);
  529.         else if (Pkg::IsAvailable (transpac + substring (loc, 0, 2)))
  530.         packages = add (packages, transpac + substring (loc, 0, 2));
  531.         else
  532.         y2warning ("No locale package found for %1", loc);
  533.     });
  534.     y2milestone ("Language packages: %1", packages);
  535.     return packages;
  536.     }
  537.  
  538.  
  539.     /**
  540.      * Compute board (vendor) dependant packages
  541.      * @return list(string)
  542.      */
  543.     define list<string> boardPackages ()
  544.     {
  545.     list<string> packages = [];
  546.  
  547.     list <map <string, any> > probe = (list <map <string, any> >)SCR::Read (.probe.system);
  548.     packages = (list<string>)probe[0,"requires"]:[];
  549.     y2milestone ("Board/Vendor specific packages: %1", packages);
  550.  
  551.     return packages;
  552.     }
  553.  
  554.  
  555.     /**
  556.      * Compute packages required to access the installation source
  557.      * @return list(string) list of the required packages
  558.      */
  559.     list<string> sourceAccessPackages()
  560.     {
  561.     list<string> ret = [];
  562.  
  563.     string instmode = Linuxrc::InstallInf("InstMode");
  564.     y2milestone("Installation mode: %1", instmode);
  565.  
  566.     if (instmode == "smb" || instmode == "cifs")
  567.     {
  568.         // /sbin/mount.cifs is required to mount a SMB/CIFS share
  569.         ret = ["cifs-mount"];
  570.     }
  571.  
  572.     y2milestone("Packages for access to the installation source: %1", ret);
  573.  
  574.     return ret;
  575.     }
  576.  
  577.     /*
  578.      * Additional kernel packages from control file
  579.      * @return list<string> Additional Kernel packages
  580.      */
  581.     define list<string> ComputeAdditionalKernelPackages ()
  582.     {
  583.     string final_kernel = Kernel::GetFinalKernel ();
  584.         integer pos = findfirstof(final_kernel, "-");
  585.         string extension = substring(final_kernel, pos, size(final_kernel));
  586.         list<string> akp = [];
  587.         if (extension!="")
  588.         {
  589.         list<string> kernel_packages = (list<string>)
  590.         ProductFeatures::GetFeature ("software", "kernel_packages");
  591.             if (size(kernel_packages) > 0 && kernel_packages != nil)
  592.             {
  593.                 akp = maplist(string p , kernel_packages, {
  594.                         return (p + "-" + extension);
  595.                         });
  596.             }
  597.         }
  598.         return akp;
  599.     }
  600.  
  601.     /*-----------------------------------------------------------------------
  602.      * GLOBAL FUNCTIONS
  603.      *-----------------------------------------------------------------------*/
  604.  
  605.  
  606. global list<string> ComputeSystemPatternList () {
  607.     list<string> pattern_list = [];
  608.     // also add the 'laptop' selection if PCMCIA detected
  609.     if (Arch::is_laptop () || Arch::has_pcmcia ())
  610.     {
  611.     foreach (string pat_name, ["laptop", "Laptop"], {
  612.         list<map<string, any> > pat_list = Pkg::ResolvableProperties (pat_name, `pattern, "");
  613.         if (size (pat_list) > 0)
  614.         pattern_list = add (pattern_list, pat_name);
  615.     });
  616.     }
  617.     y2milestone ("System patterns: %1", pattern_list);
  618.     return pattern_list;
  619. }
  620.  
  621.  
  622.     /**
  623.      * Build and return list of packages which depends on the
  624.      * the current target system and the preselected packages
  625.      * (architecture, X11....)
  626.      * @return list<string> packages
  627.      */
  628.     global define list<string> ComputeSystemPackageList ()
  629.     {
  630.     import "Storage";
  631.     list<string> install_list =  architecturePackages ();
  632.  
  633.     install_list = (list<string>) union (install_list, modePackages ());
  634.     install_list = (list<string>) union (install_list,
  635.                                          Storage::AddPackageList());
  636.     install_list = (list<string>) union (install_list,
  637.                          additional_packages);
  638.  
  639.     // Kernel is added in autoinstPackages () if autoinst is enabled
  640.     if (!Mode::update () || !Mode::autoinst ())
  641.     {
  642.             list <string> kernel_pkgs = Kernel::ComputePackages ();
  643.             list <string> kernel_pkgs_additional = ComputeAdditionalKernelPackages();
  644.         install_list = (list <string>) union (install_list, kernel_pkgs);
  645.             if (size(kernel_pkgs_additional) > 0 && kernel_pkgs_additional != nil)
  646.             {
  647.             install_list = (list <string>) union (install_list, kernel_pkgs_additional);
  648.             }
  649.         }
  650.  
  651.     if (Pkg::IsSelected("xorg-x11") && Linuxrc::vnc ())
  652.     {
  653.         install_list = (list<string>) union (install_list, graphicPackages ());
  654.     }
  655.     else
  656.     {
  657.         y2milestone ("Not selecting graphic packages");
  658.     }
  659.  
  660.     if (Pkg::IsSelected("java"))
  661.     {
  662.         install_list = (list<string>) union (install_list, javaPackages ());
  663.     }
  664.     else
  665.     {
  666.         y2milestone ("Not selecting java packages");
  667.     }
  668.  
  669.     install_list = (list<string>) union (install_list, languagePackages ());
  670.  
  671.     install_list = (list<string>) union (install_list, boardPackages ());
  672.  
  673.     // add packages required to access the installation source in the 2nd stage and at run-time
  674.     install_list = (list<string>) union (install_list, sourceAccessPackages());
  675.  
  676.     // and the most flexible enhancement for other products
  677.         // NOTE: not really flexible, because it requires the client
  678.         // in the instsys, instead use <kernel-packages> in the control file.
  679.     if (ProductFeatures::GetFeature ("software", "packages_transmogrify") != "")
  680.     {
  681.             list<string> tmp_list = (list<string>)
  682.         WFM::CallFunction (ProductFeatures::GetStringFeature ("software", "packages_transmogrify"),
  683.                    [ install_list ]);
  684.  
  685.             // Make sure we did not get a nil from calling the client, i.e.
  686.             // if the client does not exist at all..
  687.             if (tmp_list != nil)
  688.             {
  689.                 install_list = tmp_list;
  690.             }
  691.     }
  692.  
  693.     list<string> packages = (list<string>)
  694.         ProductFeatures::GetFeature ("software", "packages");
  695.         if (size(packages) > 0 && packages != nil )
  696.         {
  697.             y2milestone("Adding packages from control file: %1", packages);
  698.             install_list = (list<string>) union (install_list, packages);
  699.         }
  700.  
  701.     install_list = toset (install_list);
  702.     y2milestone ("auto-adding packages: %1", install_list);
  703.     return install_list;
  704.     }
  705.  
  706. /**
  707.  * Check whether content file in the specified source is the same
  708.  * as the one in the ramdisk
  709.  * @param source integer the source ID to check
  710.  * @return boolean true if content files match
  711.  */
  712. global boolean CheckContentFile (integer source) {
  713.     y2milestone ("Checking content file");
  714.     string instmode = Linuxrc::InstallInf("InstMode");
  715.     if (! (instmode == nil || instmode == "cd" || instmode == "dvd"))
  716.     {
  717.     y2milestone ("Installing via network, not checking the content file");
  718.     return true;
  719.     }
  720.     string media_content = Pkg::SourceProvideFile (source, 1, "/content");
  721.     string media = (string)SCR::Read (.target.string, media_content);
  722.     string ramdisk = (string)SCR::Read (.target.string, "/content");
  723.     boolean ret = (media == ramdisk);
  724.     y2milestone ("Content files are the same: %1", ret);
  725.     return ret;
  726. }
  727.  
  728. /**
  729.  * Import GPG keys found in the inst-sys
  730.  */
  731. void ImportGPGKeys () {
  732.     map out = (map) SCR::Execute (.target.bash_output, "/bin/ls -d /*.gpg");
  733.     foreach (string file, splitstring (out["stdout"]:"", "\n"), {
  734.     if (file != "")
  735.         Pkg::ImportGPGKey (file, true);
  736.     });
  737. }
  738.  
  739. string UpdateSourceURL (string url) {
  740.     string ret = "";
  741.     while (ret == "")
  742.     {
  743.     if (Popup::YesNo (_("Failed to initialize the catalog. Try again?")))
  744.     {
  745.         ret = SourceDialogs::EditPopup (url);
  746.     }
  747.     else
  748.     {
  749.         // error in proposal, %1 is URL
  750.         init_error = sformat (_("No catalog found at '%1'."),
  751.         InstURL::HidePassword (url));
  752.         return "";
  753.     }
  754.     }
  755.     return ret;
  756. }
  757.  
  758. list<string> LocaleVersions (string lang) {
  759.     list<string> ret = [ lang ];
  760.     list<string> components = splitstring (lang, ".");
  761.     if (components[0]:"" != lang && components[0]:"" != "")
  762.     {
  763.     lang = components[0]:"";
  764.     ret = add (ret, lang);
  765.     }
  766.     components = splitstring (lang, "_");
  767.     if (components[0]:"" != lang && components[0]:"" != "")
  768.     {
  769.     lang = components[0]:"";
  770.     ret = add (ret, lang);
  771.     }
  772.     return ret;
  773. }
  774.  
  775. string ContentFileProductLabel () {
  776.     string language = Language::language;
  777.     list<string> locales = LocaleVersions (Language::language);
  778.     string ret = "";
  779.     foreach (string loc, locales, {
  780.     if (ret == "")
  781.     {
  782.         string val = (string)SCR::Read (add (.content, "LABEL." + loc));
  783.         if (val != "" && val != nil)
  784.         {
  785.         ret = val;
  786.         return ret;
  787.         }
  788.     }
  789.     });
  790.     return (string)SCR::Read (.content.LABEL);
  791. }
  792.  
  793. void SlideShowSetUp (integer source) {
  794.     // setup slidedir
  795.     map productmap = Pkg::SourceProductData (source);
  796.     string datadir = productmap["datadir"]:"suse";
  797.     string slidedir_find = "/" + datadir + "/setup/slide";
  798.     string dir = Pkg::SourceProvideOptionalFile (source, 1,
  799.     slidedir_find + "/directory.yast");
  800.     string slidedir = nil;
  801.     if (dir != nil)
  802.     slidedir = Pkg::SourceProvideDir (source, 1, slidedir_find);
  803.  
  804.     string our_slidedir = (string)WFM::Read (.local.tmpdir, "");
  805.     if (slidedir == nil)
  806.      {
  807.     y2milestone("No slide directory '%1' found on source '%2'.",
  808.         slidedir_find, source);
  809.     }
  810.     else
  811.     {
  812.     // copy all files to our own copy
  813.     WFM::Execute (.local.bash,
  814.         sformat ("cp -r %1/* %2/", slidedir, our_slidedir)) ;
  815.     }
  816.     y2milestone ("Setting up the slide directory local copy: %1",
  817.     our_slidedir);
  818.     SlideShow::SetSlideDir (our_slidedir);
  819. }
  820.  
  821. integer IntegrateServicePack (boolean show_popup, string base_url) {
  822.     /* Check for Service Pack */
  823.     boolean servicepack_available = false;
  824.     if ((integer)WFM::Read(.local.size, servicepack_metadata) > 0)
  825.     {
  826.     y2milestone("Service Pack data available");
  827.     boolean popup_open = false;
  828.     if (show_popup)
  829.     {
  830.         UI::OpenDialog(`opt(`decorated ),
  831.         // popup - information label
  832.         `Label(_("Integrating booted media...")));
  833.         popup_open = true;
  834.     }
  835.     string spdir = metadir + "/Service-Pack/CD1";
  836.     WFM::Execute (.local.mkdir, spdir);
  837.     y2milestone ("Filling %1", spdir);
  838.     WFM::Execute(.local.bash, "tar -zxvf " +
  839.         servicepack_metadata + " -C " + spdir);
  840.     string sp_url = "dir:" + spdir;
  841.     integer sp_source = Pkg::SourceCreate (sp_url, "");
  842.     // close the popup in order to be able to ask about the license
  843.     if (popup_open)
  844.     {
  845.         popup_open = false;
  846.         UI::CloseDialog ();
  847.     }
  848.     if (sp_source == -1)
  849.     {
  850.         Report::Error (_("Failed to integrate service pack source."));
  851.         return nil;
  852.     }
  853.     if (! AddOnProduct::AcceptedLicenseAndInfoFile(sp_source))
  854.     {
  855.         y2milestone ("service pack license rejected");
  856.         Pkg::SourceDelete (sp_source);
  857.         return nil;
  858.     }
  859.     if ((integer)WFM::Read (.local.size, spdir + "/installation.xml") > 0)
  860.     {
  861.         AddOnProduct::WFIntegrate (spdir + "/installation.xml");
  862.     }
  863.     if ((integer)WFM::Read (.local.size, spdir + "/y2update.tgz") > 0)
  864.     {
  865.         AddOnProduct::UpdateInstSys (spdir + "/y2update.tgz");
  866.     }
  867.     theSources = add (theSources, sp_source);
  868.     y2internal ("Service pack source: %1, changing to URL: %2",
  869.          sp_source, base_url);
  870.     Pkg::SourceChangeUrl (sp_source, base_url);
  871.     }
  872. }
  873.  
  874. /**
  875.  * Initialize the installation sources
  876.  * @param show_popup boolean true to display information about initialization
  877.  */
  878. global void Initialize(boolean show_popup) {
  879.     if (init_called || init_in_progress)
  880.     {
  881.     y2warning ("Packages::Initialize() already called");
  882.     return;
  883.     }
  884.     init_in_progress = true;
  885.     boolean popup_open = false;
  886.     if (show_popup)
  887.     {
  888.     UI::OpenDialog(`opt(`decorated ),
  889.         // popup - information label
  890.         `Label(_("Initializing catalogs...")));
  891.     popup_open = true;
  892.     }
  893.  
  894.     PackageCallbacksInit::InitPackageCallbacks ();
  895.  
  896.     // Initialize package manager
  897.     init_error = nil;
  898.     y2milestone ("Packages::Initialize()");
  899.     // usual mountpoint for the source medium
  900.     string base_url = "";
  901.  
  902.     if (Mode::test ())
  903.     {
  904.     // Fake values for testing purposes
  905.     base_url = "dir:///dist/next-i386";
  906.     }
  907.     else
  908.     {
  909.     base_url = InstURL::installInf2Url ("");
  910.     }
  911.  
  912.     // hide password from URL if present
  913.     string log_url = InstURL::HidePassword(base_url);
  914.     y2milestone ("Initialize Package Manager: %1", log_url);
  915.  
  916.     // Set languages for packagemanager. Always set the UI language. Set
  917.     // language for additional packages only in Stage::initial ().
  918.     Pkg::SetLocale (Language::language);
  919.  
  920.     boolean again = true;
  921.     theSources = Pkg::SourceStartCache (true); // dummy in 1st stage
  922.     while (again)
  923.     {
  924.     if (Stage::initial ())
  925.     {
  926.         integer initial_source = nil;
  927.         ImportGPGKeys ();
  928.         while (initial_source == nil)
  929.         {
  930.         initial_source = Pkg::SourceCreateBase (base_url, "");
  931.         if (initial_source == -1 || initial_source == nil)
  932.         {
  933.             y2error ("No source on '%1'", log_url);
  934.             base_url = UpdateSourceURL (base_url);
  935.             if (base_url != "")
  936.             {
  937.             initial_source = nil;
  938.             }
  939.             else
  940.             {
  941.             if (popup_open)
  942.                 UI::CloseDialog ();
  943.             init_in_progress = false;
  944.             return;
  945.             }
  946.         }
  947.         if (! CheckContentFile (initial_source))
  948.         {
  949.             string label = ContentFileProductLabel ();
  950.             // bug #159754, release the mounted CD
  951.             Pkg::SourceReleaseAll();
  952.             Pkg::SourceDelete (initial_source);
  953.             initial_source = nil;
  954.             if (! Popup::ContinueCancel (
  955.             // message popup, %1 is product name
  956.             sformat (_("Insert %1 CD 1"), label)))
  957.             {
  958.             init_error = sformat (_("%1 CD 1 not found"), label);
  959.             if (popup_open)
  960.                 UI::CloseDialog ();
  961.             init_in_progress = false;
  962.             return;
  963.             }
  964.         }
  965.         }
  966.  
  967.         SlideShowSetUp (initial_source);
  968.  
  969.         // Set the product before setting up add-on products
  970.         // In the autoyast mode it could be that the proposal
  971.         // screen will not be displayed. So the product will
  972.         // not be set. Bug 178831
  973.         SelectProduct ();
  974.  
  975.         if (popup_open)
  976.         {
  977.         popup_open = false;
  978.         UI::CloseDialog ();
  979.         }
  980.         theSources = [ initial_source ];
  981.         integer sp_source = IntegrateServicePack (show_popup, base_url);
  982.         if (sp_source != nil)
  983.         theSources = add (theSources, sp_source);
  984.  
  985.         if (ProductFeatures::GetFeature ("software", "selection_type") == `fixed)
  986.         {
  987.                 Pkg::SetSelection (ProductFeatures::GetStringFeature ("software", "base_selection"));
  988.         }
  989.  
  990.         string tmp_add_on_products = Pkg::SourceProvideOptionalFile (initial_source, 1, "/add_on_products");
  991.         if (tmp_add_on_products != nil)
  992.         {
  993.         add_on_products_list = ((string)SCR::Read (.target.tmpdir)) + "/add_on_products";
  994.         WFM::Execute (.local.bash, sformat ("cp %1 %2", tmp_add_on_products, add_on_products_list));
  995.         }
  996.         else
  997.         {
  998.         add_on_products_list = nil;
  999.         }
  1000.  
  1001.     }
  1002.     else // cont or normal mode
  1003.     {
  1004.         if (theSources == nil || size (theSources) <= 0)
  1005.         {
  1006.         y2error ("Pkg::SourceStartCache failed");
  1007.         theSources = [];
  1008.         }
  1009.         else if ( Stage::cont ()    // rewrite URL if cd/dvd since ide-scsi might have changed it
  1010.              && ((substring (base_url, 0, 2) == "cd")
  1011.             || (substring (base_url, 0, 3) == "dvd")))
  1012.         {
  1013.         foreach (integer source, theSources, {
  1014.             map data = Pkg::SourceGeneralData (source);        // get source data
  1015.             string url = data["url"]:"";
  1016.             if ((substring (url, 0, 2) == "cd")            // source comes from cd/dvd
  1017.             || (substring (url, 0, 3) == "dvd"))
  1018.             {
  1019.                         string new_url = InstURL::RewriteCDUrl(url);
  1020.             y2milestone ("rewrite url: '%1'->'%2'", url, InstURL::HidePassword(new_url));
  1021.             Pkg::SourceChangeUrl (source, new_url);
  1022.             }
  1023.         });
  1024.         }
  1025.     }
  1026.  
  1027.     y2milestone ("theSources %1", theSources);
  1028.     y2milestone ("theSourceDirectories %1", theSourceDirectories);
  1029.     if (size (theSources) >= 0)
  1030.     {
  1031.         init_called = true;
  1032.         again = false;
  1033.     }
  1034.     else
  1035.     {
  1036.         import "PackageCallbacks";
  1037.  
  1038.         // an error message
  1039.         string errortext = sformat (_("Error while initializing package descriptions.
  1040. Check the log file %1 for more details."), Directory::logdir + "/y2log") +
  1041.         "\n" + Pkg::LastError();
  1042.  
  1043.         // FIXME somewhere get correct current_label and wanted_label
  1044.         string result = PackageCallbacks::MediaChange (errortext, base_url, "",
  1045.                                0, "", 1, "", false);
  1046.     }
  1047.     }
  1048.     if (popup_open)
  1049.     UI::CloseDialog ();
  1050.     init_in_progress = false;
  1051. }
  1052.  
  1053. global void Init(boolean unused) {
  1054.     Initialize (true);
  1055. }
  1056.  
  1057. /**
  1058.  * Select the base product on the media for installation
  1059.  * @return boolean true on success
  1060.  */
  1061. global boolean SelectProduct () {
  1062.     Packages::Initialize (true);
  1063.     list<map<string,any> > products = Pkg::ResolvableProperties ("", `product, "");
  1064.     products = filter (map<string,any> p, products, {
  1065.     return p["category"]:"" == "base";
  1066.     });
  1067.     if (size (products) == 0)
  1068.     {
  1069.     y2milestone ("No base product found on media");
  1070.     return true;
  1071.     }
  1072.     list<map<string,any> >selected_products = filter (map<string,any> p, products, {
  1073.     return p["status"]:nil == `selected;
  1074.     });
  1075.     // no product selected -> select them all
  1076.     boolean ret = true;
  1077.     if (size (selected_products) == 0)
  1078.     {
  1079.     y2milestone ("No product selected so far...");
  1080.     foreach (map<string,any> p, products, {
  1081.         y2milestone ("Selecting product %1", p["name"]:"");
  1082.         ret = Pkg::ResolvableInstall (p["name"]:"", `product) && ret;
  1083.     });
  1084.     }
  1085.     return ret;
  1086. }
  1087.  
  1088. /**
  1089.  * Select system patterns
  1090.  * @param reselect boolean true to select only those which are alrady selected
  1091.  */
  1092. void SelectSystemPatterns (boolean reselect) {
  1093.     list<string> system_patterns = ComputeSystemPatternList ();
  1094.     // autoinstallation has patterns specified in the profile
  1095.     if (! Mode::autoinst ())
  1096.     {
  1097.     system_patterns = (list<string>)
  1098.         merge (system_patterns, DefaultDesktop::PatternsToSelect ());
  1099.     system_patterns = (list<string>)
  1100.         toset (merge (system_patterns, Product::patterns));
  1101.     }
  1102.     if (! reselect)
  1103.     {
  1104.     list<string> to_deselect = DefaultDesktop::PatternsToDeselect ();
  1105.     y2milestone ("Deselecting system patterns %1", to_deselect);
  1106.     foreach (string p, to_deselect, {
  1107.         Pkg::ResolvableRemove (p, `pattern);
  1108.     });
  1109.     y2milestone ("Selecting system patterns %1", system_patterns);
  1110.     foreach (string p, system_patterns, {
  1111.         Pkg::ResolvableInstall (p, `pattern);
  1112.     });
  1113.     }
  1114.     else
  1115.     {
  1116.     y2milestone ("Re-selecting system patterns %1", system_patterns);
  1117.     list<string>pats = filter (string p, system_patterns, {
  1118.         list<map<string,any> > descrs = Pkg::ResolvableProperties (p, `pattern, "");
  1119.         descrs = filter (map<string,any> descr, descrs, {
  1120.         return descr["status"]:nil == `selected;
  1121.         });
  1122.         return size (descrs) > 0;
  1123.     });
  1124.     y2milestone ("Selected patterns to be reselected: %1", pats);
  1125.     foreach (string p, pats, {
  1126.         Pkg::ResolvableRemove (p, `pattern);
  1127.         Pkg::ResolvableInstall (p, `pattern);
  1128.     });
  1129.     }
  1130. }
  1131.  
  1132. /**
  1133.  * Select system packages
  1134.  * @param reselect boolean true to select only those which are alrady selected
  1135.  */
  1136. void SelectSystemPackages (boolean reselect) {
  1137.     list<string> system_packages = ComputeSystemPackageList();
  1138.     if (! reselect)
  1139.     {
  1140.     y2milestone ("Selecting system packages %1", system_packages);
  1141.     }
  1142.     else
  1143.     {
  1144.     y2milestone ("Re-selecting new versions of system packages %1", system_packages);
  1145.     // first deselect the package (and filter selected ones)
  1146.     system_packages = filter (string p, system_packages, {
  1147.         if (Pkg::IsProvided (p) || Pkg::IsSelected (p))
  1148.         {
  1149.         Pkg::PkgDelete (p);
  1150.         return true;
  1151.         }
  1152.         return false;
  1153.     });
  1154.     y2milestone ("System packages to be reselected: %1", system_packages);
  1155.     }
  1156.     map <string, any> res = Pkg::DoProvide (system_packages);
  1157.     if (size (res) > 0)
  1158.     {
  1159.     foreach (string s, any a, res, {
  1160.         y2warning ("Pkg::DoProvide failed for %1: %2", s, a);
  1161.     });
  1162.     }
  1163. }
  1164.  
  1165. /**
  1166.  * Select appropriate XEN kernel if the XEN pattern is selected
  1167.  */
  1168. void SelectXenKernel () {
  1169.     // check Xen pattern status
  1170.     list<map> xen_patterns  = Pkg::ResolvableProperties("xen_server", `pattern, "");
  1171.  
  1172.     // is the Xen pattern selected?
  1173.     boolean xen_selected = false;
  1174.  
  1175.     foreach(map pattern, xen_patterns,
  1176.     {
  1177.     if (pattern["status"]:`unknown == `selected)
  1178.     {
  1179.         xen_selected = true;
  1180.     }
  1181.     });
  1182.  
  1183.     if (xen_selected)
  1184.     {
  1185.     if (contains (Kernel::GetPackages (), "kernel-bigsmp"))
  1186.     {
  1187.         y2milestone("Selected Xen kernel: kernel-xenpae");
  1188.         // install PAE Xen
  1189.         Pkg::PkgNeutral("kernel-xen");
  1190.         Pkg::PkgInstall("kernel-xenpae");
  1191.     }
  1192.     else
  1193.     {
  1194.         // install standard Xen
  1195.         Pkg::PkgNeutral("kernel-xenpae");
  1196.         Pkg::PkgInstall("kernel-xen");
  1197.     }
  1198.     }
  1199. }
  1200.  
  1201. /**
  1202.  * Make a proposal for package selection
  1203.  * @param force reset
  1204.  * @param re-initialize
  1205.  * @return map for the API proposal
  1206.  */
  1207. global map Proposal (boolean force_reset, boolean reinit, boolean simple) {
  1208.  
  1209.     // if the cache is valid and reset or reinitialization is not required
  1210.     // then the cached proposal can be used
  1211.     if (cached_proposal != nil && force_reset == false && reinit == false)
  1212.     {
  1213.     // selected packages
  1214.     list<string> selected_packages = Pkg::GetPackages(`selected, false);
  1215.  
  1216.     // selected patterns
  1217.     list<map> selected_patterns = filter(map p, Pkg::ResolvableProperties("", `pattern, ""), {return p["status"]:`unknown == `selected;});
  1218.  
  1219.     // selected products
  1220.     list<map> selected_products = filter(map p, Pkg::ResolvableProperties("", `product, ""), {return p["status"]:`unknown == `selected;});
  1221.  
  1222.     // selected patches
  1223.     list<map> selected_patches = filter(map p, Pkg::ResolvableProperties("", `patch, ""), {return p["status"]:`unknown == `selected;});
  1224.  
  1225.     // selected selections
  1226.     list<map> selected_selections = filter(map s, Pkg::ResolvableProperties("", `selection, ""), {return s["status"]:`unknown == `selected;});
  1227.  
  1228.     // selected languages
  1229.     list<string> selected_languages = (list<string>)union([Pkg::GetLocale()], Pkg::GetAdditionalLocales());
  1230.  
  1231.  
  1232.     // if the package selection has not been changed the cache is up to date
  1233.     if (selected_packages == cached_proposal_packages && selected_patterns == cached_proposal_patterns
  1234.         && selected_products == cached_proposal_products && selected_patches == cached_proposal_patches
  1235.         && selected_selections == cached_proposal_selections && selected_languages == cached_proposal_languages)
  1236.     {
  1237.         y2milestone("using cached software proposal");
  1238.         return cached_proposal;
  1239.     }
  1240.     else
  1241.     {
  1242.         y2milestone("invalid cache: the software selection has been chaged");
  1243.     }
  1244.     }
  1245.     else
  1246.     {
  1247.     y2milestone("the cached proposal is empty or reset is required");
  1248.     }
  1249.  
  1250.     UI::OpenDialog(`opt(`decorated ),
  1251.     // popup label
  1252.     `Label (_("Evaluating package selection...")));
  1253.  
  1254.     y2milestone ("Packages::Proposal: force_reset %1, reinit %2, lang '%3'",
  1255.     force_reset, reinit, Language::language);
  1256.  
  1257.     if ( force_reset )
  1258.     {
  1259.     Kernel::ProbeKernel();
  1260.     Packages::Reset ([`product]);
  1261.     reinit = true;
  1262.     }
  1263.  
  1264.     boolean initial_run = reinit || ! init_called;
  1265.     Initialize (true);
  1266.  
  1267.     if (init_error != nil)
  1268.     {
  1269.     UI::CloseDialog();
  1270.     return Summary ([], false);
  1271.     }
  1272.  
  1273.     if (initial_run)
  1274.     {
  1275.     // autoyast can configure AdditionalLocales
  1276.     // we don't want to overwrite this
  1277.     if( ! Mode::autoinst ())
  1278.     {
  1279.         Pkg::SetAdditionalLocales ([Language::language]);
  1280.     }
  1281.     }
  1282.  
  1283.     SelectProduct ();
  1284.  
  1285.     if (ProductFeatures::GetFeature ("software", "selection_type") == `auto)
  1286.     {
  1287.     y2milestone ("Doing pattern-based software selection");
  1288.  
  1289.     SelectSystemPackages (system_packages_selected && ! initial_run);
  1290.     SelectSystemPatterns (system_packages_selected && ! initial_run);
  1291.     system_packages_selected = true;
  1292.     Pkg::PkgFreshen();
  1293.     }
  1294.     else if (ProductFeatures::GetFeature ("software","selection_type") == `fixed)
  1295.     {
  1296.     y2milestone ("Selection type: fixed");
  1297.     }
  1298.     else
  1299.     {
  1300.     y2error ("unknown value %1 for ProductFeatures::GetFeature (software, selection_type)",
  1301.          (symbol)ProductFeatures::GetFeature ("software", "selection_type"));
  1302.     }
  1303.  
  1304.     SelectXenKernel ();
  1305.  
  1306.     if (! Pkg::PkgSolve (false))
  1307.     {
  1308.     solve_errors = Pkg::PkgSolveErrors ();
  1309.     }
  1310.  
  1311.     map ret = Summary (
  1312.     [ `product, `pattern, `selection, `size, `desktop ],
  1313.     false);
  1314.     // TODO simple proposal
  1315.  
  1316.     // cache the proposal
  1317.     cached_proposal = ret;
  1318.  
  1319.     // remember the status
  1320.     cached_proposal_packages = Pkg::GetPackages(`selected, false);
  1321.     cached_proposal_patterns = filter(map p, Pkg::ResolvableProperties("", `pattern, ""), {return p["status"]:`unknown == `selected;});
  1322.     cached_proposal_products = filter(map p, Pkg::ResolvableProperties("", `product, ""), {return p["status"]:`unknown == `selected;});
  1323.     cached_proposal_patches = filter(map p, Pkg::ResolvableProperties("", `patch, ""), {return p["status"]:`unknown == `selected;});
  1324.     cached_proposal_selections = filter(map s, Pkg::ResolvableProperties("", `selection, ""), {return s["status"]:`unknown == `selected;});
  1325.     cached_proposal_languages = (list<string>)union([Pkg::GetLocale()], Pkg::GetAdditionalLocales());
  1326.  
  1327.     UI::CloseDialog();
  1328.  
  1329.     y2milestone ("Software proposal: %1", ret);
  1330.  
  1331.     return ret;
  1332. }
  1333.  
  1334. /**
  1335.  * Initialize the catalogs with popup feedback
  1336.  * Use Packages::Initialize (true) instead
  1337.  */
  1338. global void InitializeCatalogs() {
  1339.     Packages::Initialize (true);
  1340. }
  1341.  
  1342. global boolean InitFailed () {
  1343.     boolean ret = init_error != nil;
  1344.     y2milestone ("Package manager initialization failed: %1", ret);
  1345.     return ret;
  1346. }
  1347.  
  1348. /* EOF */
  1349. }
  1350.