diff options
| author | Can Eldem <celdem@gitlab.com> | 2020-01-16 10:24:11 +0000 |
|---|---|---|
| committer | Can Eldem <celdem@gitlab.com> | 2020-01-16 10:24:11 +0000 |
| commit | 2074e7e5ea3012be6f3a72bd4af934a42b7202ca (patch) | |
| tree | ce9ec33580f0e6e3f9cf3df1aab2f2cf7b5601cb /lib | |
| parent | f4f59927f87944a4d73be26416a7334521875f40 (diff) | |
| parent | 34f162a4903d852d47bd5440839f7519eb6fa8f0 (diff) | |
Merge branch '12012-pipfile-lock' into 'master'v2.4.0
Add support for Pipfile.lock
See merge request gitlab-org/security-products/license-management!103
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/license/management.rb | 16 | ||||
| -rw-r--r-- | lib/license/management/loggable.rb | 4 | ||||
| -rw-r--r-- | lib/license/management/python/pipenv.rb | 64 | ||||
| -rw-r--r-- | lib/license/management/python/pypi.rb | 44 | ||||
| -rw-r--r-- | lib/license/management/version.rb | 2 |
5 files changed, 129 insertions, 1 deletions
diff --git a/lib/license/management.rb b/lib/license/management.rb index a6e0664..ebab5e2 100644 --- a/lib/license/management.rb +++ b/lib/license/management.rb @@ -2,9 +2,12 @@ require 'pathname' require 'yaml' +require 'json' require 'license_finder' require 'license/management/loggable' require 'license/management/verifiable' +require 'license/management/python/pipenv' +require 'license/management/python/pypi' require 'license/management/repository' require 'license/management/report' require 'license/management/version' @@ -12,6 +15,12 @@ require 'license/management/version' # This applies a monkey patch to the JsonReport found in the `license_finder` gem. LicenseFinder::JsonReport.prepend(License::Management::Report) +# This monkey patch can be removed once https://github.com/pivotal/LicenseFinder/pull/659 is released +LicenseFinder::Scanner.const_set( + :PACKAGE_MANAGERS, + LicenseFinder::Scanner::PACKAGE_MANAGERS + [License::Management::Pipenv] +) + # This monkey patch can be removed once we upgrade to license_finder 5.9.2. Details [here](https://gitlab.com/gitlab-org/gitlab/issues/13748#note_235810786). module LicenseFinder class Bundler < PackageManager @@ -31,5 +40,12 @@ module License def self.root Pathname.new(File.dirname(__FILE__)).join('../..') end + + def self.http + @http ||= Net::Hippie::Client.new.tap do |client| + client.logger = ::Logger.new('http.log') + client.follow_redirects = 3 + end + end end end diff --git a/lib/license/management/loggable.rb b/lib/license/management/loggable.rb index a44d45d..165d8ca 100644 --- a/lib/license/management/loggable.rb +++ b/lib/license/management/loggable.rb @@ -10,6 +10,10 @@ module License def log_info(message) logger.info(self.class, message) end + + def log_error(message) + logger.info(self.class, message, color: :red) + end end end end diff --git a/lib/license/management/python/pipenv.rb b/lib/license/management/python/pipenv.rb new file mode 100644 index 0000000..482fd25 --- /dev/null +++ b/lib/license/management/python/pipenv.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module License + module Management + class Pipenv < LicenseFinder::PackageManager + include Loggable + + def initialize(options = {}) + super + @lockfile = Pathname('Pipfile.lock') + end + + def current_packages + @current_packages ||= + begin + packages = {} + each_dependency(groups: allowed_groups) do |name, data, group| + version = canonicalize(data['version']) + package = packages.fetch(key_for(name, version)) do |key| + packages[key] = build_package_for(name, version) + end + package.groups << group + end + packages.values + end + end + + def possible_package_paths + project_path ? [project_path.join(@lockfile)] : [@lockfile] + end + + private + + def each_dependency(groups: []) + dependencies = JSON.parse(IO.read(detected_package_path)) + groups.each do |group| + dependencies[group].each do |name, data| + yield name, data, group + end + end + end + + def canonicalize(version) + version.sub(/^==/, '') + end + + def build_package_for(name, version) + LicenseFinder::PipPackage.new(name, version, PyPI.definition(name, version)) + end + + def key_for(name, version) + "#{name}-#{version}" + end + + def allowed_groups + %w[default develop] - ignored_groups + end + + def ignored_groups + @ignored_groups.to_a || [] + end + end + end +end diff --git a/lib/license/management/python/pypi.rb b/lib/license/management/python/pypi.rb new file mode 100644 index 0000000..0397532 --- /dev/null +++ b/lib/license/management/python/pypi.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'net/hippie' + +module License + module Management + class PyPI + include Loggable + + def initialize(http) + @http = http + end + + def definition_for(name, version) + uri = "https://pypi.org/pypi/#{name}/#{version}/json" + process(@http.with_retry { |client| client.get(uri) }).tap do |definition| + log_info([name, version, definition["license"]].inspect) + end + rescue *Net::Hippie::CONNECTION_ERRORS + {} + end + + class << self + def definition(name, version) + @pypi ||= new(License::Management.http) + @pypi.definition_for(name, version) + end + end + + private + + def process(response) + return JSON.parse(response.body).fetch('info', {}) if ok?(response) + + log_error([response.class, response.code, response.body].inspect) + {} + end + + def ok?(response) + response.is_a?(Net::HTTPSuccess) + end + end + end +end diff --git a/lib/license/management/version.rb b/lib/license/management/version.rb index 995dee4..a5e7b07 100644 --- a/lib/license/management/version.rb +++ b/lib/license/management/version.rb @@ -2,6 +2,6 @@ module License module Management - VERSION = '2.3.1' + VERSION = '2.4.0' end end |
