Hello community, here is the log from the commit of package autoyast2 for openSUSE:Factory checked in at 2015-04-27 22:07:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/autoyast2 (Old) and /work/SRC/openSUSE:Factory/.autoyast2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "autoyast2" Changes: -------- --- /work/SRC/openSUSE:Factory/autoyast2/autoyast2.changes 2015-04-02 16:01:23.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.autoyast2.new/autoyast2.changes 2015-04-27 22:08:56.000000000 +0200 @@ -1,0 +2,19 @@ +Fri Apr 10 10:48:04 CEST 2015 - sch...@suse.de + +- New autoinst flag in general/mode section: + activate_systemd_default_target. + The default target of systemd will be activated in the second + stage of autoyast installation. + The default is "true" which is a backward compatible value. + (bnc#923992) +- 3.1.74 + +------------------------------------------------------------------- +Tue Apr 7 15:26:44 UTC 2015 - igonzalezs...@suse.com + +- Avoid ayast_probe module crashing when called from an installed + system. + (bnc#926241) +- 3.1.73 + +------------------------------------------------------------------- Old: ---- autoyast2-3.1.72.tar.bz2 New: ---- autoyast2-3.1.74.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ autoyast2.spec ++++++ --- /var/tmp/diff_new_pack.MqxT48/_old 2015-04-27 22:08:57.000000000 +0200 +++ /var/tmp/diff_new_pack.MqxT48/_new 2015-04-27 22:08:57.000000000 +0200 @@ -17,7 +17,7 @@ Name: autoyast2 -Version: 3.1.72 +Version: 3.1.74 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build ++++++ autoyast2-3.1.72.tar.bz2 -> autoyast2-3.1.74.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/CONTRIBUTING.md new/autoyast2-3.1.74/CONTRIBUTING.md --- old/autoyast2-3.1.72/CONTRIBUTING.md 2015-03-27 09:54:14.000000000 +0100 +++ new/autoyast2-3.1.74/CONTRIBUTING.md 2015-04-27 10:29:12.000000000 +0200 @@ -12,13 +12,13 @@ ----------- If you find a problem, please report it either using -[Bugzilla](https://bugzilla.novell.com/enter_bug.cgi?format=guided&product=openSUSE+Factory&component=YaST2) +[Bugzilla](https://bugzilla.suse.com/enter_bug.cgi?format=guided&product=openSUSE+Factory&component=YaST2) or [GitHub issues](../../issues). (For Bugzilla, use the [simplified registration](https://secure-www.novell.com/selfreg/jsp/createSimpleAccount.jsp) if you don't have an account yet.) If you find a problem, please report it either using -[Bugzilla](https://bugzilla.novell.com/) or GitHub issues. We can't guarantee +[Bugzilla](https://bugzilla.suse.com/) or GitHub issues. We can't guarantee that every bug will be fixed, but we'll try. When creating a bug report, please follow our [bug reporting @@ -71,7 +71,7 @@ [widely used conventions](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). -If your commit is related to a bug in Buzgilla or an issue on GitHub, make sure +If your commit is related to a bug in Bugzilla or an issue on GitHub, make sure you mention it in the commit message for cross-reference. Use format like bnc#775814 or gh#yast/yast-foo#42. See also [GitHub autolinking](https://help.github.com/articles/github-flavored-markdown#references) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/README.md new/autoyast2-3.1.74/README.md --- old/autoyast2-3.1.72/README.md 2015-03-27 09:54:14.000000000 +0100 +++ new/autoyast2-3.1.74/README.md 2015-04-27 10:29:12.000000000 +0200 @@ -1,5 +1,66 @@ -# YaST - The AutoYaST Framework # +YaST - The AutoYaST Framework +============================= [](https://travis-ci.org/yast/yast-autoinstallation) [](https://ci.opensuse.org/view/Yast/job/yast-autoinstallation-master/) + +Development +=========== + +This module is developed as part of YaST. See the +[development documentation](http://yastgithubio.readthedocs.org/en/latest/development/). + + +Getting the Sources +=================== + +To get the source code, clone the GitHub repository: + + $ git clone https://github.com/yast/yast-autoinstallation.git + +If you want to contribute into the project you can +[fork](https://help.github.com/articles/fork-a-repo/) the repository and clone your fork. + + +Testing Environment +=================== + +There are several possibilities how test an updated code. It also depends on +the fact in which stage of installation it comes into effect. First stage runs +between the start from installation media to reboot (or kexec), then continues +second stage. + +### First Stage ### + +Either use *StartShell=1* option in [Linuxrc](https://en.opensuse.org/SDB:Linuxrc), +edit the installation system and run *yast* manually or use +a [DriverUpdate](https://en.opensuse.org/SDB:Linuxrc#p_dud) via Linuxrc. + +### Second Stage ### + +There are two possible ways how to rerun this stage, just keep in mind that +the system might be already configured and thus it might behave +a bit differently: + + ``` + cp /var/lib/YaST2/install.inf /etc/ + touch /var/lib/YaST2/runme_at_boot + cp /var/adm/autoinstall/cache/installedSystem.xml \ + /var/lib/autoinstall/autoconf/autoconf.xml + reboot + ``` + +or faster without rebooting but with possible side-effects: + + ``` + yast ayast_setup setup filename=/var/adm/autoinstall/cache/installedSystem.xml + ``` + + +Contact +======= + +If you have any question, feel free to ask at the [development mailing +list](http://lists.opensuse.org/yast-devel/) or at the +[#yast](https://webchat.freenode.net/?channels=%23yast) IRC channel on freenode. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/package/autoyast2.changes new/autoyast2-3.1.74/package/autoyast2.changes --- old/autoyast2-3.1.72/package/autoyast2.changes 2015-03-27 09:54:14.000000000 +0100 +++ new/autoyast2-3.1.74/package/autoyast2.changes 2015-04-27 10:29:12.000000000 +0200 @@ -1,4 +1,23 @@ ------------------------------------------------------------------- +Fri Apr 10 10:48:04 CEST 2015 - sch...@suse.de + +- New autoinst flag in general/mode section: + activate_systemd_default_target. + The default target of systemd will be activated in the second + stage of autoyast installation. + The default is "true" which is a backward compatible value. + (bnc#923992) +- 3.1.74 + +------------------------------------------------------------------- +Tue Apr 7 15:26:44 UTC 2015 - igonzalezs...@suse.com + +- Avoid ayast_probe module crashing when called from an installed + system. + (bnc#926241) +- 3.1.73 + +------------------------------------------------------------------- Thu Mar 26 17:00:32 CET 2015 - sch...@suse.de - New autoinst flag in general/mode section: final_restart_services. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/package/autoyast2.spec new/autoyast2-3.1.74/package/autoyast2.spec --- old/autoyast2-3.1.72/package/autoyast2.spec 2015-03-27 09:54:14.000000000 +0100 +++ new/autoyast2-3.1.74/package/autoyast2.spec 2015-04-27 10:29:12.000000000 +0200 @@ -17,7 +17,7 @@ Name: autoyast2 -Version: 3.1.72 +Version: 3.1.74 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/src/clients/inst_autoconfigure.rb new/autoyast2-3.1.74/src/clients/inst_autoconfigure.rb --- old/autoyast2-3.1.72/src/clients/inst_autoconfigure.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/src/clients/inst_autoconfigure.rb 2015-04-27 10:29:12.000000000 +0200 @@ -39,7 +39,8 @@ "Profile general,mode:%1", Ops.get_map(Profile.current, ["general", "mode"], {}) ) - @need_systemd_isolate = true + @need_systemd_isolate = Ops.get_boolean( + Profile.current,["general", "mode", "activate_systemd_default_target"], true) final_restart_services = Ops.get_boolean( Profile.current,["general", "mode", "final_restart_services"], true) @max_steps = Y2ModuleConfig.ModuleMap.size + 3 # additional for scripting and finished message @@ -299,6 +300,8 @@ Builtins.y2milestone("after calling \"%1\"", @cmd) Builtins.y2milestone("ret=%1", @out) wait_systemd_finished(@max_wait, @ser_ignore) + else + Builtins.y2milestone("Do not activate systemd default target (defined in autoyast.xml)") end # Just in case, remove this file to avoid reconfiguring... diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/src/include/autoinstall/ask.rb new/autoyast2-3.1.74/src/include/autoinstall/ask.rb --- old/autoyast2-3.1.72/src/include/autoinstall/ask.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/src/include/autoinstall/ask.rb 2015-04-27 10:29:12.000000000 +0200 @@ -144,6 +144,10 @@ if Ops.greater_than(Ops.get_integer(ask, "height", 0), min_height) min_height = Ops.get_integer(ask, "height", 0) end + + # + # Script to calculate the default value (optional) + # if Builtins.haskey(ask, "default_value_script") interpreter = Ops.get_string( ask, @@ -192,6 +196,10 @@ Ops.get_string(out, "stderr", "") ) end + + # + # Start to handle questions: widgets creation (checkbox, combobox) + # dlg = Dummy() if type == "boolean" on = Ops.get(ask, "default") == "true" ? true : false @@ -216,7 +224,7 @@ elsif type == "static_text" widget = Label(Id(entry_id), Ops.get_string(ask, "default", "")) dlg = createWidget(widget, frametitle) - else + else # integer or string if Ops.get_boolean(ask, "password", false) == true widget1 = Password( Id(entry_id), @@ -225,7 +233,7 @@ Ops.get_string(ask, "default", "") ) widget2 = Password( - Id(:pass2), + Id("#{entry_id}_pass2"), Opt(:notify), "", Ops.get_string(ask, "default", "") @@ -261,35 +269,47 @@ end end end - if frametitle != "" - if frameBuffer == nil - frameBufferVBox = VBox(dlg) - else - if frametitle == frameBufferTitle - frameBufferVBox = Builtins.add(frameBufferVBox, dlg) - else - dialog_term = Builtins.add(dialog_term, frameBuffer) + # + # At this time, widgets are created. + # + + # + # Add the widget to the correct frame (using the frametitle). + # + if frametitle != "" # some frametitle is set + if frameBuffer == nil # and no frameBuffer exists + frameBufferVBox = VBox(dlg) # create a new frameBuffer + else # a frameBuffer exists + if frametitle == frameBufferTitle # with same title + frameBufferVBox = Builtins.add(frameBufferVBox, dlg) # add current to frameBuffer + else # with different title + dialog_term = Builtins.add(dialog_term, frameBuffer) # add frameBuffer to dialog dialog_term = Builtins.add(dialog_term, VSpacing(1)) - frameBufferVBox = VBox(dlg) + frameBufferVBox = VBox(dlg) # populate the frameBuffer with the new frame end end - frameBuffer = Frame(frametitle, frameBufferVBox) + frameBuffer = Frame(frametitle, frameBufferVBox) # set frameBuffer values for the next iteration frameBufferTitle = frametitle - else - if frameBuffer != nil - dialog_term = Builtins.add(dialog_term, frameBuffer) + else # frametitle is in blank + if frameBuffer != nil # a previous frameBuffer exists + dialog_term = Builtins.add(dialog_term, frameBuffer) # add frameBuffer to dialog dialog_term = Builtins.add(dialog_term, VSpacing(1)) frameBuffer = nil frameBufferVBox = nil end - dialog_term = Builtins.add(dialog_term, dlg) + dialog_term = Builtins.add(dialog_term, dlg) # add new element (with no frame) to dialog dialog_term = Builtins.add(dialog_term, VSpacing(1)) end end + + # If some frameBuffer left after iterations, it's added to the dialog. if frameBuffer != nil dialog_term = Builtins.add(dialog_term, frameBuffer) end + # + # Let's build the dialog + # help_term = HWeight(30, RichText(helptext)) if helptext != "" title_term = Heading(title) if title != "" backButton = PushButton(Id(:back), back_label) @@ -316,6 +336,10 @@ if Ops.less_than(Builtins.size(history), 2) UI.ChangeWidget(Id(:back), :Enabled, false) end + + # + # Wait for user input + # while true ret = nil if timeout == 0 @@ -324,13 +348,13 @@ ret = UI.TimeoutUserInput(Ops.multiply(timeout, 1000)) end timeout = 0 - if ret == :ok || ret == :timeout + if ret == :ok || ret == :timeout # Process users' input and save asks into dialogs hash. runAgain = 0 element_cnt2 = 0 Ops.set( dialogs, dialog_nr, - Builtins.maplist( + Builtins.maplist( # Iterate through widgets building a list of asks (containing responses) Convert.convert( Ops.get(dialogs, dialog_nr, []), :from => "list", @@ -350,10 +374,10 @@ val = Builtins.tointeger(Convert.to_string(val)) end if Ops.get_boolean(ask, "password", false) == true - pass2 = Convert.to_string(UI.QueryWidget(Id(:pass2), :Value)) + pass2 = Convert.to_string(UI.QueryWidget(Id("#{entry_id}_pass2"), :Value)) if pass2 != Convert.to_string(val) Popup.Error("The two passwords mismatch.") - runAgain = 1 + runAgain = 1 # Run the same dialog again. end end Builtins.y2debug( @@ -361,9 +385,11 @@ Ops.get_string(ask, "question", ""), val ) + + # Save the value in the profile (and also as default value) Ops.set(ask, "default", val) pos = path2pos(Ops.get_string(ask, "path", "")) - if Ops.get_string(ask, "path", "") != "" + if Ops.get_string(ask, "path", "") != "" # Set value in the profile Profile.current = Profile.setElementByList( pos, val, @@ -378,6 +404,8 @@ Profile.current ) end + + # Save the value into a file (if 'file' property was set) if file != "" if Ops.get_string(ask, "type", "string") == "boolean" if !SCR.Write( @@ -400,6 +428,8 @@ end end end + + # If ask must run an script, let's run it if script != {} scriptName = Ops.get_string( script, @@ -426,7 +456,7 @@ SCR.Execute(path(".target.mkdir"), current_logdir) end executionString = "" - if Ops.get_boolean(script, "environment", false) + if Ops.get_boolean(script, "environment", false) # FIXME: why not pass the variable always? if Ops.get_string(ask, "type", "string") == "boolean" val = Builtins.sformat( "%1", @@ -461,15 +491,19 @@ executionString ) end - runAgain = Ops.add( - runAgain, - Convert.to_integer( - SCR.Execute(path(".target.bash"), executionString) + Popup.Feedback("", _("A user defined script is running. This may take a while.")) do + runAgain = Ops.add( + runAgain, + Convert.to_integer( + SCR.Execute(path(".target.bash"), executionString) + ) ) - ) + end if Ops.get_boolean(script, "rerun_on_error", false) == false runAgain = 0 end + + # Show feedback in a dialog showFeedback = Ops.get_boolean(script, "feedback", false) feedback = "" if showFeedback @@ -487,10 +521,12 @@ Popup.LongText( "", RichText(Opt(:plainText), feedback), - 40, + 70, 15 ) end + + # Save the next_dialog if Ops.greater_than( SCR.Read(path(".target.size"), "/tmp/next_dialog"), 0 @@ -511,7 +547,7 @@ end ) break if runAgain == 0 - elsif ret == :back + elsif ret == :back # back button pressed: one step back on history. jumpToDialog = Ops.get( history, Ops.subtract(Builtins.size(history), 2), @@ -529,7 +565,7 @@ end end UI.CloseDialog - if jumpToDialog != -2 + if jumpToDialog != -2 # If we must jump to another dialog (as read on /tmp/next_dialog) dialog_nr = jumpToDialog jumpToDialog = -2 i = 0 @@ -540,7 +576,7 @@ end i = Ops.add(i, 1) end - else + else # Next dialog dialogCounter = Ops.add(dialogCounter, 1) dialog_nr = Ops.get(keys, dialogCounter, -1) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/src/modules/AutoInstallRules.rb new/autoyast2-3.1.74/src/modules/AutoInstallRules.rb --- old/autoyast2-3.1.72/src/modules/AutoInstallRules.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/src/modules/AutoInstallRules.rb 2015-04-27 10:29:12.000000000 +0200 @@ -36,6 +36,15 @@ Yast.include self, "autoinstall/io.rb" + reset + end + + # Reset the module's state + # + # @return nil + # + # @see #AutoInstallRules + def reset @userrules = false @dontmergeIsDefault = true @dontmergeBackup = [] @@ -50,19 +59,12 @@ @ATTR = {} @installed_product = "" - @installed_product_version = "" - @hostname = "" - @hostaddress = "" - @network = "" - @domain = "" - @arch = "" - @karch = "" # Taken from smbios @@ -78,31 +80,19 @@ @board = "" @memsize = 0 - @disksize = [] - @totaldisk = 0 - @hostid = "" - @mac = "" - @linux = 0 - @others = 0 - @xserver = "" - @haspcmcia = "0" #/////////////////////////////////////////// #/////////////////////////////////////////// - @NonLinuxPartitions = [] - @LinuxPartitions = [] - - @UserRules = {} # Local Variables @@ -110,7 +100,6 @@ @env = {} @tomerge = [] - @element2file = {} AutoInstallRules() end @@ -322,8 +311,8 @@ distro_str = SCR.Read(path(".content.DISTRO")) log.info "DISTRO: #{distro_str}" - distro = distro_map(distro_str) - cpe = distro ? cpeid_map(distro["cpeid"]) : {} + distro = distro_map(distro_str) || {} + cpe = cpeid_map(distro["cpeid"]) || {} @installed_product = distro["name"] || "" @installed_product_version = cpe["version"] || "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/src/modules/AutoinstClass.rb new/autoyast2-3.1.74/src/modules/AutoinstClass.rb --- old/autoyast2-3.1.72/src/modules/AutoinstClass.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/src/modules/AutoinstClass.rb 2015-04-27 10:29:12.000000000 +0200 @@ -19,7 +19,10 @@ class AutoinstClassClass < Module include Yast::Logger + MERGE_XSLT_PATH = "/usr/share/autoinstall/xslt/merge.xslt" + def main + Yast.import "AutoinstConfig" Yast.import "XML" Yast.import "Summary" @@ -38,21 +41,21 @@ AutoinstClass() end - # find a profile path + # Finds a profile path # @param string profile name # @return [String] profile Path def findPath(name, class_) - result = @confs.find { |c| c['name'] == name && c['class'] == class_ } - result ||= { 'class' => '', 'name' => 'default' } - File.join(@classDir, result['class'], result['name']) + result = @confs.find { |c| c["name"] == name && c["class"] == class_ } + result ||= { "class" => "", "name" => "default" } + File.join(@classDir, result["class"], result["name"]) end - # Read classes + # Reads classes def Read if SCR.Read(path(".target.size"), @classPath) != -1 # TODO: use XML module classes_map = Convert.to_map(SCR.Read(path(".xml"), @classPath)) - @Classes = (classes_map && classes_map['classes']) || [] + @Classes = (classes_map && classes_map["classes"]) || [] else @Classes = [] end @@ -64,15 +67,15 @@ # classes.xml files, one for each repository def Compat if !class_file_exists? && compat_class_file_exists? - log.info "Compat: #{@classPath} no found but #{compat_class_file} exists" - new_classes_map = { 'classes' => read_old_classes } + log.info "Compat: #{@classPath} not found but #{compat_class_file} exists" + new_classes_map = { "classes" => read_old_classes } log.info "creating #{new_classes_map}" XML.YCPToXMLFile(:class, new_classes_map, @classPath) end nil end - # Change the directory and read the class definitions + # Changes the directory and reads the class definitions # # @param [String] Path of the new directory # @return nil @@ -84,7 +87,7 @@ nil end - # Change the directory of classes definitions. + # Changes the directory of classes definitions. # # AutoinstConfig#classDir= is called to set the new value # in the configuration. It does not check if the directory @@ -108,76 +111,39 @@ nil end - # Merge Classes + # Merge classes # def MergeClasses(configuration, base_profile, resultFileName) - configuration = deep_copy(configuration) dontmerge_str = "" - i = 1 - Builtins.foreach(AutoinstConfig.dontmerge) do |dm| - dontmerge_str = Ops.add( - dontmerge_str, - Builtins.sformat(" --param dontmerge%1 \"'%2'\" ", i, dm) - ) - i = Ops.add(i, 1) + AutoinstConfig.dontmerge.each_with_index do |dm, i| + dontmerge_str << " --param dontmerge#{i+1} \"'#{dm}'\" " end - tmpdir = AutoinstConfig.tmpDir - _MergeCommand = Builtins.sformat( - "/usr/bin/xsltproc --novalid --param replace \"'false'\" %1 --param with ", - dontmerge_str - ) - - _MergeCommand = Ops.add( - Ops.add( - Ops.add(_MergeCommand, "\"'"), - findPath( - Ops.get_string(configuration, "name", ""), - Ops.get_string(configuration, "class", "") - ) - ), - "'\" " - ) - _MergeCommand = Ops.add( - Ops.add( - Ops.add(Ops.add(Ops.add(_MergeCommand, "--output "), tmpdir), "/"), - resultFileName - ), - " " - ) - _MergeCommand = Ops.add( - _MergeCommand, - " /usr/share/autoinstall/xslt/merge.xslt " - ) - _MergeCommand = Ops.add(Ops.add(_MergeCommand, base_profile), " ") - - - Builtins.y2milestone("Merge command: %1", _MergeCommand) - - out = Convert.to_map( - SCR.Execute(path(".target.bash_output"), _MergeCommand, {}) - ) - Builtins.y2milestone( - "Merge stdout: %1, stderr: %2", - Ops.get_string(out, "stdout", ""), - Ops.get_string(out, "stderr", "") - ) - deep_copy(out) + merge_command = + "/usr/bin/xsltproc --novalid --param replace \"'false'\" #{dontmerge_str} --param with " \ + "\"'#{findPath(configuration["name"], configuration["class"])}'\" " \ + "--output #{File.join(AutoinstConfig.tmpDir, resultFileName)} " \ + "#{MERGE_XSLT_PATH} #{base_profile} " + + out = SCR.Execute(path(".target.bash_output"), merge_command, {}) + log.info "Merge command: #{merge_command}" + log.info "Merge stdout: #{out["stdout"]}, stderr: #{out["stderr"]}" + out end - # Read files from class directories + # Reads files from class directories # @return [void] def Files @confs = [] @Classes.each do |class_| - class_name_ = class_['name'] || 'xxx' + class_name_ = class_["name"] || "xxx" files_path = File.join(@classDir, class_name_) - files = Convert.convert(SCR.Read(path('.target.dir'), files_path), + files = Convert.convert(SCR.Read(path(".target.dir"), files_path), :from => "any", :to => "list <string>") next if files.nil? log.info "Files in class #{class_name_}: #{files}" - new_confs = files.map { |f| { 'class' => class_name_, 'name' => f } } + new_confs = files.map { |f| { "class" => class_name_, "name" => f } } log.info "Configurations: #{new_confs}" @confs.concat(new_confs) end @@ -185,15 +151,11 @@ nil end - # Save Class definitions + # Saves classes definitions def Save - Builtins.foreach(@deletedClasses) do |c| - toDel = Builtins.sformat( - "/bin/rm -rf %1/%2", - AutoinstConfig.classDir, - c - ) - SCR.Execute(path(".target.bash"), toDel) + @deletedClasses.each do |c| + to_del = "/bin/rm -rf #{File.join(AutoinstConfig.classDir, c)}" + SCR.Execute(path(".target.bash"), to_del) end @deletedClasses = [] tmp = { "classes" => @Classes } @@ -202,34 +164,29 @@ end - # Import configuration + # Imports configuration + # @params [Array<Hash>] settings Configuration + # @return true def Import(settings) - settings = deep_copy(settings) @profile_conf = deep_copy(settings) true end - # Export configuration + # Exports configuration + # @return [Array<Hash>] Copy of the configuration def Export deep_copy(@profile_conf) end - # Configuration Summary + # Builds the configuration summary + # @return [String] Configuration summary def Summary summary = "" - - Builtins.foreach(@profile_conf) do |c| - summary = Summary.AddHeader( - summary, - Ops.get_string(c, "class_name", "None") - ) - summary = Summary.AddLine( - summary, - Ops.get_string(c, "configuration", "None") - ) + @profile_conf.each do |conf| + summary = Summary.AddHeader(summary, conf["class_name"] || "None") + summary = Summary.AddLine(summary, conf["configuration"] || "None") end - return Summary.NotConfigured if Builtins.size(summary) == 0 - summary + summary.empty? ? Summary.NotConfigured : summary end publish :variable => :classDir, :type => "string" @@ -276,10 +233,10 @@ # Builds a map of classes to import from /etc/autoinstall/classes.xml # @return [Array<Hash>] Classes defined in the file. def read_old_classes - old_classes_map = Convert.to_map(SCR.Read(path('.xml'), compat_class_file)) - old_classes = old_classes_map['classes'] || [] + old_classes_map = Convert.to_map(SCR.Read(path(".xml"), compat_class_file)) + old_classes = (old_classes_map && old_classes_map["classes"]) || [] old_classes.each_with_object([]) do |class_, new_classes| - class_path_ = File.join(@classDir, class_['name'] || '') + class_path_ = File.join(@classDir, class_["name"] || "") log.info "looking for #{class_path_}" new_classes << class_ unless SCR.Read(path(".target.dir"), class_path_).nil? end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/AutoInstallRules_test.rb new/autoyast2-3.1.74/test/AutoInstallRules_test.rb --- old/autoyast2-3.1.72/test/AutoInstallRules_test.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/test/AutoInstallRules_test.rb 2015-04-27 10:29:12.000000000 +0200 @@ -1,12 +1,10 @@ #!/usr/bin/env rspec -ENV["Y2DIR"] = File.expand_path("../../src", __FILE__) - -require "yast" +require_relative "test_helper" Yast.import "AutoInstallRules" -describe "Yast::AutoInstallRules" do +describe Yast::AutoInstallRules do subject { Yast::AutoInstallRules } describe "#cpeid_map" do @@ -96,6 +94,22 @@ expect(Yast::AutoInstallRules.installed_product).to eq("SUSE Linux Enterprise Server 12") expect(Yast::AutoInstallRules.installed_product_version).to eq("12") end + + context "when .content.DISTRO is not found" do + before(:each) do + subject.reset + allow(Yast::SCR).to receive(:Read).with(any_args) + allow(Yast::Arch).to receive(:architecture).and_return("x86_64") + end + + it 'set installed_product and installed_product_version to blank string' do + expect(Yast::SCR).to receive(:Read).with(Yast::Path.new(".content.DISTRO")). + and_return(nil) + subject.ProbeRules + expect(Yast::AutoInstallRules.installed_product).to eq('') + expect(Yast::AutoInstallRules.installed_product_version).to eq('') + end + end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/AutoinstClass_test.rb new/autoyast2-3.1.74/test/AutoinstClass_test.rb --- old/autoyast2-3.1.72/test/AutoinstClass_test.rb 2015-03-27 09:54:15.000000000 +0100 +++ new/autoyast2-3.1.74/test/AutoinstClass_test.rb 2015-04-27 10:29:12.000000000 +0200 @@ -1,19 +1,17 @@ #!/usr/bin/env rspec -root_path = File.expand_path('../..', __FILE__) -ENV["Y2DIR"] = File.join(root_path, 'src') - -require "yast" +require_relative "test_helper" Yast.import "AutoinstClass" describe Yast::AutoinstClass do subject { Yast::AutoinstClass } + let(:root_path) { File.expand_path('../..', __FILE__) } let(:test_xml_dir) { File.join(root_path, 'test', 'fixtures') } let(:class_dir) { File.join(test_xml_dir, 'classes') } let(:class_path) { File.join(class_dir, 'classes.xml') } - let(:faked_autoinstall_dir) { File.join(test_xml_dir, 'etc', 'autoinstall') } + let(:settings) { [ { 'class_name' => 'swap', 'configuration' => 'largeswap.xml' } ] } before(:each) do subject.class_dir = class_dir @@ -159,20 +157,27 @@ describe '#Compat' do let(:faked_autoinstall_dir) { File.join(test_xml_dir, 'etc', 'autoinstall') } - context 'when /etc/autoinstall/classes.xml exists' do - around(:each) do |example| - subject.ClassConf = faked_autoinstall_dir - example.call - subject.ClassConf = '/etc/autoinstall' + around(:each) do |example| + subject.ClassConf = faked_autoinstall_dir + example.call + subject.ClassConf = '/etc/autoinstall' + end + + context 'when a classes.xml file exists in the new location' do + it 'does not overwrite classes.xml file' do + expect(Yast::XML).to_not receive(:YCPToXMLFile) + subject.Compat end + end - context 'and a classes.xml file does not exist in the new location' do - before(:each) do - allow(Yast::SCR).to receive(:Read).and_call_original - allow(Yast::SCR).to receive(:Read). - with(Yast::Path.new('.target.size'), class_path).and_return(-1) - end + context 'when a classes.xml file does not exist in the new location' do + before(:each) do + allow(Yast::SCR).to receive(:Read).and_call_original + allow(Yast::SCR).to receive(:Read). + with(Yast::Path.new('.target.size'), class_path).and_return(-1) + end + context 'and /etc/autoinstall/classes.xml exists' do it 'creates a classes.xml file in the new location' do expect(Yast::XML).to receive(:YCPToXMLFile) do |type, data, path| expect(type).to eq(:class) @@ -183,9 +188,16 @@ end end - context 'and a classes.xml file exists in the new location' do - it 'does not create a classes.xml file' do - expect(Yast::XML).to_not receive(:YCPToXMLFile) + context 'and /etc/autoinstall/classes.xml is empty or not valid XML' do + before(:each) do + allow(Yast::SCR).to receive(:Read). + with(Yast::Path.new('.xml'), File.join(faked_autoinstall_dir, 'classes.xml')). + and_return(nil) + end + + it 'creates a classes.xmlfile in the new location with no classes' do + expect(Yast::XML).to receive(:YCPToXMLFile). + with(:class, {"classes" => []}, File.join(class_dir, 'classes.xml')) subject.Compat end end @@ -198,4 +210,176 @@ expect(subject.classDir).to eq(test_xml_dir) end end + + describe '#MergeClasses' do + let(:base_profile_path) { File.join('test', 'fixtures', 'profiles', 'partitions.xml') } + let(:tmp_dir) { File.join(root_path, 'tmp') } + let(:expected_xml) { File.read(expected_xml_path) } + let(:output_path) { File.join(tmp_dir, 'output.xml') } + let(:output_xml) { File.read(output_path) } + let(:dontmerge) { [] } + let(:merge_xslt_path) { File.join('xslt', 'merge.xslt') } + let(:xsltproc_command) { + "/usr/bin/xsltproc --novalid --param replace \"'false'\" " \ + "--param with \"'#{subject.findPath("largeswap.xml", "swap")}'\" "\ + "--output #{File.join(tmp_dir, "output.xml")} " \ + "#{merge_xslt_path} test/fixtures/profiles/partitions.xml " + } + + before(:each) do + stub_const("Yast::AutoinstClassClass::MERGE_XSLT_PATH", merge_xslt_path) + end + + around(:each) do |example| + FileUtils.rm_rf(tmp_dir) if Dir.exist?(tmp_dir) + FileUtils.mkdir(tmp_dir) + example.run + FileUtils.rm_rf(tmp_dir) + end + + before(:each) do + allow(Yast::AutoinstConfig).to receive(:tmpDir).and_return(tmp_dir) + allow(Yast::AutoinstConfig).to receive(:dontmerge).and_return(dontmerge) + subject.Files + end + + it 'executes xsltproc and returns a hash with info about the result' do + expect(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.bash_output"), xsltproc_command, {}).and_call_original + out = subject.MergeClasses(subject.confs[0], base_profile_path, 'output.xml') + expect(out).to eq({ 'exit' => 0, 'stderr' => '', 'stdout' => '' }) + end + + context 'when all elements must be merged' do + let(:expected_xml_path) { File.join(root_path, 'test', 'fixtures', 'output', 'partitions-merged.xml') } + + it 'merges elements from profile and configuration' do + expect(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.bash_output"), xsltproc_command, {}).and_call_original + subject.MergeClasses(subject.confs[0], base_profile_path, 'output.xml') + expect(output_xml).to eq(expected_xml) + end + end + + context 'when some elements are not intended to be merged' do + let(:expected_xml_path) { File.join(root_path, 'test', 'fixtures', 'output', 'partitions-dontmerge.xml') } + let(:dontmerge) { ['partition'] } + let(:xsltproc_command) { + "/usr/bin/xsltproc --novalid --param replace \"'false'\" " \ + "--param dontmerge1 \"'partition'\" " \ + "--param with \"'#{subject.findPath("largeswap.xml", "swap")}'\" "\ + "--output #{File.join(tmp_dir, "output.xml")} " \ + "#{merge_xslt_path} test/fixtures/profiles/partitions.xml " + } + + it 'does not merge those elements' do + expect(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.bash_output"), xsltproc_command, {}).and_call_original + subject.MergeClasses(subject.confs[0], base_profile_path, 'output.xml') + expect(output_xml).to eq(expected_xml) + end + end + end + + describe '#Import' do + it 'sets profile_conf variable as a copy of the given settings' do + subject.Import(settings) + expect(subject.profile_conf).to eq(settings) + expect(subject.profile_conf).to_not equal(settings) + end + + after(:each) do + subject.Import([]) + end + end + + describe '#Export' do + around(:each) do |example| + subject.Import(settings) + example.call + subject.Import([]) # reset settings + end + + it 'returns a copy of profile_conf' do + exported = subject.Export + expect(exported).to eq(settings) + expect(exported).to_not equal(settings) + end + end + + describe '#Summary' do + context 'when some settings are given' do + around(:each) do |example| + subject.Import(settings) + example.call + subject.Import([]) # reset settings + end + + it 'returns a summary containing class names and configurations' do + expect(Yast::Summary).to receive(:AddHeader).with(anything, 'swap'). + and_return('<h3>swap</h3>') + expect(Yast::Summary).to receive(:AddLine).with(anything, 'largeswap.xml'). + and_return('<h3>swap</h3><p>largeswap.xml</p>') + expect(subject.Summary).to eq('<h3>swap</h3><p>largeswap.xml</p>') + end + + context 'when no class name is given' do + let(:settings) { [ { 'configuration' => 'largeswap.xml' } ] } + + it "'None' is used instead" do + expect(Yast::Summary).to receive(:AddHeader).with(anything, 'None'). + and_return('<h3>None</h3>') + subject.Summary + end + end + + context 'when no configuration is given' do + let(:settings) { [ { 'class_name' => 'swap' } ] } + + it "'None' is used instead" do + expect(Yast::Summary).to receive(:AddLine).with(anything, 'None'). + and_return('<h3>None</h3><p>largeswap.xml</p>') + subject.Summary + end + end + end + + context 'when no settings are given' do + it 'returns an empty summary' do + expect(subject.Summary).to eq(Yast::Summary.NotConfigured) + end + end + end + + describe '#Save' do + before(:each) do + subject.Read + end + + it 'creates a classes.xml file in the new location' do + expect(Yast::XML).to receive(:YCPToXMLFile) do |type, data, path| + expect(type).to eq(:class) + expect(data['classes']).to be_kind_of(Array) + expect(path).to eq(File.join(class_dir, 'classes.xml')) + end + subject.Save + end + + context 'when classes are marked for deletion' do + around(:each) do |example| + subject.deletedClasses = ['swap'] + example.call + subject.deletedClasses = [] + end + + it 'deletes classes files' do + allow(Yast::XML).to receive(:YCPToXMLFile).with(any_args) + expect(Yast::SCR).to receive(:Execute).with( + Yast::Path.new('.target.bash'), + "/bin/rm -rf #{class_dir}/swap") + + subject.Save + end + end + end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/fixtures/output/partitions-dontmerge.xml new/autoyast2-3.1.74/test/fixtures/output/partitions-dontmerge.xml --- old/autoyast2-3.1.72/test/fixtures/output/partitions-dontmerge.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/autoyast2-3.1.74/test/fixtures/output/partitions-dontmerge.xml 2015-04-27 10:29:12.000000000 +0200 @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns"> + <partitioning config:type="list"> + <drive> + <device>/dev/sda</device><disklabel>msdos</disklabel><enable_snapshots config:type="boolean">true</enable_snapshots><initialize config:type="boolean">true</initialize><partitions config:type="list"> + <partition> + <create config:type="boolean">true</create> + <crypt_fs config:type="boolean">false</crypt_fs> + <filesystem config:type="symbol">swap</filesystem> + <format config:type="boolean">true</format> + <loop_fs config:type="boolean">false</loop_fs> + <mount>swap</mount> + <mountby config:type="symbol">uuid</mountby> + <partition_id config:type="integer">130</partition_id> + <partition_nr config:type="integer">1</partition_nr> + <resize config:type="boolean">false</resize> + <size>1043496448</size> + </partition><partition> + <create config:type="boolean">true</create> + <crypt_fs config:type="boolean">false</crypt_fs> + <filesystem config:type="symbol">ext4</filesystem> + <format config:type="boolean">true</format> + <fstopt>acl,user_xattr</fstopt> + <loop_fs config:type="boolean">false</loop_fs> + <mount>/</mount> + <mountby config:type="symbol">uuid</mountby> + <partition_id config:type="integer">131</partition_id> + <partition_nr config:type="integer">2</partition_nr> + <resize config:type="boolean">false</resize> + <size>5381455360</size> + </partition><partition> + <filesystem config:type="symbol">swap</filesystem> + <format config:type="boolean">true</format> + <mount>swap</mount> + <partition_id config:type="integer">130</partition_id> + <size>2000mb</size> + </partition> + <partition> + <filesystem config:type="symbol">ext3</filesystem> + <partition_type>primary</partition_type> + <size>4Gb</size> + <mount>/</mount> + </partition> + </partitions> + <pesize/><type config:type="symbol">CT_DISK</type><use>all</use> + </drive> + </partitioning> +</profile> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/fixtures/output/partitions-merged.xml new/autoyast2-3.1.74/test/fixtures/output/partitions-merged.xml --- old/autoyast2-3.1.72/test/fixtures/output/partitions-merged.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/autoyast2-3.1.74/test/fixtures/output/partitions-merged.xml 2015-04-27 10:29:12.000000000 +0200 @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns"> + <partitioning config:type="list"> + <drive> + <device>/dev/sda</device><disklabel>msdos</disklabel><enable_snapshots config:type="boolean">true</enable_snapshots><initialize config:type="boolean">true</initialize><partitions config:type="list"> + <partition> + <create config:type="boolean">true</create><crypt_fs config:type="boolean">false</crypt_fs><filesystem config:type="symbol">swap</filesystem> + <format config:type="boolean">true</format> + <loop_fs config:type="boolean">false</loop_fs><mount>swap</mount> + <mountby config:type="symbol">uuid</mountby><partition_id config:type="integer">130</partition_id> + <partition_nr config:type="integer">1</partition_nr><resize config:type="boolean">false</resize><size>2000mb</size> + </partition> + <partition> + <create config:type="boolean">true</create><crypt_fs config:type="boolean">false</crypt_fs><filesystem config:type="symbol">ext3</filesystem> + <format config:type="boolean">true</format><fstopt>acl,user_xattr</fstopt><loop_fs config:type="boolean">false</loop_fs><partition_type>primary</partition_type> + <size>4Gb</size> + <mount>/</mount> + <mountby config:type="symbol">uuid</mountby> + <partition_id config:type="integer">131</partition_id> + <partition_nr config:type="integer">2</partition_nr> + <resize config:type="boolean">false</resize> + <size>5381455360</size> + </partition> + </partitions> + <pesize/><type config:type="symbol">CT_DISK</type><use>all</use> + </drive> + </partitioning> +</profile> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/fixtures/profiles/partitions.xml new/autoyast2-3.1.74/test/fixtures/profiles/partitions.xml --- old/autoyast2-3.1.72/test/fixtures/profiles/partitions.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/autoyast2-3.1.74/test/fixtures/profiles/partitions.xml 2015-04-27 10:29:12.000000000 +0200 @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<!DOCTYPE profile> +<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns"> + <partitioning config:type="list"> + <drive> + <device>/dev/sda</device> + <disklabel>msdos</disklabel> + <enable_snapshots config:type="boolean">true</enable_snapshots> + <initialize config:type="boolean">true</initialize> + <partitions config:type="list"> + <partition> + <create config:type="boolean">true</create> + <crypt_fs config:type="boolean">false</crypt_fs> + <filesystem config:type="symbol">swap</filesystem> + <format config:type="boolean">true</format> + <loop_fs config:type="boolean">false</loop_fs> + <mount>swap</mount> + <mountby config:type="symbol">uuid</mountby> + <partition_id config:type="integer">130</partition_id> + <partition_nr config:type="integer">1</partition_nr> + <resize config:type="boolean">false</resize> + <size>1043496448</size> + </partition> + <partition> + <create config:type="boolean">true</create> + <crypt_fs config:type="boolean">false</crypt_fs> + <filesystem config:type="symbol">ext4</filesystem> + <format config:type="boolean">true</format> + <fstopt>acl,user_xattr</fstopt> + <loop_fs config:type="boolean">false</loop_fs> + <mount>/</mount> + <mountby config:type="symbol">uuid</mountby> + <partition_id config:type="integer">131</partition_id> + <partition_nr config:type="integer">2</partition_nr> + <resize config:type="boolean">false</resize> + <size>5381455360</size> + </partition> + </partitions> + <pesize/> + <type config:type="symbol">CT_DISK</type> + <use>all</use> + </drive> + </partitioning> +</profile> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/include/ask_test.rb new/autoyast2-3.1.74/test/include/ask_test.rb --- old/autoyast2-3.1.72/test/include/ask_test.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/autoyast2-3.1.74/test/include/ask_test.rb 2015-04-27 10:29:12.000000000 +0200 @@ -0,0 +1,337 @@ +#!/usr/bin/env rspec + +require_relative "../test_helper" + +require "yast" + +Yast.import "Profile" +Yast.import "Stage" +Yast.import "UI" + +describe "Yast::AutoinstallAskInclude" do + module DummyYast + class AutoinstallAskClient < Yast::Client + def main + Yast.include self, "autoinstall/ask.rb" + end + + def initialize + main + end + end + end + + BASE_ASK = { + "type" => "string", "question" => "hostname?", "default" => "my.site.de", + "help" => "Some help", "dialog" => 0, "element" => 0, + "stage" => "initial" } + + subject(:client) { DummyYast::AutoinstallAskClient.new } + let(:profile) { { "general" => { "ask-list" => ask_list } } } + let(:pressed_button) { :ok } + + describe "#askDialog" do + let(:ask_list) { [ask] } + + before do + allow(Yast::Profile).to receive(:current).and_return(profile) + allow(Yast::Stage).to receive(:initial).and_return(true) + allow(Yast::UI).to receive(:UserInput).and_return(pressed_button) + end + + context "when ask-list is empty" do + let(:ask_list) { [] } + + it "no dialog is shown" do + expect(Yast::UI).to_not receive(:OpenDialog) + client.askDialog + end + end + + describe "dialogs creation" do + context "when the ask-list contains a question with type 'string'" do + let(:ask) { BASE_ASK } + + it "creates a TextEntry widget" do + expect(Yast::UI).to receive(:OpenDialog) + expect(client).to receive(:TextEntry). + with(Id("0_0"), Opt(:notify), ask["question"], ask["default"]). + and_call_original + client.askDialog + end + end + + context "when ask-list contains a question with type 'selection'" do + let(:ask) { BASE_ASK.merge("selection" => items, "default" => "desktop") } + let(:items) { + %w(desktop server).map { |i| { "value" => i, "label" => i.capitalize } } + } + + it "creates a ComboBox widget" do + expect(Yast::UI).to receive(:OpenDialog) + expected_options = [ + Item(Id("desktop"), "Desktop", true), + Item(Id("server"), "Server", false) + ] + expect(client).to receive(:ComboBox). + with(Id("0_0"), Opt(:notify), ask["question"], expected_options). + and_call_original + client.askDialog + end + end + + context "when ask-list contains a question with type 'password'" do + let(:ask) { BASE_ASK.merge("password" => true) } + + it "creates two Password widgets" do + expect(Yast::UI).to receive(:OpenDialog) + expect(client).to receive(:Password). + with(Id("0_0"), Opt(:notify), ask["question"], ask["default"]). + and_call_original + expect(client).to receive(:Password). + with(Id("0_0_pass2"), Opt(:notify), "", ask["default"]). + and_call_original + client.askDialog + end + end + + context "when ask-list contains a question with type 'static_text'" do + let(:ask) { BASE_ASK.merge("type" => "static_text") } + + it "creates a Label widget" do + expect(Yast::UI).to receive(:OpenDialog) + expect(client).to receive(:Label). + with(Id("0_0"), ask["default"]). + and_call_original + client.askDialog + end + end + + context "when ask-list contains question with type 'symbol'" do + let(:ask) { + BASE_ASK.merge("type" => "symbol", "default" => :desktop, "selection" => items) + } + let(:items) { + %w(desktop server).map { |i| { "value" => i.to_sym, "label" => i.capitalize } } + } + + it "creates a ComboBox widget" do + expect(Yast::UI).to receive(:OpenDialog) + expected_options = [ + Item(Id(:desktop), "Desktop", true), + Item(Id(:server), "Server", false) + ] + expect(client).to receive(:ComboBox). + with(Id("0_0"), Opt(:notify), ask["question"], expected_options). + and_call_original + client.askDialog + end + end + + context "when ask-list contains a question with type 'boolean'" do + let(:ask) do + BASE_ASK.merge("type" => "boolean", "question" => "Register system?", "default" => "true") + end + + it "creates a CheckBox widget" do + expect(Yast::UI).to receive(:OpenDialog) + expect(client).to receive(:CheckBox). + with(Id("0_0"), Opt(:notify), ask["question"], true). + and_call_original + client.askDialog + end + end + + context "when ask-list contains more than one question" do + let(:string_ask) { BASE_ASK } + let(:boolean_ask) do + BASE_ASK.merge("type" => "boolean", "element" => 1, "default" => "true") + end + let(:ask_list) { [string_ask, boolean_ask] } + + it "creates one widget for each one of them" do + expect(Yast::UI).to receive(:OpenDialog) + expect(client).to receive(:TextEntry). + with(Id("0_0"), Opt(:notify), string_ask["question"], string_ask["default"]). + and_call_original + expect(client).to receive(:CheckBox). + with(Id("0_1"), Opt(:notify), boolean_ask["question"], true). + and_call_original + client.askDialog + end + end + + context "when ask-list contains more than one password question" do + let(:first_pass_ask) { BASE_ASK.merge("password" => true)} + let(:second_pass_ask) { BASE_ASK.merge("password" => true, "element" => 1)} + let(:ask_list) { [first_pass_ask, second_pass_ask] } + + it "creates two password widgets for each question without repeating the Ids" do + expect(Yast::UI).to receive(:OpenDialog) + ["0_0", "0_0_pass2", "0_1", "0_1_pass2"].each do |wid| + expect(client).to receive(:Password). + with(Id(wid), anything, anything, anything).and_call_original + end + client.askDialog + end + end + end + + describe "dialogs actions" do + + context "when ok button is pressed" do + let(:pressed_button) { :ok } + let(:response) { "some-user-response" } + + before do + allow(Yast::UI).to receive(:QueryWidget). + with(Id("0_0"), :Value).and_return(response) + end + + context "when a path was specified" do + let(:ask) { BASE_ASK.merge("path" => "users,0,gecos") } + + it "response is saved into the Profile at the specified path" do + expect(Yast::Profile).to receive(:setElementByList). + with(["users", 0, "gecos"], response, profile) + client.askDialog + end + end + + context "when a pathlist was specified" do + let(:ask) { BASE_ASK.merge("pathlist" => ["users,1000,login", "groups,1000,name"]) } + + it "saves response into Profile at the paths specified in the pathlist" do + expect(Yast::Profile).to receive(:setElementByList). + with(["users", 1000, "login"], response, profile) + expect(Yast::Profile).to receive(:setElementByList). + with(["groups", 1000, "name"], response, profile) + client.askDialog + end + end + + context "when a file was specified" do + let(:file_path) { "/tmp/response" } + let(:ask) { BASE_ASK.merge("file" => file_path) } + + it "saves the user answer in the file" do + expect(Yast::SCR).to receive(:Write). + with(Yast::Path.new(".target.string"), file_path, response). + and_return(true) + client.askDialog + end + + context "when response is a boolean" do + let(:response) { true } + let(:ask) { BASE_ASK.merge("type" => "boolean", "file" => file_path)} + + it "converts the answer to a string and saves it in the file" do + expect(Yast::SCR).to receive(:Write). + with(Yast::Path.new(".target.string"), file_path, "true"). + and_return(true) + client.askDialog + end + end + + context "when asking for a 'password' and values don't match" do + let(:ask) { BASE_ASK.merge("password" => true) } + + it "shows an error message and try run the dialog again" do + expect(Yast::UI).to receive(:QueryWidget). + with(Id("0_0_pass2"), :Value).and_return("some-other-thing", response) + expect(Yast::Popup).to receive(:Error).with("The two passwords mismatch.") + client.askDialog + end + end + end + + context "when a script was specified" do + let(:script) { { "source" => "echo", "filename" => "test.sh" } } + let(:ask) { BASE_ASK.merge("script" => script) } + let(:tmp_dir) { "/tmp" } + let(:log_dir) { "/var/log/YaST2" } + + before do + allow(Yast::AutoinstConfig).to receive(:tmpDir).and_return(tmp_dir) + allow(Yast::AutoinstConfig).to receive(:logs_dir). + and_return(log_dir) + script_path = "#{tmp_dir}/#{script["filename"]}" + allow(Yast::SCR).to receive(:Write). + with(Yast::Path.new(".target.string"), script_path, script["source"]). + and_return(true) + allow(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.mkdir"), File.join(tmp_dir, "ask_scripts_log")) + end + + context "when 'environment' property is not set" do + it "runs the script without passing the ask response" do + expect(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.bash"), + "/bin/sh -x /tmp/test.sh 2&> /tmp/ask_scripts_log/test.sh.log ") + client.askDialog + end + end + + context "when 'environment' property is set" do + let(:script) { { "source" => "echo", "filename" => "test.sh", "environment" => true } } + + it "runs the script passing the ask response" do + expect(Yast::SCR).to receive(:Execute). + with(Yast::Path.new(".target.bash"), + "VAL=\"some-user-response\" /bin/sh -x /tmp/test.sh 2&> /tmp/ask_scripts_log/test.sh.log ") + client.askDialog + end + end + + it "shows some feedback while script is running" do + message = "A user defined script is running. This may take a while." + allow(Yast::SCR).to receive(:Execute) + expect(Yast::Popup).to receive(:Feedback). + with("", client._(message)) + client.askDialog + end + end + + context "when more dialogs left" do + let(:ask_list) { [BASE_ASK, BASE_ASK.merge("dialog" => "1")] } + + it "next dialog is shown" do + expect(Yast::UI).to receive(:UserInput).twice + client.askDialog + end + end + + context "when no more dialogs left" do + let(:ask_list) { [BASE_ASK] } + + it "finishes dialog processing and returns" do + expect(Yast::UI).to receive(:UserInput).once + client.askDialog + end + end + + context "when a value for 'next dialog' is set" do + let(:ask_list) { [BASE_ASK, BASE_ASK.merge("dialog" => 1), BASE_ASK.merge("dialog" => 2)] } + + before do + expect(Yast::SCR).to receive(:Read). + with(Yast::Path.new(".target.size"), "/tmp/next_dialog"). + and_return(1) + expect(Yast::SCR).to receive(:Read). + with(Yast::Path.new(".target.string"), "/tmp/next_dialog"). + and_return("2") + end + + it "jumps to that dialog" do + expect(Yast::UI).to_not receive(:QueryWidget). + with(Id("1_0"), :Value) # Skips dialog 1. + expect(Yast::UI).to receive(:QueryWidget). + with(Id("2_0"), :Value) + expect(Yast::UI).to receive(:UserInput).twice.and_return(:ok) + client.askDialog + end + end + end + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/autoyast2-3.1.72/test/test_helper.rb new/autoyast2-3.1.74/test/test_helper.rb --- old/autoyast2-3.1.72/test/test_helper.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/autoyast2-3.1.74/test/test_helper.rb 2015-04-27 10:29:12.000000000 +0200 @@ -0,0 +1,12 @@ +root_location = File.expand_path("../../", __FILE__) +ENV["Y2DIR"] = File.expand_path("../../src", __FILE__) + +require "yast" +require "yast/rspec" +require "fileutils" + +if ENV["COVERAGE"] + STDERR.puts "COVERAGE is disabled because when requiring some modules (like AutoinstPartition) "\ + "errors are raised in other YaST components." +end +