有没有办法在Ruby程序中验证我是否拥有最新版本的gem?也就是说,有没有办法以编程方式进行bundle outdated #{gemname}
?
我尝试查看bundler的源代码,但我找不到直截了当的方法。目前我正在这样做,这是脆弱,缓慢和如此不优雅:
IO.popen(%w{/usr/bin/env bundle outdated gemname}) do |proc|
output = proc.readlines.join("\n")
return output.include?("Your bundle is up to date!")
end
答案 0 :(得分:6)
避免外部执行的方法:
对于bundler 1.2.x
require 'bundler/cli'
# intercepting $stdout into a StringIO
old_stdout, $stdout = $stdout, StringIO.new
# running the same code run in the 'bundler outdated' utility
Bundler::CLI.new.outdated('rails')
# storing the output
output = $stdout.string
# restoring $stdout
$stdout = old_stdout
对于bundler 1.3.x
require 'bundler/cli'
require 'bundler/friendly_errors'
# let's cheat the CLI class with fake exit method
module Bundler
class CLI
desc 'exit', 'fake exit' # this is required by Thor
def exit(*); end # simply do nothing
end
end
# intercepting $stdout into a StringIO
old_stdout, $stdout = $stdout, StringIO.new
# running the same code run in the 'bundler outdated' utility
Bundler.with_friendly_errors { Bundler::CLI.start(['outdated', 'rails']) }
# storing the output
output = $stdout.string
# restoring $stdout
$stdout = old_stdout
答案 1 :(得分:4)
在bundler中没有以编程方式使用outdated
命令,因为代码位于Thor CLI文件中,该文件将输出打印给用户。 Bundler的测试也向系统发出命令并检查输出(Link to outdated
tests)。
编写自己的方法来反映cli.rb中的outdated
方法正在做什么应该相当简单。请参阅此处突出显示的代码:Link to outdated method in Bundler source。删除Bundler.ui
行,并根据out_count
更新:我已经提取了过时的'没有控制台输出和退出的可重用方法。你可以在这里找到要点:link to gist。我已经在bundler 1.3上测试了它,它似乎有效。
答案 2 :(得分:0)
bundle check
列出过时的宝石,您可能想要使用它。
答案 3 :(得分:0)
嗯,听起来你可能想要bundle show
或gem env
答案 4 :(得分:0)
令人失望,这看起来非常困难。
此时,没有记录的ruby API。 不过,这是我们名单上的内容。
查看bundler源代码cli.rb,很明显从ruby调用或以合理的方式重现代码会很棘手。
从CLI调用方法很困难,因为它们带有calls to exit。
重现代码看起来并不好看,因为那里有很多捆绑逻辑。
祝你好运!答案 5 :(得分:0)
检查最新bundler源代码的源代码
我能想出这个
https://github.com/carlhuda/bundler/blob/master/lib/bundler/cli.rb#L398
$ irb
1.9.3p327 :001 > require 'bundler'
=> true
1.9.3p327 :002 > def outdated_gems(gem_name,options={})
1.9.3p327 :003?> options[:source] ||= 'https://rubygems.org'
1.9.3p327 :004?> sources = Array(options[:source])
1.9.3p327 :005?> current_spec= Bundler.load.specs[gem_name].first
1.9.3p327 :006?> raise "not found in Gemfile" if current_spec.nil?
1.9.3p327 :007?> definition = Bundler.definition(:gems => [gem_name], :sources => sources)
1.9.3p327 :008?> options["local"] ? definition.resolve_with_cache! : definition.resolve_remotely!
1.9.3p327 :009?> active_spec = definition.index[gem_name].sort_by { |b| b.version }
1.9.3p327 :010?> if !current_spec.version.prerelease? && !options[:pre] && active_spec.size > 1
1.9.3p327 :011?> active_spec = active_spec.delete_if { |b| b.respond_to?(:version) && b.version.prerelease? }
1.9.3p327 :012?> end
1.9.3p327 :013?> active_spec = active_spec.last
1.9.3p327 :014?> raise "Error" if active_spec.nil?
1.9.3p327 :015?> outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version)
1.9.3p327 :016?> {:outdated=>outdated,:current_spec_version=>current_spec.version.to_s,:latest_version=>active_spec.version.to_s}
1.9.3p327 :017?> end
=> nil
1.9.3p327 :018 >
1.9.3p327 :019 >
1.9.3p327 :020 >
1.9.3p327 :021 >
1.9.3p327 :022 > outdated_gems('rake')
=> {:outdated=>true, :current_spec_version=>"10.0.3", :latest_version=>"10.0.4"}
这可能不适用于早期版本的bundler。