Skip to content

Commit

Permalink
Set installation_package in SoftwareSearch queries
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Nov 2, 2021
1 parent efd7e26 commit 6af7e8b
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 6 deletions.
83 changes: 83 additions & 0 deletions library/packages/src/lib/y2packager/installation_package_map.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright (c) [2021] 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"
Yast.import "Pkg"

module Y2Packager
# Installation packages map
#
# This map contains the correspondence between products and the
# installation package for each product.
#
# The information is always read again. Reason is that that url can be invalid,
# but user fix it later. This way it cache invalid result. See bsc#1086840
# ProductReader instance cache it properly, but caching for installation life-time
# should be prevented.
#
# @return [Hash<String,String>] product name -> installation package name
class InstallationPackageMap
include Yast::Logger

def initialize
@packages_map = nil
end

def for(pkg_name)
packages_map[pkg_name]
end

private

def packages_map
return @packages_map if @packages_map

install_pkgs = Yast::Pkg.PkgQueryProvides("system-installation()")
log.info "Installation packages: #{install_pkgs.inspect}"

@packages_map = {}

install_pkgs.each do |list|
pkg_name = list.first
# There can be more instances of same package in different version.
# Prefer the selected or the available package, they should provide newer data
# than the installed one.
packages = Yast::Pkg.Resolvables({ name: pkg_name, kind: :package }, [:dependencies, :status])
package = packages.find { |p| p["status"] == :selected } ||
packages.find { |p| p["status"] == :available } ||
packages.first

dependencies = package["deps"]
install_provides = dependencies.find_all do |d|
d["provides"]&.match(/system-installation\(\)/)
end

# parse product name from provides. Format of provide is
# `system-installation() = <product_name>`
install_provides.each do |install_provide|
product_name = install_provide["provides"][/system-installation\(\)\s*=\s*(\S+)/, 1]
log.info "package #{pkg_name} install product #{product_name}"
@packages_map[product_name] = pkg_name
end
end

@packages_map
end
end
end
8 changes: 6 additions & 2 deletions library/packages/src/lib/y2packager/libzypp_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
require "y2packager/rpm_repo"
require "y2packager/package"
require "y2packager/product"
require "y2packager/installation_package_map"

module Y2Packager
# Backend implementation for libzypp
Expand Down Expand Up @@ -54,9 +55,11 @@ def repositories
# @todo Allow passing multiple statuses
# @todo Use a set of default properties so you do not need to explictly pass them
def search(conditions:, properties:)
@packages_map = InstallationPackageMap.new

resolvables = Yast::Pkg.Resolvables(
conditions,
(properties + [:kind]).uniq
(properties + [:name, :kind]).uniq
)

resolvables.map do |res|
Expand All @@ -71,7 +74,8 @@ def search(conditions:, properties:)

def hash_to_product(hsh)
Y2Packager::Product.new(
name: hsh["name"], arch: hsh["arch"], version: hsh["version"]
name: hsh["name"], arch: hsh["arch"], version: hsh["version"],
installation_package: @packages_map.for(hsh["name"])
)
end

Expand Down
53 changes: 53 additions & 0 deletions library/packages/test/y2packager/installation_package_map_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) [2021] 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_relative "../test_helper"
require "y2packager/installation_package_map"

describe Y2Packager::InstallationPackageMap do
describe "#packages_map" do
before do
allow(Yast::Pkg).to receive(:PkgQueryProvides).with("system-installation()").and_return(
# the first is the old product which will be removed from the system
[["openSUSE-release", :CAND, :NONE], ["openSUSE-release", :CAND, :CAND]]
)
allow(Yast::Pkg).to receive(:Resolvables).with({ name: "openSUSE-release", kind: :package },
[:dependencies, :status]).and_return(
[
{
# emulate an older system with no "system-installation()" provides
"deps" => [],
# put the removed product first so we can check it is skipped
"status" => :removed
},
{
# in reality there are many more dependencies, but they are irrelevant for this test
"deps" => [{ "provides" => "system-installation() = openSUSE" }],
"status" => :selected
}
]
)
end

it "prefers the data from the new available product instead of the old installed one" do
expect(subject.for("openSUSE")).to eq("openSUSE-release")
# expect(described_class.installation_package_mapping).to eq("openSUSE" => "openSUSE-release")
end
end
end
17 changes: 13 additions & 4 deletions library/packages/test/y2packager/libzypp_backend_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
end

describe "#search" do
let(:installation_package_map) do
instance_double(Y2Packager::InstallationPackageMap, for: "openSUSE-release")
end

before do
allow(Y2Packager::InstallationPackageMap).to receive(:new)
.and_return(installation_package_map)
end

context "searching a package by name" do
it "returns the package with the given name" do
expect(Yast::Pkg).to receive(:Resolvables)
Expand All @@ -78,16 +87,16 @@
.with(
{ kind: :product, name: "openSUSE" }, [:name, :version, :kind]
)
.and_return([
{ "name" => "openSUSE", "version" => "20211027-0", "kind" => :product }
])

.and_return(
[{ "name" => "openSUSE", "version" => "20211027-0", "kind" => :product }]
)
prod = backend.search(
conditions: { kind: :product, name: "openSUSE" }, properties: [:name, :version]
).first
expect(prod).to be_a(Y2Packager::Product)
expect(prod.name).to eq("openSUSE")
expect(prod.version).to eq("20211027-0")
expect(prod.installation_package).to eq("openSUSE-release")
end
end
end
Expand Down

0 comments on commit 6af7e8b

Please sign in to comment.