如何使用 Gemfile.lock 和 LockfileParser 类仅列出 ruby 生产依赖项 [英] How to list ruby production only dependencies using Gemfile.lock and LockfileParser class
问题描述
我有一个工具可以分析一些包含 Gemfile 和 Gemfile.lock 文件的 ruby 项目.这个工具在输入 ruby 项目所在的路径中给出了它的所有依赖项.
I have a tool that analyze some ruby projects having Gemfile and Gemfile.lock files. This tool given in input the path where ruby project is, list all its dependencies.
我的问题是我只需要打印不包括开发和测试的生产依赖项.今天我发现我的代码没有排除它们,我不知道如何为我的目的修改它.如何从列表中删除开发和测试依赖项?
My problem is that I only need to print production dependencies excluding development and test. Today I find out that my code does not exclude them and I do not know how to modify it for my purpose. How I can remove development and test dependencies from the list?
这里是我用来列出依赖项的 ruby 代码的简化版本:
Here a simplified version of the ruby code I use to list dependencies:
project_path = ARGV.map {|path| File.expand_path(path) }
ENV['BUNDLE_GEMFILE'] = project_path+"/Gemfile"
lockfile_path=project_path+"/Gemfile.lock"
lockfile_contents = File.read(lockfile_path)
parser = Bundler::LockfileParser.new(lockfile_contents)
lockfile_contents = File.read(lockfile_path)
parser = Bundler::LockfileParser.new(lockfile_contents)
to_fetch = []
parser.specs.each do |spec|
gem_basename = "#{spec.name},#{spec.version}"
to_fetch << gem_basename
end
to_fetch.uniq!
to_fetch.sort!
变量 to_fetch 包含依赖项.
The variable to_fetch contains the dependencies.
这里是 Gemfile:
Here the Gemfile:
source "https://rubygems.org"
gem "cf-message-bus", git: "https://github.com/cloudfoundry/cf-message-bus.git"
gem "vcap_common", git: "https://github.com/cloudfoundry/vcap-common.git"
gem "aws-sdk", '~> 2', require: false
gem "steno"
gem "httparty"
group :test do
gem 'codeclimate-test-reporter', require: false
gem "rake"
gem "rspec"
gem "ci_reporter"
gem "timecop"
gem "webmock"
end
如果您还需要 149 行长的 Gemfile.lock,请告诉我.
Let me know if you need also the Gemfile.lock that is 149 lines long.
推荐答案
我会留下我的另一个答案,以防它对其他人有帮助:这是基于我认为您想要的修订版
I will leave my other answer in case it helps someone else: Here is the revised version based on what I think you want
require 'bundler'
class DependencyTree
attr_reader :definition
def initialize(gemfile,lockfile)
@gemfile = gemfile
@definition = Bundler::Definition.build(gemfile,lockfile,nil)
end
def all_dependencies
return @all_dependencies if @all_dependencies
collect_dependencies
end
def inspect
"#<#{self.class.name}:#{self.object_id} Gemfile: #{Pathname.new(@gemfile).expand_path} >"
end
def lock_file
@definition.locked_gems
end
def to_h
lock_file.specs.each_with_object(Hash.new {|h,k| h[k] = []}) do |lock,obj|
gem_file_dep = all_dependencies.detect {|dep| dep[:name] == lock.name} || {group: :unknown}
name = lock.full_name.dup
name << " (#{gem_file_dep[:error]})" if gem_file_dep[:error]
obj[gem_file_dep[:group]] << name
end
end
private
def groupify(dep)
dep.groups.map do |g|
a = [{group: g, name: dep.name}]
begin
a << runtime_dependencies(g,dep.to_spec)
rescue Gem::LoadError => e
a[-1] = {group: g, name: dep.name,error: 'NOT INSTALLED'}
end
end
end
def collect_dependencies
@all_dependencies = @definition.dependencies.map do |dep|
groupify(dep)
end.flatten
group_missing
@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.to_spec.dependencies.empty? ? a : [a] << runtime_dependencies(group,dep.to_spec)
end
end
def group_missing
all_locks.cycle(2) do |a|
deep_dep = @all_dependencies.find_all {|h| a.include?(h[:name])}.uniq
a.each do |k|
deep_dep.each do |h|
all_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.delete(' ').split("\n").map do |s|
s.slice(/^[\w\-]+/)
end
end
end
end
用法是:
dt = DependencyTree.new('Gemfile','Gemfile.lock')
dt.to_h
输出片段:
{:default=>
["actionmailer-4.2.5.2 (NOT INSTALLED)",
"actionpack-4.2.5.2",
"actionview-4.2.5.2",
"activejob-4.2.5.2 (NOT INSTALLED)",
"activemodel-4.2.5.2",
"activerecord-4.2.5.2",
"activerecord-sqlserver-adapter-4.2.17",
"activesupport-4.2.5.2",
"arel-6.0.3 (NOT INSTALLED)",
"axlsx-2.0.1 (NOT INSTALLED)",
"binding_of_caller-0.7.2 (NOT INSTALLED)",
"builder-3.2.3",
"coffee-rails-4.1.1 (NOT INSTALLED)",
"coffee-script-2.4.1 (NOT INSTALLED)",
"coffee-script-source-1.12.2 (NOT INSTALLED)",
"concurrent-ruby-1.0.4",
"debug_inspector-0.0.2 (NOT INSTALLED)",
"erubis-2.7.0",
"execjs-2.7.0"],
:development=>
["airbrussh-1.1.2",
"byebug-9.0.6 (NOT INSTALLED)",
"capistrano-3.7.2"],
:doc => ["sdoc-0.4.2 (NOT INSTALLED)"]}
生产 gems 将在 :default
开发 gems 将是 :default
+ :development
production gems will be in :default
development gems would be :default
+ :development
这篇关于如何使用 Gemfile.lock 和 LockfileParser 类仅列出 ruby 生产依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!