library/packages/src/lib/y2packager/license.rb
# ------------------------------------------------------------------------------
# Copyright (c) 2018 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.
# ------------------------------------------------------------------------------
require "yast"
require "digest"
require "y2packager/licenses_fetchers"
require "y2packager/licenses_handlers"
module Y2Packager
# Represent a License which could be the same for multiple products.
#
# This class represents a license.
class License
include Yast::Logger
# Default language for licenses.
DEFAULT_LANG = "en_US".freeze
# @return [Boolean] whether the license has been accepted or not
attr_reader :accepted
# @return [Hash<String, String>] language -> content
attr_reader :translations
# @return [Yast::LicensesFetchers::Base]
attr_reader :fetcher
# @return [Yast::LicensesHandlers::Base]
attr_reader :handler
alias_method :accepted?, :accepted
class << self
# Find a license for a given product
#
# This method uses a cache to return the same license if it was already
# used for another product.
#
# @param product_name [String] Product's name
# @param content [String] License content. If this argument is given, this
# string is used as the license's content (and `product_name` is ignored).
#
# @return [License, nil]
def find(product_name, content: nil)
log.info "Searching for a license for product #{product_name}"
return cache[product_name] if cache[product_name]
fetcher = LicensesFetchers.for(product_name) unless content
handler = LicensesHandlers.for(fetcher, product_name) if fetcher
license = License.new(product_name: product_name, fetcher: fetcher,
handler: handler, content: content)
return unless license.id
cached_license = cache.values.find { |l| l.id == license.id }
if cached_license
log.info "Found cached license: #{cached_license.id}"
else
log.info "Caching license: #{license.id}"
end
cache[product_name] = cached_license || license
end
# Clean licenses cache
def clear_cache
@cache = nil
end
private
# Licenses cache
#
# @return [Hash<String,License>]
def cache
@cache ||= {}
end
end
# Constructor
#
# This class should be able to use the proper fetcher (see Y2Packager::LicensesFetchers)
# in order to retrieve license content (including translations). However, for compatibility
# reasons, the constructor can receive a `content` that will be used as licence's
# content. The reason is that, in some parts of YaST, the license content/translations
# is retrieved in different ways. We might need to unify them.
#
# Bear in mind that `fetcher` will be ignored if `content` is specified.
#
# @param product_name [String] Product name to retrieve license information
# @param content [String] License content. When given, this string is used as the license's
# content, ignoring the `product_name`
# @param fetcher [LicensesFetchers::Base] The license's fetcher
# @param handler [LicensesHandlers::Base] The license's handler
def initialize(product_name: nil, content: nil, fetcher: nil, handler: nil)
@accepted = false
@translations = {}
@product_name = product_name
@fetcher = fetcher
@handler = handler
add_content_for(DEFAULT_LANG, content) if content
end
# License unique identifier
#
# This identifier is based on the given default language translation.
#
# @return [String,nil] Unique identifier; nil if the license was not found.
def id
return @id if @id
content = content_for(DEFAULT_LANG)
return unless content
@id = Digest::SHA2.hexdigest(content)
end
# Return the license translated content for the given language
#
# @param lang [String] Contents' language
#
# @return [String, nil] the license translated content or nil if not found
def content_for(lang = DEFAULT_LANG)
return @translations[lang] if @translations[lang]
return unless fetcher
content = fetcher.content(lang)
add_content_for(lang, content)
end
# Return license's available locales
#
# @return [Array<String>] List of available language codes ("de_DE", "en_US", etc.)
def locales
return [DEFAULT_LANG] unless fetcher
fetcher.locales
end
# Add the license translated content for the given language
#
# @param lang [String] Language to add the translation to
# @param content [String] Content to add
#
# @return [String] the license translated content
def add_content_for(lang, content)
@translations[lang] = content
end
# Set the license as accepted
def accept!
@accepted = true
end
# Set the license as rejected
def reject!
@accepted = false
end
private
# @return [String] Product name
attr_reader :product_name
end
end