简体   繁体   English

从Ruby内部使用bundler验证gem的版本

[英]Verify version of a gem with bundler from inside Ruby

Is there a way to verify that I have the latest version of a gem from inside a Ruby program? 有没有办法在Ruby程序中验证我是否拥有最新版本的gem? That is, is there a way to do bundle outdated #{gemname} programmatically? 也就是说,有没有办法以编程方式bundle outdated #{gemname}

I tried looking at bundler's source code but I couldn't find a straight-forward way. 我试着查看bundler的源代码,但我找不到直截了当的方法。 Currently I'm doing this, which is fragile, slow and so inelegant: 目前我正在这样做,这是脆弱,缓慢和如此不优雅:

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

A way to avoid external execution: 一种避免外部执行的方法:

For bundler 1.2.x 对于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 

For bundler 1.3.x 对于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     

There is no programmatic way to use outdated command in bundler, because the code is in a Thor CLI file which prints output to the user. 在bundler中没有使用outdated命令的编程方法,因为代码位于Thor CLI文件中,该文件将输出打印给用户。 Bundler's tests are also issuing the command to the system and checking the output ( Link to outdated tests ). Bundler的测试也是向系统发出命令并检查输出( 链接到outdated测试 )。

It should be fairly simple to write your own method to mirror what the outdated method in cli.rb is doing, though. 但是编写自己的方法来镜像cli.rb中outdated方法应该是相当简单的。 See the highlighted code here : Link to outdated method in Bundler source . 请参阅此处突出显示的代码: 链接到Bundler源中的过时方法 Remove lines with Bundler.ui and return true/false based on the value of out_count 使用Bundler.ui删除行,并根据out_count的值返回true / false

Update : I've extracted 'bundle outdated' into a reusable method without the console output and the exits. 更新 :我已经将'bundle outdated'解压缩成一个可重用的方法,没有控制台输出和退出。 You can find the gist here : link to gist . 你可以在这里找到要点: 链接到要点 I have tested this on bundler 1.3 and it seems to work. 我在bundler 1.3上测试了它,它似乎工作。

bundle check列表已更新的宝石,您可能想要使用它。

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

Disappointing, this looks surprisingly difficult. 令人失望的是,这看起来非常困难。

There are a couple of open issues in bundler where the official line appears to be: 在捆绑器中有几个 解决的问题 ,官方线路似乎是:

At this point in time, there isn't a documented ruby API. 目前,还没有记录的ruby API。 It's something that's on our list, though. 不过,这是我们名单上的内容。

Looking through the bundler source code cli.rb , it's fairly clear that it's going to be tricky to call from ruby, or reproduce the code in a sensible manner. 通过捆绑源代码cli.rb ,很明显从ruby调用或以合理的方式重现代码会很棘手。

Calling methods from CLI will be difficult because they're sprinkled with calls to exit . 从CLI调用方法很困难,因为它们会被调用退出

Reproducing the code doesn't look fun either because there is quite a lot of bundler logic in there. 重现代码看起来并不好看,因为那里有很多捆绑器逻辑。

Good luck! 祝好运!

checking the source code of latest bundler source code 检查最新的bundler源代码的源代码

I could come up with this 我能想出来

https://github.com/carlhuda/bundler/blob/master/lib/bundler/cli.rb#L398 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"} 

This may not work with earlier version of bundler. 这可能不适用于早期版本的bundler。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM