Last active
October 25, 2018 18:38
-
-
Save nicolas-brousse/4ae026966fee51831c01cf725d726514 to your computer and use it in GitHub Desktop.
Get dependencies list of a Ruby project by reading its Gemfile and Gemfile.lock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# frozen_string_literal: true | |
# USAGE: | |
# $ ./list_dependencies.rb | |
# $ ./list_dependencies.rb /path/to/project | |
# | |
# @see: https://stackoverflow.com/questions/44681231/how-to-list-ruby-production-only-dependencies-using-gemfile-lock-and-lockfilepar | |
require "bundler" | |
project_path = File.expand_path(ARGV[0] || ".", __dir__) | |
gemfile_path = File.expand_path("./Gemfile", project_path) | |
gemfile_lock_path = File.expand_path("./Gemfile.lock", project_path) | |
class DependecyTree | |
def initialize(gemfile_path, gemfile_lock_path) | |
@definition = Bundler::Definition.build(gemfile_path, gemfile_lock_path, nil) | |
end | |
def all_dependencies | |
return @all_dependencies if @all_dependencies | |
collect_dependencies | |
end | |
def lock_file | |
@definition.locked_gems | |
end | |
def groupify(dep) | |
dep.groups.map do |g| | |
a = [{ group: g, name: dep.name, dep: dep }] | |
begin | |
a << runtime_dependencies(g, dep.to_spec) | |
rescue Gem::LoadError => _e | |
a[-1] = { group: g, name: dep.name, dep: dep, error: "NOT INSTALLED" } | |
end | |
end | |
end | |
def collect_dependencies | |
@all_dependencies = @definition.dependencies.map do |dep| | |
groupify(dep) | |
end.flatten | |
group_missing(@all_dependencies) | |
@all_dependencies.uniq! | |
end | |
def runtime_dependencies(group, spec) | |
spec.dependencies.select { |dep| dep.type == :runtime }.map do |dep| | |
a = { group: group, name: dep.name, dep: dep } | |
dep.to_spec.dependencies.empty? ? a : [a] << runtime_dependencies(group, dep.to_spec) | |
end | |
end | |
def group_missing(dependencies) | |
all_locks.cycle(2) do |a| | |
deep_dep = dependencies.find_all { |h| a.include?(h[:name]) }.uniq | |
a.each do |k| | |
deep_dep.each do |h| | |
dependencies << { group: h[:group], name: k, error: "NOT INSTALLED" } | |
end | |
end | |
end | |
end | |
def all_locks | |
lock_file.specs.map do |spec| | |
spec.to_lock.split("\n").map do |s| | |
s.slice(/[\w\-]+/) | |
end | |
end | |
end | |
end | |
$stdout.puts "Ruby\t#{RUBY_VERSION}\tRuby is a dynamic, interpreted, reflective, object-oriented, general-purpose programming language.\tGPLv2 or 2-clause BSD license\thttps://www.ruby-lang.org" | |
$stdout.puts "" | |
$stdout.puts "Name\tVersion\tDescription\tLicense(s)\tWebsite" | |
DependecyTree.new(gemfile_path, gemfile_lock_path).all_dependencies.uniq { |s| s[:name] }.sort{ |a, b| a[:name] <=> b[:name] }.each do |desc| | |
gemspec = desc[:dep].to_spec | |
$stdout.puts "#{gemspec.name}\t#{gemspec.version}\t#{gemspec.summary}\t#{gemspec.licenses.join(", ")}\t#{gemspec.homepage}" | |
rescue Gem::MissingSpecError => _e | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment