如何使用 Gemfile.lock 和 LockfileParser 类仅列出 ruby​​ 生产依赖项 [英] How to list ruby production only dependencies using Gemfile.lock and LockfileParser class

查看:46
本文介绍了如何使用 Gemfile.lock 和 LockfileParser 类仅列出 ruby​​ 生产依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个工具可以分析一些包含 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆