lib/licensed/sources/bundler.rb in licensed-2.0.1 vs lib/licensed/sources/bundler.rb in licensed-2.1.0
- old
+ new
@@ -1,6 +1,7 @@
# frozen_string_literal: true
+require "delegate"
begin
require "bundler"
rescue LoadError
end
@@ -34,10 +35,47 @@
def error
"could not find #{name} (#{requirement}) in any sources"
end
end
+ class BundlerSpecification < ::SimpleDelegator
+ def gem_dir
+ dir = super
+ return dir if File.exist?(dir)
+
+ File.join(Gem.dir, "gems", full_name)
+ end
+ end
+
+ class Dependency < Licensed::Dependency
+ attr_reader :loaded_from
+
+ def initialize(name:, version:, path:, loaded_from:, errors: [], metadata: {})
+ @loaded_from = loaded_from
+ super name: name, version: version, path: path, errors: errors, metadata: metadata
+ end
+
+ # Load a package manager file from the base Licensee::Projects::FsProject
+ # or from a gem specification file.
+ def package_file
+ super || spec_file
+ end
+
+ private
+
+ # Find a package manager file from the given bundler specification's
+ # `loaded_from` if available.
+ def spec_file
+ return @spec_file if defined?(@spec_file)
+ return @spec_file = nil unless loaded_from && File.exist?(loaded_from)
+ @spec_file = begin
+ file = { name: File.basename(loaded_from), dir: File.dirname(loaded_from) }
+ Licensee::ProjectFiles::PackageManagerFile.new(File.read(loaded_from), file)
+ end
+ end
+ end
+
GEMFILES = %w{Gemfile gems.rb}.freeze
DEFAULT_WITHOUT_GROUPS = %i{development test}
def enabled?
# running a ruby-packer-built licensed exe when ruby isn't available
@@ -48,14 +86,15 @@
def enumerate_dependencies
with_local_configuration do
specs.map do |spec|
error = spec.error if spec.respond_to?(:error)
- Licensed::Dependency.new(
+ Dependency.new(
name: spec.name,
version: spec.version.to_s,
path: spec.gem_dir,
+ loaded_from: spec.loaded_from,
errors: Array(error),
metadata: {
"type" => Bundler.type,
"summary" => spec.summary,
"homepage" => spec.homepage
@@ -110,11 +149,11 @@
# find a specifiction from the resolved ::Bundler::Definition specs
spec = definition.resolve.find { |s| s.satisfies?(dependency) }
# a nil spec should be rare, generally only seen from bundler
- return bundle_exec_gem_spec(dependency.name) if spec.nil?
+ return matching_spec(dependency) || bundle_exec_gem_spec(dependency.name) if spec.nil?
# try to find a non-lazy specification that matches `spec`
# spec.source.specs gives access to specifications with more
# information than spec itself, including platform-specific gems.
# these objects should have all the information needed to detect license metadata
@@ -177,9 +216,24 @@
spec.gem_dir
spec
end
rescue Licensed::Shell::Error
# return nil
+ ensure
+ ::Bundler.configure
+ end
+ end
+
+ # Loads a dependency specification using rubygems' built-in
+ # `Dependency#matching_specs` and `Dependency#to_spec`, from the original
+ # gem environment
+ def matching_spec(dependency)
+ begin
+ ::Bundler.with_original_env do
+ ::Bundler.rubygems.clear_paths
+ return unless dependency.matching_specs(true).any?
+ BundlerSpecification.new(dependency.to_spec)
+ end
ensure
::Bundler.configure
end
end