ACC SHELL

Path : /usr/share/YaST2/clients/
File Upload :
Current File : //usr/share/YaST2/clients/inst_rpmcopy.ycp

/**
 * Module: 		inst_rpmcopy.ycp
 *
 * Authors:		Klaus Kaempf <kkaempf@suse.de>
 *			Stefan Hundhammer <sh@suse.de> (slide show)
 *			Arvin Schnell <arvin@suse.de>
 *
 * Purpose:
 * Install all the RPM packages the user has selected.
 * Show installation dialogue. Show progress bars.
 * Request medium change from user.
 *
 * Packages module :
 *			"installed"
 *
 * $Id: inst_rpmcopy.ycp 61082 2010-03-02 09:10:41Z ug $
 */

{
    textdomain "packager";

    import "Mode";
    import "Stage";
    import "Installation";
    import "Language";
    import "PackageInstallation";
    import "Packages";
    import "SlideShow";
    import "PackageSlideShow";
    import "SlideShowCallbacks";
    import "Popup";
    import "Report";
    import "SourceManager";
    import "Linuxrc";
    import "FileUtils";
    import "AutoinstData";

    include "packager/storage_include.ycp";

    /**
     * Removes all already installed patches and selections.
     * See bugzilla #210552 for more information.
     */
    void RemoveObsoleteResolvables () {
        y2milestone ("--------- removing obsolete selections ---------");

        // this removes only information about selections and applied patches
	// it doesn't remove any package
        y2milestone ("Removing all information about selections and patches in %1", Installation::destdir);
        Pkg::TargetStoreRemove (Installation::destdir, `selection);

	// disabled by FATE #301990, bugzilla #238488
	// Pkg::TargetStoreRemove (Installation::destdir, `patch);

        y2milestone ("--------- removing obsolete selections ---------");
    }

    // ------------------------------------------------------------------------------------------------------
    // begin of commit installation functions
    // ------------------------------------------------------------------------------------------------------

    list <map <string, any> > remaining = [];
    list <string> srcremaining = [];

    /**
     * Fills-up 'remaining' and 'srcremaining' lists with information of
     * objects that need to be installed.
     */
    void InitRemainingPackages () {
	y2milestone ("Looking for remaining packages");

	string file_remaining_packages = Installation::destdir + "/var/lib/YaST2/remaining";
	string file_remaining_srcs     = Installation::destdir + "/var/lib/YaST2/srcremaining";

	// Packages remaining for installation
	if (FileUtils::Exists (file_remaining_packages)) {
	    remaining =
		(list <map <string, any> >) SCR::Read (.target.ycp, [file_remaining_packages, []]);
	    if (remaining == nil)
		remaining = [];
	    y2milestone ("File %1 contains %2 packages",
		file_remaining_packages, size (remaining));
	}

	// repositories remaining for installation
	if (FileUtils::Exists (file_remaining_srcs)) {
	    srcremaining =
		(list<string>) SCR::Read (.target.ycp, [file_remaining_srcs, []]);
	    if (srcremaining == nil)
		srcremaining = [];
	    y2milestone ("File %1 contains %2 packages",
		file_remaining_srcs, size (srcremaining));
	}
    }

    /**
     * And returns whether some objects need to be installed as the result.
     *
     * @return boolean whether some packages need to be installed
     */
    boolean SomePackagesAreRemainForInstallation () {
	// Either 'remaining' or 'srcremaining' are not empty
	integer size_remaining    = (remaining    == nil ? 0 : size (remaining));
	integer size_srcremaining = (srcremaining == nil ? 0 : size (srcremaining));

	y2milestone ("remaining: %1, srcremaining: %2", size_remaining, size_srcremaining);
	return (size_remaining > 0 || size_srcremaining > 0);
    }

    /**
     * Sets remaining packages to be installed
     */
    void InstallRemainingAndBinarySource () {
	// second stage of package installation, re-read list of remaining binary and source
	// packages

	string backupPath = (string) SCR::Read(.target.string, [Installation::destdir + "/var/lib/YaST2/backup_path", ""]);
	if ( backupPath != nil && backupPath != "")
	{
	    y2milestone("create package backups in %1",backupPath);
	    Pkg::CreateBackups (true);
	    Pkg::SetBackupPath (backupPath);
	}

	integer failed_packages = 0;
	y2milestone ("%1 resolvables remaining", size (remaining));
	foreach (map<string,any> res, remaining, ``{
	    string name = res["name"]:"";
	    symbol kind = res["kind"]:`package;
	    string arch = res["arch"]:"";
	    string vers = res["version"]:"";
	    if (! Pkg::ResolvableInstallArchVersion (name, kind, arch, vers))
		failed_packages = failed_packages + 1;
	});

	y2milestone ("%1 source packages remaining", size (srcremaining));
	foreach (string pkg, srcremaining, ``{
	    if (! Pkg::PkgSrcInstall (pkg))
		failed_packages = failed_packages + 1;
	});
	if (failed_packages > 0)
	{
	    // error report, %1 is number
	    Report::Error (sformat(_("Failed to select %1 packages for installation."), failed_packages));
	}
    }

    void AutoinstPostPackages () {
	// post packages from autoinstall
	map <string, any> res = Pkg::DoProvide (AutoinstData::post_packages);
	if (size (res) > 0)
	{
	    foreach (string s, any a, res, ``{
		y2warning ("Pkg::DoProvide failed for %1: %2", s, a);
	    });
	}

        list<string> failed = [];
        list<string> patterns = AutoinstData::post_patterns;
        /* set SoftLock to avoid the installation of recommended patterns (#159466) */
        foreach( map<string,any> p, Pkg::ResolvableProperties ("", `pattern, ""), ``{
            Pkg::ResolvableSetSoftLock( p["name"]:"", `pattern );
        });
        foreach(string p, toset(patterns),
                ``{
            if (! Pkg::ResolvableInstall( p, `pattern ) )
            {
                failed = add(failed, p);
            }
        });

        if (size(failed) > 0 )
        {
            y2error("Error while setting pattern: %1",  mergestring(failed, ","));
            Report::Warning(sformat(_("Could not set patterns: %1."), mergestring(failed, ",")));
        }
        //
        // Solve dependencies
        //
        if( !Pkg::PkgSolve(false) ) {
            Report::Error( _("The package resolver run failed. Please check your software section in the autoyast profile.") );
        }
    }

    symbol InstallPackagesFromMedia (integer current_cd_no, integer maxnumbercds) {
      symbol result = `next;

      y2milestone("Installing packages from media %1 -> %2", current_cd_no, maxnumbercds);

      // 1->1 for default fist stage installation
      // 0->0 for default second stage (or other) installation
      while (current_cd_no <= maxnumbercds) {
	// nothing to install/delete
	if (Pkg::IsAnyResolvable(`any, `to_remove) == false
	    && Pkg::IsAnyResolvable(`any, `to_install) == false)
	{
	    y2milestone ("No package left for installation");
	    break;
	}

	// returns [ int successful, list failed, list remaining ]
	list commit_result = PackageInstallation::CommitPackages( current_cd_no, 0 );

	if (commit_result == nil || size (commit_result) == 0)
	{
	    y2error("Commit failed");
	    string failed = mergestring(commit_result[1]:[], "\n");
	    // error message - displayed in a scrollable text area
	    // %1 - an error message (details)
            Report::LongError(sformat(_("Installation Failed

Details:
%1

Package installation will be aborted.
"),
		Pkg::LastError())
	    );


	    return `abort;
	}

	integer count = commit_result[0]:0;
	y2milestone ("%1 packages installed", count);

	list failed = commit_result[1]:[];
	if (size (failed) > 0)
	{
	    y2milestone ("failed: %1", failed);
	    list previous_failed = (list) SCR::Read (.target.ycp, [Installation::destdir +
								   "/var/lib/YaST2/failed_packages", []]);
	    if (size (previous_failed) > 0)
		failed = union (previous_failed, failed);
	    SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/failed_packages", failed);
	}

	list remaining = commit_result[2]:[];
	if (size (remaining) >= 0)
	{
	    y2milestone ("remaining: %1", remaining);
	    SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/remaining", remaining);
	}
	else
	{
	    SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST2/remaining");
	}

	list srcremaining = commit_result[3]:[];
	if (size (srcremaining) >= 0)
	{
	    y2milestone ("repository remaining: %1", srcremaining);
	    SCR::Write (.target.ycp, Installation::destdir + "/var/lib/YaST2/srcremaining", srcremaining);
	}
	else
	{
	    SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST2/srcremaining");
	}

	if (count < 0)					// aborted by user
	{
	    result = `abort;
	    break;
	}

	// break on first round with Mediums
	if (Stage::initial () && !Mode::test ())
	    break;

	current_cd_no = current_cd_no + 1;
      }
      return result;
    }

    map <string, integer> CountStartingAndMaxMediaNumber () {
	// Bugzilla #170079
	// Default - unrestricted
	map <string, integer> ret = $["maxnumbercds" : 0, "current_cd_no" : 0];

	// has the inst-sys been successfuly unmounted?
	string umount_result = Linuxrc::InstallInf ("umount_result");
	string media = Linuxrc::InstallInf ("InstMode");
	y2milestone("umount result: %1, inst repository type: %2", umount_result, media);

	if (Packages::metadir_used) {
	    // all is in ramdisk, we can install all repositories now, works in every stage
	    ret["current_cd_no"] = 0;
	    ret["maxnumbercds"]  = 0;
	    y2milestone("StartingAndMaxMediaNumber: MetaDir used %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
	} else if (Stage::initial ()) {
	    // is CD or DVD medium mounted? (inst-sys)
	    if (umount_result != "0" && (media == "cd" || media == "dvd"))
	    {
		y2milestone("The installation CD/DVD cannot be changed.");
		// only the first CD will be installed
		ret["current_cd_no"] = 1;
		ret["maxnumbercds"]  = 1;
	    }
	    // otherwise use the default setting - install all media
	    y2milestone("StartingAndMaxMediaNumber: Stage initial %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);

	// Three following cases have the same solution, CDstart = 0, CDfinish = 0
	// ZYPP should solve what it needs and when.
	// Leaving it here as the backward compatibility if someone decides to change it back.

	} else if (Mode::autoinst () && Stage::cont () && size( AutoinstData::post_packages ) > 0) {
	    // one more compatibility feature to old YaST, post-packages
	    // Simply install a list of package after initial installation (only
	    // makes sense with nfs installatons)
	    ret["current_cd_no"]  = 0; // was 1
	    ret["maxnumbercds"]   = 0; // was 10
	    y2milestone("StartingAndMaxMediaNumber: Autoinst in cont %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
	} else if (Stage::cont ()) {
	    // continue with second CD but only in continue mode
	    // bug #170079, let zypp solve needed CDs
	    ret["current_cd_no"]  = 0;
	    ret["maxnumbercds"]   = 0;
	    y2milestone("StartingAndMaxMediaNumber: Stage cont %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
	} else if (Installation::dirinstall_installing_into_dir) {
	    // All in one
	    ret["current_cd_no"]  = 0; // was 1
	    ret["maxnumbercds"]   = 0; // was 10
	    y2milestone("StartingAndMaxMediaNumber: Dir install %1/%2", ret["current_cd_no"]:nil, ret["maxnumbercds"]:nil);
	}

	return ret;
    }

    // ------------------------------------------------------------------------------------------------------
    // end of commit installation functions
    // ------------------------------------------------------------------------------------------------------

    if (Installation::image_only)
	return `auto;

    // bugzilla #208222
    ReleaseHDDUsedAsInstallationSource();

    // bugzilla #326327
    Packages::SlideShowSetUp (Language::language);

    Pkg::SetTextLocale (Language::language);

    SlideShow::SetLanguage (Language::language);

    // Initialize and check whether some packages need to be installed
    // stop proceeding the script if they don't (Second stage)
    if (Stage::cont() && ! Mode::live_installation () && !Mode::autoinst() ) {
	InitRemainingPackages();
	if (SomePackagesAreRemainForInstallation() != true) {
	    y2milestone ("No packages need to be installed, skipping...");
	    return `auto;
	} else {
	    y2milestone ("Some packages need to be installed...");
	}
    }

    // start target, create new rpmdb if none is existing
    // FIXME error checking is missing all around here, initialization could actually fail!
    if (Pkg::TargetInitialize (Installation::destdir) != true) {
	// continue-cancel popup
	if(Popup::ContinueCancel(_("Initializing the target directory failed")) == false) {
	    return `abort;
    	}
    }
    
    if (Mode::update()) {
	// Removes all already installed patches and selections.
	// See bugzilla #210552 for more information.
	RemoveObsoleteResolvables();
    } 

    if (Stage::cont() && ! Mode::live_installation ()) {
	// initialize the package agent in continue mode
	Packages::Init( true );

	// in 1st stage, this is opened already
	SlideShow::OpenDialog ();
    }

    if  (Mode::autoinst () && Stage::cont ()) {
	AutoinstPostPackages();
    }

    // initial mode, move download area, check for repository caching
    if (Stage::initial ()) {
	SourceManager::InstInitSourceMoveDownloadArea();

    // continue mode, set remaining packages to be installed
    } else if (! Mode::live_installation ()){
	InstallRemainingAndBinarySource();
    }

    // Install the software from Medium1 to Mediummax, but not the already
    // installed base packages.
    // This part is also used for installation in running system (Stage::cont ())

    map <string, integer> cdnumbers = CountStartingAndMaxMediaNumber();
    integer maxnumbercds  = cdnumbers["maxnumbercds"]:10;
    integer current_cd_no = cdnumbers["current_cd_no"]:1;

   map <string, map <string,any> > get_setup = SlideShow::GetSetup();
    if (get_setup == nil || get_setup == $[]) {
	y2milestone ("No SlideShow setup has been set, adjusting");
	SlideShow::Setup([$[
	    "name" : "packages",
	    "description" : _("Installing Packages..."),
	    "value" : PackageSlideShow::total_size_to_install / 1024 , // kilobytes
	    "units" : `kb,
	]]);
    }
    get_setup = nil;

    // re-initialize package information
    PackageSlideShow::InitPkgData(true);
    // we want the table
    SlideShow::ShowTable();

    // Do not open a new SlideShow widget, reuse the old one instead
    boolean required_to_open_sl_dialog = (! SlideShow::HaveSlideWidget());

    // BNC #443755
    if (required_to_open_sl_dialog) {
	y2milestone ("SlideShow dialog not yet created");
	SlideShow::OpenDialog();
    }

    // move the progress to the packages stage
    SlideShow::MoveToStage("packages");

    // install packages from CD current_cd_no to CD maxnumbercds
    symbol result = InstallPackagesFromMedia (current_cd_no, maxnumbercds);

    // sync package manager FIXME
    if (result != `abort && ! Stage::initial ())
    {
	y2milestone ("Calling PkgCommit (%1)", 9999);
	Pkg::PkgCommit (9999);
    }

    // BNC #443755
    if (required_to_open_sl_dialog) {
	y2milestone ("Closing previously opened SlideShow dialog");
	SlideShow::CloseDialog();
    }

    if (result != `abort)
    {
	if (Stage::cont ())
	{
	    // some new SCR asgents might have been installed
	    SCR::RegisterNewAgents();
	}
    }
    
    return result;
}

ACC SHELL 2018