Skip to content

Commit

Permalink
Move license retrieving logic to License class
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Apr 5, 2018
1 parent c52e45f commit dc30944
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 26 deletions.
84 changes: 64 additions & 20 deletions library/packages/src/lib/y2packager/license.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,96 @@

require "yast"
require "digest"
require "y2packager/licenses_fetchers"

module Y2Packager
# Represent a License which could be the same for multiple products.
#
# This class stores the license ID and the traslated content of the license
# for different languages.
# This class represents a license.
class License
DEFAULT_LANG = "en_US".freeze
# @return [String] License unique identifier
attr_reader :id

# @return [Boolean] whether the license has been accepted or not
attr_reader :accepted

# @return [Hash<String, String>] language -> content
attr_reader :translations

# @return [Y2Packager::LicensesFetchers::Base] License fetcher object
attr_reader :fetcher

alias_method :accepted?, :accepted

class << self
# Find a license for a given product
#
# @param product_name [String] Product's name
# @param source [:rpm,:url] Source to get the license from. For the time being,
# only :rpm is really supported.
# @return [License]
def find(product_name, source)
return cache[product_name] if cache[product_name]

# This could be done in the constructor.
fetcher = LicensesFetchers.for(source)
new_license = License.new(fetcher)
return unless new_license.id

eq_license = cache.values.find { |l| l.id == new_license.id }
license = eq_license || new_license
cache[product_name] = license
end

def clear_cache
@cache = nil
end

private def cache
@cache ||= {}
end
end

# Constructor
#
# @param options [Hash<String, String>]
def initialize(options = {})
def initialize(fetcher)
@accepted = false
@id = id_for(options)
@translations = { DEFAULT_LANG => options[:content] }
@fetcher = fetcher
@translations = {}
end

# License unique identifier
#
# This identifier is based on the given default language translation.
#
# @return [String] Unique identifier
def id
@id ||= Digest::MD5.hexdigest(content_for(DEFAULT_LANG))
end

# Return the license translated content for the given language
#
# It will return the empty string ("") if the license does not exist
#
# @param [String] language
# @return [String,nil] the license translated content or nil if not found
def content_for(lang = DEFAULT_LANG)
translations[lang]
return @translations[lang] if @translations[lang]
content = fetcher.license_content(lang)
return add_content_for(lang, content) if content
content_for(DEFAULT_LANG) unless lang == DEFAULT_LANG
end

# FIXME: Probably the locales should be obtained through the licenses
# translations, and probably could be initialized the first time a license
# is instantiated.
def locales
fetcher.license_locales
end

def license_confirmation_required?
# FIXME
true
end

# Add the license translated content for the given language
Expand All @@ -66,17 +122,5 @@ def accept!
def reject!
@accepted = false
end

private

# Generate the license unique identifier based on the given options.
# Currently the id is obtained using the MD5 digest of te license's
# content (in the default language).
#
# @param options [Hash<String,String>] License map options
# @return [String] MD5 digest of the license's content
def id_for(options)
Digest::MD5.hexdigest(options[:content])
end
end
end
26 changes: 26 additions & 0 deletions library/packages/src/lib/y2packager/licenses_fetchers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ------------------------------------------------------------------------------
# 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 "y2packager/licenses_fetchers/rpm"
require "y2packager/licenses_fetchers/url"

module Y2Packager
module LicensesFetchers
# Return the licenses proper fetcher for a given source
#
# @param source [Symbol] :rpm or :url
def self.for(source)
const_get(source.to_s.capitalize)
end
end
end
111 changes: 105 additions & 6 deletions library/packages/test/y2packager/license_test.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,129 @@
#!/usr/bin/env rspec
# ------------------------------------------------------------------------------
# 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_relative "../test_helper"

require "y2packager/license"

describe Y2Packager::License do
let(:license) { Y2Packager::License.new(content: "dummy content") }
subject(:license) { Y2Packager::License.new(fetcher) }

let(:fetcher) do
instance_double(Y2Packager::LicensesFetchers::Rpm, license_content: "license")
end

before do
described_class.clear_cache
allow(Y2Packager::LicensesFetchers::Rpm).to receive(:new).and_return(fetcher)
end

describe ".find" do
it "returns a license for the given product" do
license = described_class.find("SLES", :rpm)
expect(license).to be_a(Y2Packager::License)
end

context "when a license with the same ID was already retrieved" do
it "returns the already retrieved instance" do
sles_license = described_class.find("SLES", :rpm)
sled_license = described_class.find("SLED", :rpm)
expect(sles_license).to be(sled_license)
end
end

context "when no license with the same ID was already retrieved" do
before do
allow(fetcher).to receive(:license_content).and_return("sles license", "sled license")
end

it "returns a new license instance" do
sles_license = described_class.find("SLES", :rpm)
sled_license = described_class.find("SLED", :rpm)
expect(sles_license).to_not be(sled_license)
expect(sles_license.id).to_not eq(sled_license.id)
end
end
end

describe "#id" do
before do
allow(fetcher).to receive(:license_content).and_return("content")
end

it "returns the license unique identifier" do
expect(license.id).to eq("9a0364b9e99bb480dd25e1f0284c8555")
end
end

describe "#content_for" do
it "returns the license content for the given language if exists" do
expect(license.content_for(described_class::DEFAULT_LANG)).to eq("dummy content")
let(:lang) { "es_ES" }

context "when no language is given" do
it "returns the license content for the default language" do
expect(fetcher).to receive(:license_content).with(described_class::DEFAULT_LANG)
.and_return("dummy content")
expect(license.content_for).to eq("dummy content")
end
end

it "returns the license content for the given language" do
expect(fetcher).to receive(:license_content).with(lang)
.and_return("dummy content")
expect(license.content_for(lang)).to eq("dummy content")
end

context "when there is no translation for the given language" do
before do
allow(fetcher).to receive(:license_content).with(lang).and_return(nil)
allow(fetcher).to receive(:license_content).with(described_class::DEFAULT_LANG)
.and_return("dummy content")
end

it "returns the license content for the default language" do
expect(license.content_for(lang)).to eq("dummy content")
end
end

it "returns nil if there is no content for the given language" do
expect(license.content_for("es_ES")).to eq(nil)
context "license content for the given languages was already retrieved" do
before do
allow(fetcher).to receive(:license_content).with(lang).and_return("content")
license.content_for(lang)
end

it "returns cached content" do
expect(fetcher).to_not receive(:license_content)
expect(license.content_for(lang)).to eq("content")
end
end
end

describe "#add_content_for" do
it "adds a new translated content to the license" do
expect(license.content_for("es_ES")).to eq(nil)
expect(license.add_content_for("es_ES", "contenido ficticio"))
expect(license.content_for("es_ES")).to eq("contenido ficticio")
end
end

describe "#locales" do
before do
allow(fetcher).to receive(:license_locales).and_return(["en_US", "cz_CZ"])
end

it "returns list of available translations for the license" do
expect(license.locales).to eq(["en_US", "cz_CZ"])
end
end

describe "#accept!" do
it "marks the license as accepted" do
expect(license.accepted?).to be(false)
Expand Down

0 comments on commit dc30944

Please sign in to comment.