/**
 * File:	OSRPkg.ycp
 * Module:	repair
 * Summary:	Packages check
 * Authors:	Johannes Buchhold <jbuch@suse.de>
 *
 * $Id: OSRPkg.ycp 21333 2005-02-07 15:59:08Z jsuchome $
 *
 * Provide osr mode information.
 */

{
    module "OSRPkg";

    textdomain "repair";

    import "Kernel";
    import "Mode";
    import "Report";
    import "Wizard";
    import "Popup";
    import "Stage";

    import "OSRCommon";
    import "OSRSystem";
    import "OSRExecute";
    import "OSRLogFile";
    import "OSRPopup";
    import "OSRPkgUI";
    import "OSRPkgVerify";

    /**
     * Package database files
     */
    list<string> rpm3_db_files = [
				 "/var/lib/rpm/conflictsindex.rpm",
				 "/var/lib/rpm/fileindex.rpm",
				 "/var/lib/rpm/groupindex.rpm",
				 "/var/lib/rpm/nameindex.rpm",
				 "/var/lib/rpm/packages.rpm",
				 "/var/lib/rpm/providesindex.rpm",
				 "/var/lib/rpm/requiredby.rpm",
				 "/var/lib/rpm/triggerindex.rpm"
    ];

    /**
     * Package database files (version >=4)
     */
    list<string> rpm4_db_files = [
	"/var/lib/rpm/Basenames",
	"/var/lib/rpm/Conflictname",
	"/var/lib/rpm/Dirnames",
	"/var/lib/rpm/Filemd5s",
	"/var/lib/rpm/Group",
	"/var/lib/rpm/Installtid",
	"/var/lib/rpm/Name",
	"/var/lib/rpm/Packages",
	"/var/lib/rpm/Providename",
	"/var/lib/rpm/Provideversion",
	"/var/lib/rpm/Pubkeys",
	"/var/lib/rpm/Requirename",
	"/var/lib/rpm/Requireversion",
	"/var/lib/rpm/Sha1header",
	"/var/lib/rpm/Sigmd5",
	"/var/lib/rpm/Triggername"
    ];

    /**
     * Current package database files
     */
    list<string> rpm_db_files	= rpm3_db_files;

    /**
     * if a backup (YaST) of the package  database was
     * created.
     * Save rpm?_db_files[X] -> rpm?_db_files[X].old
     */
    boolean backup_created = false;

    /**
     * Mount point where the target system is mounted.
     */
    global string root_mountpoint = "";

    /**
     * Help text to show errors.
     */
    global string help_text	   = "";

    /**
     * Error text.
     */
    global string error_text	   = "";

    /**
     * Dialog description for the install missing or damaged packages.
     */
    global list install_missing_dialog_data = [];

    /**
     * Missing packages database files.
     */
    global list <string> not_found_files  = [];

    /**
     * Not installed base packages or damaged packages.
     */
    global list <string> missing_packages = [];

    /**
     * All new installed packages.
     */
    list <string> reinstalled_packages    = [];

    /**
     * This will be local when converted to a Module::
     * Has Pkg::TargetInit run?
     */
    boolean target_initialized = false;

    /**
     * Before first opening pkg database, we need to close it preventively
     * (because it could be opened with a different root path).
     * This variable says, if it is first time now.
     */
    boolean first_time_openpkg = true;

    /**
     * This will be local when converted to a Module::
     * Has Pkg::SourceStartCache run?
     */
    boolean source_initialized = false;

    boolean package_db_repaired = false;


    list<string> architecture_packages = [];

    // list of packages in minimal selection (read it just after pkg target is
    // initialized to avoid bug #30423)
    list<string> minimal_selection = [];

    // general help text about package database
    string default_package_help  = _("
<p>The package database administers all
information of the installed software packages.
The most common way to add a new program or library
to a Linux system is to install a new package.
In doing so, the install routine copies all files of the
package to the target and registers the package in
the package database.</P>
");

    // general help text about damaged package database
    string damaged_package_help = _("
<P>If the package database is damaged, installing
and removing packages or updating the system
is not possible.</P>
");

    /**
     * Reset the module settings.
     */
    global define void Reset()``{

	not_found_files		= [];
	error_text		= "";
	help_text		= "";
	root_mountpoint		= "";
	missing_packages	= [];

	architecture_packages	= [];
	package_db_repaired	= false;
	reinstalled_packages    = [];
	install_missing_dialog_data = [];

	if (target_initialized )
	{
	    target_initialized = ! Pkg::TargetFinish ();
	}
	// don't reset source_initialized
	// don't reset reinstalled_packages
	OSRPkgUI::Reset();
	OSRPkgVerify::Reset();
    }

    /**
     * Constructor.
     */
    global define void OSRPkg()``{
	Reset();
    }

    define list<string> get_minimal_selection () ``{

	if (Mode::test ())
	{
	    return [ "test" ];
	}
	if (minimal_selection == [] || minimal_selection == nil)
	{
	    minimal_selection = (list<string>)
		Pkg::SelectionContent("Minimal", false, "");
	    // add also contents of required selections: (bug #37133)
	    map sel_data = Pkg::SelectionData ("Minimal");
	    foreach (string req, sel_data["requires"]:[], ``{
		y2debug ("required selection: %1", req);
		minimal_selection = (list<string>) union (
		    minimal_selection, Pkg::SelectionContent (req, false, ""));
		y2debug ("minimal: %1", minimal_selection);
	    });
	}
	return minimal_selection;
    }

    /**
     * Open the package database.
     */
    global define boolean OpenPkg( string root )``{

	if (Mode::test ()) return true;

	import "Packages";

	y2milestone("Open pkg database with target system  -%1-", root );
	if (root != "" && root != nil ) root_mountpoint = root;

	// open the package source
	if (! Stage::initial () )
	{
	    source_initialized = source_initialized ||
		Pkg::SourceStartCache (true) != [];
	}
	else
	{
	    if (! source_initialized  )
	    {
		y2milestone("Calling package module");

		//change root for the Package module call
		OSRSystem::SetOrgRoot();

		Packages::Init (true);

		architecture_packages = Packages::ComputeSystemPackageList();
		y2milestone("Add architecture packages %1",
		    architecture_packages );

		//reset root environment
		OSRSystem::ChangeRoot(root);

		source_initialized = true;
	    }
	}

	// open target system for Pkg access
	if (!target_initialized)
	{
	    if (first_time_openpkg)
	    {
		y2milestone ("first time initializig -> finish target before");
		Pkg::TargetFinish ();
		first_time_openpkg = false;
	    }
	    target_initialized = Pkg::TargetInit ( root, false);
	    get_minimal_selection ();
	}

	// something failed
	if (! target_initialized || ! source_initialized )
	{
	    y2error("Opening the package database failed. ");
	    y2error("Target is initialised: %1", target_initialized);
	    y2error("Source is initialised: %1", source_initialized);

	    // build help and error text for following repair dialog
	    help_text  = default_package_help + damaged_package_help;
	    // error popup
	    error_text = _("
YaST cannot open the package database.
Try rebuilding the package
database or reverting a backup.
");
	}
	return target_initialized && source_initialized;
    }

    /**
     * Check if target product is the same as the source (bug #45306)
     * @return true if product are the same
     */
    global define boolean CheckProductVersions () {

	if (Mode::test ()) return true;

	integer source_id	= 1;

	// TODO we could use Packages::theSources
	list curr_sources	= Pkg::SourceGetCurrent (true);

	source_id		= curr_sources[0]:source_id;
	map source_product	= Pkg::SourceProduct (source_id);
	list all_products	= Pkg::TargetProducts ();
	map target_product	= all_products[0]:$[];

	y2debug ("source product: %1", source_product);
	y2debug  ("target_product: %1", target_product);

	if (source_product["product"]:"" != target_product["product"]:"")
	{
	    y2error("target product (%1) is different from source product (%2)",
		target_product["product"]:"", source_product["product"]:"");
	    y2warning ("source product: %1", source_product);
	    y2warning ("target_product: %1", target_product);
	    return false;
	}
	return true;
    }

    /**
     * Return false if db files are missing.
     * Save missing files in the list not_found_files.
     */
    global define boolean CheckDB (string root )``{

	if (root != "" && root != nil ) root_mountpoint = root;
	not_found_files = [];

	// Now the version of pkg databse is checked
	rpm_db_files = rpm3_db_files;
	if (OSRExecute::Command (.local.bash, sformat("/usr/bin/test -f %1",
	    root_mountpoint + "/var/lib/rpm/Packages")))
	    rpm_db_files = rpm4_db_files;

	// check all database files
	foreach(string file, rpm_db_files, ``{
	    if (!OSRExecute::Command (.local.bash,
		    sformat("/usr/bin/test -f %1", root_mountpoint + file)))
		not_found_files = add(not_found_files, file);
	});

	// if files are missing
	if (size( not_found_files ) > 0 )
	{
	    help_text  = default_package_help + damaged_package_help;
	    // error message: files (%1) not found
	    error_text = sformat(_("
YaST checked the package database and
did not find the following files
that belong to the package database.

%1
"),mergestring(not_found_files,"\n"));

	}
	else
	{
	    // try to open the database.
	    // if open fails OpenPkg set help and error text
	    return OpenPkg( root_mountpoint );
	}
	return size( not_found_files ) == 0;
    }

    /**
     * Make a backup of the package database
     * files.
     */
    define boolean backup_package_db()``{

	// only create one package at the
	// first call of backup_package_db
	if (backup_created ) return true;
	list<boolean> ret = [];

	foreach(string file, rpm_db_files, ``{
	    string f = root_mountpoint  + file;
	    if (!contains (not_found_files , file))
		ret = add (ret, OSRExecute::Command (.local.bash,
		    sformat("/bin/cp %1 %1.old",f)));
	});

	// if not error was found
	if (size(filter(boolean r, ret, ``( r != true ))) == 0 )
	{
	    backup_created = true;
	}
	return backup_created;
    }

    /**
     * Revert the YaST backup of the package database.
     */
    define boolean revert_packages_backup()``{
	if (! backup_created ) return false;

	list<boolean> ret = [];
	foreach (string file, rpm_db_files, ``{
	    string f = root_mountpoint  + file;

	    //if orginal file exists
	    if (! contains( not_found_files , file))
	    {
		ret = add( ret , OSRExecute::Command(.local.bash, sformat("/bin/cp %1.old %1",f)));
	    }
	});

	// if not error was occurred
	if (size(filter(boolean r, ret, ``( r != true ))) == 0 )
	{
	    Report::Message(_("\nReverting to the backup was successful.
"));
	    return true;
	}
	else
	{
	    // error popup
	    Report::Error(_("
Reverting to the backup was not
successful. Select another
backup or try to rebuild
the package database.
"));
	    return false;
	}
    };

    /**
     * Rebuild the package database.
     */
    define boolean rebuild_package_db( boolean show_message )``{

	boolean ret = true;

	UI::OpenDialog (`VBox (
	    `VSpacing(1),
	    // wait popup label
	    `Label(_("Rebuilding the package database. Please wait...")),
	    `VSpacing(1)
	));

	if (backup_created || size(not_found_files ) > 0 )
	{
	    // some package database files are missing
	    if ((! Mode::test ())  && size( not_found_files ) > 0 )
	    {
		ret = WFM::Execute (.local.bash,
		    sformat("/bin/rpm --root %1 --initdb",root_mountpoint))== 0;
	    }

	    // rebuild package database
	    ret = ret && WFM::Execute (.local.bash,
		sformat("/bin/rpm --root %1 --rebuilddb",root_mountpoint)) == 0;

	    package_db_repaired = true;

	    UI::CloseDialog();
	    if (show_message )
	    {
		if (ret )
		{
		    Report::Message(_("
YaST successfully rebuilt the package
database.
"));
		}
		else
		{
		    Report::Error(_("
YaST could not rebuild the package
database. Revert to a backup of
the package database.
"));
		}
	    }
	}
	else {
	    UI::CloseDialog();
	    ret = false;
	}
	return ret;
    }


    /**
     * Revert a backup of the package database
     * from /var/adm/backup/rpmdb.
     */
    define boolean revert_daily_backup()``{

	if (!backup_created && size(not_found_files) == 0 )
	    return false;

	boolean ret		= false;
	string file_path	= "packages.rpm";
	string backup_path	= (string)
	    SCR::Read(.sysconfig.backup.RPMDB_BACKUP_DIR);

	if (backup_path == "" || backup_path == nil )
	{
	    y2error ("No sysconfig backup path found. Use default /var/adm/backup/rpmdb");
	    backup_path = "/var/adm/backup/rpmdb";
	}

	list<string> files = (list<string>) SCR::Read(.target.dir, backup_path);
	files = filter(string f, files, ``(substring(f, 0, size(file_path)) == file_path ));
	y2milestone("Found files for backup: %1", files );

	//packages.rpm-20021105.gz
	list<string> dates = maplist(string f, files, ``(substring(f, size(file_path)+1 , 8)));
	dates 	   = sort(string f, string ff, dates, ``( f > ff ));
	dates      = maplist(string f, dates, ``(sformat("%1.%2.%3", substring( f,0,4),
							 substring(f,4,2),
							 substring(f,6,2))));
	list<list> items = maplist(string f, dates, ``([f,""]));

	// no backup was found
	if (size(items ) == 0 )
	{
	    Report::Error(sformat(_("
YaST could not find any package database
backup files. Normally, a cron job creates
daily backups of the package database and
stores the backups in the directory
%1. However, no backup files could
be found in this directory.
Try another repair method.
"),backup_path));
	    return false;
	}

	string selected  = OSRPopup::RadioButtonGroupText(_("Select one backup time:"),
						   _("
YaST found several backups
of the package database.
Select the date (YYYY/MM/DD)
of the backup to which 
to revert.
"), items, dates[0]:"", "", false);

	y2milestone("The selected item %1", selected);

	if (selected != "" )
	{
	    selected = find(string f, files, ``(issubstring(f, mergestring(splitstring(selected, "."),"") )));
	    selected = backup_path + "/"+selected;
	    if (OSRExecute::Command(.local.bash, sformat("/usr/bin/test -f %2/%1", selected, root_mountpoint )))
	    {
		if (! Mode::test () && WFM::Execute(.local.bash, sformat("/bin/gunzip < %2/%1  \
> %2/var/lib/rpm/packages.rpm", selected ,root_mountpoint )) == 0   )
		{
		    if (rebuild_package_db(false) ) 
		    {
			Report::Message(_("
Reverting to the backup of the package
database was successful.
"));
			ret = true;
		    }
		}
		else
		{
		    Report::Error(_("
Reverting to the backup of the package
database was not successful.
"));
		}
		package_db_repaired = true;
	    }
	    else
	    {
		//should never happpen
		y2error("Selected package update file not found");
	    }
	}
	return ret;
    }

    /**
     * Repair or initialise a damaged package
     * damaged. Call CheckDB before.
     */
    global define symbol RepairDB()``{

	string repair_header = _("Repair Package Database");

	if (! backup_package_db())
	{
	    y2error("Creating backup of package db was not successful");
	    if (size(not_found_files ) == 0 ) return `error;
	}

	term r_options = `VBox (
	    `Left (
		// popup headline
		`Label(_("Select a repair method or skip repairing."))),
	    `VSpacing(0.5),
	    `Left (
		// radio button label
		`RadioButton(`id(`rebuild), _("Rebuild Package Database"),true)
	    ),
	    `Left (
		// radio button label
		`RadioButton(`id(`daily), _("Revert to Daily Backup"), false)
	    )
	);

	term last_entry = `RadioButton(`id(`revert ));

	if (! package_db_repaired )
	    last_entry = add( last_entry , `opt(`disabled ));

	last_entry = add( last_entry,  _("Revert to Orginal Package Database (saved by YaST)"));
	last_entry = add( last_entry, false);
	r_options  = add( r_options, last_entry);

	if (! OSRPopup::OpenMainRepairDialog( repair_header , error_text, r_options ))
	{
	    y2error("Could not open main dialog for repairing package database.");
	    return `error;
	}

	symbol ret = `ok;
	repeat
	{
	    ret             = (symbol)UI::UserInput();
	    symbol selected = (symbol)UI::QueryWidget(`id(`rb), `CurrentButton);

	    if (ret == `help )
	    {
		Popup::LongText( OSRPopup::help_headline , `RichText( help_text ), 50, 20);
	    }
	    else if (ret == `ok )
	    {
		UI::CloseDialog();

		boolean rret = false;
		// execute selected repair method
		if (selected == `rebuild)
		    rret = rebuild_package_db(true);
		else if (selected == `daily)
		    rret = revert_daily_backup();
		else if (selected == `revert)
		    rret = revert_packages_backup();

		if (!rret)
		{
		    if (!OSRPopup::OpenMainRepairDialog (repair_header,
			error_text, r_options))
		    {
			y2error("Could not open main dialog");
			return `error;
		    }
		    ret = `again;
		}
	    }
	} until( ret == `cancel || ret == `abort || ret == `ok );

	if (ret != `ok )  UI::CloseDialog();

	return ret;
    }

    /**
     * Return all packages which should be verified
     */
    define list<string> get_verify_packages(string what ) ``{

	list<string>  ret = [];

	// return all packages
	if (what == "all" )
	{
	    ret = Pkg::GetPackages(`installed, true);
	}
	// return base packages only
	else if (what == "base")
	{
	    list<string> minimal = get_minimal_selection ();
	    list<string> special = [];

	    minimal	= filter (string p, minimal, ``( Pkg::IsAvailable(p)));
	    ret		= (list<string>) union (minimal, special) ;
	}
	else
	{
	    y2error("Parameter what not valid. Only all or base are allowed.");
	    ret =  nil;
	}
	if (ret != nil )
	{
	    ret = (list<string>) union (ret, architecture_packages );
	}
	return ret;
    }


    /**
     * Check if all minimal required packages are installed.
     */
    global define boolean CheckMinimum(string root )``{

	// reset missing package
	missing_packages = [];

	if (root != "" && root != nil ) root_mountpoint = root;

	if (! OpenPkg( root_mountpoint ))
	{
	    y2error("Opening the package database failed. Checking minimal package selection is not possible.");
	    y2error("Please call CheckDB before calling CheckMinimum");
	    return false;
	}

	list<string> installed_packages = Pkg::GetPackages(`installed, true);
	list<string> minimal_packages   = get_verify_packages( "base" );

	missing_packages = filter(string pkg_name, minimal_packages, ``( ! contains(installed_packages, pkg_name )));

	// fix Pkg bug. GetPackages get not the reinstalled_packages!!
	// (seems to be fixed in 9.0 ...)
	missing_packages = filter(string pkg_name, missing_packages, ``( ! contains( reinstalled_packages, pkg_name)));


	boolean ret      = size(missing_packages) == 0;

	if (! ret )
	{
	    y2error ("These packages belonging to the minimal selection were not found: %1", missing_packages);
	    // set information for repair dialog
	    install_missing_dialog_data = [
		// headline
		_("Missing Packages"),
		// check for package minimum summary, 1st part (table follows)
		_("
YaST checked the package selection of
the system. The following packages are
not installed."),

		// check for package minimum summary, last part (below table)
		_("
The listed packages belong to the minimal
package selection. Installing these
packages is recommended.  Press
\"Repair \" to install all selected 
packages in the list.
"),
		// check for package minimum help text 1/2
		_("
<P>&product; needs at least some packages for
basic system functionality. Without these
packages, the system is not executable.</P>
") +

		// check for package minimum help text 2/2, %1 is tool name
		sformat (_("<P>%1 checks if all required packages for a
minimal system are installed. If
some packages are missing, %1 offers to
install the missing packages.</P>
"), OSRCommon::tool_name),
		// table headline (package list follows)
		_("&Missing Packages to Install:"),
		[]
	    ];
	}
	return ret;

    };

    /**
     * Verify all specified packages.
     * @param root The mount point where the target system is mounted.
     * @param what "all" or "base" packages
     * @param expert_mode Show the verify protocol too
     * @param reset Clear missing_packages before start verifying.
     */
    global define symbol VerifyPackages(string root, string what , boolean expert_mode, boolean reset )``{

	if (Mode::test ())
	    return `next;

	if (root != "" && root != nil )
	{
	    root_mountpoint = root;
	}

	if (reset )
	{
	    missing_packages = [];
	}

	// open package database
	if (! OpenPkg(root_mountpoint) )
	{
	    y2error("Opening the package database failed. Verify package not possible");
	    return `error;
	}

	if (! CheckProductVersions ())
	{
	    return `different_products;
	}

	list<string> check_packages = toset(get_verify_packages(what));

	if (check_packages == nil ||  size(check_packages) == 0 )
	{
	    y2error("No packages to verify found. Stop verify and return error.");
	    return `error;
	}

	// dialog headline
	string headline = ( what != "all" ) ? _("Verifying base packages...") :
	// dialog headline
	_("Verifying all installed packages...");

	// open dialog
	if (! OSRPkgUI::OpenVerifyDialog (size(check_packages), headline , expert_mode) )
	{
	    y2error("Verify Dialog can not be opened");
	    return `error;
	}

	symbol ret  = `again;
	string rret = "";
	repeat
	{
	    // verify all selected packages
	    foreach(string p, check_packages, ``{

		if (ret != `abort )
		{
		    rret = (string) UI::PollInput();

		    if (! (rret == "" || rret == nil ))
		    {
			ret = OSRPkgUI::EvalUserInput(rret );
			if (ret == `abort ) return `abort;
			if (ret == `pause )
			{
			    repeat
			    {
				y2milestone("Starting pause loop");
				rret = (string) UI::UserInput();
				ret  = OSRPkgUI::EvalUserInput (rret);
				if (ret == `abort )
				    return `abort;
			    } until (ret == `continue || ret == `abort ||
				     ret == `cancel);
			}
		    }

		    if (! OSRPkgVerify::PackageVerified (p) &&
			ret != `abort && ret != `cancel)
		    {
			boolean ver = OSRPkgVerify::Verify (p, root_mountpoint);
			OSRPkgUI::AddPackageSummary (p);
			if (!ver )
			{
			    missing_packages = add (missing_packages, p );
			}
		    }
		}
	    });
	    OSRPkgUI::Finish();

	    // finish verified wait for user input in expert mode.
	    if (ret != `abort && OSRPkgUI::expert_mode )
	    {
		check_packages = [];
		rret = (string) UI::UserInput();
		y2milestone(" user input get signal %1", rret);
		if (ret != nil  )  // e.g.: get a `cancel or `abort
		{
		    ret = OSRPkgUI::EvalUserInput( rret );
		}
		else {
		    ret = `next;
		}

		// all packages verified.
		if (ret == `abort || ret == `cancel ) ret = `next;
	    }
	    // close dialog in normal mode
	    else {
		ret = `next;
	    }
	} until ( ret == `next || ret == `abort || ret == `cancel );
	UI::CloseDialog();

	missing_packages = OSRPkgVerify::not_successful_verified;
	OSRPkgVerify::WriteVerifiedPackages( check_packages, false);

	if (size( missing_packages ) > 0)
	{
	    // button label
	    string protocol_label = _("Show Log");
	    OSRPkgUI::expert_mode = true;
	    install_missing_dialog_data = [
		// dialog headline
		_("Unverified Packages"),
		// package verification summary, 1st part (table follows)
		_("
YaST verified the installed software
and found problems in the following
packages.
"),
		// package verification summary, last part
		_("
These packages probably differ from their
originally installed versions. Check
the packages to reinstall and start
the reinstallation process by pressing
\"Repair\".
"),

		// package verification summary, help text (%1 is button label)
		sformat (_("
<p>YaST has verified all installed packages. Some
of these packages contain errors. For details,
see the log of the verification process.
To open the log, press <b>%1</b>.</p>
"), protocol_label) +

		// package verification summary 2/3
_("<p>There, see if files of the package are
missing or the data of the package in the package
database differs from the installed files of the
package.</P>")	+

		// package verification summary 3/3
_("<p>Sometimes, verification of the package could 
report errors even if the package is correctly
installed and works fine. That is why you should
reinstall only the packages that do not work properly.</p>
"),
		// table headline (package list follows)
		_("Packages with Problems:"),
		[ [
		    `Right(`PushButton( `id(`protocol), protocol_label )),
		    `protocol, OSRPkgUI::ProtocolDialog
		] ]
	     ];
	}
	return ret;
    }

    /**
     * Install selected Packages. The packages are damaged or not install.
     * Call CheckMinimum or VerifyPackages before.
     */
    global define symbol InstallMissing(boolean use_dialog )``{

	symbol ret = `ok;

	if (size(missing_packages) > 0 )
	{
	    list<list> item_list = [];
	    foreach(string item, missing_packages, ``{
		item_list = add( item_list, [item, false]);
	    });
	    item_list = OSRPkgUI::update_missing_packages (item_list, true);

	    if (use_dialog )
	    {
		missing_packages = OSRPopup::MultiSelectionBox (
		    install_missing_dialog_data[0]:"",
		    install_missing_dialog_data[1]:"",
		    install_missing_dialog_data[2]:"",
		    install_missing_dialog_data[3]:"",
		    install_missing_dialog_data[4]:"",
		    item_list,
		    install_missing_dialog_data[5]:[]
		);
	    }

	   if (missing_packages == [] )
	   {
	       y2milestone("No packages to install. User skiped reinstall.");
	       ret = `cancel;
	   }
	   else
	   {
		y2milestone("Install missing or damaged packages %1", missing_packages );
		if (OpenPkg(root_mountpoint ))
		{
		    boolean ok = true;

		    foreach (string p, missing_packages , ``{
			ok = ok && Pkg::PkgInstall (p);
			if (! ok )
			{
			    y2error("Change the state to install for package %1 failed", p );
			}
		    });

		    ok = ok && Pkg::PkgSolve (false);

		    y2milestone("Solving dependencies returned %1", ok );

		    list result = Pkg::PkgCommit (0);
		    y2milestone ("PkgCommit: %1", result );

		    ok = ok && result[1]:nil == [] && result[2]:nil == [];
		    Wizard::CreateDialog ();
//                    Wizard::SetTitleIcon("repair");TODO
		    Wizard::SetTitleIcon("misc");
                    WFM::CallFunction ("inst_suseconfig", [false, false]);

		    Wizard::CloseDialog ();

		    if (ok)
		    {
			reinstalled_packages = missing_packages;
			y2milestone("All reinstalled_packages: %1",
			    reinstalled_packages );
			ret = `ok;
		    }
		    else ret = `error;
		}
		else {
		    y2error("Opening the ppackage database failed");
		    ret = `error;
		}
	    }
	}
	else {
	    y2error("No missing packages. Set missing_packages before.");
	    ret = `cancel;
	}
	return ret;
    }


}//EOF
