10

有没有办法从 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
4

6 回答 6

6

一种避免外部执行的方法:

对于捆绑器 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 

对于捆绑器 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     
于 2013-04-06T22:52:07.867 回答
4

在 bundler中没有使用命令的编程方式outdated,因为代码位于 Thor CLI 文件中,该文件将输出打印给用户。Bundler 的测试也在向系统发出命令并检查输出(链接到outdated测试)。

outdated不过,编写自己的方法来反映cli.rb 中的方法正在做什么应该相当简单。请参阅此处突出显示的代码:Link to outdated method in Bundler source。删除行Bundler.ui并根据值返回真/假out_count

更新:我已经将'bundle outdated'提取到一个没有控制台输出和出口的可重用方法中。你可以在这里找到要点:链接到要点。我已经在 bundler 1.3 上对此进行了测试,它似乎可以工作。

于 2013-04-05T22:23:27.780 回答
0

嗯,听起来你可能想要bundle showgem env

于 2013-04-05T22:48:32.793 回答
0

bundle check列出过时的宝石,您可能想要使用它。

于 2013-03-20T10:58:09.070 回答
0

令人失望的是,这看起来非常困难。

bundler 中有几个 解决的问题,官方似乎是:

目前,还没有记录在案的 ruby​​ API。不过,这是我们名单上的东西。

查看捆绑程序源代码cli.rb,很明显从 ruby​​ 调用或以合理的方式重现代码会很棘手。

从 CLI 调用方法会很困难,因为它们到处都是对 exit 的调用

重现代码看起来也不好玩,因为那里有很多捆绑器逻辑。

祝你好运!

于 2013-04-06T00:10:15.873 回答
0

检查最新捆绑器源代码的源代码

我可以想出这个

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"} 

这可能不适用于早期版本的捆绑程序。

于 2013-04-12T07:12:25.710 回答