【问题标题】:Parsing direct and indirect Gems of Gemfile.lock file [duplicate]解析 Gemfile.lock 文件的直接和间接 Gems [重复]
【发布时间】:2021-10-03 12:29:35
【问题描述】:

我正在尝试解析以下 Gemfile.lock 以包含 GEM 规范中的所有 Gem(直接和间接依赖项):

GEM
  remote: http://rubygems.org/
  specs:
    coderay (1.1.3)
    domain_name (0.5.20190701)
      unf (>= 0.0.5, < 1.0.0)
    http-accept (1.7.0)
    http-cookie (1.0.4)
      domain_name (~> 0.5)
    json (2.5.1)
    method_source (1.0.0)
    mime-types (3.3.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2021.0704)
    netrc (0.11.0)
    rest-client (2.1.0)
      http-accept (>= 1.7.0, < 2.0)
      http-cookie (>= 1.0.2, < 2.0)
      mime-types (>= 1.16, < 4.0)
      netrc (~> 0.8)
    unf (0.1.4)
      unf_ext
    unf_ext (0.0.7.7)
    yaml (0.1.1)

PLATFORMS
  ruby
  x86_64-darwin-20

DEPENDENCIES
  json
  rest-client
  yaml

RUBY VERSION
   ruby 2.7.3p183

BUNDLED WITH
   2.2.23

但是使用我的函数,我只能获得直接依赖关系而没有间接依赖关系。 例如:直接依赖: http-cookie (1.0.4)... 间接依赖: domain_name (~> 0.5)

我的代码:

require 'bundler'

def gemlock(file_path)
  file = file_path
  gemlock_array = []

  context = Bundler::LockfileParser.new(Bundler.read_file(file))

  # Gems
  context.specs.each do |spec|
    name = spec.name
    version = spec.version.to_s

    gemlock_array << {'name' => name, 'version' => version}
  end
  puts gemlock_array
end

gemlock('Gemfile.lock')

我得到以下哈希值:

{"name"=>"coderay", "version"=>"1.1.3"}
{"name"=>"domain_name", "version"=>"0.5.20190701"}
{"name"=>"http-accept", "version"=>"1.7.0"}
...

如您所见,间接依赖被自动忽略了!但我仍然需要得到它。

我没有任何使用打包程序的经验,也不知道如何解决这个问题。 非常感谢您对此事的任何帮助!

提前致谢。

【问题讨论】:

    标签: ruby rubygems bundler gemfile gemfile.lock


    【解决方案1】:

    间接依赖被自动忽略

    如果您包含完整输出,那将会有所帮助。我只是自己运行它,你会得到:

    [{"name"=>"coderay", "version"=>"1.1.3"},
     {"name"=>"domain_name", "version"=>"0.5.20190701"},
     {"name"=>"http-accept", "version"=>"1.7.0"},
     {"name"=>"http-cookie", "version"=>"1.0.4"},
     {"name"=>"json", "version"=>"2.5.1"},
     {"name"=>"method_source", "version"=>"1.0.0"},
     {"name"=>"mime-types", "version"=>"3.3.1"},
     {"name"=>"mime-types-data", "version"=>"3.2021.0704"},
     {"name"=>"netrc", "version"=>"0.11.0"},
     {"name"=>"rest-client", "version"=>"2.1.0"},
     {"name"=>"unf", "version"=>"0.1.4"}, # <------ !!!!!!!!!!!!
     {"name"=>"unf_ext", "version"=>"0.0.7.7"},
     {"name"=>"yaml", "version"=>"0.1.1"}]
    

    总而言之,domain_name 的间接依赖关系,即unf,大概就是您所指的,包含在列表的下方。您的代码已经完全按照您的预期运行。

    不过,有一个小问题:您可以通过这样做稍微简化实现:

    gemlock_array = context.specs.map { |s| {'name' => s.name, 'version' => s.version.to_s} }
    

    在 ruby​​ 中,分配一个临时数组并在 .each 循环中附加到它通常是次优的。改用map,直接构造数组。

    【讨论】:

    • 另外:感谢使用 Bundler::LockfileParser 而不是尝试使用正则表达式构建自己的 hacky 解决方案!看到有人在 StackOverflow 上为他们的预期用例使用解析器,而不是试图用正则表达式重新发明轮子(很糟糕),这是一股清新的空气:D
    • 嘿汤姆!我已经尝试了几个小时,但不知道为什么我没有注意到它们已经包含在内:D 是的,老实说,我对正则表达式没有经验,这就是为什么我一直在寻找一种更简单的方法,直到我找到了这个 ;) 我非常喜欢它!非常感谢!
    猜你喜欢
    • 2014-07-08
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    相关资源
    最近更新 更多