我正在开发一个gem,我想模拟一下它将如何在实际环境中使用。我想用它的依赖项的任何令人满意的版本自动测试它。
例如,如果我的gemspec声明spec.add_dependency "nokogiri", '~> 1.2'
,那么我希望自动安装从1.2.0到最新的1.x的任何地方。理想情况下,它也会对nokogiri的依赖项执行相同的操作。
如果你真的在寻找一种方法来列出一个Gem的每一个可能的依赖,以及这些依赖的每一个可能的依赖,等等。
下面的代码在技术上应该可以工作
def gem_list(gem)
gem.runtime_dependencies.each_with_object({}) do |dep,obj|
# considerations for platform may be required
# check the output from the gem list command
obj[dep.name] = `gem list #{dep.name} -r -e -a`.scan(/d+.d+.d+/)
.filter_map do |v|
if dep.requirement.satisfied_by?(Gem::Version.create(v))
# load spec from the yaml output of the gem specification command
spec = Gem::Specification.from_yaml(`gem specification #{dep.name} -r -v #{v}`)
# recursively load the spec dependency chains for each dependent gem
{ v=> gem_list(spec)}
end
end
end
end
spec = Gem::Specification.load(PATH_TO_YOUR_GEMSPEC)
dependency_trees = gem_list(spec)
使用nokogiri的例子。Gemspec(这是一个相当短的列表)
spec.add_runtime_dependency("mini_portile2", "~> 2.8.0")
spec.add_runtime_dependency("racc", "~> 1.4")
输出{"mini_portile2"=>[{"2.8.0"=>{}}],
"racc"=>
[{"1.6.1"=>{}},
{"1.6.0"=>{}},
{"1.5.2"=>{}},
{"1.5.1"=>{}},
{"1.5.0"=>{}},
{"1.4.16"=>{}},
{"1.4.15"=>{}},
{"1.4.14"=>{}},
{"1.4.13"=>{}},
{"1.4.12"=>{}},
{"1.4.11"=>{}},
{"1.4.10"=>{}},
{"1.4.9"=>{}},
{"1.4.8"=>{}},
{"1.4.7"=>{}},
{"1.4.6"=>{}}]}
请注意,这可能会持续很长一段时间,这取决于满足需求的宝石数量和依赖链中的宝石数量。
这不会实际安装gems。所以我推荐处理过程为:
- 构建此列表
- 然后遍历深度嵌套的堆栈并将每个堆栈平铺成依赖链
- 安装单个依赖链 测试清除所有宝石
- 重复3-5直到没有链条留下