Skip to content

Commit

Permalink
improve default pattern evaluation
Browse files Browse the repository at this point in the history
added tests
  • Loading branch information
lslezak committed Apr 4, 2016
1 parent 3f4ef86 commit 12fd9e6
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 44 deletions.
105 changes: 62 additions & 43 deletions src/lib/packager/default_pattern.rb
Expand Up @@ -18,34 +18,24 @@
module Packager
class DefaultPatterns
include Yast::Logger
include Yast::I18n

def initialize
Yast.import "Pkg"
Yast.import "Report"

textdomain "packager"
end

# Find the default patterns for all selected products.
# @return [Array<String>] pattern names
def names
@names ||= find
end

def select
names.each do |name|
if !Yast::Pkg.ResolvableInstall(name, :pattern, "")
# TRANSLATORS: error message, %s is a pattern name, e.g. "ha_sles"
Yast::Report.Error(_("Error: Cannot preselect pattern '%s' to install.") % name)
end
end
@names ||= validate(find)
end

private

# Find the default patterns for all selected products.
# @return [Array<String>] pattern names
def find
products = Yast::Pkg.ResolvableInstall("", :product, "")
# FIXME: uncomment
# products.select! { |product| product["status"] == :selected }
products = Yast::Pkg.ResolvableProperties("", :product, "")
products.select! { |product| product["status"] == :selected }
products.map!{ |product| product["name"] }
log.info "Found selected products: #{products}"

Expand All @@ -55,37 +45,64 @@ def find
patterns
end

# Remove unavailable patterns from the list
# @param [Array<String>] patterns pattern names
# @return [Array<String>] returns only the available patterns
def validate(patterns)
patterns.select do |pattern|
properties = Yast::Pkg.ResolvableProperties(pattern, :pattern, "")

valid = !properties.nil? && !properties.empty?
log.warn "Pattern '#{pattern}' was not found" unless valid

valid
end
end

# Find the default patterns for the product.
# @param [String] product product name
# @return [Array<String>] pattern names
def product_patterns(product)
product_dependencies = dependencies(product)
product_provides = provides(product_dependencies)

default_patterns(product_provides)
end

# Find dependencies for the product (it's product package).
# @param [String] product product name
# @return [Array<Hash>] product dependencies, e.g. [{"provides" => "foo"},
# {"requires" => "bar"}, ...]
def dependencies(product)
product_dependencies = []

resolvables = Yast::Pkg.ResolvableProperties(product, :product, "")
# FIXME: uncomment
# resolvables.select! { |p| p["status"] == :selected }
resolvables.select! { |p| p["status"] == :selected }

resolvables.each do |resolvable|
prod_pkg = resolvable["product_package"]
next unless prod_pkg

release_resolvables = Yast::Pkg.ResolvableDependencies(prod_pkg, :package, "")
# FIXME: uncomment
# release_resolvables.select! { |p| p["status"] == :selected }
next unless release_resolvables
release_resolvables.select! { |p| p["status"] == :selected }

release_resolvables.each do |release_resolvable|
deps = release_resolvable["deps"]
product_dependencies.concat(deps) if deps
end
end

log.info "Product #{product} depependencies: #{product_dependencies}"
log.debug "Product #{product} depependencies: #{product_dependencies}"

product_dependencies
end

# Collect "provides" dependencies from the list.
# @param [Array<Hash>] dependencies all dependencies
# @return [Array<String>] only the "provides" dependencies
# @example
# provides([{"provides" => "foo"}, {"requires" => "bar"}, ...]) => ["foo"]
def provides(dependencies)
provides = []

Expand All @@ -94,18 +111,23 @@ def provides(dependencies)
provides << prov if prov
end

log.info "Collected provides dependencies: #{provides.inspect}"
log.debug "Collected provides dependencies: #{provides.inspect}"

provides
end

# Collect default pattern names from the provides list.
# The default pattern is described by the tag "defaultpattern(foo)"
# @param [Array<String>] provides the "provides" dependencies
# @return [Array<String>] the default pattern names, empty if no default
# pattern is found
def default_patterns(provides)
patterns = []

provides.each do |provide|
# is it a defaultpattern() provides?
if provide.match(/\Adefaultpattern\((.*)\)\z/)
log.info "Found default pattern provides: #{provide}"
log.info "Found default pattern provide: #{provide}"
patterns << Regexp.last_match[1].strip
end
end
Expand All @@ -117,22 +139,19 @@ def default_patterns(provides)
end
end

# just a testing code
# can be executed via "ruby default_pattern.rb"
if $PROGRAM_NAME
Yast.import "Pkg"

# Yast.import "PackageCallbacks"
# Yast::PackageCallbacks.InitPackageCallbacks

Yast::Pkg.TargetInitialize("/")
Yast::Pkg.TargetLoad
Yast::Pkg.SourceRestore
Yast::Pkg.SourceLoad

# a testing HA product is available in the SP2 repo:
# zypper ar -f http://download.suse.de/ibs/SUSE:/SLE-12-SP2:/GA/standard sp2

p = Packager::DefaultPatterns.new(product: "sle-ha")
p.select
end
# just a testing code:
# Yast.import "Pkg"
#
# # Yast.import "PackageCallbacks"
# # Yast::PackageCallbacks.InitPackageCallbacks
#
# Yast::Pkg.TargetInitialize("/")
# Yast::Pkg.TargetLoad
# Yast::Pkg.SourceRestore
# Yast::Pkg.SourceLoad
#
# # a testing HA product is available in the SP2 repo:
# # zypper ar -f http://download.suse.de/ibs/SUSE:/SLE-12-SP2:/GA/standard sp2
#
# p = Packager::DefaultPatterns.new
# puts p.names.inspect
2 changes: 2 additions & 0 deletions src/modules/Packages.rb
Expand Up @@ -1111,6 +1111,8 @@ def ComputeSystemPatternList
end
end

# TODO: preselect the default product patterns here

# FATE #302116
# BNC #431580
required_patterns = PackagesProposal.GetAllResolvables(:pattern)
Expand Down
3 changes: 2 additions & 1 deletion test/Makefile.am
@@ -1,5 +1,6 @@
TESTS = \
addon_product_test.rb \
default_pattern_test.rb \
package_installation_test.rb \
packages_test.rb \
source_dialogs_test.rb \
Expand All @@ -8,4 +9,4 @@ TESTS = \
TEST_EXTENSIONS = .rb
RB_LOG_COMPILER = rspec
VERBOSE = 1
EXTRA_DIST = $(TESTS)
EXTRA_DIST = $(TESTS) product_factory.rb test_helper.rb
38 changes: 38 additions & 0 deletions test/default_pattern_test.rb
@@ -0,0 +1,38 @@
#! /usr/bin/env rspec

require_relative "./test_helper"
require_relative "./product_factory"

require "packager/default_pattern"

Yast.import "Pkg"

describe Packager::DefaultPatterns do
describe ".names" do
it "returns empty list when there are no products" do
expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "")
.and_return([])

expect(subject.names).to eq([])
end

it "returns empty list when there is no selected product" do
expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "")
.and_return([ProductFactory.create_product])

expect(subject.names).to eq([])
end

it "returns empty list when the product release package is not found" do
product = ProductFactory.create_product("status" => :selected,
"product_package" => nil)

expect(Yast::Pkg).to receive(:ResolvableProperties).with("", :product, "")
.and_return([product])
expect(Yast::Pkg).to receive(:ResolvableProperties).with(product["name"], :product, "")
.and_return([product])

expect(subject.names).to eq([])
end
end
end
52 changes: 52 additions & 0 deletions test/product_factory.rb
@@ -0,0 +1,52 @@

class ProductFactory
def self.create_product(attrs = {})
product = {}

# generate 12 random characters from a-z
charset = ('a'..'z').to_a
name = (1..12).map{ charset[rand(charset.size)] }.join

product_name = name.capitalize
product_id = name[0..4]
sp = rand(4) + 1

product["arch"] = attrs["arch"] || "x86_64"
product["category"] = attrs["category"] || "addon"
product["description"] = attrs["description"] || "SUSE Linux Enterprise #{product_name}."
product["display_name"] = attrs["display_name"] || "SUSE Linux Enterprise #{product_name}"
product["download_size"] = attrs["download_size"] || 0
product["eol"] = attrs["eol"] || 1730332800
product["flags"] = attrs["flags"] || []
product["flavor"] = attrs["flavor"] || "POOL"
product["inst_size"] = attrs["inst_size"] || 0
product["locked"] = attrs.fetch("locked", false)
product["medium_nr"] = attrs["medium_nr"] || 0
product["name"] = attrs["name"] || "sle-#{product_id}"
product["on_system_by_user"] = attrs.fetch("on_system_by_user", false)
product["product_file"] = attrs["product_file"] || "sle-#{product_id}.prod"
product["product_line"] = attrs["product_line"] || ""
product["product_package"] = attrs.fetch("product_package", "sle-#{product_id}-release")
product["register_release"] = attrs["register_release"] || ""
product["register_target"] = attrs["register_target"] || "sle-12-x86_64"
product["relnotes_url"] = attrs["relnotes_url"] || "https://www.suse.com/releasenotes/#{product["arch"]}/SLE-#{product_id}/12-SP#{sp}/release-notes-#{product_id}.rpm"
product["relnotes_urls"] = attrs["relnotes_urls"] || ["https://www.suse.com/releasenotes/#{product["arch"]}/SLE-#{product_id}/12-SP#{sp}/release-notes-#{product_id}.rpm"]
product["short_name"] = attrs["short_name"] || "SLE#{product_id.upcase}12-SP#{sp}"
product["source"] = attrs["source"] || rand(10)
product["status"] = attrs["status"] || :available
product["summary"] = attrs["summary"] || "SUSE Linux Enterprise #{product_name}"
product["transact_by"] = attrs["transact_by"] || :solver
product["type"] = attrs["type"] || "addon"
product["update_urls"] = attrs["update_urls"] || []
product["vendor"] = attrs["vendor"] || "SUSE LLC <https://www.suse.com/>"
product["version"] = attrs["version"] || "12.#{sp}-0"
product["version_epoch"] = attrs["version_epoch"] || nil
product["version_release"] = attrs["version_release"] || "0"
product["version_version"] = attrs["version_version"] || "12.#{sp}"

# add optional dependencies (returned only by ResolvableDependencies)
product["deps"] = attrs["deps"] if attrs.has_key?("deps")

product
end
end

0 comments on commit 12fd9e6

Please sign in to comment.