class Gemterms::GemFiler
Accepts a Gemfile and Gemfile.lock to produce a Gemterm::Project
based upon the rubygems defined. Can output statistics on that basis.
Attributes
bundle[R]
disable_api[RW]
project[R]
use_remotes[RW]
Public Class Methods
new(licenser)
click to toggle source
# File lib/gemterms/gem_filer.rb, line 14 def initialize(licenser) @licenser = licenser @use_remotes = @disable_api = false end
Public Instance Methods
process(gemfile, lockfile)
click to toggle source
# File lib/gemterms/gem_filer.rb, line 59 def process(gemfile, lockfile) @gemfile = gemfile @lockfile = lockfile @project = Project.new read_bundle_specs load_specs @project end
read_bundle()
click to toggle source
# File lib/gemterms/gem_filer.rb, line 19 def read_bundle # Read the Bundle from the Gem and Lockfiles Bundler.settings[:frozen] = true @bundle = Bundler::Dsl.evaluate(@gemfile, @lockfile, {}) end
read_bundle_specs()
click to toggle source
# File lib/gemterms/gem_filer.rb, line 25 def read_bundle_specs read_bundle missing = [] @specs = bundle.resolve.materialize(bundle.dependencies, missing) # Happy path - all the specs are available locally. if missing.length == 0 # Use requested specs instead. This is due to the fact that # bundler cleverly excludes itself. However, if it's an explicit # spec we want to evaluate it's licence too (ps. It's MIT) @specs = bundle.requested_specs return true end # If we can, try and get the additional gem data from RubyGem sources # (typically https://rubygems.org). Otherwise give the user a warning. if use_remotes puts "Sourcing gem information from gem sources. This may take some time." read_bundle @specs = bundle.resolve_remotely! else # @todo This path will be missing bundler - if it was supplied. puts missing.length == 1 ? "The following gem isn't installed:" : "The following gems aren't installed:" puts <<-INST #{missing.map { |s| s.full_name } * ', '} We cannot report on uninstalled gems. You can use `bundle install` to install. Alternatively, if you run with the `--use-remotes` option, gemterms will use your RubyGem sources to load gem metadata (note, this will be slower). INST end end
Protected Instance Methods
load_spec_as_component(spec)
click to toggle source
# File lib/gemterms/gem_filer.rb, line 84 def load_spec_as_component(spec) if spec.licenses.nil? || spec.licenses == [] licenses = [] if (spec.source.class == Bundler::Source::Rubygems) && !disable_api puts "Getting missing license data from gem source (use --disable-api to skip) " if @sources.length == 0 STDOUT.print(".") & STDOUT.flush licenses = rubygem_licences_from_spec(spec) end else licenses = spec.licenses end component = Component.new(spec.name, spec.version, @licenser.rubygem_licenses(licenses)) end
load_specs()
click to toggle source
# File lib/gemterms/gem_filer.rb, line 71 def load_specs # @todo Do we include *all* dependencies of a given gem here? Technically # they are not in use, but they are linked to the gem. Maybe one for # --very-strict mode @sources = {} @specs.each do |spec| spec = spec.__materialize__ if Bundler::LazySpecification == spec @project << load_spec_as_component(spec) end puts "\n\n" if @sources.length > 0 @project end
rubygem_licences_from_spec(spec)
click to toggle source
Iterates over the remotes in the spec, using the API to access rubygem data. If a particular remote ever fails, it’s not tried again.
@param [ Gem::Specification ] spec The specification to source @return [ Array<String> ] the array of license strings (can be empty)
# File lib/gemterms/gem_filer.rb, line 103 def rubygem_licences_from_spec(spec) # Try every remote until we (hopefully) get a result licenses = spec.source.remotes.each do |remote| begin source = @sources[remote] next if source == :unavailable @sources[remote] = source = RubyGems.new(remote) if source.nil? licenses = rubygem_licenses_from_versions(spec, source) return licenses unless licenses.nil? rescue SourceUnavailableError => sae @sources[source] = :unavailable nil end end [] end
rubygem_licenses_from_versions(spec, source)
click to toggle source
# File lib/gemterms/gem_filer.rb, line 120 def rubygem_licenses_from_versions(spec, source) versions = source.versions(spec.name) # Try for an exact match. If this has license information, we'll use it. version = versions.detect { |v| v["number"] == spec.version.to_s } licenses = version.nil? ? nil : version["licenses"] # Try for any later version. e.g. Rails 4 is marked as MIT licensed, # but earlier versions aren't. We assume MIT for the earlier versions. # @todo this should be disabled when a --strict mode is introduced. if licenses.nil? || licenses == [] version = versions.detect do |v| (Gem::Version.new(v["number"]) > spec.version) && !v["licenses"].nil? && v["licenses"].length > 0 end licenses = version.nil? ? nil : version["licenses"] end licenses end