From 8da6a13c19d21b47b4d8ca395c4969661d96dcef Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Thu, 28 Nov 2019 14:11:17 +0100 Subject: [PATCH] Decreasing required memory (#976) * Decreasing required memory --- library/control/src/modules/ProductProfile.rb | 15 +- .../control/src/modules/WorkflowManager.rb | 24 +-- library/control/test/workflow_manager_test.rb | 46 +++--- .../lib/y2packager/licenses_fetchers/rpm.rb | 8 +- .../packages/src/lib/y2packager/product.rb | 27 +++- .../src/lib/y2packager/product_reader.rb | 55 +++---- .../src/lib/y2packager/product_upgrade.rb | 13 +- .../y2packager/release_notes_fetchers/rpm.rb | 7 +- .../packages/src/lib/y2packager/resolvable.rb | 148 ++++++++++++++++++ library/packages/src/modules/Product.rb | 33 ++-- .../packages/test/data/products-sles15.yml | 1 + library/packages/test/data/zypp/products.yml | 2 + library/packages/test/product_test.rb | 8 +- .../y2packager/licenses_fetchers/rpm_test.rb | 11 +- .../test/y2packager/product_reader_test.rb | 96 ++++++++---- .../packages/test/y2packager/product_test.rb | 51 ++++-- .../test/y2packager/product_upgrade_test.rb | 51 +++--- .../release_notes_fetchers/rpm_test.rb | 12 +- .../test/y2packager/resolvable_test.rb | 109 +++++++++++++ .../test/y2packager/zypp/test_repo/README.md | 4 + ...b288eb13cf01c09ae2a65a7eeab-primary.xml.gz | Bin 0 -> 88670 bytes .../zypp/test_repo/repodata/repomd.xml | 32 ++++ .../zypp/test_repo/repodata/repomd.xml.asc | 7 + .../zypp/test_repo/repodata/repomd.xml.key | 19 +++ package/yast2.changes | 8 + package/yast2.spec | 2 +- 26 files changed, 615 insertions(+), 174 deletions(-) create mode 100644 library/packages/src/lib/y2packager/resolvable.rb create mode 100755 library/packages/test/y2packager/resolvable_test.rb create mode 100644 library/packages/test/y2packager/zypp/test_repo/README.md create mode 100644 library/packages/test/y2packager/zypp/test_repo/repodata/4d295860e625859a714dcc91c6a2e6f7634aab288eb13cf01c09ae2a65a7eeab-primary.xml.gz create mode 100644 library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml create mode 100644 library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.asc create mode 100644 library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.key diff --git a/library/control/src/modules/ProductProfile.rb b/library/control/src/modules/ProductProfile.rb index 6407bbb91..2f6e5288d 100644 --- a/library/control/src/modules/ProductProfile.rb +++ b/library/control/src/modules/ProductProfile.rb @@ -6,6 +6,7 @@ # $Id$ require "yast" require "shellwords" +require "y2packager/resolvable" module Yast class ProductProfileClass < Module @@ -82,11 +83,11 @@ def IsCompliant(product_id) end # iterate all (or given) products and get the info about them - Builtins.foreach(Pkg.ResolvableProperties("", :product, "")) do |product| - src_id = Ops.get_integer(product, "source", -1) - name = Ops.get_string(product, "name", "") + Y2Packager::Resolvable.find(kind: :product).each do |product| + src_id = product.source + name = product.name if product_id.nil? && - Ops.get_symbol(product, "status", :none) != :selected + product.status != :selected next end next if !product_id.nil? && src_id != product_id @@ -109,16 +110,16 @@ def IsCompliant(product_id) end # generate product map: version_release = Builtins.splitstring( - Ops.get_string(product, "version", ""), + product.version, "-" ) products = Builtins.add( products, - "arch" => Ops.get_string(product, "arch", ""), + "arch" => product.arch, "name" => name, "version" => Ops.get(version_release, 0, ""), "release" => Ops.get(version_release, 1, ""), - "vendor" => Ops.get_string(product, "vendor", "") + "vendor" => product.vendor ) sigkeys = Convert.convert( Builtins.union(sigkeys, GetSigKeysForProduct(src_id)), diff --git a/library/control/src/modules/WorkflowManager.rb b/library/control/src/modules/WorkflowManager.rb index 5a73ddbb4..afd0dbe7c 100644 --- a/library/control/src/modules/WorkflowManager.rb +++ b/library/control/src/modules/WorkflowManager.rb @@ -37,6 +37,7 @@ require "packages/package_downloader" require "packages/package_extractor" +require "y2packager/resolvable" module Yast class WorkflowManagerClass < Module @@ -414,12 +415,12 @@ def control_file(source) package = case source when ::Integer product = find_product(source) - return nil unless product && product["product_package"] + return nil unless product&.product_package - product_package = product["product_package"] + product_package = product.product_package # the dependencies are bound to the product's -release package - release_package = Pkg.ResolvableDependencies(product_package, :package, "").first + release_package = Y2Packager::Resolvable.find(kind: :package, name: product_package).first # find the package name with installer update in its Provide dependencies control_file_package = find_control_package(release_package) @@ -1609,14 +1610,14 @@ def merge_modules_extensions(packages) # @return [Hash,nil] pkg-bindings product hash or nil if not found def find_product(repo_id) # identify the product - products = Pkg.ResolvableDependencies("", :product, "") + products = Y2Packager::Resolvable.find(kind: :product) return nil unless products - products.select! { |p| p["source"] == repo_id } + products.select! { |p| p.source == repo_id } if products.size > 1 log.warn("More than one product found in the repository: #{products}") - log.warn("Using the first one: #{products.first}") + log.warn("Using the first one: #{products.first.name}") end products.first @@ -1625,11 +1626,12 @@ def find_product(repo_id) # Find the extension package name for the specified release package. # The extension package is defined by the "installerextension()" # RPM "Provides" dependency. + # @param [Y2Packager::Resolvable] release package # @return [String,nil] a package name or nil if not found def find_control_package(release_package) - return nil unless release_package && release_package["deps"] + return nil unless release_package&.deps - release_package["deps"].each do |dep| + release_package.deps.each do |dep| provide = dep["provides"] next unless provide @@ -1648,7 +1650,7 @@ def find_control_package(release_package) # @return [Fixnum,nil] repository ID or nil if not found def package_repository(package_name) # Identify the installation repository with the package - pkgs = Pkg.ResolvableProperties(package_name, :package, "") + pkgs = Y2Packager::Resolvable.find(kind: :package, name: package_name) if pkgs.empty? log.warn("The installer extension package #{package_name} was not found") @@ -1656,7 +1658,7 @@ def package_repository(package_name) end latest_package = pkgs.reduce(nil) do |a, p| - (!a || (Pkg.CompareVersions(a["version"], p["version"]) < 0)) ? p : a + (!a || (Pkg.CompareVersions(a.version, p.version) < 0)) ? p : a end if pkgs.size > 1 @@ -1664,7 +1666,7 @@ def package_repository(package_name) log.info("Using the latest package: #{latest_package}") end - latest_package["source"] + latest_package.source end # Download and extract a package from a repository. diff --git a/library/control/test/workflow_manager_test.rb b/library/control/test/workflow_manager_test.rb index d57c9ad29..4d1c7e8ff 100755 --- a/library/control/test/workflow_manager_test.rb +++ b/library/control/test/workflow_manager_test.rb @@ -286,19 +286,25 @@ # setup fake products and their packages let(:repo_id) { 42 } let(:product_package) { "foo-release" } - let(:product) { { "name" => "foo", "source" => repo_id, "product_package" => product_package } } + let(:product) do + Y2Packager::Resolvable.new("kind" => :product, "name" => "foo", "source" => repo_id, + "version" => "1.0", "arch" => "x86_64", "product_package" => product_package) + end let(:ext_package) { "foo-installation" } - let(:extension) { { "name" => ext_package, "source" => repo_id } } + let(:extension) do + Y2Packager::Resolvable.new("kind" => :package, "name" => ext_package, "source" => repo_id, + "version" => "1.0", "arch" => "x86_64", "deps" => []) + end let(:release) do - { "name" => product_package, "source" => repo_id, - "deps" => ["provides" => "installerextension(#{ext_package})"] } + Y2Packager::Resolvable.new("name" => product_package, "source" => repo_id, "version" => "1.0", "arch" => "x86_64", + "kind" => :package, "deps" => ["provides" => "installerextension(#{ext_package})"]) end before do # generic mocks, can be are overriden in the tests - allow(Yast::Pkg).to receive(:ResolvableDependencies).with("", :product, "").and_return([product]) - allow(Yast::Pkg).to receive(:ResolvableDependencies).with(product_package, :package, "").and_return([release]) - allow(Yast::Pkg).to receive(:ResolvableProperties).with(ext_package, :package, "").and_return([extension]) + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return([product]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: product_package, kind: :package).and_return([release]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: ext_package, kind: :package).and_return([extension]) allow_any_instance_of(Packages::PackageDownloader).to receive(:download) allow_any_instance_of(Packages::PackageExtractor).to receive(:extract) # allow using it at other places @@ -307,42 +313,46 @@ context "when repository id is passed" do it "returns nil if the repository does not provide any product" do - expect(Yast::Pkg).to receive(:ResolvableDependencies).with("", :product, "").and_return([]) + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return([]) expect(subject.control_file(repo_id)).to be nil end it "returns nil if the product does not refer to a release package" do - product = { "name" => "foo", "source" => repo_id } - expect(Yast::Pkg).to receive(:ResolvableDependencies).with("", :product, "").and_return([product]) + product = Y2Packager::Resolvable.new("kind" => :product, "name" => "foo", "source" => repo_id, + "version" => "1.0", "arch" => "x86_64", "product_package" => product_package) + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return([product]) expect(subject.control_file(repo_id)).to be nil end it "returns nil if the product belongs to a different repository" do - product = { "name" => "foo", "source" => repo_id + 1 } - expect(Yast::Pkg).to receive(:ResolvableDependencies).with("", :product, "").and_return([product]) + product = Y2Packager::Resolvable.new("kind" => :product, "name" => "foo", "source" => repo_id + 1, + "version" => "1.0", "arch" => "x86_64", "product_package" => product_package) + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return([product]) expect(subject.control_file(repo_id)).to be nil end it "returns nil if the release package cannot be found" do - expect(Yast::Pkg).to receive(:ResolvableDependencies).with(product_package, :package, "").and_return([]) + expect(Y2Packager::Resolvable).to receive(:find).with(name: product_package, kind: :package).and_return([]) expect(subject.control_file(repo_id)).to be nil end it "returns nil if the release package does not have any dependencies" do - release = { "name" => "foo", "source" => repo_id } - expect(Yast::Pkg).to receive(:ResolvableDependencies).with(product_package, :package, "").and_return([release]) + release = Y2Packager::Resolvable.new("kind" => :package, "name" => "foo", "source" => repo_id, + "version" => "1.0", "arch" => "x86_64", "deps" => []) + expect(Y2Packager::Resolvable).to receive(:find).with(name: product_package, kind: :package).and_return([release]) expect(subject.control_file(repo_id)).to be nil end it "returns nil if the release package does not have any installerextension() provides" do - release = { "name" => "foo", "source" => repo_id, "deps" => ["provides" => "foo"] } - expect(Yast::Pkg).to receive(:ResolvableDependencies).with(product_package, :package, "").and_return([release]) + release = Y2Packager::Resolvable.new("kind" => :package, "name" => "foo", "source" => repo_id, + "version" => "1.0", "arch" => "x86_64", "deps" => ["provides" => "foo"]) + expect(Y2Packager::Resolvable).to receive(:find).with(name: product_package, kind: :package).and_return([release]) expect(subject.control_file(repo_id)).to be nil end end it "returns nil if the installer extension package is not found" do - expect(Yast::Pkg).to receive(:ResolvableProperties).with(ext_package, :package, "").and_return([]) + expect(Y2Packager::Resolvable).to receive(:find).with(name: ext_package, kind: :package).and_return([]) expect(subject.control_file(repo_id)).to be nil end diff --git a/library/packages/src/lib/y2packager/licenses_fetchers/rpm.rb b/library/packages/src/lib/y2packager/licenses_fetchers/rpm.rb index 411f2ae97..c24c8cc54 100644 --- a/library/packages/src/lib/y2packager/licenses_fetchers/rpm.rb +++ b/library/packages/src/lib/y2packager/licenses_fetchers/rpm.rb @@ -11,6 +11,7 @@ # ------------------------------------------------------------------------------ require "y2packager/licenses_fetchers/archive" +require "y2packager/resolvable" module Y2Packager module LicensesFetchers @@ -66,11 +67,8 @@ def package def package_name return @package_name if @package_name - package_properties = Yast::Pkg.ResolvableProperties(product_name, :product, "") - package_properties = package_properties.find { |props| props.key?("product_package") } - package_properties ||= {} - - @package_name = package_properties.fetch("product_package", nil) + package_property = Y2Packager::Resolvable.find(kind: :product, name: product_name).first + @package_name = package_property.product_package if package_property end end end diff --git a/library/packages/src/lib/y2packager/product.rb b/library/packages/src/lib/y2packager/product.rb index d8ad544b9..1770047f3 100644 --- a/library/packages/src/lib/y2packager/product.rb +++ b/library/packages/src/lib/y2packager/product.rb @@ -14,6 +14,7 @@ require "y2packager/product_reader" require "y2packager/release_notes_reader" require "y2packager/product_license_mixin" +require "y2packager/resolvable" module Y2Packager # Represent a product which is present in a repository. At this @@ -64,6 +65,22 @@ def from_h(product) Y2Packager::Product.new(params) end + # Create a product from Y2Packager::Resolvable + # @param product [Y2Packager::Resolvable] product + # @param installation_package [String] installation package name + # @param displayorder [Integer] display order from the package provides + # @return [Y2Packager::Product] converted product + def from_resolvable(product, installation_package = "", + displayorder = nil) + Y2Packager::Product.new( + name: product.name, short_name: product.short_name, + display_name: product.display_name, version: product.version, + arch: product.arch, category: product.category, + vendor: product.vendor, order: displayorder, + installation_package: installation_package + ) + end + # Return all known available products # # @return [Array] Known available products @@ -247,7 +264,7 @@ def release_notes(user_lang, format = :txt) def relnotes_url return nil unless resolvable_properties - url = resolvable_properties["relnotes_url"] + url = resolvable_properties.relnotes_url url.empty? ? nil : url end @@ -260,8 +277,8 @@ def relnotes_url # @param statuses [Array] Status to compare with. # @return [Boolean] true if it is in the given status def status?(*statuses) - Yast::Pkg.ResolvableProperties(name, :product, "").any? do |res| - statuses.include?(res["status"]) + Y2Packager::Resolvable.find(kind: :product, name: name).any? do |res| + statuses.include?(res.status) end end @@ -273,9 +290,7 @@ def status?(*statuses) # # @return [Hash] properties def resolvable_properties - @resolvable_properties ||= Yast::Pkg.ResolvableProperties(name, :product, "").find do |data| - data["version"] == version - end + @resolvable_properties ||= Y2Packager::Resolvable.find(kind: :product, name: name, version: version).first end end end diff --git a/library/packages/src/lib/y2packager/product_reader.rb b/library/packages/src/lib/y2packager/product_reader.rb index e43df0f66..8b2421e8f 100644 --- a/library/packages/src/lib/y2packager/product_reader.rb +++ b/library/packages/src/lib/y2packager/product_reader.rb @@ -13,6 +13,7 @@ require "yast" require "y2packager/product" require "y2packager/product_sorter" +require "y2packager/resolvable" Yast.import "Pkg" Yast.import "Linuxrc" @@ -83,37 +84,31 @@ def all_products(force_repos: false) if Yast::Stage.initial && Y2Packager::MediumType.online? && !force_repos return Y2Packager::ProductControlProduct.products.each_with_object([]) do |p, result| - result << Y2Packager::Product.new(name: p.name, display_name: p.label, - version: p.version, arch: p.arch, - short_name: p.name, # TODO: verify that name and shortname are same for control products - installation_package: "Test") # just hack as we do not know current package name yet + result << Y2Packager::Product.from_resolvable(p) end end @all_products = [] available_products.each do |prod| - prod_pkg = product_package(prod["product_package"]) + prod_pkg = product_package(prod.product_package) if prod_pkg # remove special products if they have not been defined in linuxrc - prod_pkg["deps"].find { |dep| dep["provides"] =~ /\Aspecialproduct\(\s*(.*?)\s*\)\z/ } + prod_pkg.deps.find { |dep| dep["provides"] =~ /\Aspecialproduct\(\s*(.*?)\s*\)\z/ } special_product_tag = linuxrc_string(Regexp.last_match[1]) if Regexp.last_match if special_product_tag && !linuxrc_special_products.include?(special_product_tag) - log.info "Special product #{prod["name"]} has not been defined via linuxrc. --> do not offer it" + log.info "Special product #{prod.name} has not been defined via linuxrc. --> do not offer it" next end # Evaluating display order - prod_pkg["deps"].find { |dep| dep["provides"] =~ /\Adisplayorder\(\s*([0-9]+)\s*\)\z/ } + prod_pkg.deps.find { |dep| dep["provides"] =~ /\Adisplayorder\(\s*([0-9]+)\s*\)\z/ } displayorder = Regexp.last_match[1].to_i if Regexp.last_match end - @all_products << Y2Packager::Product.new( - name: prod["name"], short_name: prod["short_name"], display_name: prod["display_name"], - version: prod["version"], arch: prod["arch"], category: prod["category"], - vendor: prod["vendor"], order: displayorder, - installation_package: installation_package_mapping[prod["name"]] + @all_products << Y2Packager::Product.from_resolvable( + prod, installation_package_mapping[prod.name], displayorder ) end @@ -145,21 +140,23 @@ def installed_base_product base = base_product return nil unless base - Y2Packager::Product.from_h(base) + Y2Packager::Product.from_resolvable(base, installation_package_mapping[base.name]) end # All installed products # @return [Array] the product list def all_installed_products - installed_products.map { |p| Y2Packager::Product.from_h(p) } + installed_products.map do |p| + Y2Packager::Product.from_resolvable(p, installation_package_mapping[p.name]) + end end def product_package(name, _repo_id = nil) return nil unless name # find the highest version - Yast::Pkg.ResolvableDependencies(name, :package, "").reduce(nil) do |a, p| - (!a || (Yast::Pkg.CompareVersions(a["version"], p["version"]) < 0)) ? p : a + Y2Packager::Resolvable.find(kind: :package, name: name).reduce(nil) do |a, p| + (!a || (Yast::Pkg.CompareVersions(a.version, p.version) < 0)) ? p : a end end @@ -168,43 +165,43 @@ def product_package(name, _repo_id = nil) # read the available products, remove potential duplicates # @return [Array] pkg-bindings data structure def zypp_products - products = Yast::Pkg.ResolvableProperties("", :product, "") + products = Y2Packager::Resolvable.find(kind: :product) # remove duplicates, there might be different flavors ("DVD"/"POOL") # or archs (x86_64/i586), when selecting the product to install later # libzypp will select the correct arch automatically, # keep products with different location, they are filtered out later - products.uniq! { |p| "#{p["name"]}__#{p["version"]}__#{resolvable_location(p)}" } - log.info "Found products: #{products.map { |p| p["name"] }}" + products.uniq! { |p| "#{p.name}__#{p.version}__#{resolvable_location(p)}" } + log.info "Found products: #{products.map(&:name)}" products end # read the available products, remove potential duplicates - # @return [Array] pkg-bindings data structures + # @return [Array] list of products def available_products # select only the available or to be installed products - zypp_products.select { |p| p["status"] == :available || p["status"] == :selected } + zypp_products.select { |p| p.status == :available || p.status == :selected } end # read the installed products - # @return [Array] pkg-bindings data structures + # @return [Array] list of products def installed_products # select only the installed or to be removed products - zypp_products.select { |p| p["status"] == :installed || p["status"] == :removed } + zypp_products.select { |p| p.status == :installed || p.status == :removed } end # find the installed base product - # @return[Hash,nil] the pkg-bindings product structure or nil if not found + # @return[Y2Packager::Resolvable,nil] the pkg-bindings product structure or nil if not found def base_product # The base product is identified by the /etc/products.d/baseproduct symlink # and because a symlink can point only to one file there can be only one base product. # The "installed" condition is actually not required because that symlink is created # only for installed products. (Just make sure it still works in case the libzypp # internal implementation is changed.) - base = installed_products.find { |p| p["type"] == "base" } + base = installed_products.find { |p| p.type == "base" } - log.info("Found installed base product: #{base}") + log.info("Found installed base product: #{base.name}") base end @@ -234,14 +231,14 @@ def linuxrc_string(input) # @return [Symbol] `:on_medium` or `:on_system` # def resolvable_location(res) - case res["status"] + case res.status when :available, :selected :on_medium when :installed, :removed :on_system else # just in case pkg-bindings add some new status... - raise "Unexpected resolvable status: #{res["status"]}" + raise "Unexpected resolvable status: #{res.status}" end end end diff --git a/library/packages/src/lib/y2packager/product_upgrade.rb b/library/packages/src/lib/y2packager/product_upgrade.rb index f123ea359..1e18f53be 100644 --- a/library/packages/src/lib/y2packager/product_upgrade.rb +++ b/library/packages/src/lib/y2packager/product_upgrade.rb @@ -128,6 +128,7 @@ def will_be_obsoleted_by(old_product_name) # @return [] Product names which should be uninstalled from the system def obsolete_upgrades system_installed = Y2Packager::Product.installed_products.map(&:name) + UPGRADE_REMOVAL_MAPPING.each_with_object([]) do |(installed_products, obsolete_products), a| # all products from the mapping are installed and the obsolete one # is removed by the solver (i.e. not removed by YaST or user) @@ -198,16 +199,16 @@ def find_by_name(available) # just a helper for logging the details for easier debugging def log_products - products = Yast::Pkg.ResolvableProperties("", :product, "") - log.debug("All products: #{products.inspect}") - names = products.select { |p| p["status"] == :selected }.map { |p| p["name"] } + products = Y2Packager::Resolvable.find(kind: :product) + log.debug("All products: #{products.map(&:name)}") + names = products.select { |p| p.status == :selected }.map(&:name) log.info("Selected products: #{names.inspect}") end def removed_by_solver?(product_name) - products = Yast::Pkg.ResolvableProperties(product_name, :product, "") - # any item removed by the solver? - products.any? { |p| p["status"] == :removed && p["transact_by"] == :solver } + Y2Packager::Resolvable.any?( + name: product_name, kind: :product, status: :removed, transact_by: :solver + ) end end end diff --git a/library/packages/src/lib/y2packager/release_notes_fetchers/rpm.rb b/library/packages/src/lib/y2packager/release_notes_fetchers/rpm.rb index ba8f6aad1..2bf3f6155 100644 --- a/library/packages/src/lib/y2packager/release_notes_fetchers/rpm.rb +++ b/library/packages/src/lib/y2packager/release_notes_fetchers/rpm.rb @@ -16,6 +16,7 @@ require "y2packager/release_notes" require "y2packager/release_notes_content_prefs" require "y2packager/release_notes_fetchers/base" +require "y2packager/resolvable" require "packages/package_downloader" require "tmpdir" @@ -95,14 +96,14 @@ def release_notes_package provides = Yast::Pkg.PkgQueryProvides("release-notes()") release_notes_packages = provides.map(&:first).uniq package_name = release_notes_packages.sort.find do |name| - package_list = Yast::Pkg.ResolvableDependencies(name, :package, "") + package_list = Y2Packager::Resolvable.find(kind: :package, name: name) log.debug "Evaluating #{name} provides: #{package_list}" - package = package_list.find { |p| p["status"] == :selected } || package_list.find { |p| p["status"] == :available } + package = package_list.find { |p| p.status == :selected } || package_list.find { |p| p.status == :available } log.debug "Checking package #{package}" next false unless package - dependencies = package["deps"] + dependencies = package.deps dependencies.any? do |dep| # mind $ at the end of the regexp, otherwise for SLES you may get RNs of any SLES.* product dep["provides"].to_s.match(/^\s*release-notes\(\)\s*=\s*#{Regexp.escape(product.name)}\s*$/) diff --git a/library/packages/src/lib/y2packager/resolvable.rb b/library/packages/src/lib/y2packager/resolvable.rb new file mode 100644 index 000000000..bcaa49a78 --- /dev/null +++ b/library/packages/src/lib/y2packager/resolvable.rb @@ -0,0 +1,148 @@ +# ------------------------------------------------------------------------------ +# Copyright (c) 2019 SUSE LINUX GmbH, Nuremberg, Germany. +# +# 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. +# ------------------------------------------------------------------------------ + +require "yast" + +Yast.import "Pkg" + +module Y2Packager + # + # This class represents a libzypp resolvable object (package, pattern, patch, + # product, source package) + # + # @note The returned Resolvables might not be valid anymore after changing + # the package manager status (installing/removing packages, changing + # repositories, etc.). After such a change you need to load the resolvables + # again, avoid storing them for later if possible. + # + # @example All installed packages + # Y2Packager::Resolvable.find(kind: :package, status: :installed) + # + # @example Available (not installed) "yast2" packages + # Y2Packager::Resolvable.find(kind: :package, status: :available, name: "yast2") + # + # @example Lazy loading + # res = Y2Packager::Resolvable.find(kind: :package, status: :installed) + # # the `summary` attribute is loaded from libzypp when needed + # res.each {|r| puts "#{r.name} - {r.summary}"} + # + # @example Preloading the attributes + # # the `summary` attribute is loaded from libzypp already at the initial state + # res = Y2Packager::Resolvable.find(kind: :package, status: :installed, [:summary]) + # # this returns the cached `summary` attribute, this is much more efficient + # res.each {|r| puts "#{r.name} - {r.summary}"} + # + # @since 4.2.6 + class Resolvable + include Yast::Logger + + # + # Find the resolvables which match the input parameters. See Yast::Pkg.Resolvables + # + # @param params [Hash] The search filter, only the matching resolvables + # are returned. + # @param preload [Array] The list of attributes which should be preloaded. + # The missing attributes are lazy loaded, however for performance reasons + # you might ask to preload the attributes right at the beginning and avoid + # querying libzypp again later. + # @return [Array] Found resolvables or empty array if nothing found + # @see https://yast-pkg-bindings.surge.sh/ Yast::Pkg.Resolvables + def self.find(params, preload = []) + attrs = (preload + UNIQUE_ATTRIBUTES).uniq + Yast::Pkg.Resolvables(params, attrs).map { |r| new(r) } + end + + # + # Is there any resolvable matching the requested parameters? This is similar to + # the .find method, just instead of a resolvable list it returns a simple Boolean. + # + # @param params [Hash] The requested attributes + # @return [Boolean] `true` if any matching resolvable is found, `false` otherwise. + # @see .find + def self.any?(params) + Yast::Pkg.AnyResolvable(params) + end + + # + # Constructor, initialize the object from a pkg-bindings resolvable hash. + # + # @param hash [Hash] A pkg-bindings resolvable hash. + def initialize(hash) + from_hash(hash) + end + + # + # Dynamically load the missing attributes from libzypp. + # + # @param method [Symbol] the method called + # @param args not used so far, raises ArgumentError if anything is passed + # + # @return the loaded value from libzypp + # + def method_missing(method, *args) + if instance_variable_defined?("@#{method}") + raise ArgumentError, "Method #{method} does not accept arguments" unless args.empty? + + return instance_variable_get("@#{method}") + end + + # load a missing attribute + raise "Missing attributes for identifying the resolvable." if !UNIQUE_ATTRIBUTES.all? { |a| instance_variable_defined?("@#{a}") } + + load_attribute(method) + super unless instance_variable_defined?("@#{method}") + raise ArgumentError, "Method #{method} does not accept arguments" unless args.empty? + + instance_variable_get("@#{method}") + end + + # defines for dynamic methods also respond_to? + def respond_to_missing?(method, _private) + return true if instance_variable_defined?("@#{method}") + return true if UNIQUE_ATTRIBUTES.include?(method.to_sym) + + false + end + + private + + # attributes required for identifying a resolvable + UNIQUE_ATTRIBUTES = [:kind, :name, :version, :arch, :source].freeze + + # Load the attributes from a Hash + # + # @param hash [Hash] The resolvable Hash obtained from pkg-bindings. + def from_hash(hash) + hash.each do |k, v| + instance_variable_set("@#{k}", v) + end + end + + # + # Lazy load a missing attribute. + # + # @param attr [Symbol] The required attribute to load. + # @return [Object] The read value. + def load_attribute(attr) + attrs = Hash[(UNIQUE_ATTRIBUTES.map { |a| [a, instance_variable_get("@#{a}")] })] + resolvables = Yast::Pkg.Resolvables(attrs, [attr]) + + # Finding more than one result is suspicious, log a warning + log.warn("Found several resolvables: #{resolvables.inspect}") if resolvables.size > 1 + + resolvable = resolvables.first + return unless resolvable&.key?(attr.to_s) + + instance_variable_set("@#{attr}", resolvable[attr.to_s]) + end + end +end diff --git a/library/packages/src/modules/Product.rb b/library/packages/src/modules/Product.rb index 1eca864b5..fabf6e315 100644 --- a/library/packages/src/modules/Product.rb +++ b/library/packages/src/modules/Product.rb @@ -28,6 +28,7 @@ # $Id$ require "yast" require "y2packager/product_reader" +require "y2packager/resolvable" module Yast class ProductClass < Module @@ -93,13 +94,13 @@ def FindBaseProducts log.info "Looking for base products" - products = Pkg.ResolvableProperties("", :product, "") || [] + products = Y2Packager::Resolvable.find(kind: :product) || [] # For all (not only base) products # FIXME: filling release notes is a nasty side effect of searching the base product, # it should be handled separately... required_status = use_installed_products? ? :installed : :selected - fill_up_relnotes(products.select { |p| p["status"] == required_status }) + fill_up_relnotes(products.select { |p| p.status == required_status }) # list of products defined by the "system-installation()" provides system_products = Y2Packager::ProductReader.installation_package_mapping.keys @@ -110,18 +111,18 @@ def FindBaseProducts # The category "base" is not set during installation yet, it is set # only for _installed_ base product (otherwise "addon" is reported). if use_installed_products? - p["category"] == "base" + p.category == "base" elsif system_products && !system_products.empty? # the base product is marked by "system-installation()" provides status = selected ? :selected : :available - system_products.include?(p["name"]) && p["status"] == status + system_products.include?(p.name) && p.status == status else # Use the product from the initial repository as a fallback - p["source"] == 0 + p.source == 0 end end - log.info "Found #{products.size} base product(s): #{products.map { |p| p["name"] }.inspect}" + log.info "Found #{products.size} base product(s): #{products.map(&:name).inspect}" if products.empty? log.error "No base product found" @@ -130,7 +131,19 @@ def FindBaseProducts log.warn "More than one base product found!" end - deep_copy(products) + # returns a hash in order to not change the interface + products.map do |p| + { "name" => p.name, + "short_name" => p.short_name, + "display_name" => p.display_name, + "version" => p.version, + "arch" => p.arch, + "category" => p.category, + "vendor" => p.vendor, + "status" => p.status, + "relnotes_url" => p.relnotes_url, + "register_target" => p.register_target } + end end # Reads products from libzypp and fills the internal products cache @@ -211,11 +224,11 @@ def fill_up_relnotes(products) release_notes_to_product = {} products.map do |p| - next if p["relnotes_url"] == "" + next if p.relnotes_url == "" - url = p["relnotes_url"] + url = p.relnotes_url all_release_notes << url - release_notes_to_product[url] = (p["display_name"] || "") + release_notes_to_product[url] = p.display_name end set_property(:relnotesurl_all, all_release_notes) diff --git a/library/packages/test/data/products-sles15.yml b/library/packages/test/data/products-sles15.yml index ee44578a7..ea00fb172 100644 --- a/library/packages/test/data/products-sles15.yml +++ b/library/packages/test/data/products-sles15.yml @@ -1,5 +1,6 @@ --- - arch: x86_64 + kind: :product category: addon description: |- SUSE Linux Enterprise offers a comprehensive diff --git a/library/packages/test/data/zypp/products.yml b/library/packages/test/data/zypp/products.yml index 1fa83b915..72fee1722 100644 --- a/library/packages/test/data/zypp/products.yml +++ b/library/packages/test/data/zypp/products.yml @@ -1,5 +1,6 @@ --- - arch: x86_64 + kind: :product category: base description: openSUSE is a distribution by the openSUSE.org project. display_name: openSUSE (INSTALLED) @@ -27,6 +28,7 @@ vendor: openSUSE version: 13.1-1.10 - arch: x86_64 + kind: :product category: base description: openSUSE is a distribution by the openSUSE.org project. display_name: openSUSE (SELECTED) diff --git a/library/packages/test/product_test.rb b/library/packages/test/product_test.rb index 1058d2cbe..09113fc0a 100755 --- a/library/packages/test/product_test.rb +++ b/library/packages/test/product_test.rb @@ -28,7 +28,9 @@ def load_zypp(file_name) YAML.load_file(file_name) end -PRODUCTS_FROM_ZYPP = load_zypp("products.yml").freeze +def product_from_zypp + load_zypp("products.yml").map { |p| Y2Packager::Resolvable.new(p) } +end def stub_defaults Yast.y2milestone "--------- Running test ---------" @@ -37,7 +39,7 @@ def stub_defaults allow(Yast::PackageSystem).to receive(:EnsureSourceInit).and_return(true) allow(Yast::Pkg).to receive(:PkgSolve).and_return(true) allow(Yast::PackageLock).to receive(:Check).and_return(true) - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "").and_return(PRODUCTS_FROM_ZYPP.dup) + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return(product_from_zypp) end # Describes Product handling as a whole (due to lazy loading and internal caching), @@ -284,7 +286,7 @@ def stub_defaults context "while called on a broken system (no os-release, no zypp information)" do before(:each) do allow(Yast::OSRelease).to receive(:os_release_exists?).and_return(false) - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "").and_return([]) + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product).and_return([]) end context "in installation" do diff --git a/library/packages/test/y2packager/licenses_fetchers/rpm_test.rb b/library/packages/test/y2packager/licenses_fetchers/rpm_test.rb index 85107df35..47a65fd2e 100755 --- a/library/packages/test/y2packager/licenses_fetchers/rpm_test.rb +++ b/library/packages/test/y2packager/licenses_fetchers/rpm_test.rb @@ -29,7 +29,10 @@ def rpm_path_for(package) let(:lang) { "cz_CZ" } let(:product_name) { "SLES" } let(:package_name) { "sles-release" } - let(:package_properties) { [{ "product_package" => package_name }] } + let(:package_properties) do + [Y2Packager::Resolvable.new(kind: :product, + name: "SLE_RT", status: :available, source: 2, product_package: package_name)] + end let(:package_status) { :selected } let(:package_path) { rpm_path_for("licenses_test_package-0.1-0.noarch.rpm") } let(:package) do @@ -42,8 +45,8 @@ def rpm_path_for(package) let(:found_packages) { [package] } before do - allow(Yast::Pkg).to receive(:ResolvableProperties) - .with(product_name, :product, "") + allow(Y2Packager::Resolvable).to receive(:find) + .with(kind: :product, name: product_name) .and_return(package_properties) allow(Y2Packager::Package).to receive(:find) @@ -79,7 +82,7 @@ def rpm_path_for(package) end context "when package name is not found" do - let(:package_properties) { {} } + let(:package_properties) { [] } it "returns nil" do expect(fetcher.content(lang)).to be_nil diff --git a/library/packages/test/y2packager/product_reader_test.rb b/library/packages/test/y2packager/product_reader_test.rb index 2970a8978..060429d77 100755 --- a/library/packages/test/y2packager/product_reader_test.rb +++ b/library/packages/test/y2packager/product_reader_test.rb @@ -17,29 +17,35 @@ describe Y2Packager::ProductReader do subject { Y2Packager::ProductReader.new } - let(:products) { YAML.load(File.read(File.join(PACKAGES_FIXTURES_PATH, "products-sles15.yml"))) } # rubocop:disable Security/YAMLLoad + let(:products_hash) { YAML.load(File.read(File.join(PACKAGES_FIXTURES_PATH, "products-sles15.yml"))) } # rubocop:disable Security/YAMLLoad + let(:products) do + products_hash.map { |p| Y2Packager::Resolvable.new(p) } + end + let(:installation_package_map) { { "SLES" => "skelcd-SLES" } } describe "#available_base_products" do before do # TODO: proper mocking of pkg methods allow(subject).to receive(:installation_package_mapping).and_return(installation_package_map) + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :package, name: //) + .and_return([]) end it "returns empty list if there is no product" do - expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return([]) expect(subject.available_base_products).to eq([]) end it "returns Installation::Product objects" do - expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(products) expect(subject.available_base_products.first).to be_a(Y2Packager::Product) end it "returns the correct product properties" do - expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(products) ret = subject.available_base_products.first expect(ret.name).to eq("SLES") @@ -47,13 +53,16 @@ end it "returns only the products from the initial repository" do - sp3 = products.first - addon1 = sp3.dup - addon1["source"] = 1 - addon2 = sp3.dup - addon2["source"] = 2 - - expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + sp3_hash = products_hash.first + addon1_hash = sp3_hash.dup + addon1_hash["source"] = 1 + addon2_hash = sp3_hash.dup + addon2_hash["source"] = 2 + sp3 = Y2Packager::Resolvable.new(sp3_hash) + addon1 = Y2Packager::Resolvable.new(addon1_hash) + addon2 = Y2Packager::Resolvable.new(addon2_hash) + + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return([addon2, addon1, sp3]) expect(subject.available_base_products.size).to eq(1) @@ -61,11 +70,24 @@ context "when no product with system-installation() tag exists" do let(:installation_package_map) { {} } - let(:prod1) { { "name" => "SLES", "status" => :available } } - let(:prod2) { { "name" => "SLED", "status" => :available } } + let(:prod1) do + Y2Packager::Resolvable.new("kind" => :product, + "name" => "SLES", "status" => :available, "source" => 1, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany") + end + + let(:prod2) do + Y2Packager::Resolvable.new("kind" => :product, + "name" => "SLED", "status" => :available, "source" => 2, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany") + end before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(products) end @@ -90,15 +112,15 @@ describe "#installed_base_product" do let(:base_prod) do # reuse the available SLES15 product, just change some attributes - base = products.first.dup + base = products_hash.first.dup base["name"] = "base_product" base["type"] = "base" base["status"] = :installed - base + Y2Packager::Resolvable.new(base) end it "returns the installed base product" do - expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + expect(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(products + [base_prod]) expect(subject.installed_base_product.name).to eq("base_product") end @@ -107,25 +129,27 @@ describe "#all_products" do let(:special_prod) do # reuse the available SLES15 product, just change some attributes - special = products.first.dup + special = products_hash.first.dup special["name"] = "SLES_BCL" special["status"] = :available special["product_package"] = "SLES_BCL-release" special["display_name"] = "SUSE Linux Enterprise Server 15 Business Critical Linux" special["short_name"] = "SLE-15-BCL" - special + Y2Packager::Resolvable.new(special) end before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(products + [special_prod]) allow(Yast::Pkg).to receive(:PkgQueryProvides).with("system-installation()") .and_return([]) allow(subject).to receive(:product_package).with("sles-release") .and_return(nil) allow(subject).to receive(:product_package).with("SLES_BCL-release") - .and_return("deps" => [{ "conflicts"=>"kernel < 4.4" }, - { "provides"=>"specialproduct(SLES_BCL)" }]) + .and_return(Y2Packager::Resolvable.new("name" => "product_package", + "source" => 1, "version" => "1.0", "arch" => "x86_64", + "kind" => :package, "deps" => [{ "conflicts"=>"kernel < 4.4" }, + { "provides"=>"specialproduct(SLES_BCL)" }])) allow(Yast::Linuxrc).to receive(:InstallInf).with("specialproduct").and_return(nil) end @@ -164,26 +188,30 @@ end it "returns the available product also when an installed product is found" do - installed = products.first.dup - installed["status"] = :installed - available = products.first.dup - available["status"] = :available + installed_hash = products_hash.first.dup + installed_hash["status"] = :installed + available_hash = products_hash.first.dup + available_hash["status"] = :available + available = Y2Packager::Resolvable.new(available_hash) + installed = Y2Packager::Resolvable.new(installed_hash) # return the installed product first to ensure the following available duplicate is not lost - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return([installed, available]) expect(subject.all_products).to_not be_empty end it "treats the selected and available products as duplicates even with different arch" do - selected = products.first.dup - selected["status"] = :selected - available = products.first.dup - available["status"] = :available - available["arch"] = "i586" - - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + selected_hash = products_hash.first.dup + selected_hash["status"] = :selected + available_hash = products_hash.first.dup + available_hash["status"] = :available + available_hash["arch"] = "i586" + selected = Y2Packager::Resolvable.new(selected_hash) + available = Y2Packager::Resolvable.new(available_hash) + + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return([selected, available]) expect(subject.all_products.size).to eq(1) diff --git a/library/packages/test/y2packager/product_test.rb b/library/packages/test/y2packager/product_test.rb index b1340df7b..7b2074b34 100755 --- a/library/packages/test/y2packager/product_test.rb +++ b/library/packages/test/y2packager/product_test.rb @@ -166,8 +166,13 @@ describe "#selected?" do before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with(product.name, :product, "") - .and_return([{ "name" => product.name, "status" => status }]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: product.name, kind: :product) + .and_return([Y2Packager::Resolvable.new("kind" => :product, + "name" => product.name, "status" => status, + "source" => 1, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany")]) end context "if product was selected for installation" do @@ -189,8 +194,13 @@ describe "#installed?" do before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with(product.name, :product, "") - .and_return([{ "name" => product.name, "status" => status }]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: product.name, kind: :product) + .and_return([Y2Packager::Resolvable.new("kind" => :product, + "name" => product.name, "status" => status, + "source" => 1, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany")]) end context "if product is installed" do @@ -421,14 +431,24 @@ describe "#status?" do let(:properties) do [ - { "name" => "openSUSE", "status" => :removed }, - { "name" => "openSUSE", "status" => :selected } + Y2Packager::Resolvable.new("kind" => :product, + "name" => "openSUSE", "status" => :removed, + "source" => 1, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany"), + Y2Packager::Resolvable.new("kind" => :product, + "name" => "openSUSE", "status" => :selected, + "source" => 1, "short_name" => "short_name", + "version" => "1.0", "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany") ] end before do - allow(Yast::Pkg).to receive(:ResolvableProperties) - .with("openSUSE", :product, "").and_return(properties) + allow(Y2Packager::Resolvable).to receive(:find) + .with(name: "openSUSE", kind: :product).and_return(properties) end context "when given status is within product statuses" do @@ -448,8 +468,15 @@ let(:relnotes_url) { "http://doc.opensuse.org/openSUSE/release-notes-openSUSE.rpm" } before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with(product.name, :product, "") - .and_return([{ "version" => product.version, "relnotes_url" => relnotes_url }]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: product.name, + kind: :product, version: product.version) + .and_return([Y2Packager::Resolvable.new("kind" => :product, + "name" => "openSUSE", "status" => :selected, + "source" => 1, "short_name" => "short_name", + "version" => product.version, "relnotes_url" => relnotes_url, + "arch" => "x86_64", "product_package" => "testpackage", + "display_name" => "display_name", "category" => "addon", + "vendor" => "SUSE LINUX Products GmbH, Nuernberg, Germany")]) end it "returns relnotes_url property" do @@ -466,8 +493,8 @@ context "when product properties are not found" do before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with(product.name, :product, "") - .and_return([]) + allow(Y2Packager::Resolvable).to receive(:find).with(name: product.name, + kind: :product, version: product.version).and_return([]) end it "returns nil" do diff --git a/library/packages/test/y2packager/product_upgrade_test.rb b/library/packages/test/y2packager/product_upgrade_test.rb index af5fff46b..68b7352c0 100755 --- a/library/packages/test/y2packager/product_upgrade_test.rb +++ b/library/packages/test/y2packager/product_upgrade_test.rb @@ -31,7 +31,7 @@ context "only one base product is available" do before do expect(Y2Packager::Product).to receive(:available_base_products).and_return([product1]) - allow(Yast::Pkg).to receive(:ResolvableProperties).and_return([]) + allow(Y2Packager::Resolvable).to receive(:find).and_return([]) end it "returns that product" do @@ -120,43 +120,56 @@ describe ".obsolete_upgrades" do before do - allow(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "") + allow(Y2Packager::Resolvable).to receive(:find).with(kind: :product) .and_return(suma_products) end # upgrade from SLE12-SP3 + SUMA Proxy 3.2 + SUMA Branch Server 3.2 # to SLE15-SP1 (actually to SUMA Branch Server 4.0) context "SUSE Manager Branch Retail Server 3.2 upgrade" do - let(:suma_products) { YAML.load_file(File.join(__dir__, "../data/zypp/products_update_suma_branch_server.yml")) } + let(:suma_hash) { YAML.load_file(File.join(__dir__, "../data/zypp/products_update_suma_branch_server.yml")) } + + let(:suma_products) do + suma_hash.map { |p| Y2Packager::Resolvable.new(p) } + end + + before do + allow(Y2Packager::Resolvable).to receive(:find).with(name: "SLES", kind: :product) + .and_return(suma_products.select { |p| p.name == "SLES" }) + allow(Y2Packager::Resolvable).to receive(:find).with(name: "SUSE-Manager-Proxy", kind: :product) + .and_return(suma_products.select { |p| p.name == "SUSE-Manager-Proxy" }) + end it "returns obsoleted SLES + SUMA Proxy product" do - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SUSE-Manager-Proxy", :product, "") - .and_return(suma_products.select { |p| p["name"] == "SUSE-Manager-Proxy" }) - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SLES", :product, "") - .and_return(suma_products.select { |p| p["name"] == "SLES" }) + allow(Y2Packager::Resolvable).to receive(:any?).with(name: "SUSE-Manager-Proxy", + kind: :product, status: :removed, transact_by: :solver).and_return(true) + allow(Y2Packager::Resolvable).to receive(:any?).with(name: "SLES", + kind: :product, status: :removed, transact_by: :solver).and_return(true) + expect(described_class.obsolete_upgrades).to contain_exactly("SLES", "SUSE-Manager-Proxy") end it "returns empty list if the old product is removed by user" do - proxy_products = suma_products.select { |p| p["name"] == "SUSE-Manager-Proxy" } - # make it removed by user - proxy_products.find { |p| p["status"] == :removed }["transact_by"] = :user - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SUSE-Manager-Proxy", :product, "") - .and_return(proxy_products) - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SLES", :product, "") - .and_return(suma_products.select { |p| p["name"] == "SLES" }) + allow(Y2Packager::Resolvable).to receive(:any?).with(name: "SUSE-Manager-Proxy", + kind: :product, status: :removed, transact_by: :solver).and_return(false) + allow(Y2Packager::Resolvable).to receive(:any?).with(name: "SLES", + kind: :product, status: :removed, transact_by: :solver).and_return(false) + expect(described_class.obsolete_upgrades).to eq([]) end end context "SUSE Manager Proxy 3.2 upgrade" do - let(:suma_products) { YAML.load_file(File.join(__dir__, "../data/zypp/products_update_suma_proxy.yml")) } + let(:suma_products) do + suma_hash = YAML.load_file(File.join(__dir__, "../data/zypp/products_update_suma_proxy.yml")) + suma_hash.map { |p| Y2Packager::Resolvable.new(p) } + end it "returns empty list" do - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SUSE-Manager-Proxy", :product, "") - .and_return(suma_products.select { |p| p["name"] == "SUSE-Manager-Proxy" }) - allow(Yast::Pkg).to receive(:ResolvableProperties).with("SLES", :product, "") - .and_return(suma_products.select { |p| p["name"] == "SLES" }) + allow(Y2Packager::Resolvable).to receive(:find).with(name: "SUSE-Manager-Proxy", kind: :product) + .and_return(suma_products.select { |p| p.name == "SUSE-Manager-Proxy" }) + allow(Y2Packager::Resolvable).to receive(:find).with(name: "SLES", kind: :product) + .and_return(suma_products.select { |p| p.name == "SLES" }) expect(described_class.obsolete_upgrades).to eq([]) end end diff --git a/library/packages/test/y2packager/release_notes_fetchers/rpm_test.rb b/library/packages/test/y2packager/release_notes_fetchers/rpm_test.rb index 7d0a48631..468b6871c 100755 --- a/library/packages/test/y2packager/release_notes_fetchers/rpm_test.rb +++ b/library/packages/test/y2packager/release_notes_fetchers/rpm_test.rb @@ -11,10 +11,10 @@ let(:package) { Y2Packager::Package.new("release-notes-dummy", 2, "15.1") } let(:dependencies) do [ - { - "status" => :selected, - "deps" => [{ "provides" => "release-notes() = dummy" }] - } + Y2Packager::Resolvable.new("kind" => :package, + "name" => "release-notes-dummy", "source" => 1, + "version" => "1.0", "arch" => "x86_64", "status" => :selected, + "deps" => [{ "provides" => "release-notes() = dummy" }]) ] end @@ -31,8 +31,8 @@ before do allow(Yast::Pkg).to receive(:PkgQueryProvides).with("release-notes()") .and_return(provides) - allow(Yast::Pkg).to receive(:ResolvableDependencies) - .with("release-notes-dummy", :package, "").and_return(dependencies) + allow(Y2Packager::Resolvable).to receive(:find) + .with(name: "release-notes-dummy", kind: :package).and_return(dependencies) allow(Y2Packager::Package).to receive(:find).with(package.name) .and_return(packages) allow(package).to receive(:download_to) do |path| diff --git a/library/packages/test/y2packager/resolvable_test.rb b/library/packages/test/y2packager/resolvable_test.rb new file mode 100755 index 000000000..cb7a56fc4 --- /dev/null +++ b/library/packages/test/y2packager/resolvable_test.rb @@ -0,0 +1,109 @@ +#!/usr/bin/env rspec + +require_relative "../test_helper" +require "y2packager/resolvable" +require "tmpdir" + +# This is rather an integration test because it actually +# reads a real repository metadata using libzypp. +describe Y2Packager::Resolvable do + before(:all) do + # avoid writing to the protected /var/cache/zypp path + @tmpdir = Dir.mktmpdir + Yast::Pkg.TargetInitialize(@tmpdir) + + # import the repository GPG key + gpg_key = File.join(__dir__, "/zypp/test_repo/repodata/repomd.xml.key") + Yast::Pkg.ImportGPGKey(gpg_key, true) + + # add the repository + test_repo = File.join(__dir__, "/zypp/test_repo") + Yast::Pkg.SourceCreate("dir:#{test_repo}", "/") + end + + after(:all) do + # close the package manager + Yast::Pkg.SourceFinishAll + Yast::Pkg.TargetFinish + + # remove the tmpdir + FileUtils.remove_entry(@tmpdir) + end + + describe ".find" do + it "finds packages" do + res = Y2Packager::Resolvable.find(kind: :package) + expect(res).to_not be_empty + expect(res.all? { |r| r.kind == :package }).to be true + end + + it "finds packages with a name" do + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.find(kind: :package, name: "yast2-add-on") + expect(res).to_not be_empty + expect(res.all? { |r| r.kind == :package && r.name == "yast2-add-on" }).to be true + end + end + + describe ".any?" do + it "returns true if a package is found" do + expect(Y2Packager::Resolvable.any?(kind: :package)).to be true + end + + it "returns true if a package with name is found" do + # use some noarch package here, the testing data covers only the x86_64 arch + expect(Y2Packager::Resolvable.any?(kind: :package, name: "yast2-add-on")).to be true + end + + it "returns false if a package is not found" do + expect(Y2Packager::Resolvable.any?(kind: :package, name: "not existing")).to be false + end + + it "returns false if a product is not found" do + expect(Y2Packager::Resolvable.any?(kind: :product)).to be false + end + end + + describe "#vendor" do + it "lazy loads the missing attributes" do + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.find(kind: :package, name: "yast2-add-on").first + expect(Yast::Pkg).to receive(:Resolvables).with(anything, [:vendor]).and_call_original + expect(res.vendor).to eq("obs://build.opensuse.org/YaST") + end + + it "does not load the preloaded attributes again" do + res = Y2Packager::Resolvable.find({ kind: :package, name: "yast2-add-on" }, [:vendor]).first + expect(Yast::Pkg).to_not receive(:Resolvables).with(anything, [:vendor]) + expect(res.vendor).to eq("obs://build.opensuse.org/YaST") + end + + it "raises an exception if the resolvable cannot be uniquely identified for lazy loading" do + # this a bit artificial situation, create a Resolvable from an incomplete hash + # (missing version and other attributes) + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.new(kind: :package, name: "yast2-add-on") + expect { res.vendor }.to raise_error(RuntimeError, /missing attributes/i) + end + end + + describe "#method_missing" do + it "raises NoMethodError when the attribute does not exist" do + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.find(kind: :package, name: "yast2-add-on").first + expect { res.not_existing_method(:foo) }.to raise_error(NoMethodError) + end + + it "raises ArgumentError when an argument is passed to a preloaded attribute" do + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.find(kind: :package, name: "yast2-add-on").first + expect { res.name("dummy") }.to raise_error(ArgumentError) + end + + it "raises ArgumentError when an argument is passed to a lazy loaded method" do + # use some noarch package here, the testing data covers only the x86_64 arch + res = Y2Packager::Resolvable.find(kind: :package, name: "yast2-add-on").first + expect { res.vendor("dummy") }.to raise_error(ArgumentError) + end + end +end diff --git a/library/packages/test/y2packager/zypp/test_repo/README.md b/library/packages/test/y2packager/zypp/test_repo/README.md new file mode 100644 index 000000000..ac2a9b9fd --- /dev/null +++ b/library/packages/test/y2packager/zypp/test_repo/README.md @@ -0,0 +1,4 @@ +The testing data was downloaded from the [YaST:Head OBS]( +https://build.opensuse.org/project/show/YaST:Head) repository. + +- repodata: https://download.opensuse.org/repositories/YaST:/Head/openSUSE_Leap_15.0/repodata/ diff --git a/library/packages/test/y2packager/zypp/test_repo/repodata/4d295860e625859a714dcc91c6a2e6f7634aab288eb13cf01c09ae2a65a7eeab-primary.xml.gz b/library/packages/test/y2packager/zypp/test_repo/repodata/4d295860e625859a714dcc91c6a2e6f7634aab288eb13cf01c09ae2a65a7eeab-primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..bee12362b8952595eea793b5835243ee1279540c GIT binary patch literal 88670 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 AU;qFB literal 0 HcmV?d00001 diff --git a/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml new file mode 100644 index 000000000..6c3176f69 --- /dev/null +++ b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml @@ -0,0 +1,32 @@ + + + 1558080877 + + obsrepository://build.opensuse.org/YaST:Head/openSUSE_Leap_15.0 + obsbuildid:1533048310 + + + 4d295860e625859a714dcc91c6a2e6f7634aab288eb13cf01c09ae2a65a7eeab + 6c154c0ff76aca4f1b376bbe91f5bf00d56eff19bf5cdf08b680472e42fb4ee1 + + 1558080876 + 88670 + 762992 + + + 1d3843cc83a1bd651295caf1790d9487739a0df387e7cdf1251edbb284f8c387 + 4921d6efe5170264f781275d9ca0408c37d96f262191c143ba6e06562d601820 + + 1558080876 + 239386 + 3058860 + + + 06ae21ca0bb3653b69dc367b078d56d7c73004d1c6dbc0c730a2eff9dd84a9ac + f770a3ae116812d8eeba60b2912d1205175026e1efcefaf899c2d3e03f44888f + + 1558080876 + 230366 + 1439396 + + diff --git a/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.asc b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.asc new file mode 100644 index 000000000..cadeb3446 --- /dev/null +++ b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBc3m1tWyVH2GHn0GwRAgZfAJ49sk+alvmPOAGhdAaH7Y4TwpTM6ACZAXnG +Oqgdb6W/cPGRP7c7vIhT/Y8= +=kSvT +-----END PGP SIGNATURE----- diff --git a/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.key b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.key new file mode 100644 index 000000000..6993e1a77 --- /dev/null +++ b/library/packages/test/y2packager/zypp/test_repo/repodata/repomd.xml.key @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBEfZbkMRBADjWPMrWcXDcSDlPYsnn5tgT1LMJqqJwBisS6fNYWAxEMof4lWJ +MIiRyDE86uAgUvwCsDxmTHeM5uV8KOmsKedxd2bU8lNPSwcSXMLrVhL0mUpPz+EP +eq3VJkLCR+HSszWGkOrh8FddeaQBR5gYiwYu3Spoc8lHiUncbw/N2CeWDwCggMO/ +GsLl+mXbmn4AYFLhNGvRUPUD/2tSlTOAIiGF3Y3svpYdIidMZlNo/+nss0qOMWaM +gZ+3pgXpZ+5pdXbukBupXipEvk+6JnmZjE/sZ/iY2j3WDb9Bh45ix7CA1zXMYtTk +0oAzUmxSWbJVqegcMQkR+9HT1Ys5x+7TQKuQQWXBPtp79zAQlOOa3Vy9Blgnom4R +nue8BACps5N0eQovsbBhGHr9uDcHrYRt74sgLqA83MP6voATCj+NLMFhHgIxJYrt +bItoeEeoPBaJ77AkcMJpitUBW2Ud6bDeChqf48nlnGjVBlIAwx63d0kkYPnsn5kN +BnhkkH9fUDgc934krzsf7dPrpFIkG0LI/TlSshI3HDI71m0r07QqWWFTVCBPQlMg +UHJvamVjdCA8WWFTVEBidWlsZC5vcGVuc3VzZS5vcmc+iGYEExECACYFAlrseIYC +GwMFCRcxukMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBbJUfYYefQbHQDAJ9Q +4JMWDMaX74S6exNQQiMTdO3whACcDz1jkagJ0BBQY8usbzaJsjCmOm2IRgQTEQIA +BgUCR9luQwAKCRA7MBG3a51lI3yCAJ4jfMqPAn8uPoosOSeA80t7MQdYOACgq9yA +o67MnrLsqTdAM0Ud3ld3NhA= +=JmLZ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/package/yast2.changes b/package/yast2.changes index c58aa9779..8cc4e6592 100644 --- a/package/yast2.changes +++ b/package/yast2.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Nov 28 11:21:31 UTC 2019 - schubi@suse.de + +- Using Y2Packager::Resolvable.any? and Y2Packager::Resolvable.find + in order to decrease the required memory (bsc#1132650, + bsc#1140037). +- 4.2.43 + ------------------------------------------------------------------- Thu Nov 28 10:21:31 UTC 2019 - Knut Anderssen diff --git a/package/yast2.spec b/package/yast2.spec index 372226444..4d925f465 100644 --- a/package/yast2.spec +++ b/package/yast2.spec @@ -17,7 +17,7 @@ Name: yast2 -Version: 4.2.42 +Version: 4.2.43 Release: 0 Summary: YaST2 Main Package License: GPL-2.0-only