2013-03-20 13 views
10

C'è un modo per verificare di avere l'ultima versione di una gemma all'interno di un programma Ruby? Cioè, c'è un modo per fare bundle outdated #{gemname} a livello di programmazione?Verifica la versione di una gemma con il bundler dall'interno di Ruby

Ho provato a guardare il codice sorgente di bundler ma non sono riuscito a trovare un modo diretto. Attualmente sto facendo questo, che è fragile, lenta e così poco elegante:

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

Grazie ragazzi, molte risposte confermano le mie conclusioni: non ci sono API per farlo. Ne ho scelto uno basato sul fatto che fornisce un pezzo di codice funzionante per raggiungere questo compito. – Pablo

+0

Penso che la risposta che hai scelto abbia dei trucchi. Esiste un 'exit 1' che interrompe l'esecuzione del programma. Sei riuscito a far funzionare quel codice? Ho avuto un errore durante il tentativo. – Emil

+0

Hanno appena introdotto il 'exit 1' tra le versioni 1.2.xe 1.3.x, quindi ora richiede un po 'di patch-patch per risolvere il problema. –

risposta

6

Un modo per evitare l'elaborazione dall'esterno:

Per fardellatrice 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 

Per fardellatrice 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

Ho ricevuto un errore durante l'esecuzione di questo. Inoltre, 'obsoleto' ha un 'uscita 1 'in esso. Non penso che possa funzionare in questo modo. – Emil

+0

Hmm. Vero. Funziona con bundler 1.2.3 e rompe con 1.3.5. –

+0

Ho pubblicato un aggiornamento con 1.3.5 –

0

bundle check elenco le gemme che sono fino ad oggi, si potrebbe desiderare di usarlo.

+0

La mia domanda riguarda la sua esecuzione dall'interno di Ruby, a livello di programmazione. – Pablo

3

Non esiste un modo programmatico per utilizzare il comando outdated in bundler, poiché il codice si trova in un file CLI Thor che stampa l'output per l'utente. I test di Bundler stanno anche impartendo il comando al sistema e controllando l'output (Link to outdated tests).

Dovrebbe essere abbastanza semplice scrivere il proprio metodo per rispecchiare ciò che sta facendo il metodo outdated in cli.rb. Vedere il codice evidenziato qui: Link to outdated method in Bundler source. Rimuovere le linee con Bundler.ui e tornare true/false in base al valore di out_count

Aggiornamento: Ho estratto 'pacchetto obsoleto' in un metodo riutilizzabile senza l'output della console e le uscite. Puoi trovare l'essenza qui: link to gist. Ho provato questo su bundler 1.3 e sembra funzionare.

+0

Sfortunatamente, questo finirà per essere l'unico vero modo per farlo a livello di programmazione. Sono sorpreso di quanto Bundler sia scritto male. Nessuna separazione delle preoccupazioni in corso; il codice dell'interfaccia utente è completamente intrecciato con la logica di controllo della versione. È un po 'triste da guardare. –

+0

@JimStewart, sono abbastanza sicuro che accetteranno un contributo con alcuni refactories. –

0

Hmmm, suona come si potrebbe desiderare bundle show o gem env

0

Deludente, questo sembra sorprendentemente difficile.

ci sono un paio di openissues nel bundler dove la linea ufficiale sembra essere:

A questo punto nel tempo, non v'è un'API rubino documentata. È qualcosa che è nella nostra lista, però.

Guardando attraverso il codice sorgente Bundler cli.rb, è abbastanza chiaro che sarà difficile da chiamare dal rubino, o riprodurre il codice in maniera sensata.

I metodi di chiamata da CLI saranno difficili perché sono cosparsi di calls to exit.

Riprodurre il codice non sembra divertente perché la logica del bundle è piuttosto ampia.

Buona fortuna!

0

controllo del codice sorgente del codice sorgente più recente bundler

ho potuto venire con questo

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

questo potrebbe non funzionare con la versione precedente di bundler.

Problemi correlati