summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2019-08-15 10:54:48 -0600
committermo khan <mo@mokhan.ca>2019-08-15 11:08:16 -0600
commitd57e616015f96681f8c3cf2ce36bdd85a24e2163 (patch)
tree935866b3ec0337d459cc701cb375d563a5d03d3f /lib
parent19f8fdcd8b2351daf220e3a3a456db84dd661280 (diff)
insert shim to generate report via ruby API
Diffstat (limited to 'lib')
-rw-r--r--lib/license/management.rb20
-rw-r--r--lib/license/management/json_report.rb28
-rw-r--r--lib/license/management/loggable.rb15
-rw-r--r--lib/license/management/repository.rb46
-rw-r--r--lib/license/management/verifiable.rb15
-rw-r--r--lib/license/management/version.rb7
-rw-r--r--lib/license/management/versions/base.rb34
-rw-r--r--lib/license/management/versions/v1.rb72
8 files changed, 237 insertions, 0 deletions
diff --git a/lib/license/management.rb b/lib/license/management.rb
new file mode 100644
index 0000000..3b41843
--- /dev/null
+++ b/lib/license/management.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'pathname'
+require 'yaml'
+require 'license_finder'
+require 'license/management/loggable'
+require 'license/management/verifiable'
+require 'license/management/repository'
+require 'license/management/versions/base'
+require 'license/management/versions/v1'
+require 'license/management/json_report'
+require 'license/management/version'
+
+module License
+ module Management
+ def self.root
+ Pathname.new(File.dirname(__FILE__)).join('../..')
+ end
+ end
+end
diff --git a/lib/license/management/json_report.rb b/lib/license/management/json_report.rb
new file mode 100644
index 0000000..19a44c4
--- /dev/null
+++ b/lib/license/management/json_report.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# This is a monkey patch of the JsonReport found in `license_finder`
+module LicenseFinder
+ class JsonReport < CsvReport
+ DEFAULT_VERSION = '1'
+ VERSIONS = {
+ nil => ::License::Management::Versions::V1,
+ '' => ::License::Management::Versions::V1,
+ '1' => ::License::Management::Versions::V1,
+ '1.0' => ::License::Management::Versions::V1
+ }.freeze
+
+ def to_s
+ JSON.pretty_generate(version_for(report_version).to_h) + "\n"
+ end
+
+ private
+
+ def report_version
+ ENV.fetch('LM_REPORT_VERSION', DEFAULT_VERSION)
+ end
+
+ def version_for(version)
+ VERSIONS.fetch(version.to_s).new(dependencies)
+ end
+ end
+end
diff --git a/lib/license/management/loggable.rb b/lib/license/management/loggable.rb
new file mode 100644
index 0000000..a44d45d
--- /dev/null
+++ b/lib/license/management/loggable.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ module Loggable
+ def logger
+ ::LicenseFinder::Core.default_logger
+ end
+
+ def log_info(message)
+ logger.info(self.class, message)
+ end
+ end
+ end
+end
diff --git a/lib/license/management/repository.rb b/lib/license/management/repository.rb
new file mode 100644
index 0000000..707d9f0
--- /dev/null
+++ b/lib/license/management/repository.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ class Repository
+ include Loggable
+ include Verifiable
+
+ def initialize(
+ compatibility_path: License::Management.root.join('licenses.yml')
+ )
+ @compatibility_data = YAML.safe_load(IO.read(compatibility_path))
+ end
+
+ def item_for(license)
+ id = id_for(license)
+ item = id ? compatibility_data['items'][id] : nil
+ item ? { 'id' => id }.merge(item) : generate_item_for(license)
+ end
+
+ private
+
+ attr_reader :compatibility_data
+
+ def id_for(license)
+ ids = compatibility_data['ids']
+ ids[license.send(:short_name)] || ids[license.url]
+ end
+
+ def take_first_line_from(content)
+ return '' if blank?(content)
+
+ content.split(/[\r\n]+/)[0]
+ end
+
+ def generate_item_for(license)
+ log_info("detected unknown license named `#{license.send(:short_name)}`")
+ {
+ 'id' => 'unknown',
+ 'name' => take_first_line_from(license.name),
+ 'url' => present?(license.url) ? license.url : ''
+ }
+ end
+ end
+ end
+end
diff --git a/lib/license/management/verifiable.rb b/lib/license/management/verifiable.rb
new file mode 100644
index 0000000..72667fb
--- /dev/null
+++ b/lib/license/management/verifiable.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ module Verifiable
+ def blank?(item)
+ item.nil? || item.empty?
+ end
+
+ def present?(item)
+ !blank?(item)
+ end
+ end
+ end
+end
diff --git a/lib/license/management/version.rb b/lib/license/management/version.rb
new file mode 100644
index 0000000..d679b3f
--- /dev/null
+++ b/lib/license/management/version.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ VERSION = '1.6.0'
+ end
+end
diff --git a/lib/license/management/versions/base.rb b/lib/license/management/versions/base.rb
new file mode 100644
index 0000000..6e30e20
--- /dev/null
+++ b/lib/license/management/versions/base.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ module Versions
+ class Base
+ include Loggable
+ include Verifiable
+
+ attr_reader :dependencies, :repository
+
+ def initialize(dependencies)
+ @dependencies = dependencies
+ @repository = License::Management::Repository.new
+ end
+
+ private
+
+ def paths_from(dependency)
+ return [] unless dependency.respond_to?(:aggregate_paths)
+
+ paths = dependency.aggregate_paths
+ return [] if blank?(paths)
+
+ paths.map { |x| x.gsub(Dir.pwd, '.') }
+ end
+
+ def description_for(dependency)
+ present?(dependency.summary) ? dependency.summary : dependency.description
+ end
+ end
+ end
+ end
+end
diff --git a/lib/license/management/versions/v1.rb b/lib/license/management/versions/v1.rb
new file mode 100644
index 0000000..d448397
--- /dev/null
+++ b/lib/license/management/versions/v1.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module License
+ module Management
+ module Versions
+ class V1 < Base
+ def to_h
+ {
+ licenses: license_summary,
+ dependencies: formatted_dependencies(dependencies)
+ }
+ end
+
+ private
+
+ # when a dependency has multiple licenses, this will join the licenses into a single name
+ # this defect was backported from the htmltojson version of this script.
+ def license_summary
+ dependencies
+ .map { |x| x.licenses.map { |y| best_name_for(y) }.sort.reverse.join(', ') }
+ .flatten
+ .group_by { |name| name }
+ .map { |(license, items)| { count: items.count, name: license } }
+ .sort_by { |x| [-x[:count], x[:name]] }
+ end
+
+ # when a dependency has more than one license
+ # this method chooses one of the urls.
+ # to maintain backwards compatibility this bug has been carried forward.
+ def license_for(dependency)
+ name = join_license_names(dependency.licenses)
+ urls = dependency.licenses.map(&:url).reject { |x| blank?(x) }.uniq.sort
+ log_info("multiple urls detected: #{urls.inspect}") if urls.size > 1
+ url = urls[0] || data_for(dependency.licenses.first)['url']
+ blank?(url) ? { name: name } : { name: name, url: url }
+ end
+
+ def join_license_names(licenses)
+ licenses.map { |x| best_name_for(x) }.join(', ')
+ end
+
+ def map_from_dependency(dependency)
+ result = {
+ license: license_for(dependency),
+ dependency: {
+ name: dependency.name,
+ url: dependency.homepage,
+ description: description_for(dependency),
+ pathes: paths_from(dependency)
+ }
+ }
+ result[:dependency].delete(:url) if blank?(dependency.homepage)
+ result
+ end
+
+ def formatted_dependencies(dependencies)
+ dependencies
+ .sort_by(&:name)
+ .map { |x| map_from_dependency(x) }
+ end
+
+ def best_name_for(license)
+ data_for(license)['name']
+ end
+
+ def data_for(license)
+ repository.item_for(license)
+ end
+ end
+ end
+ end
+end