diff --git a/service/bin/d-installer b/service/bin/d-installer index 0fb40e0d6b..4e3f966c79 100755 --- a/service/bin/d-installer +++ b/service/bin/d-installer @@ -22,7 +22,6 @@ # find current contact information at www.suse.com. # TEMPORARY overwrite of Y2DIR to use DBus for communication with dependent yast modules -ENV["Y2DIR"] = File.expand_path("../lib/dinstaller/dbus/y2dir", __dir__) $LOAD_PATH.unshift File.expand_path("../lib", __dir__) @@ -35,10 +34,12 @@ require "dinstaller/dbus/service_runner" # @param name [Symbol] Service name # @see ORDERED_SERVICES def start_service(name) + general_y2dir = File.expand_path("../lib/dinstaller/dbus/y2dir", __dir__) + module_y2dir = File.expand_path("../lib/dinstaller/dbus/y2dir/#{name}", __dir__) + ENV["Y2DIR"] = "#{module_y2dir}:#{general_y2dir}" + logger = Logger.new($stdout, progname: name.to_s) - service_runner = DInstaller::DBus::ServiceRunner.new( - name, logger: logger - ) + service_runner = DInstaller::DBus::ServiceRunner.new(name, logger: logger) service_runner.run end @@ -51,6 +52,8 @@ ORDERED_SERVICES = [:software, :users, :manager].freeze def start_all_services ORDERED_SERVICES.map do |name| fork { exec("#{__FILE__} #{name}") } + # TODO: implement a better mechanism to check whether the service is running + sleep(1) end end diff --git a/service/lib/dinstaller/dbus/clients/dinstaller.rb b/service/lib/dinstaller/dbus/clients/dinstaller.rb deleted file mode 100644 index 8f2b6498dc..0000000000 --- a/service/lib/dinstaller/dbus/clients/dinstaller.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -# Copyright (c) [2022] SUSE LLC -# -# All Rights Reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of version 2 of the GNU General Public License as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, contact SUSE LLC. -# -# To contact SUSE LLC about this file by physical or electronic mail, you may -# find current contact information at www.suse.com. - -require "dbus" - -module DInstaller - module DBus - module Clients - # Client class to call methods from main dinstaller service - class DInstaller - class << self - def provision_selected?(provision) - software.ProvisionSelected(provision) - end - - def provisions_selected?(provisions) - software.ProvisionsSelected(provisions) - end - - private - - def bus - @bus ||= ::DBus.system_bus - end - - def service - @service ||= bus["org.opensuse.DInstaller"] - end - - def object - @object ||= service["/org/opensuse/DInstaller/Software1"] - end - - def software - @software ||= object["org.opensuse.DInstaller.Software1"] - end - end - end - end - end -end diff --git a/service/lib/dinstaller/dbus/clients/software.rb b/service/lib/dinstaller/dbus/clients/software.rb index 32c6905be1..9d31e10d99 100644 --- a/service/lib/dinstaller/dbus/clients/software.rb +++ b/service/lib/dinstaller/dbus/clients/software.rb @@ -26,9 +26,15 @@ module DBus module Clients # D-Bus client for software configuration class Software + TYPES = [:package, :pattern].freeze + private_constant :TYPES + def initialize @dbus_object = service.object("/org/opensuse/DInstaller/Software1") @dbus_object.introspect + + @dbus_proposal = service.object("/org/opensuse/DInstaller/Software/Proposal1") + @dbus_proposal.introspect end # Available products for the installation @@ -79,8 +85,73 @@ def finish dbus_object.Finish end + # Determine whether the given tag are provided by the selected packages + # + # @param tag [String] Tag to search for (package names, requires/provides, or file + # names) + # @return [Boolean] true if it is provided; false otherwise + def provision_selected?(tag) + dbus_object.ProvisionSelected(tag) + end + + # Determine whether the given tags are provided by the selected packages + # + # @param tags [Array] Tags to search for (package names, requires/provides, or file + # names) + # @return [Array] An array containing whether each tag is selected or not + def provisions_selected?(tags) + dbus_object.ProvisionsSelected(tags) + end + + # Add the given list of resolvables to the packages proposal + # + # @param unique_id [String] Unique identifier for the resolvables list + # @param type [Symbol] Resolvables type (:package or :pattern) + # @param resolvables [Array] Resolvables to add + # @param [Boolean] optional True for optional list, false (the default) for + # the required list + def add_resolvables(unique_id, type, resolvables, optional: false) + dbus_proposal.AddResolvables(unique_id, TYPES.index(type), resolvables, optional) + end + + # Returns a list of resolvables + # + # @param unique_id [String] Unique identifier for the resolvables list + # @param type [Symbol] Resolvables type (:package or :pattern) + # @param [Boolean] optional True for optional list, false (the default) for + # the required list + # @return [Array] Resolvables + def get_resolvables(unique_id, type, optional: false) + dbus_proposal.GetResolvables(unique_id, TYPES.index(type), optional).first + end + + # Replace a list of resolvables in the packages proposal + # + # @param unique_id [String] Unique identifier for the resolvables list + # @param type [Symbol] Resolvables type (:package or :pattern) + # @param resolvables [Array] List of resolvables + # @param [Boolean] optional True for optional list, false (the default) for + # the required list + def set_resolvables(unique_id, type, resolvables, optional: false) + dbus_proposal.SetResolvables(unique_id, TYPES.index(type), resolvables, optional) + end + + # Remove resolvables from a list + # + # @param unique_id [String] Unique identifier for the resolvables list + # @param type [Symbol] Resolvables type (:package or :pattern) + # @param resolvables [Array] Resolvables to remove + # @param [Boolean] optional True for optional list, false (the default) for + # the required list + def remove_resolvables(unique_id, type, resolvables, optional: false) + dbus_proposal.RemoveResolvables(unique_id, TYPES.index(type), resolvables, optional) + end + private + # @return [::DBus::Object] + attr_reader :dbus_proposal + # @return [::DBus::Object] attr_reader :dbus_object diff --git a/service/lib/dinstaller/dbus/software.rb b/service/lib/dinstaller/dbus/software.rb index 902c609f3d..6859b7573e 100644 --- a/service/lib/dinstaller/dbus/software.rb +++ b/service/lib/dinstaller/dbus/software.rb @@ -19,116 +19,13 @@ # To contact SUSE LLC about this file by physical or electronic mail, you may # find current contact information at www.suse.com. -require "dbus" -require "dinstaller/progress" - module DInstaller module DBus - # D-Bus object to manage software installation - class Software < ::DBus::Object - PATH = "/org/opensuse/DInstaller/Software1" - private_constant :PATH - - SOFTWARE_INTERFACE = "org.opensuse.DInstaller.Software1" - private_constant :SOFTWARE_INTERFACE - - # Constructor - # - # @param backend [DInstaller::Software] - # @param logger [Logger] - def initialize(backend, logger) - @backend = backend - @logger = logger - - register_progress_callback - - super(PATH) - end - - # rubocop:disable Metrics/BlockLength - dbus_interface SOFTWARE_INTERFACE do - dbus_reader :available_base_products, "a(ssa{sv})" - attr_writer :available_base_products - - dbus_watcher :available_base_products - - dbus_reader :selected_base_product, "s" - - dbus_method :SelectProduct, "in ProductID:s" do |product_id| - logger.info "SelectProduct #{product_id}" - - select_product(product_id) - PropertiesChanged(SOFTWARE_INTERFACE, { "SelectedBaseProduct" => product_id }, []) - end - - dbus_method :ProvisionSelected, "in Provision:s, out Result:b" do |provision| - backend.provision_selected?(provision) - end - - dbus_method :ProvisionsSelected, "in Provisions:as, out Result:ab" do |provisions| - [provisions.map { |p| backend.provision_selected?(p) }] - end - - dbus_method :Propose do - backend.propose - end - - dbus_method :Probe do - backend.probe - end - - dbus_method :Install do - backend.install - end - - dbus_method :Finish do - backend.finish - end - - # Progress has struct with values: - # s message - # t total major steps to do - # t current major step (0-based) - # t total minor steps. Can be zero which means no minor steps - # t current minor step - dbus_reader :progress, "(stttt)" - end - # rubocop:enable Metrics/BlockLength - - def available_base_products - backend.products.map do |product| - [product.name, product.display_name, {}].freeze - end - end - - def selected_base_product - backend.product - end - - def select_product(product_id) - backend.select_product(product_id) - end - - def progress - backend.progress.to_a - end - - private - - # @return [Logger] - attr_reader :logger - - # @return [DInstaller::Software] - attr_reader :backend - - # Registers callback to be called when the progress changes - # - # The callback will emit a signal - def register_progress_callback - backend.progress.on_change do - PropertiesChanged(SOFTWARE_INTERFACE, { "Progress" => progress }, []) - end - end + # Name space for software D-Bus classes + module Software end end end + +require "dinstaller/dbus/software/manager" +require "dinstaller/dbus/software/proposal" diff --git a/service/lib/dinstaller/dbus/software/manager.rb b/service/lib/dinstaller/dbus/software/manager.rb new file mode 100644 index 0000000000..e23db38266 --- /dev/null +++ b/service/lib/dinstaller/dbus/software/manager.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +# Copyright (c) [2022] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "dbus" + +module DInstaller + module DBus + module Software + # D-Bus object to manage software installation + class Manager < ::DBus::Object + PATH = "/org/opensuse/DInstaller/Software1" + private_constant :PATH + + SOFTWARE_INTERFACE = "org.opensuse.DInstaller.Software1" + private_constant :SOFTWARE_INTERFACE + + # Constructor + # + # @param backend [DInstaller::Software] + # @param logger [Logger] + def initialize(backend, logger) + @backend = backend + @logger = logger + + register_progress_callback + + super(PATH) + end + + # rubocop:disable Metrics/BlockLength + dbus_interface SOFTWARE_INTERFACE do + dbus_reader :available_base_products, "a(ssa{sv})" + + dbus_reader :selected_base_product, "s" + + dbus_method :SelectProduct, "in ProductID:s" do |product_id| + logger.info "SelectProduct #{product_id}" + + select_product(product_id) + PropertiesChanged(SOFTWARE_INTERFACE, { "SelectedBaseProduct" => product_id }, []) + end + + # TODO: just for performance comparison (see `perf.rb`) + dbus_method :ProvisionSelected, "in Provision:s, out Result:b" do |provision| + backend.provision_selected?(provision) + end + + dbus_method :ProvisionsSelected, "in Provisions:as, out Result:ab" do |provisions| + [provisions.map { |p| backend.provision_selected?(p) }] + end + + dbus_method :Propose do + backend.propose + end + + dbus_method :Probe do + backend.probe + end + + dbus_method :Install do + backend.install + end + + dbus_method :Finish do + backend.finish + end + + # Progress has struct with values: + # s message + # t total major steps to do + # t current major step (0-based) + # t total minor steps. Can be zero which means no minor steps + # t current minor step + dbus_reader :progress, "(stttt)" + end + # rubocop:enable Metrics/BlockLength + + def available_base_products + backend.products.map do |product| + [product.name, product.display_name, {}].freeze + end + end + + def selected_base_product + backend.product + end + + def select_product(product_id) + backend.select_product(product_id) + end + + def progress + backend.progress.to_a + end + + private + + # @return [Logger] + attr_reader :logger + + # @return [DInstaller::Software] + attr_reader :backend + + # Registers callback to be called when the progress changes + # + # The callback will emit a signal + def register_progress_callback + backend.progress.on_change do + PropertiesChanged(SOFTWARE_INTERFACE, { "Progress" => progress }, []) + end + end + end + end + end +end diff --git a/service/lib/dinstaller/dbus/software/proposal.rb b/service/lib/dinstaller/dbus/software/proposal.rb new file mode 100644 index 0000000000..c354f3d4d1 --- /dev/null +++ b/service/lib/dinstaller/dbus/software/proposal.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +# Copyright (c) [2022] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast" +require "dbus" +Yast.import "PackagesProposal" + +module DInstaller + module DBus + module Software + # Software proposal D-Bus representation + # + # This class allows to change software proposal settings through D-Bus. + # + # @see Yast::PackagesProposal + class Proposal < ::DBus::Object + PATH = "/org/opensuse/DInstaller/Software/Proposal1" + private_constant :PATH + + INTERFACE = "org.opensuse.DInstaller.Software.Proposal1" + private_constant :INTERFACE + + TYPES = [:package, :pattern].freeze + private_constant :TYPES + + # Constructor + # + # @param logger [Logger] + def initialize(logger) + @logger = logger + + super(PATH) + end + + dbus_interface INTERFACE do + dbus_method :AddResolvables, + "in Id:s, in Type:y, in Resolvables:as, in Optional:b" do |id, type, resolvables, opt| + Yast::PackagesProposal.AddResolvables(id, TYPES[type], resolvables, optional: opt) + end + + dbus_method :GetResolvables, + "in Id:s, in Type:y, in Optional:b, out Resolvables:as" do |id, type, opt| + [Yast::PackagesProposal.GetResolvables(id, TYPES[type], optional: opt)] + end + + dbus_method :SetResolvables, + "in Id:s, in Type:y, in Resolvables:as, in Optional:b" do |id, type, resolvables, opt| + Yast::PackagesProposal.SetResolvables(id, TYPES[type], resolvables, optional: opt) + end + + dbus_method :RemoveResolvables, + "in Id:s, in Type:y, in Resolvables:as, in Optional:b" do |id, type, resolvables, opt| + Yast::PackagesProposal.RemoveResolvables(id, TYPES[type], resolvables, optional: opt) + end + end + + private + + # @return [Logger] + attr_reader :logger + end + end + end +end diff --git a/service/lib/dinstaller/dbus/software_service.rb b/service/lib/dinstaller/dbus/software_service.rb index 903bce3004..f7cf6597fa 100644 --- a/service/lib/dinstaller/dbus/software_service.rb +++ b/service/lib/dinstaller/dbus/software_service.rb @@ -71,7 +71,8 @@ def service # @return [Array<::DBus::Object>] def dbus_objects @dbus_objects ||= [ - DInstaller::DBus::Software.new(@backend, logger) + DInstaller::DBus::Software::Manager.new(@backend, logger), + DInstaller::DBus::Software::Proposal.new(logger) ] end end diff --git a/service/lib/dinstaller/dbus/storage.rb b/service/lib/dinstaller/dbus/storage.rb index 1efb9ca1ae..69b7189bbc 100644 --- a/service/lib/dinstaller/dbus/storage.rb +++ b/service/lib/dinstaller/dbus/storage.rb @@ -21,7 +21,7 @@ module DInstaller module DBus - # Namespace for storage DBus objects + # Namespace for storage D-Bus classes module Storage end end diff --git a/service/lib/dinstaller/dbus/y2dir/manager/modules/Package.rb b/service/lib/dinstaller/dbus/y2dir/manager/modules/Package.rb new file mode 100644 index 0000000000..b40fd560ec --- /dev/null +++ b/service/lib/dinstaller/dbus/y2dir/manager/modules/Package.rb @@ -0,0 +1,43 @@ +# Copyright (c) [2022] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast" + +# :nodoc: +module Yast + # Replacement for the Yast::Package module + # + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/packages/src/modules/Package.rb + class PackageClass < Module + def main + puts "Loading mocked module #{__FILE__}" + end + + # Determines whether the package is available + # + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/packages/src/modules/Package.rb#L72 + # @todo Perform a real D-Bus call. + def Available(_package_name) + true + end + end + + Package = PackageClass.new + Package.main +end diff --git a/service/lib/dinstaller/dbus/y2dir/manager/modules/PackagesProposal.rb b/service/lib/dinstaller/dbus/y2dir/manager/modules/PackagesProposal.rb new file mode 100644 index 0000000000..35c3647802 --- /dev/null +++ b/service/lib/dinstaller/dbus/y2dir/manager/modules/PackagesProposal.rb @@ -0,0 +1,62 @@ +# Copyright (c) [2022] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast" +require "dinstaller/dbus/clients/software" + +# :nodoc: +module Yast + # Replacement for the Yast::PackagesProposal module + class PackagesProposalClass < Module + def main + puts "Loading mocked module #{__FILE__}" + @client = DInstaller::DBus::Clients::Software.new + end + + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/general/src/modules/PackagesProposal.rb#L118 + def AddResolvables(unique_id, type, resolvables, optional: false) + client.add_resolvables(unique_id, type, resolvables, optional: optional) + true + end + + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/general/src/modules/PackagesProposal.rb#L145 + def SetResolvables(unique_id, type, resolvables, optional: false) + client.set_resolvables(unique_id, type, resolvables, optional: optional) + true + end + + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/general/src/modules/PackagesProposal.rb#L285 + def GetResolvables(unique_id, type, optional: false) + client.get_resolvables(unique_id, type, optional: optional) + end + + # @see https://github.com/yast/yast-yast2/blob/b8cd178b7f341f6e3438782cb703f4a3ab0529ed/library/general/src/modules/PackagesProposal.rb#L177 + def RemoveResolvables(unique_id, type, resolvables, optional: false) + client.remove_resolvables(unique_id, type, resolvables, optional: optional) + true + end + + private + + attr_reader :client + end + + PackagesProposal = PackagesProposalClass.new + PackagesProposal.main +end diff --git a/service/lib/dinstaller/dbus/y2dir/modules/Autologin.rb b/service/lib/dinstaller/dbus/y2dir/modules/Autologin.rb index 1dd3a57497..9bd5e72da8 100644 --- a/service/lib/dinstaller/dbus/y2dir/modules/Autologin.rb +++ b/service/lib/dinstaller/dbus/y2dir/modules/Autologin.rb @@ -28,7 +28,7 @@ # $Id$ require "yast" -require "dinstaller/dbus/clients/dinstaller" +require "dinstaller/dbus/clients/software" module Yast @@ -64,6 +64,9 @@ def main # Pkg stuff initialized? @pkg_initialized = false + + # D-Bus software client + @dbus_client = DInstaller::Clients::Software.new end def available @@ -178,7 +181,7 @@ def AskForDisabling(new) # # @return Boolean def supported? - supported = DInstaller::DBus::Clients::DInstaller.provisions_selected?(DISPLAY_MANAGERS).any? + supported = @dbus_client.provisions_selected?(DISPLAY_MANAGERS).any? if supported log.info("Autologin is supported") diff --git a/service/lib/dinstaller/dbus/y2dir/software/modules/SpaceCalculation.rb b/service/lib/dinstaller/dbus/y2dir/software/modules/SpaceCalculation.rb new file mode 100644 index 0000000000..6f2d4e9a00 --- /dev/null +++ b/service/lib/dinstaller/dbus/y2dir/software/modules/SpaceCalculation.rb @@ -0,0 +1,44 @@ +# Copyright (c) [2022] SUSE LLC +# +# All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, contact SUSE LLC. +# +# To contact SUSE LLC about this file by physical or electronic mail, you may +# find current contact information at www.suse.com. + +require "yast" + +# :nodoc: +module Yast + # Replacement for the Yast::SpaceCalculation module. + class SpaceCalculationClass < Module + def main + puts "Loading mocked module #{__FILE__}" + end + + # @see https://github.com/yast/yast-packager/blob/master/src/modules/SpaceCalculation.rb#L711 + def GetPartitionInfo; end + + # @see https://github.com/yast/yast-packager/blob/master/src/modules/SpaceCalculation.rb#L860 + def CheckDiskSize; end + + # @see https://github.com/yast/yast-packager/blob/master/src/modules/SpaceCalculation.rb#L60 + def GetFailedMounts + [] + end + end + + SpaceCalculation = SpaceCalculationClass.new + SpaceCalculation.main +end diff --git a/service/lib/dinstaller/manager.rb b/service/lib/dinstaller/manager.rb index 2b075f6e8e..0589484c4c 100644 --- a/service/lib/dinstaller/manager.rb +++ b/service/lib/dinstaller/manager.rb @@ -78,7 +78,7 @@ def probe rescue StandardError => e status = Status::Error.new.tap { |s| s.messages << e.message } status_manager.change(status) - logger.error "Probing error: #{e.inspect}" + logger.error "Probing error: #{e.inspect}. Backtrace: #{e.backtrace}" end # rubocop:disable Metrics/AbcSize @@ -214,10 +214,8 @@ def probe_steps def finish_installation progress.init_minor_steps(2, "Copying logs") Yast::WFM.CallFunction("copy_logs_finish", ["Write"]) - progress.next_minor_step("Unmounting target system") - Yast::WFM.CallFunction("pre_umount_finish", ["Write"]) - Yast::WFM.CallFunction("umount_finish", ["Write"]) + storage.finish progress.next_minor_step("Target system correctly unmounted") end diff --git a/service/lib/dinstaller/software.rb b/service/lib/dinstaller/software.rb index b9516e580e..556a9318e9 100644 --- a/service/lib/dinstaller/software.rb +++ b/service/lib/dinstaller/software.rb @@ -130,9 +130,13 @@ def finish restore_original_repos end - # checks if given provision is provided by any resolvable marked for installation - def provision_selected?(provision) - Yast::Pkg.IsSelected(provision) || Yast::Pkg.IsProvided(provision) + # Determine whether the given tag is provided by the selected packages + # + # @param tag [String] Tag to search for (package names, requires/provides, or file + # names) + # @return [Boolean] true if it is provided; false otherwise + def provision_selected?(tag) + Yast::Pkg.IsSelected(tag) || Yast::Pkg.IsProvided(tag) end private diff --git a/service/lib/dinstaller/storage/manager.rb b/service/lib/dinstaller/storage/manager.rb index 48cc092def..ec22ec5bb3 100644 --- a/service/lib/dinstaller/storage/manager.rb +++ b/service/lib/dinstaller/storage/manager.rb @@ -54,6 +54,11 @@ def install(_progress) Yast::WFM.CallFunction("inst_prepdisk", []) end + # Umounts the target file system + def finish + Yast::WFM.CallFunction("umount_finish", ["Write"]) + end + # Storage proposal manager # # @return [Storage::Proposal] diff --git a/service/test/dinstaller/dbus/clients/software_test.rb b/service/test/dinstaller/dbus/clients/software_test.rb index 4f9ef275e7..6051d5b12f 100644 --- a/service/test/dinstaller/dbus/clients/software_test.rb +++ b/service/test/dinstaller/dbus/clients/software_test.rb @@ -32,11 +32,15 @@ allow(dbus_object).to receive(:introspect) allow(dbus_object).to receive(:[]).with("org.opensuse.DInstaller.Software1") .and_return(software_iface) + + allow(service).to receive(:object).with("/org/opensuse/DInstaller/Software/Proposal1") + .and_return(dbus_proposal) end let(:bus) { instance_double(::DBus::SystemBus) } let(:service) { instance_double(::DBus::Service) } let(:dbus_object) { instance_double(::DBus::ProxyObject) } + let(:dbus_proposal) { instance_double(::DBus::ProxyObject, introspect: nil) } let(:software_iface) { instance_double(::DBus::ProxyObjectInterface) } subject { described_class.new } @@ -80,8 +84,9 @@ end end - describe "#Probe" do + describe "#probe" do let(:dbus_object) { double(::DBus::ProxyObject, Probe: nil) } + it "calls the D-Bus Probe method" do expect(dbus_object).to receive(:Probe) @@ -98,5 +103,16 @@ subject.probe(&callback) end end + + describe "#provisions_selected" do + let(:dbus_object) { double(::DBus::ProxyObject) } + + it "returns true/false for every tag given" do + expect(dbus_object).to receive(:ProvisionsSelected) + .with(["sddm", "gdm"]).and_return([true, false]) + expect(subject.provisions_selected?(["sddm", "gdm"])) + .to eq([true, false]) + end + end end end diff --git a/service/test/dinstaller/manager_test.rb b/service/test/dinstaller/manager_test.rb index e0990ba63a..a8acd04df4 100644 --- a/service/test/dinstaller/manager_test.rb +++ b/service/test/dinstaller/manager_test.rb @@ -37,7 +37,9 @@ end let(:language) { instance_double(DInstaller::Language, probe: nil, install: nil) } let(:network) { instance_double(DInstaller::Network, probe: nil, install: nil) } - let(:storage) { instance_double(DInstaller::Storage::Manager, probe: nil, install: nil) } + let(:storage) do + instance_double(DInstaller::Storage::Manager, probe: nil, install: nil, finish: nil) + end let(:security) { instance_double(DInstaller::Security, probe: nil, write: nil) } let(:status_manager) do instance_double(DInstaller::StatusManager, change: nil) @@ -91,8 +93,10 @@ expect(language).to receive(:install).with(subject.progress) expect(network).to receive(:install).with(subject.progress) expect(software).to receive(:install) + expect(software).to receive(:finish) expect(security).to receive(:write).with(subject.progress) expect(storage).to receive(:install).with(subject.progress) + expect(storage).to receive(:finish) expect(users_client).to receive(:write).with(subject.progress) subject.install end diff --git a/service/test/dinstaller/software_test.rb b/service/test/dinstaller/software_test.rb index 61c8f82983..66dbe60ab9 100644 --- a/service/test/dinstaller/software_test.rb +++ b/service/test/dinstaller/software_test.rb @@ -108,4 +108,33 @@ end end end + + describe "#finish" do + let(:rootdir) { Dir.mktmpdir } + let(:repos_dir) { File.join(rootdir, "etc", "zypp", "repos.d") } + let(:backup_repos_dir) { File.join(rootdir, "etc", "zypp", "repos.d.backup") } + + before do + stub_const("DInstaller::Software::REPOS_DIR", repos_dir) + stub_const("DInstaller::Software::REPOS_BACKUP", backup_repos_dir) + FileUtils.mkdir_p(repos_dir) + FileUtils.mkdir_p(backup_repos_dir) + FileUtils.touch(File.join(backup_repos_dir, "example.repo")) + puts Dir[File.join(repos_dir, "**", "*")] + end + + after do + FileUtils.remove_entry(rootdir) + end + + it "releases the packaging system and restores the backup" do + expect(Yast::Pkg).to receive(:SourceSaveAll) + expect(Yast::Pkg).to receive(:TargetFinish) + expect(Yast::Pkg).to receive(:SourceCacheCopyTo) + .with(Yast::Installation.destdir) + + subject.finish + expect(File).to exist(File.join(repos_dir, "example.repo")) + end + end end diff --git a/service/test/dinstaller/storage/manager_test.rb b/service/test/dinstaller/storage/manager_test.rb index 96a5a91e8c..34fbd97d21 100644 --- a/service/test/dinstaller/storage/manager_test.rb +++ b/service/test/dinstaller/storage/manager_test.rb @@ -72,4 +72,11 @@ expect(storage.proposal).to be_a(DInstaller::Storage::Proposal) end end + + describe "#finish" do + it "runs the umount_finish client" do + expect(Yast::WFM).to receive(:CallFunction).with("umount_finish", ["Write"]) + storage.finish + end + end end