2013-03-20 85 views
10

有沒有辦法從Ruby程序中驗證是否有最新版本的gem?也就是說,有沒有辦法以編程方式執行bundle outdated #{gemname}使用Ruby中的打包器驗證gem的版本

我試着看着打包機的源代碼,但我找不到一個簡單的方法。目前,我這樣做,這是脆弱的,速度慢等不雅:

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

謝謝大家,很多答案證實了我的發現:沒有API來做到這一點。我選擇了一個基於,它提供了一個工作的代碼來完成這項任務。 – Pablo 2013-04-08 12:57:56

+0

我認爲你選擇的答案有一些問題。有一個'exit 1'會終止你的程序執行。你是否能夠獲得該代碼的工作?嘗試時發生錯誤。 – Emil 2013-04-09 20:49:35

+0

他們剛剛在版本1.2.x和1.3.x之間引入了'exit 1',所以現在需要一些猴子補丁來解決問題。 – 2013-04-09 21:50:40

回答

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  
+0

運行此錯誤時出現錯誤。另外,'過時'裏面有一個鬼鬼祟祟的'出口1'。我不認爲它可以這樣工作。 – Emil 2013-04-09 20:45:51

+0

嗯。真正。它與bundler 1.2.3協同工作,並且與1.3.5一起工作。 – 2013-04-09 21:23:01

+0

我已經發布了1.3.5更新工作 – 2013-04-09 21:40:05

0

bundle check列表超出迄今爲止的寶石,你可能想使用它。

+0

我的問題是關於從Ruby內部以編程方式運行它。 – Pablo 2013-03-20 11:49:10

3

還有就是用在打捆outdated命令沒有編程的方式,因爲該代碼是在它打印輸出給用戶的CLI托爾文件。 Bundler的測試也將命令發佈到系統並檢查輸出(Link to outdated tests)。

它應該是相當簡單的寫你自己的方法,以反映什麼cli.rb的outdated方法是幹什麼的,雖然。請參閱突出顯示的代碼:Link to outdated method in Bundler source。與Bundler.ui刪除線,並返回真/假基於out_count

更新的價值:我已經提取的「捆綁過時」到無控制檯輸出和退出可重複使用的方法。您可以在這裏找到要點:link to gist。我已經在捆綁器1.3上測試過了,它似乎可行。

+0

不幸的是,這將最終成爲以編程方式實現它的唯一真正方法。我很驚訝Bundler寫得不好。根本不存在關注的分離; UI代碼與版本檢查邏輯完全交織在一起。看起來很傷心。 – 2013-04-05 23:36:50

+0

@JimStewart,我很確定他們會接受幾個重構貢獻。 – 2013-04-11 07:22:29

0

嗯,聽起來像是你可能想bundle showgem env

0

令人失望,這看起來相當困難。

有在捆綁幾個openissues在官網上顯示爲:

在這個時間點,沒有成文的紅寶石API。不過,這是我們列表中的東西。

通過捆綁源代碼cli.rb來看,這是相當清楚,這將是棘手的紅寶石打電話,或以合理的方式再現的代碼。

從CLI調用方法將很困難,因爲他們灑了calls to exit

重現代碼看起來並不好玩,因爲那裏有相當多的bundler邏輯。

祝你好運!

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

這可能不是捆綁的早期版本。

相關問題