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 / sw_single.ycp < prev    next >
Text File  |  2006-11-29  |  13KB  |  418 lines

  1. /**
  2.  * Module:         sw_single.ycp
  3.  *
  4.  * Authors:         Gabriele Strattner (gs@suse.de)
  5.  *            Klaus Kaempf <kkaempf@suse.de>
  6.  *
  7.  * Purpose:         contains dialog loop for workflows:
  8.  *    "Install/Remove software"
  9.  *
  10.  * $Id: sw_single.ycp 34559 2006-11-22 12:38:46Z lslezak $
  11.  */
  12.  
  13. {
  14.     textdomain "packager";
  15.  
  16.     import "Arch";
  17.     import "Confirm";
  18.     import "Installation";
  19.     import "Directory";
  20.     import "Mode";
  21.     import "PackageCallbacks";
  22.     import "PackageLock";
  23.     import "SlideShow";
  24.     import "SlideShowCallbacks";
  25.     import "Kernel";
  26.     import "Wizard";
  27.     import "Popup";
  28.     import "GetInstArgs";
  29.     import "Label";
  30.     import "PackageSystem";
  31.     import "Report";
  32.     import "FileUtils";
  33.  
  34.     Wizard::CreateDialog();
  35.     Wizard::SetDesktopIcon("sw_single");
  36.     Wizard::SetContents(_("Initializing..."), `Empty (), "", false, true);
  37.  
  38.     import "Packages";
  39.  
  40.     list<string> packagelist = [];        // list of packages to act on
  41.  
  42.     // `install
  43.     // `remove, `update: used from gnome-main-menu (#222757)
  44.     symbol action = `install;
  45.  
  46.     boolean test_popup = false;
  47.     boolean skip_source = false;
  48.  
  49.     // =============================================================
  50.  
  51.     // check test_popup
  52.     // test_mode is checked for in Installation constructor
  53.  
  54.     define list<string> CheckArguments ()
  55.     {
  56.     integer arg_n = size (WFM::Args()) - 1;
  57.  
  58.     list<string> arg_list = [];
  59.  
  60.     while (arg_n >= 0)
  61.     {
  62.         if (WFM::Args(arg_n) == .test)
  63.         {
  64.         Mode::SetTest ("test");
  65.         }
  66.         else if (WFM::Args(arg_n) == .testp)
  67.         {
  68.         Mode::SetTest ("test");        // .testp implies .test
  69.         test_popup = true;
  70.         }
  71.         else if (is (WFM::Args(arg_n), string))
  72.         {
  73.         string s = tostring (WFM::Args(arg_n));
  74.         if (s == "--install")
  75.             action = `install;
  76.         else if (s == "--remove")
  77.             action = `remove;
  78.         else if (s == "--update")
  79.             action = `update;
  80.         else
  81.             arg_list = add (arg_list, s);
  82.         }
  83.         else if (is (WFM::Args(arg_n), list))
  84.         {
  85.         foreach (any arg, (list)WFM::Args(arg_n), ``{ arg_list = add (arg_list, tostring (arg));});
  86.         }
  87.         arg_n = arg_n - 1;
  88.     }
  89.  
  90.     y2milestone ("action: %1", action);
  91.     return arg_list;
  92.  
  93.     };  // CheckArguments
  94.  
  95.     //
  96.     // CheckWhichPackages
  97.     //
  98.     // Check arg_list:
  99.     // If we're called with an absolute package path just install
  100.     // this package without paying attention to dependencies.
  101.     //
  102.     // returns    `done        all done
  103.     //        `failed        package not found
  104.     //        `next        workflow "Change source of installation"
  105.     //        `found_descr    started package manager
  106.     //        `unknown_descr    found nothing
  107.     //
  108.  
  109.    define symbol CheckWhichPackages (list<string> arg_list)
  110.    {
  111.     PackageSystem::EnsureTargetInit();
  112.  
  113.        y2milestone ("CheckWhichPackages (%1)", arg_list);
  114.        // if sw_single is called with a list of packages or a package name
  115.  
  116.        string first_arg = "";
  117.  
  118.        if (size (arg_list) > 0)
  119.        {
  120.        first_arg = arg_list[0]:"";
  121.        }
  122.  
  123.        /*
  124.     * If the first argument is a package ending with .rpm call Pkg::TargetInstall for
  125.     * each arg.
  126.     */
  127.        if (regexpmatch (first_arg, "\\.rpm$"))        // package name given
  128.        {
  129.        // if sw_single is called with an absolute package-pathname, there is no need to
  130.        // mount the source medium or check SuSE version or dependencies
  131.  
  132.        Pkg::TargetLogfile (Installation::destdir + Directory::logdir + "/y2logRPM");
  133.  
  134.        SlideShow::InitPkgData(true);    // force reinitialization
  135.  
  136.        foreach (string package, arg_list, {
  137.            if (SCR::Read (.target.size, package) > 0)
  138.            {
  139.            y2milestone ("SW_SINGLE: installing %1", package);
  140.            Pkg::TargetInstall (package);
  141.            }
  142.            else
  143.            {
  144.            // error popup, %1 is the name of the .rpm package
  145.            string message = sformat (_("Package %1 was not found on the medium."), package);
  146.            y2error ("SW_SINGLE: Package %1 was not found on the medium", package);
  147.            Popup::Message (message);
  148.            return `failed;
  149.            }
  150.        });
  151.  
  152.        // package is installed without paying attention to SuSE dependencies
  153.        // don't call SuSEConfig -> dialog loop ends
  154.        return `done;
  155.        }
  156.        else if (first_arg != "")        // firstarg given, but not *.rpm
  157.        {
  158.        string arg_name = arg_list[0]:"";
  159.  
  160.        if ( ! FileUtils::IsFile(arg_name) || FileUtils::GetSize(arg_name) <= 0 )        // Check: a local file ? bigger than 0?
  161.        {
  162.            packagelist = arg_list;                    // No: expect package names
  163.        }
  164.        else                            // Yes: try to read the file
  165.        {
  166.            y2milestone("Reading file %1", arg_name );
  167.            packagelist = (list<string>) SCR::Read( .target.ycp, arg_name);    // try .ycp list first
  168.            if ((packagelist == nil)
  169.            || (packagelist == []))
  170.            {
  171.            string packagestr = (string) SCR::Read( .target.string, arg_name);    // string ascii file next
  172.            packagelist = splitstring (packagestr, "\n");
  173.            // filter empty lines out,  bug #158226
  174.            packagelist = filter (string package, packagelist, { return !regexpmatch(package, "^ *$"); });
  175.            }
  176.        }
  177.        y2milestone("packagelist: %1", packagelist );
  178.        }
  179.  
  180.        // start package manager
  181.        const boolean enabled_only = true;
  182.        boolean mgr_ok = Pkg::SourceStartManager(enabled_only);
  183.        if (!mgr_ok)
  184.        {
  185.        Report::LongWarning(_("There was an error in installation source initialization.") + "\n" + Pkg::LastError ());
  186.        }
  187.        if (size(Pkg::SourceGetCurrent(enabled_only)) == 0)
  188.     {
  189.  
  190.        Report::Warning(_("No installation source is defined.
  191. Only installed packages are displayed."));
  192.     }
  193.  
  194.        Pkg::TargetInit (Installation::destdir, false);
  195.  
  196.        return `found_descr;
  197.  
  198.    };    // CheckWhichPackages
  199.  
  200.    // originally stolen from inst_do_net_test.ycp:IsDownloadedVersionNewer
  201.    /**
  202.     * Function checks two versions of installed rpm and decides
  203.     * whether the second one is newer than the first one. This
  204.     * function ignores non-numerical values in versions.
  205.     * Version and Release parts are merged!
  206.     * FIXME make a binding to librpm.
  207.     * @param string first version
  208.     * @param string second version
  209.     * @return boolean true if the second one is newer than the first one
  210.     */
  211.    boolean VersionALtB (string a_version, string b_version) {
  212.        list <string> a_version_l = filter(string s, splitstring(a_version, "-\."), {
  213.        return regexpmatch(s, "^[0123456789]+$");
  214.        });
  215.        list <string> b_version_l = filter(string s, splitstring(b_version, "-\."), {
  216.        return regexpmatch(s, "^[0123456789]+$");
  217.        });
  218.     
  219.        y2milestone("Comparing versions %1 and %2", a_version_l, b_version_l);
  220.        integer a_size = size (a_version_l);
  221.        integer b_size = size (b_version_l);
  222.        integer longer_size = a_size > b_size? a_size: b_size;
  223.  
  224.        boolean b_version_is_newer = false;
  225.        integer compare = 0; // <0 if a<b, =0 if a==b, >0 if a>b
  226.        integer i = 0;
  227.        while (i < longer_size) {
  228.        // -1 will make the desirable outcome of "2" < "2.0"
  229.        integer a_item = tointeger(a_version_l[i]:"-1");
  230.        integer b_item = tointeger(b_version_l[i]:"-1");
  231.        if (a_item < b_item) {
  232.            compare = -1;
  233.            break;
  234.        }
  235.        if (a_item > b_item) {
  236.            compare = 1;
  237.            break;
  238.        }
  239.        i = i + 1;
  240.        };
  241.     
  242.        y2milestone("%1 <=> %2 -> %3", a_version, b_version, compare);
  243.        return compare < 0;
  244.    }
  245.  
  246.    /**
  247.     * Check if there is an uninstalled package of the same name with a
  248.     * higher version. Otherwise we would forcefully reinstall it. #222757#c9
  249.     */
  250.    boolean CanBeUpdated (string package) {
  251.        list< map<string,any> > props = Pkg::ResolvableProperties (package, `package, "" /*any version*/);
  252.        // find maximum version and remember
  253.        // if it is installed
  254.        string max_ver = "0";
  255.        boolean max_is_installed = false;
  256.        foreach (map<string,any> prop, props, {
  257.        string cur_ver = prop["version"]:"0";
  258.        if (VersionALtB (max_ver, cur_ver)) {
  259.            max_ver = cur_ver;
  260.            // `installed or `selected is ok
  261.            max_is_installed = prop["status"]:`available != `available;
  262.            y2milestone ("new max: installed: %1", max_is_installed);
  263.        }
  264.        });
  265.        return !max_is_installed;
  266.    }
  267.  
  268.    // =============================================================
  269.  
  270.  
  271.    // check whether running as root
  272.    // and having the packager for ourselves
  273.    if (! Confirm::MustBeRoot () || ! PackageLock::Check ())
  274.    {
  275.     UI::CloseDialog ();
  276.     return `abort;
  277.    }
  278.  
  279.    // check Args
  280.    // set test_mode, test_popup
  281.    list<string> arg_list = CheckArguments();
  282.  
  283.    // check the arguments and try the mount/search for local description
  284.    symbol result = CheckWhichPackages (arg_list);
  285.  
  286.    Pkg::SetLocale (UI::GetLanguage (true));
  287.  
  288.    y2milestone ("SW_SINGLE: result CheckWhichPackages %1", result);
  289.  
  290.    if ((result == `done)
  291.        || (result == `failed))
  292.    {
  293.        UI::CloseDialog();
  294.        UI::CloseDialog();
  295.        return `next;
  296.    }
  297.  
  298.  
  299.    boolean ask = false;
  300.    boolean found_descr = result == `found_descr;
  301.  
  302.    do
  303.    {
  304.     list<string> old_failed_packs = [];
  305.     if ((integer)SCR::Read (.target.size,
  306.         "/var/lib/YaST2/failed_packages") > 0)
  307.     {
  308.         old_failed_packs = (list<string>)
  309.         SCR::Read (.target.ycp, "/var/lib/YaST2/failed_packages");
  310.     }
  311.     if (size (old_failed_packs) > 0 && Popup::YesNo (
  312. _("During the last package installation,
  313. several package failed to install.
  314. Install them now?
  315. ")))
  316.     {
  317.         foreach (string p, old_failed_packs, {
  318.         Pkg::PkgInstall (p);
  319.         });
  320.     }
  321.  
  322.        if ( found_descr )
  323.        {
  324.        if (size (packagelist) == 0)            // packages given ?
  325.        {
  326.            result = (symbol)WFM::CallFunction( "inst_packages", []);    // No: ask user via package selection widget
  327.            y2milestone ("inst_packages returns %1", result);
  328.            if (result == `accept)
  329.            {
  330.            result = `next;
  331.            ask = true;
  332.            }
  333.        }
  334.        else
  335.        {
  336.         list<string>nonexisting = filter (string p, packagelist, {
  337.             return ! Pkg::IsAvailable (p);
  338.         });
  339.         if (action != `remove && size (nonexisting) > 0)
  340.         {
  341.             string missing = mergestring (nonexisting, ", ");
  342.             y2error ("Tags %1 aren't available",
  343.                 mergestring (nonexisting, ", "));
  344.             Report::Error (sformat (
  345.             // error report, %1 is a list of packages
  346.             _("Following packages haven't been found on the medium:\n%1"),
  347.             mergestring (nonexisting, "\n")));
  348.             return `cancel;
  349.         }
  350.            foreach (string package, packagelist,        // Yes: install them
  351.            {
  352.            if (action == `install
  353.                // TODO `update: tell the user if already up to date
  354.                || (action == `update && CanBeUpdated (package))) {
  355.                // select package for installation
  356.                if (!Pkg::PkgInstall (package)) {
  357.                // oops, package not found ? try capability
  358.                Pkg::DoProvide ([package]);
  359.                }
  360.            }
  361.            else if (action == `remove) {
  362.                if (!Pkg::PkgDelete (package)) {
  363.                // package failed, try capability
  364.                Pkg::DoRemove ([package]);
  365.                }
  366.            }
  367.            });
  368.  
  369.            if (Pkg::PkgSolve (false))                // Solve dependencies
  370.            {
  371.            result = `next;                    // go-on if no conflicts
  372.            }
  373.            else
  374.            {
  375.            result = (symbol)WFM::CallFunction( "inst_packages", []);    // Ask user if conflicts
  376.            y2milestone ("inst_packages returns %1", result);
  377.            if (result == `accept)
  378.                result = `next;
  379.            }
  380.        }
  381.        }
  382.  
  383.        if (result == `next)                // packages selected ?
  384.        {
  385.        SCR::Write (.target.ycp, "/var/lib/YaST2/failed_packages", []);
  386.        boolean anyToDelete = Pkg::PkgAnyToDelete();
  387.        SlideShow::SetLanguage (UI::GetLanguage(true));
  388.        SlideShow::InitPkgData(true);    // force reinitialization
  389.        SlideShow::OpenSlideShowDialog();
  390.  
  391.        import "PackageInstallation";
  392.        Pkg::TargetLogfile (Installation::destdir + Directory::logdir + "/y2logRPM");
  393.        integer oldvmlinuzsize = (integer) SCR::Read(.target.size, "/boot/vmlinuz");
  394.        list commit_result = PackageInstallation::CommitPackages (0, 0);                // Y: commit them !
  395.        integer newvmlinuzsize = (integer) SCR::Read(.target.size, "/boot/vmlinuz");
  396.  
  397.        SlideShow::CloseSlideShowDialog();
  398.  
  399.        if (Mode::normal ()                // run SuSEconfig only in normal system, not during installation
  400.            && Installation::destdir == "/"
  401.            && ((commit_result[0]:0 > 0)
  402.            || anyToDelete))
  403.        {
  404.            // prepare "you must boot" popup in inst_suseconfig
  405.            Kernel::SetInformAboutKernelChange (oldvmlinuzsize != newvmlinuzsize);
  406.  
  407.            result = (symbol) WFM::CallFunction ("inst_suseconfig", [GetInstArgs::Buttons(false, false)]);
  408.        }
  409.        }
  410.    } while ( ask && Popup::YesNo (
  411.        // Popup dialog contents
  412.        _("Install or remove more packages?")));
  413.  
  414.    UI::CloseDialog();
  415.  
  416.    return (symbol) result;
  417. }
  418.