[yast-commit] r39786 - in /trunk/metapackage: OneClickInstall.ycp OneClickInstallUI.ycp OneClickInstallUrlHandler.ycp OneClickInstallWorker.ycp OneClickInstallWorkerResponse.ycp YPX.pm
Author: mvidner Date: Mon Jul 30 14:56:09 2007 New Revision: 39786 URL: http://svn.opensuse.org/viewcvs/yast?rev=39786&view=rev Log: Implementing http://en.opensuse.org/Standards/One_Click_Install - Added http://benjiweber.co.uk/OCI/deploy.tar.gz - see http://lists.opensuse.org/yast-devel/2007-07/msg00082.html Added: trunk/metapackage/OneClickInstall.ycp (with props) trunk/metapackage/OneClickInstallUI.ycp (with props) trunk/metapackage/OneClickInstallUrlHandler.ycp (with props) trunk/metapackage/OneClickInstallWorker.ycp (with props) trunk/metapackage/OneClickInstallWorkerResponse.ycp (with props) trunk/metapackage/YPX.pm Added: trunk/metapackage/OneClickInstall.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/OneClickInstall.ycp?rev=39786&view=auto ============================================================================== --- trunk/metapackage/OneClickInstall.ycp (added) +++ trunk/metapackage/OneClickInstall.ycp Mon Jul 30 14:56:09 2007 @@ -0,0 +1,739 @@ +{ + /** + * Module to provide simple API for working with the One Click Install metapackages. + * Enables removal of non-UI logic from UI module. + **/ + textdomain "OneClickInstall"; + module "OneClickInstall"; + + import "XML"; + import "Product"; + import "Language"; + + import "YPX"; + + /** + * repositories = + * $[ url => + * $[ + * name, + * summary, + * description, + * recommended + * ] + * + * ] + **/ + map<string, map<string,string> > repositories = $[]; + + /** + * software = + * $[ name => + * $[ + * summary, + * description, + * recommended + * ] + * ] + **/ + map<string, map<string,string> > software = $[]; + + //Whether the user should remain subscribed to these repositories post installation. + boolean remainSubscribed = true; + + //The name of this software bundle. + string name = ""; + + //The summary of this software bundle. + string summary = ""; + + //The description of this software bundle. + string description = ""; + + /** + * + * Load the Metapackage from the URL supplied for further processing. + * Converts from original form into a simple two lists, one of repositories, other of software. + * Uses the Product.ycp to obtain the correct version for our product. + * Uses the Language.ycp to obtain correct strings for our language. + * + * Picks the strings, mirror, and product at evaluation time. + + * N.B. This must be called before any of the rest of the methods. + * + * Internally the following format is used: + * repositories = + * $[ url => + * $[ + * name, + * summary, + * description, + * recommended + * ] + * + * ] + * + * software = + * $[ name => + * $[ + * summary, + * description, + * action, + * type, + * recommended + * ] + * ] + * @param url The file to load the xml from. + **/ + global void Load(string url) + { + //Load the XML from file. + any xml = YPX::Load(url); + + //Try and load the name. + name = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/name"); + if (name == "") + name = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/name"); + + string rs = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/remainSubscribed"); + if (rs == "") + rs = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/remainSubscribed"); + if (rs == "false") + remainSubscribed = false; + else + remainSubscribed = true; + + + //Try and load the summary. + summary = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/summary[@lang='" + Language::language + "']"); + if (summary == "") + summary = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/summary[not(@lang)]"); + if (summary == "") + summary = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/summary[@lang='" + Language::language + "']"); + if (summary == "") + summary = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/summary[not(@lang)]"); + + //Try and load the description. + description = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/description[@lang='" + Language::language + "']"); + if (description == "") + description = YPX::SelectValue(xml,"/metapackage/group[@distversion='" + Product::name + "']/description[not(@lang)]"); + if (description == "") + description = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/description[@lang='" + Language::language + "']"); + if (description == "") + description = YPX::SelectValue(xml,"/metapackage/group[not(@distversion)]/description[not(@lang)]"); + + //Load the repository details into our internal format from xml. + //We want to load details for our specific version. + string REPO_XPATH = "/metapackage/group[@distversion='" + Product::name + "']/repositories/repository"; + //If that fails, use any. + string FALLBACK_REPO_XPATH = "/metapackage/group[not(@distversion)]/repositories/repository"; + + + //Select the repository URLs from the XML. + list<string> repoURLs = YPX::SelectValues(xml,REPO_XPATH + "/url"); + //If we didn't have any try fallback xpath. + if (size(repoURLs) == 0) + { + REPO_XPATH = FALLBACK_REPO_XPATH; + repoURLs = YPX::SelectValues(xml,REPO_XPATH + "/url"); + } + //Loop through the repo URLs and query the other details from the XML. + foreach (string url, repoURLs, + { + //Construct xpath to query details of this specific repository + string THIS_REPO_XPATH = REPO_XPATH + "[url='" + url + "']/"; + string recommended = YPX::SelectValue(xml,THIS_REPO_XPATH + "@recommended"); + + //If recommended not specified we default to true. + if (recommended != "false") + recommended = "true"; + + //Find the name of this repository + string name = YPX::SelectValue(xml,THIS_REPO_XPATH + "name"); + //Find the summary of this repository, in our language. + string summary = YPX::SelectValue(xml,THIS_REPO_XPATH + "summary[@lang='"+ Language::language +"']"); + //If that failed, try without a language. + if (summary == "") + summary = YPX::SelectValue(xml,THIS_REPO_XPATH + "summary[not(@lang)]"); + //Find the description of this repository, in our language. + string description = YPX::SelectValue(xml,THIS_REPO_XPATH + "description[@lang='"+ Language::language +"']"); + //If that failed, try without a language. + if (description == "") + description = YPX::SelectValue(xml,THIS_REPO_XPATH + "description[not(@lang)]"); + //Store this repository details in our list. + map<string,string> repoDetails = + $[ + "name":name, + "summary":summary, + "description":description, + "recommended":recommended + ]; + repositories = add(repositories,url,repoDetails); + }); + + //Load package names for this distversion. + string SOFTWARE_XPATH = "/metapackage/group[@distversion='" + Product::name + "']/software/item"; + //Incase that isn't specified use any where distversion is not specified. + string FALLBACK_SOFTWARE_XPATH = "/metapackage/group[not(@distversion)]/software/item"; + list<string> softwareNames = YPX::SelectValues(xml,SOFTWARE_XPATH+ "/name"); + //If we didn't have any try fallback xpath. + if (size(softwareNames) == 0) + { + SOFTWARE_XPATH = FALLBACK_SOFTWARE_XPATH; + softwareNames = YPX::SelectValues(xml,SOFTWARE_XPATH + "/name"); + } + foreach (string name, softwareNames, + { + //Construct xpath to query details of this specific software. + string THIS_SOFTWARE_XPATH = SOFTWARE_XPATH + "[name='" + name + "']/"; + //Check whether it was recommended. + string recommended = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "@recommended"); + //If recommended not specified we default to true. + if (recommended != "false") + recommended = "true"; + string action = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "@action"); + //If action not specified we default to install. + if (action != "remove") + action = "install"; + string type = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "@type"); + //If action not specified we default to install. + if (type != "pattern") + type = "package"; + //Find the summary for this software, preferably in our language. + string summary = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "summary[@lang='"+ Language::language +"']"); + if (summary == "") + summary = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "summary[not(@lang)]"); + //Find the description of this software, preferably in our language. + string description = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "description[@lang='"+ Language::language +"']"); + if (description == "") + description = YPX::SelectValue(xml,THIS_SOFTWARE_XPATH + "description[not(@lang)]"); + //Store these software details in our list. + map<string,string> softwareDetails = + $[ + "summary":summary, + "description":description, + "action":action, + "type":type, + "recommended":recommended + ]; + software = add(software,name,softwareDetails); + }); + } + + /** <region name="Repositories"> **/ + + /** + * @return a list of the URLs of the repositories currently selected for addition. + **/ + global list<string> GetRequiredRepositories() + { + list<string> repoURLs = []; + foreach (string repoURL, map<string,string> repoDetails, repositories, + { + if (repoDetails["recommended"]:"false" == "true") + repoURLs = add(repoURLs, repoURL); + }); + return repoURLs; + } + + /** + * Ensures that the repository with the specified URL is selected for addition. + * @param url the url of the repository to ensure is selected for addition. + **/ + global void SetRequiredRepository(string url) + { + map<string,string> repoDetails = repositories[url]:nil; + if (repoDetails == nil) + return; + repoDetails = add(repoDetails,"recommended","true"); + repositories = add(repositories,url,repoDetails); + } + + /** + * @return a list of the URLs of the repositories currently NOT selected for addition. + **/ + global list<string> GetNonRequiredRepositories() + { + list<string> repoURLs = []; + foreach (string repoURL, map<string,string> repoDetails, repositories, + { + if (repoDetails["recommended"]:"false" == "false") + repoURLs = add(repoURLs, repoURL); + }); + return repoURLs; + } + + /** + * Ensures that the repository with the specified URL is NOT selected for addition. + * @param url the url to ensure is not selected for addition + **/ + global void SetNonRequiredRepository(string url) + { + map<string,string> repoDetails = repositories[url]:nil; + if (repoDetails == nil) + return; + repoDetails = add(repoDetails,"recommended","false"); + repositories = add(repositories,url,repoDetails); + } + + + /** + * Ensures that the repositories with specified URLs are selected for addition, and all others are not. + * @param urls the urls to ensure are selected. + **/ + global void SetRequiredRepositories(list<string> urls) + { + foreach (string url, map<string,string> repoDetails, repositories, + { + if (contains(urls,url)) + { + SetRequiredRepository(url); + } else + { + SetNonRequiredRepository(url); + } + }); + } + + + /** + * @return the name of the repository with the specified name. + **/ + global string GetRepositoryName(string url) + { + map<string,string> repoDetails = repositories[url]:nil; + if (repoDetails == nil) + return ""; + return repoDetails["name"]:""; + } + + /** + * @return the summary of the repository with the specified name. + * This will be in the user's current language if there was a localised summary available. + **/ + global string GetRepositorySummary(string url) + { + map<string,string> repoDetails = repositories[url]:nil; + if (repoDetails == nil) + return ""; + return repoDetails["summary"]:""; + } + + /** + * @return the description of the repository with the specified name. + * This will be in the user's current language if there was a localised description available. + **/ + global string GetRepositoryDescription(string url) + { + map<string,string> repoDetails = repositories[url]:nil; + if (repoDetails == nil) + return ""; + return repoDetails["description"]:""; + } + + /** </region> **/ + + /** <region name="Software"> **/ + + /** + * @return a list of the names of the software currently selected for installation. + **/ + global list<string> GetRequiredSoftware() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["recommended"]:"false" == "true") && (softwareDetails["action"]:"install" == "install")) + names = add(names, name); + }); + return names; + } + + global list<string> GetRequiredPackages() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ( + (softwareDetails["recommended"]:"false" == "true") && + (softwareDetails["action"]:"install" == "install") && + (softwareDetails["type"]:"package" == "package") + ) + { + names = add(names, name); + } + }); + return names; + } + + global list<string> GetRequiredPatterns() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ( + (softwareDetails["recommended"]:"false" == "true") && + (softwareDetails["action"]:"install" == "install") && + (softwareDetails["type"]:"package" == "pattern") + ) + { + names = add(names, name); + } + }); + return names; + } + + /** + * @return a list of the names of the software currently selected for removal. + **/ + global list<string> GetRequiredRemoveSoftware() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["recommended"]:"false" == "true") && (softwareDetails["action"]:"install" == "remove")) + names = add(names, name); + }); + return names; + } + + /** + * Ensures the software with the specified name is selected for installation or removal. + * @param the name of the software to ensure is selected for installation. + **/ + global void SetRequiredSoftware(string name) + { + map<string,string> softwareDetails = software[name]:nil; + if (softwareDetails == nil) + return; + softwareDetails = add(softwareDetails,"recommended","true"); + software = add(software,name,softwareDetails); + } + + /** + * @return a list of the names of the software currently NOT selected for installation. + **/ + global list<string> GetNonRequiredSoftware() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["recommended"]:"false" == "false") && (softwareDetails["action"]:"install" == "install")) + names = add(names, name); + }); + return names; + } + + /** + * @return a list of the names of the software currently selected for removal. + **/ + global list<string> GetNonRequiredRemoveSoftware() + { + list<string> names = []; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["recommended"]:"false" == "false") && (softwareDetails["action"]:"install" == "remove")) + names = add(names, name); + }); + return names; + } + + /** + * Ensures the software with the specified name is NOT selected for installation or removal. + * @param the name of the software to ensure is NOT selected for installation. + **/ + global void SetNonRequiredSoftware(string name) + { + map<string,string> softwareDetails = software[name]:nil; + if (softwareDetails == nil) + return; + softwareDetails = add(softwareDetails,"recommended","false"); + software = add(software,name,softwareDetails); + } + + /** + * Ensures that the repositories with specified URLs are selected for addition, and all others are not. + * Invalid pluralisation due to lack of proper overloading :( + * @param the names of the software to ensure is selected for installation. + **/ + global void SetRequiredSoftwares(list<string> names) + { + foreach (string name, map<string,string> softwareDetails, software, + { + if (contains(names,name)) + { + SetRequiredSoftware(name); + } else + { + SetNonRequiredSoftware(name); + } + }); + } + + /** + * @return the summary for the software with specified name. + * This will be in the user's current language if there was a localised summary available. + **/ + global string GetSoftwareSummary(string name) + { + map<string,string> softwareDetails = software[name]:nil; + if (softwareDetails == nil) + return ""; + return softwareDetails["summary"]:""; + } + + /** + * @return the description for the software with specified name. + * This will be in the user's current language if there was a localised description available. + **/ + global string GetSoftwareDescription(string name) + { + map<string,string> softwareDetails = software[name]:nil; + if (softwareDetails == nil) + return ""; + return softwareDetails["description"]:""; + } + + /** </region> **/ + + /** <region name="Processing"> **/ + + /** + * Specify whether the user should remain subscribed to the repositories after installation of this software is complete. + * @param the boolean value indicating whether the user should remain subscribed. + **/ + global void SetRemainSubscribed(boolean value) + { + remainSubscribed = value; + } + + /** + * @return the current setting of whether the user should remain subscribed to repositories after installation. + **/ + global boolean GetRemainSubscribed() + { + return remainSubscribed; + } + + /** + * @return the name for this software bundle. + **/ + global string GetName() + { + return name; + } + + /** + * @return the summary for this software bundle. + * This will be in the user's current language if there was a localised summary available. + **/ + global string GetSummary() + { + return summary; + } + + /** + * @return the description for this software bundle. + * This will be in the user's current language if there was a localised description available. + **/ + global string GetDescription() + { + return description; + } + + /** + * @return Find out whether we have any repositories that need to be added for this installation. + * Useful to find out whether to display this wizard step. + **/ + global boolean HaveRepositories() + { + return (size(repositories) > 0); + } + + /** + * @return Find out whether we have any software that needs to be installed for this installation. + * Useful to find out whether to display this wizard step. + **/ + global boolean HaveSoftware() + { + boolean haveSoftware = false; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["action"]:"install") == "install") + { + haveSoftware = true; + return haveSoftware; + } + }); + return haveSoftware; + } + + global boolean HavePackagesToInstall() + { + boolean have = false; + foreach (string name, map<string,string> softwareDetails, software, + { + if ( + (softwareDetails["recommended"]:"false" == "true") && + (softwareDetails["action"]:"install" == "install") && + (softwareDetails["type"]:"package" == "package") + ) + { + have = true; + return have; + } + }); + return have; + } + + global boolean HavePatternsToInstall() + { + boolean have = false; + foreach (string name, map<string,string> softwareDetails, software, + { + if ( + (softwareDetails["recommended"]:"false" == "true") && + (softwareDetails["action"]:"install" == "install") && + (softwareDetails["type"]:"package" == "pattern") + ) + { + have = true; + return have; + } + }); + return have; + } + + global boolean HaveRepositoriesToInstall() + { + boolean have = false; + foreach (string url, map<string,string> repoDetails, repositories, + { + if ( + (repoDetails["recommended"]:"false" == "true") + ) + { + have = true; + return have; + } + }); + return have; + } + + global boolean HaveRemovalsToInstall() + { + boolean have = false; + foreach (string name, map<string,string> softwareDetails, software, + { + if ( + (softwareDetails["action"]:"install" == "remove") && + (softwareDetails["recommended"]:"false" == "true") + ) + { + have = true; + return have; + } + }); + return have; + } + + /** + * @return Find out whether we have any software that needs to be removed for this installation. + * Useful to find out whether to display this wizard step. + **/ + global boolean HaveRemovals() + { + boolean haveSoftware = false; + foreach (string name, map<string,string> softwareDetails, software, + { + if ((softwareDetails["action"]:"install") == "remove") + { + haveSoftware = true; + return haveSoftware; + } + }); + return haveSoftware; + } + + /** + * Converts our map -> map structure to a list of maps with a "key" element. + * This is friendly for yast's XML serialisation support. + **/ + list<map<string,string> > makeXMLFriendly(map<string,map<string,string> > toFlatten) + { + list<map<string,string> > flattened = []; + foreach(string key,map<string,string> value, toFlatten, + { + flattened = add(flattened,add(value,"key",key)); + }); + return flattened; + } + + /** + * Converts back from the above to our original structure + **/ + map<string,map<string,string> > fromXMLFriendly(list<map<string,string> > toUnFlatten) + { + map<string,map<string,string> > unflattened = $[]; + foreach (map<string,string> item, toUnFlatten, + { + string key = item["key"]:"nokey"; + unflattened = add(unflattened,key,remove(item,"key")); + }); + return unflattened; + } + + /** + * Sets up a doctype for YaST's XML serialisation. + **/ + void SetupXML() + { + map doc = $[]; + doc["listEntries"] = + $[ + "repositories":"repository" + ]; + doc["cdataSections"] = []; + doc["rootElement"] = "OneClickInstall"; + doc["systemID"] = "/un/defined"; + doc["nameSpace"] = "http://www.suse.com/1.0/yast2ns"; + doc["typeNamespace"] = "http://www.suse.com/1.0/configns"; + XML::xmlCreateDoc(`OneClickInstall,doc); + } + + /** + * Serialises this data structure to XML. + * @param filename the file to write the XML to. + **/ + global void ToXML(string filename) + { + SetupXML(); + map<string,any > toSerialise = $[]; + toSerialise = add(toSerialise,"software",software); + toSerialise = add(toSerialise,"repositories",makeXMLFriendly(repositories)); + toSerialise = add(toSerialise,"remainSubscribed",remainSubscribed); + toSerialise = add(toSerialise,"name",name); + toSerialise = add(toSerialise,"summary",summary); + toSerialise = add(toSerialise,"description",description); + + boolean success = XML::YCPToXMLFile(`OneClickInstall,toSerialise, filename); + } + + /** + * DeSerialises this data structure from XML. + * @param filename the file to read the XML from. + **/ + global void FromXML(string filename) + { + SetupXML(); + map<string,any> deSerialised = (map<string,any >)XML::XMLToYCPFile(filename); + software = deSerialised["software"]:$[]; + repositories = fromXMLFriendly((list<map<string,string> >)deSerialised["repositories"]:[]); + remainSubscribed = deSerialised["remainSubscribed"]:false; + summary = deSerialised["summary"]:""; + description = deSerialised["description"]:""; + name = deSerialised["name"]:""; + } + /** </region> **/ + +} \ No newline at end of file Added: trunk/metapackage/OneClickInstallUI.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/OneClickInstallUI.ycp?rev=39786&view=auto ============================================================================== --- trunk/metapackage/OneClickInstallUI.ycp (added) +++ trunk/metapackage/OneClickInstallUI.ycp Mon Jul 30 14:56:09 2007 @@ -0,0 +1,790 @@ +/* + * User Interface for the One Click Install Feature. + */ +{ + textdomain "OneClickInstall"; + + import "OneClickInstall"; + import "OneClickInstallWorkerResponse"; + import "Wizard"; + import "Popup"; + import "Label"; + import "HTTP"; + import "FTP"; + list args = WFM::Args(); + + string SU_CMD = "xdg-su -c"; + string SEPARATOR = "/"; + + string metaPackageUrl = "http://opensuse.org/repos.ymp"; + + + + if (size(args) > 0) + metaPackageUrl = args[0]:metaPackageUrl; + + if (substring(metaPackageUrl,0,1) != "/") + { + string newUrl = (string)SCR::Read (.target.tmpdir) + SEPARATOR + "metapackage.xml"; + if (substring(metaPackageUrl,0,4) == "http") + { + map response = HTTP::Get(metaPackageUrl,newUrl); + if (response["code"]:400 >= 400) + return; + metaPackageUrl = newUrl; + } else if (substring(metaPackageUrl,0,3) == "ftp") + { + FTP::Get(metaPackageUrl,newUrl); + metaPackageUrl = newUrl; + } else return false; + } + + OneClickInstall::Load(metaPackageUrl); + + /** <region name="String constants"> **/ + + string SOFTWARE_DESCRIPTION = _("Select the software components you wish to install:"); + string REMOVE_DESCRIPTION = _("Select the software components you wish to remove:"); + string REPOSITORIES_DESCRIPTION = _("Select the software repositories you wish to subscribe to:"); + string REPOSITORY_DESCRIPTION_HEADING = _("Repository Description:"); + string SOFTWARE_DESCRIPTION_HEADING = _("Package Description:"); + string REPOSITORY_HEADING = _("Additional Software Repositories"); + string SOFTWARE_HEADING = _("Software to be installed"); + string REMOVE_HEADING = _("Software to be Removed"); + string PLEASE_WAIT = _("Please wait patiently while this software is installed."); + string INSTALLATION_HEADING = _("Software installation"); + string HELP1 = _("This wizard will install software onto your computer"); + string HELP2 = _("See http://en.opensuse.org/MetaPackages for more information"); + string WARNING = _("Warning:"); + string WARNING1 = _("If you choose to continue the following changes will be made to your system"); + string REPOSITORY_SUMMARY = _("The following repositories will be subscribed to:"); + string SOFTWARE_SUMMARY = _("The following software items will be installed:"); + string REMOVE_SUMMARY = _("The following software items will be REMOVED:"); + string FAILED = _("Unfortunately the installation has failed, see the log file at /var/log/YaST2/y2log for more information. Failure stage was: "); + string ERROR_MESSAGE = _("Error Message"); + string SUCCESSFUL = _("Installation was successful"); + string ONLY_PARTIALLY_SUCCESSFUL = _("Installation was only partially successful."); + string STATUS = _("Installation status:"); + string REMAIN_SUBSCRIBED = _("Remain subscribed to these repositories after installation"); + string WILL_REMAIN_SUBSCRIBED = _("You will remain subscribed to these repositories after installation."); + string WILL_NOT_REMAIN_SUBSCRIBED = _("These repositories will only be added during installation, you will not remain subscribed."); + string NB = _("Note:"); + string NOTHING = _("There is nothing to do."); + string REQUIRE_ADVANCED = _("Advanced mode, with ability to change settings."); + string SPLASH_HEADING = _("Welcome"); + string WIZARD_DESCRIPTION1 = _("This wizard will install"); + string WIZARD_DESCRIPTION2 = _("onto your computer."); + string SUMMARY_HEADING = _("Summary"); + string DESCRIPTION_HEADING = _("Description"); + string REPOSITORIES_FAILED = _("The following repositories could not be added"); + string PATTERNS_FAILED = _("The following patterns could not be installed"); + string PACKAGES_FAILED = _("The following packages could not be installed"); + /** </region> **/ + + /** <region name="Define the UI components"> **/ + + string HELP_TEXT = + "<h3>" + SOFTWARE_DESCRIPTION + "</h3>" + + "<p>" + HELP1 + "</p>" + + "<p>" + HELP2 + "</p>"; + + //xxx without this the width of the items in the multi-selection-box seems to be broken. + string SPACER = " "; + term repositoriesUI = `VBox + ( + `VWeight(2, + `Heading(REPOSITORY_HEADING) + ), + `VWeight(10, + `MultiSelectionBox(`id(`repositoriesCheckList),`opt(`notify), REPOSITORIES_DESCRIPTION, [SPACER]) + ), + `VWeight(1, + `CheckBox(`id(`remain),REMAIN_SUBSCRIBED,true) + ), + `VWeight(5, + `RichText(`id(`descrLabel),"") + ) + ); + + term softwareUI = `VBox + ( + `VWeight(2, + `Heading(SOFTWARE_HEADING) + ), + `VWeight(10, + `MultiSelectionBox(`id(`softwareCheckList),`opt(`notify), SOFTWARE_DESCRIPTION, [SPACER]) + ), + `VWeight(5, + `RichText(`id(`packageDescrLabel),"") + ) + + ); + + term removeUI = `VBox + ( + `VWeight(2, + `Heading(REMOVE_HEADING) + ), + `VWeight(10, + `MultiSelectionBox(`id(`removeCheckList),`opt(`notify), REMOVE_DESCRIPTION, [SPACER]) + ), + `VWeight(5, + `RichText(`id(`removeDescrLabel),"") + ) + ); + + term nothing = `VBox + ( + `Heading(NOTHING) + ); + + term confirm = `HBox( + `VBox( + + `VWeight(5, + `RichText(`id(`summary),"")) + ) + ); + + term splash = `HBox( + `VBox( + + `VWeight(5, + `RichText(`id(`splashMessage),"")), + `VWeight(1, + `CheckBox(`id(`advanced),REQUIRE_ADVANCED,false) + ) + ) + ); + + term perform = `HBox( + `HSpacing(1), + `VBox( + `VSpacing(0.2), + `Heading(PLEASE_WAIT), + `VSpacing(0.2) + ), + `HSpacing(1) + ); + + term result = `HBox( + `HSpacing(1), + `VBox( + `VSpacing(0.1), + `RichText(`id(`resultLabel),""), + `VSpacing(0.2) + ), + `HSpacing(1) + ); + /** </region> **/ + /** <region name="Setup the Wizard Steps"> **/ + + list<map> installation_steps_simple = []; + list<map> installation_widgets_simple = []; + + installation_steps_simple = + [ + $[ "id": "splash", "label": _("Software Description") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + + installation_widgets_simple = + [ + $["id": "splash", "widget":splash], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + + list<map> installation_steps = installation_steps_simple; + list<map> installation_widgets = installation_widgets_simple; + + list<map> installation_steps_advanced = []; + list<map> installation_widgets_advanced = []; + + if (OneClickInstall::HaveRepositories() && OneClickInstall::HaveSoftware() && !OneClickInstall::HaveRemovals()) + { + installation_steps_advanced = + [ + $[ "id": "repositoriesUI", "label": _("Repositories") ], + $[ "id": "softwareUI", "label": _("Software") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + + installation_widgets_advanced = + [ + $["id": "repositoriesUI", "widget":repositoriesUI], + $["id": "softwareUI", "widget":softwareUI], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + } else if (OneClickInstall::HaveRepositories() && OneClickInstall::HaveSoftware() && OneClickInstall::HaveRemovals()) + { + installation_steps_advanced = + [ + $[ "id": "repositoriesUI", "label": _("Repositories") ], + $[ "id": "softwareUI", "label": _("Software") ], + $[ "id": "removeUI", "label": _("Removals") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + installation_widgets_advanced = + [ + $["id": "repositoriesUI", "widget":repositoriesUI], + $["id": "softwareUI", "widget":softwareUI], + $["id": "removeUI", "widget":removeUI], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + } else if (OneClickInstall::HaveRepositories() && !OneClickInstall::HaveSoftware()) + { + installation_steps_advanced = + [ + $[ "id": "repositoriesUI", "label": _("Repositories") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + installation_widgets_advanced = + [ + $["id": "repositoriesUI", "widget":repositoriesUI], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + } else if (!OneClickInstall::HaveRepositories() && OneClickInstall::HaveSoftware() && !OneClickInstall::HaveRemovals()) + { + installation_steps_advanced = + [ + $[ "id": "softwareUI", "label": _("Software") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + installation_widgets_advanced = + [ + $["id": "softwareUI", "widget":softwareUI], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + } else if (!OneClickInstall::HaveRepositories() && OneClickInstall::HaveSoftware() && OneClickInstall::HaveRemovals()) + { + installation_steps_advanced = + [ + $[ "id": "softwareUI", "label": _("Software") ], + $[ "id": "removeUI", "label": _("Removals") ], + $[ "id": "confirm", "label": _("Installation Settings") ], + $[ "id": "perform", "label": _("Perform Installation") ], + $[ "id": "result", "label": _("Results") ] + ]; + installation_widgets_advanced = + [ + $["id": "softwareUI", "widget":softwareUI], + $["id": "removeUI", "widget":removeUI], + $["id": "confirm", "widget":confirm], + $["id": "perform", "widget":perform], + $["id": "result", "widget":result] + ]; + } else + { + installation_steps_advanced = + [ + $[ "id": "nothing", "label": _("Nothing to do") ], + ]; + installation_widgets_advanced = + [ + $["id": "nothing", "widget":nothing] + ]; + } + /** </region> **/ + + /** <region name="wizardy bits"> **/ + + define list<term> StringListToTermList(list<string> strList,boolean checked) + { + list<term> items = []; + foreach(string str, strList, + { + items = add(items,`item(`id(str),str,checked)); + }); + return items; + } + + + + define boolean is_performing(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "perform"); + }; + + define boolean is_confirming(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "confirm"); + }; + + define boolean is_selecting_repositories(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "repositoriesUI"); + }; + + define boolean is_selecting_software(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "softwareUI"); + }; + + define boolean is_selecting_removals(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "removeUI"); + }; + + define boolean is_done(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "result"); + }; + + define boolean is_viewing_splash(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + return (current_id == "splash"); + }; + + define void SetupWizard() + { + UI::OpenDialog(`opt(`defaultsize ), + `Wizard(`opt(`stepsEnabled), + `back, "&Back", + `abort, "Ab&ort", + `next, "&Next" ) ); + + UI::WizardCommand(`SetDialogIcon( "/usr/share/YaST2/theme/SuSELinux/icons/22x22/apps/user_add.png" ) ); + UI::WizardCommand(`SetDialogHeading( "Software Installation" ) ); + UI::WizardCommand(`SetHelpText( HELP_TEXT ) ); + + UI::WizardCommand(`AddStepHeading( "Installation Steps" ) ); + + foreach ( map step,installation_steps, ``{ + UI::WizardCommand(`AddStep( step["label"]:"", step["id"]:"" ) ); + }); + } + SetupWizard(); + + integer current_step = 0; + + boolean done = false; + + /** </region> **/ + + /** <region name="wire up the wizard UI to the OCI module">**/ + + //This wouldn't be necessary if regexpsub wasn't so retarded. + define string NewLinesToRichText(string original) + { + string result = ""; + list<string> lines = splitstring(original,"\n"); + foreach(string line, lines, + { + result = result + line + "<br/>"; + }); + return result; + } + + + define void show_step(integer no) + { + string current_id = (installation_steps[ no ]:nil)["id"]:""; + if (is_done(no)) + { + Wizard::SetNextButton (`finish, Label::FinishButton()); + } + + UI::ReplaceWidget(`id(`contents),(installation_widgets[ no ]:$[])["widget"]:nothing); + + UI::WizardCommand(`SetCurrentStep( current_id ) ); + if (is_viewing_splash(no)) + { + string splashStr = "<body bgcolor=\"White\"><h2>" + SPLASH_HEADING + "</h2>" ; + splashStr = splashStr + WIZARD_DESCRIPTION1 + " <b>" + OneClickInstall::GetName() + "</b> " + WIZARD_DESCRIPTION2; + splashStr = splashStr + "<h3>" + SUMMARY_HEADING + "</h3><p style=\"background-color:white;\">" + NewLinesToRichText(OneClickInstall::GetSummary()) + "</p>"; + splashStr = splashStr + "<h3>" + DESCRIPTION_HEADING + "</h3><p>" + NewLinesToRichText(OneClickInstall::GetDescription()) + "</p></body>"; + UI::ChangeWidget(`id(`splashMessage),`Value,splashStr); + } + + if (is_selecting_repositories(no)) + { + UI::ChangeWidget(`id(`remain),`Value,OneClickInstall::GetRemainSubscribed()); + list<term> newRepositoryNames = (list<term>) merge + ( + StringListToTermList(OneClickInstall::GetRequiredRepositories(),true), + StringListToTermList(OneClickInstall::GetNonRequiredRepositories(),false) + ); + UI::ChangeWidget(`id(`repositoriesCheckList),`Items, + newRepositoryNames + ); + term first = newRepositoryNames[0]:nil; + string firstUrl = ""; + if (first != nil) + firstUrl = first[1]:""; + UI::ChangeWidget(`descrLabel, `Value,"<body bgcolor=\"White\"><h3>" + REPOSITORY_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetRepositoryDescription(firstUrl)) + "</body>"); + + } + if (is_selecting_software(no)) + { + list<term> newSoftwareNames = (list<term>) merge + ( + StringListToTermList(OneClickInstall::GetRequiredSoftware(),true), + StringListToTermList(OneClickInstall::GetNonRequiredSoftware(),false) + ); + UI::ChangeWidget(`id(`softwareCheckList),`Items, + newSoftwareNames + ); + term first = newSoftwareNames[0]:nil; + string firstname = ""; + if (first != nil) + firstname = first[1]:""; + UI::ChangeWidget(`packageDescrLabel, `Value,"<body bgcolor=\"White\"><h3>" + SOFTWARE_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetSoftwareDescription(firstname)) + "</body>"); + } + if (is_selecting_removals(no)) + { + list<term> newSoftwareNames = (list<term>) merge + ( + StringListToTermList(OneClickInstall::GetRequiredRemoveSoftware(),true), + StringListToTermList(OneClickInstall::GetNonRequiredRemoveSoftware(),false) + ); + UI::ChangeWidget(`id(`removeCheckList),`Items, + newSoftwareNames + ); + term first = newSoftwareNames[0]:nil; + string firstname = ""; + if (first != nil) + firstname = first[1]:""; + UI::ChangeWidget(`removeDescrLabel, `Value,"<body bgcolor=\"White\"><h3>" + SOFTWARE_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetSoftwareDescription(firstname)) + "</body>"); + } + }; + + define boolean events_before_stage_change(integer step, symbol button) + { + if (is_selecting_repositories(step)) + { + OneClickInstall::SetRemainSubscribed((boolean)UI::QueryWidget(`id(`remain), `Value)); + } + if (is_viewing_splash(step)) + { + if((boolean)UI::QueryWidget(`id(`advanced), `Value)) + { + installation_steps = installation_steps_advanced; + installation_widgets = installation_widgets_advanced; + SetupWizard(); + show_step(0); + return false; + } + } + if (is_confirming(step) && (button == `next) ) + { + return Popup::AnyQuestion ("Warning","Have you reviewed the changes that will be made to your system?\n\nMalicious packages could damage your system.","Yes","No",`focus_no); + } + return true; + } + + + define void events_after_stage_change(integer step, symbol button) + { + if (is_confirming(step)) + { + string repoStr = ""; + string packageStr = ""; + string removeStr = ""; + foreach (string repo, OneClickInstall::GetRequiredRepositories(), + { + repoStr = repoStr + "<li>" + repo + " (" + OneClickInstall::GetRepositoryName(repo) + ")</li>"; + } + ); + + foreach (string package, OneClickInstall::GetRequiredSoftware(), + { + packageStr = packageStr + "<li>" + package + "</li>"; + } + ); + + foreach (string package, OneClickInstall::GetRequiredRemoveSoftware(), + { + removeStr = removeStr + "<li>" + package + "</li>"; + } + ); + + string tempOrPerm = WILL_REMAIN_SUBSCRIBED; + if ( !OneClickInstall::GetRemainSubscribed()) + { + tempOrPerm = WILL_NOT_REMAIN_SUBSCRIBED; + } else + { + tempOrPerm = WILL_REMAIN_SUBSCRIBED; + } + + string summaryStr = "<body bgcolor=\"White\"><h1>" + WARNING + "</h1>" + + "<font color='red'>" + WARNING1 + "</font>"; + + //Put remove message at top, incase people try to push it off the bottom of the warning by adding lots of packages. + if (removeStr != "") + { + summaryStr = summaryStr +"<h2><font color='red'>" + REMOVE_SUMMARY + "</font></h2>" + + removeStr; + } + + if (repoStr != "") + { + summaryStr = summaryStr + "<h2>" + REPOSITORY_SUMMARY +"</h2>" + + repoStr + "<h3>" + NB + "</h3>" + + "<li>" + tempOrPerm + "</li>"; + } + + if (packageStr != "") + { + summaryStr = summaryStr + "<h2>" + SOFTWARE_SUMMARY + "</h2>" + + packageStr; + } + + + summaryStr = summaryStr + "</body>"; + UI::ChangeWidget(`summary, `Value, + summaryStr + ); + } + if (is_performing(step)) + { + Wizard::DisableBackButton(); + Wizard::DisableNextButton(); + + //I don't think we need to include timestamp/random seed here as yast seems to generate its own for tmpdir. + string communication_file =(string)SCR::Read (.target.tmpdir) + SEPARATOR + "oneclickinstall.xml"; + OneClickInstall::ToXML(communication_file); + + integer ret = (integer)SCR::Execute (.target.bash, SU_CMD + " '/sbin/yast2 OneClickInstallWorker " + communication_file + "'"); + + //Load the response. + OneClickInstallWorkerResponse::FromXML(communication_file); + + string statusStr = "<body bgcolor=\"White\"><h1>" + INSTALLATION_HEADING + "</h1>"; + + if (OneClickInstallWorkerResponse::GetSuccess()) + { + if ( + (size(OneClickInstallWorkerResponse::GetFailedRepositories()) == 0) && + (size(OneClickInstallWorkerResponse::GetFailedPatterns()) == 0 ) && + (size(OneClickInstallWorkerResponse::GetFailedPackages()) == 0 ) + ) + { + statusStr = statusStr + "<p>" + SUCCESSFUL + "</p>"; + } + else + { + statusStr = statusStr + "<p>" + ONLY_PARTIALLY_SUCCESSFUL + "</p>"; + } + } else + { + statusStr = statusStr + "<p>" + FAILED + " " + OneClickInstallWorkerResponse::GetFailureStage() + "<p>"; + statusStr = statusStr + "<h2>"+ ERROR_MESSAGE + "</h2><p>" + OneClickInstallWorkerResponse::GetErrorMessage() + "</p>"; + } + + if (size(OneClickInstallWorkerResponse::GetFailedRepositories()) > 0 ) + { + statusStr = statusStr + "<h3>" + REPOSITORIES_FAILED + "</h3><p>"; + foreach (string failed, OneClickInstallWorkerResponse::GetFailedRepositories(), + { + statusStr = statusStr + "<li>" + failed + "</li>"; + }); + statusStr = statusStr + "</p>"; + } + + if (size(OneClickInstallWorkerResponse::GetFailedPatterns()) > 0 ) + { + statusStr = statusStr + "<h3>" + PATTERNS_FAILED + "</h3><p>"; + foreach (string failed, OneClickInstallWorkerResponse::GetFailedPatterns(), + { + statusStr = statusStr + "<li>" + failed + "</li>"; + }); + statusStr = statusStr + "</p>"; + } + + if (size(OneClickInstallWorkerResponse::GetFailedPackages()) > 0 ) + { + statusStr = statusStr + "<h3>" + PACKAGES_FAILED + "</h3><p>"; + foreach (string failed, OneClickInstallWorkerResponse::GetFailedPackages(), + { + statusStr = statusStr + "<li>" + failed + "</li>"; + }); + statusStr = statusStr + "</p>"; + } + + statusStr = statusStr + "<p>" + OneClickInstallWorkerResponse::GetNote() + "</p>"; + + statusStr = statusStr + "</body>"; + + current_step = current_step + 1; + Wizard::EnableNextButton(); + + show_step( current_step ); + + UI::ChangeWidget(`resultLabel, `Value, + statusStr); + } + } + define void handle_input(symbol button) + { + + if (button == `repositoriesCheckList) + { + //Get the description of this one. + string selected = (string) UI::QueryWidget( `id(button), `CurrentItem ); + UI::ChangeWidget(`descrLabel, `Value,"<body bgcolor=\"White\"><h3>" + REPOSITORY_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetRepositoryDescription(selected)) + "</body>"); + //Set all repositories to non-required + + //Set the currently selected repositories back to subscribed. + OneClickInstall::SetRequiredRepositories((list<string>)UI::QueryWidget(`id(button), `SelectedItems)); + } + + if (button == `softwareCheckList) + { + string selected = (string) UI::QueryWidget( `id(button), `CurrentItem ); + UI::ChangeWidget(`packageDescrLabel, `Value,"<body bgcolor=\"White\"><h3>" + SOFTWARE_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetSoftwareDescription(selected)) + "</body>"); + //Set the currently selected software back to install. + OneClickInstall::SetRequiredSoftwares((list<string>)UI::QueryWidget(`id(button), `SelectedItems)); + } + + if (button == `removeCheckList) + { + string selected = (string) UI::QueryWidget( `id(button), `CurrentItem ); + UI::ChangeWidget(`removeDescrLabel, `Value,"<body bgcolor=\"White\"><h3>" + SOFTWARE_DESCRIPTION_HEADING + "</h3>" + NewLinesToRichText(OneClickInstall::GetSoftwareDescription(selected)) + "</body>" ); + //Set the currently selected removals back to remove. + OneClickInstall::SetRequiredSoftwares((list<string>)UI::QueryWidget(`id(button), `SelectedItems)); + } + } + + /** </region> **/ + /** <region name="event loop">**/ + show_step(0); + while( !done ) + { + symbol button = nil; + repeat + { + button = (symbol) Wizard::UserInput(); + handle_input(button); + + } until ((button != `repositoriesCheckList) && (button != `softwareCheckList)); + if ( button == `abort ) + break; + + if ( button == `next || button == `back ) + { + if (events_before_stage_change(current_step,button)) + { + + if ( button == `next && current_step+1 < size( installation_steps ) ) + { + current_step = current_step+1; + } + + if ( button == `back && current_step > 0 ) + { + current_step = current_step -1; + } + + show_step( current_step ); + + events_after_stage_change(current_step,button); + + if ( button == `finish ) + { + done = true; + } + } + } + + if ( button == `finish ) + { + done = true; + } + } + UI::CloseDialog(); + /** </region> **/ +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: trunk/metapackage/OneClickInstallUrlHandler.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/OneClickInstallUrlHandler.ycp?rev=39786&view=auto ============================================================================== --- trunk/metapackage/OneClickInstallUrlHandler.ycp (added) +++ trunk/metapackage/OneClickInstallUrlHandler.ycp Mon Jul 30 14:56:09 2007 @@ -0,0 +1,9 @@ +{ + //Allows embedding just the URL to the metapackage in the web page, instead of the entire package. + textdomain "OneClickInstall"; + + list<string> args = (list<string>)WFM::Args(); + string urlurl = args[0]:""; + string url = (string)SCR::Read(.target.string,urlurl); + WFM::call("OneClickInstallUI",[url]); +} \ No newline at end of file Added: trunk/metapackage/OneClickInstallWorker.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/OneClickInstallWorker.ycp?rev=39786&view=auto ============================================================================== --- trunk/metapackage/OneClickInstallWorker.ycp (added) +++ trunk/metapackage/OneClickInstallWorker.ycp Mon Jul 30 14:56:09 2007 @@ -0,0 +1,267 @@ +{ + textdomain "OneClickInstall"; + + import "OneClickInstall"; + import "OneClickInstallWorkerResponse"; + import "Popup"; + include "packager/inst_source_dialogs.ycp"; + import "PackageCallbacks"; + import "SourceManager"; + import "Progress"; + /** + ** Check whether this repository is already subscribed + **/ + list<string> DeDupe(list<string> url_list) + { + list<integer> sources = Pkg::SourceStartCache(true); + + list<string> existingSources = []; + list<string> deduped = []; + foreach (integer value, sources, + { + string url = Pkg::SourceMediaData(value)["url"]:"Error"; + + existingSources = add(existingSources,url); + }); + + foreach(string new, url_list, + { + if (!contains(existingSources,new)) + { + deduped = add(deduped,new); + } + }); + + return deduped; + } + + list<integer> sourceids = []; + /** + ** Subscribe to all the specified repositories + ** return true if all catalogues were added successfully, false otherwise. + **/ + boolean addRepositories(list<string> repositories) + { + list<string> dedupedRepos = DeDupe(repositories); + foreach (string new_url, dedupedRepos, + { + boolean again = true; + while(again) + { + integer srcid = Pkg::SourceCreate(new_url, "/"); + if (srcid == -1) + { + if (Popup::YesNo (_("An error occurred while creating the installation source.") + "\n" + _("Details:") + "\n" + Pkg::LastError() + "\n" + _("Try again?"))) + { + new_url = editUrl (new_url); + } + else + { + OneClickInstallWorkerResponse::AddFailedRepository(new_url); + again = false; + return false; + } + } + else + { + sourceids = add(sourceids,srcid); + // enable and save the source + Pkg::SourceSetEnabled(srcid, true); + Pkg::SourceSaveAll(); + again = false; + } + } + }); + return true; + } + + /** + ** Install all the specified packages + ** return true if all installations were successful, false otherwise + **/ + boolean installPackages(list<string> packages) + { + foreach (string name, packages, + { + if (!Pkg::PkgInstall(name)) + OneClickInstallWorkerResponse::AddFailedPackage(name); + }); + + boolean state = true; + Pkg::TargetInit( "/", false ); + if(Pkg::PkgSolve(true)) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else //xxx no callback for resolve failures + { + symbol result = (symbol)WFM::CallFunction( "inst_packages", [`summaryMode]); + if (result == `accept) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else + { + state = false; + } + } + + return state; + } + + /** + ** Install all the specified patterns + ** return true if all installations were successful, false otherwise + **/ + boolean installPatterns(list<string> patterns) + { + foreach (string name, patterns, + { + if (!Pkg::ResolvableInstall(name,`pattern)) + OneClickInstallWorkerResponse::AddFailedPattern(name); + }); + + boolean state = true; + Pkg::TargetInit( "/", false ); + if(Pkg::PkgSolve(true)) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else //xxx no callback for resolve failures + { + symbol result = (symbol)WFM::CallFunction( "inst_packages", [`summaryMode]); + if (result == `accept) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else + { + state = false; + } + } + + return state; + } + + /** + ** Remove all the specified packages + ** return true if all installations were successful, false otherwise + **/ + boolean removePackages(list<string> packages) + { + boolean result = true; + foreach (string name, packages, + { + if (Pkg::IsProvided (name)) + result = Pkg::PkgDelete(name); + }); + + boolean state = true; + Pkg::TargetInit( "/", false ); + if(Pkg::PkgSolve(true)) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else //xxx no callback for resolve failures + { + symbol result = (symbol)WFM::CallFunction( "inst_packages", [`summaryMode]); + if (result == `accept) + { + state = !(Pkg::PkgCommit(0)[0]:-1 < 0); + } else + { + state = false; + } + } + + return state; + } + + boolean removeAddedRepositories() + { + boolean success = true; + foreach(integer srcid, sourceids, + { + success = success && Pkg::SourceDelete(srcid); + } + ); + Pkg::SourceSaveAll(); + return success; + } + + //Get the catalogues to add and packages to install from the arguments + + list args = WFM::Args(); + + string xmlFileName = args[0]:""; + + if (xmlFileName == "") + return false; + + //Load the xml communication from the user interface. + OneClickInstall::FromXML(xmlFileName); + + boolean success = true; + + //try and add the repositories + if (OneClickInstall::HaveRepositoriesToInstall()) + { + success = addRepositories(OneClickInstall::GetRequiredRepositories()); + } + if (!success) + { + OneClickInstallWorkerResponse::SetFailureStage("Adding Repositories"); + OneClickInstallWorkerResponse::SetErrorMessage(_("An error occurred while attempting to subscribe to the required repositories. Please review the yast2 logs for more information")); + } + + //Remove any removals + if (success && OneClickInstall::HaveRemovalsToInstall()) + { + success = removePackages(OneClickInstall::GetRequiredRemoveSoftware()); + } + if (!success) + { + OneClickInstallWorkerResponse::SetFailureStage("Removing Packages"); + OneClickInstallWorkerResponse::SetErrorMessage(_("An error occurred while attempting to remove the specified packages. Please review the yast2 logs for more information")); + } + + //if that was successful now try and install the patterns + if (success && OneClickInstall::HavePatternsToInstall()) + { + success = installPatterns(OneClickInstall::GetRequiredPatterns()); + } + if (!success) + { + OneClickInstallWorkerResponse::SetFailureStage("Installing Patterns"); + OneClickInstallWorkerResponse::SetErrorMessage(_("An error occurred while attempting to install the specified patterns. Please review the yast2 logs for more information")); + } + + //if that was successful now try and install the packages + if (success && OneClickInstall::HavePackagesToInstall()) + { + success = installPackages(OneClickInstall::GetRequiredPackages()); + } + if (!success) + { + OneClickInstallWorkerResponse::SetFailureStage("Installing Packages"); + OneClickInstallWorkerResponse::SetErrorMessage(_("An error occurred while attempting to install the specified packages. Please review the yast2 logs for more information")); + } + + //If we don't want to remain subscribed, remove the repositories that were added for installation. + if (OneClickInstall::HaveRepositoriesToInstall() && !OneClickInstall::GetRemainSubscribed()) + { + success = removeAddedRepositories(); + } + if (!success) + { + OneClickInstallWorkerResponse::SetFailureStage("Removing temporarily installed repositories."); + OneClickInstallWorkerResponse::SetErrorMessage(_("An error occurred while attempting to unsubscribe from the repositories that were used to perform the installation. You can remove them manually in YaST > Installation Sources. Please review the yast2 logs for more information")); + } + + OneClickInstallWorkerResponse::SetSuccess(success); + + if (success) + { + OneClickInstallWorkerResponse::SetFailureStage("No Failure"); + OneClickInstallWorkerResponse::SetErrorMessage(_("No error occurred")); + } + + //Overwrite the information we were passed with our response back to the UI. + OneClickInstallWorkerResponse::ToXML(xmlFileName); + return success; +} \ No newline at end of file Added: trunk/metapackage/OneClickInstallWorkerResponse.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/OneClickInstallWorkerResponse.ycp?rev=39786&view=auto ============================================================================== --- trunk/metapackage/OneClickInstallWorkerResponse.ycp (added) +++ trunk/metapackage/OneClickInstallWorkerResponse.ycp Mon Jul 30 14:56:09 2007 @@ -0,0 +1,164 @@ +{ + textdomain "OneClickInstall"; + module "OneClickInstallWorkerResponse"; + + import "XML"; + + string DEFAULT_FAILURE_STAGE = _("unknown"); + string DEFAULT_ERROR_MESSAGE = _("An unknown error occurred."); + string DEFAULT_NOTE = ""; + string success = "false"; + string note = DEFAULT_NOTE; + string failureStage = DEFAULT_FAILURE_STAGE; + string errorMessage = DEFAULT_ERROR_MESSAGE; + list<string> failedPackages = []; + list<string> failedPatterns = []; + list<string> failedRepositories = []; + + + /** + * @return the success indicator. + **/ + global boolean GetSuccess() + { + return (success == "true"); + } + /** + * @param the success status to set. + **/ + global void SetSuccess(boolean value) + { + if (value) + { + success = "true"; + } else + { + success = "false"; + } + } + /** + * @return the string representation of the failure stage of the install process. + **/ + global string GetFailureStage() + { + return failureStage; + } + /** + * @param value the string representation of the failure stage of the install process. + **/ + global void SetFailureStage(string value) + { + failureStage = value; + } + /** + * @return the error message. + **/ + global string GetErrorMessage() + { + return errorMessage; + } + /** + * @param value the error message. + **/ + global void SetErrorMessage(string value) + { + errorMessage = value; + } + /** + * @return the note. + **/ + global string GetNote() + { + return note; + } + /** + * @param value the note to set. + **/ + global void SetNote(string value) + { + note = value; + } + + global list<string> GetFailedPackages() + { + return failedPackages; + } + global void AddFailedPackage(string value) + { + failedPackages = add(failedPackages,value); + } + + global list<string> GetFailedPatterns() + { + return failedPatterns; + } + global void AddFailedPattern(string value) + { + failedPatterns = add(failedPatterns,value); + } + + global list<string> GetFailedRepositories() + { + return failedRepositories; + } + global void AddFailedRepository(string value) + { + failedRepositories = add(failedRepositories,value); + } + + + /** + * Sets up YaST's XML serialisation for this data structure. + **/ + void SetupXML() + { + map doc = $[]; + doc["listEntries"] = + $[ + "failedRepositories":"repository", + "failedPackages":"package", + "failedPatterns":"pattern" + ]; + doc["cdataSections"] = []; + doc["rootElement"] = "OneClickInstallWorkerResponse"; + doc["systemID"] = "/un/defined"; + doc["nameSpace"] = "http://www.suse.com/1.0/yast2ns"; + doc["typeNamespace"] = "http://www.suse.com/1.0/configns"; + XML::xmlCreateDoc(`OneClickInstallWorkerResponse,doc); + } + + /** + * Serialises this data structure to XML. + * @param filename the file to serialise to. + **/ + global void ToXML(string filename) + { + SetupXML(); + map<string,any > toSerialise = $[]; + toSerialise = add(toSerialise,"success",success); + toSerialise = add(toSerialise,"failureStage",failureStage); + toSerialise = add(toSerialise,"errorMessage",errorMessage); + toSerialise = add(toSerialise,"note",note); + toSerialise = add(toSerialise,"failedRepositories",failedRepositories); + toSerialise = add(toSerialise,"failedPackages",failedPackages); + toSerialise = add(toSerialise,"failedPatterns",failedPatterns); + boolean success = XML::YCPToXMLFile(`OneClickInstallWorkerResponse,toSerialise, filename); + } + + /** + * DeSerialises this data structure from XML. + * @param filename the file to deserialise from. + **/ + global void FromXML(string filename) + { + SetupXML(); + map<string,any> deSerialised = (map<string,any >)XML::XMLToYCPFile(filename); + success = deSerialised["success"]:"false"; + failureStage = deSerialised["failureStage"]:DEFAULT_FAILURE_STAGE; + errorMessage = deSerialised["errorMessage"]:DEFAULT_ERROR_MESSAGE; + note = deSerialised["note"]:DEFAULT_NOTE; + failedRepositories = deSerialised["failedRepositories"]:[]; + failedPackages = deSerialised["failedPackages"]:[]; + failedPatterns = deSerialised["failedPatterns"]:[]; + } +} \ No newline at end of file Added: trunk/metapackage/YPX.pm URL: http://svn.opensuse.org/viewcvs/yast/trunk/metapackage/YPX.pm?rev=39786&view=auto ============================================================================== --- trunk/metapackage/YPX.pm (added) +++ trunk/metapackage/YPX.pm Mon Jul 30 14:56:09 2007 @@ -0,0 +1,47 @@ + #!/usr/bin/perl -w + +package YPX; + +#use Data::Dumper; +use XML::XPath; +use XML::XPath::XMLParser; + +our %TYPEINFO; + +BEGIN { $TYPEINFO{Load} = ["function","any","string"]; } + +sub Load +{ + my ($package,$url) = @_; + return XML::XPath->new(filename => $url); +} + +BEGIN { $TYPEINFO{SelectValue} = ["function","string","any","string"]; } +sub SelectValue +{ + my ($package,$xp,$xpath) = @_; + my $value = $xp->getNodeText($xpath)->value(); + return $value; +} + +BEGIN { $TYPEINFO{SelectValues} = ["function",["list","string"],"any","string"]; } +sub SelectValues +{ + my ($package,$xp,$xpath) = @_; + my $nodes = $xp->findnodes($xpath); + my $values = []; + foreach my $node ($nodes->get_nodelist) { + push(@$values,$node->string_value()); + } + + return $values; +} + + +sub GotData +{ + my ($package,$data) = @_; + print $data; +} +1; + -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org
participants (1)
-
mvidner@svn.opensuse.org