Class | AutomateIt::PackageManager::Gem |
In: |
lib/automateit/package_manager/gem.rb
|
Parent: | AutomateIt::PackageManager::BaseDriver |
The Gem driver for the PackageManager provides a way to manage software packages for RubyGems using the gem command.
You can specify the specific version of a particular gem to use with the :version option, e.g., the "2.1.2" below:
package_manager.install "rails", :with => :gem, :version => "2.1.2"
Note that you can only install one single gem with a version at a time.
You can specify the command to use with each call using the :gem option, e.g., the "gem1.8" below:
package_manager.install "rails", :with => :gem, :gem => "gem1.8"
Or set a default and all subsequent calls will use it:
package_manager[:gem].setup(:gem => "gem1.8") package_manager.install "rails", :with => :gem
gem | [RW] |
Special options:
# File lib/automateit/package_manager/gem.rb, line 101 def install(*packages) return _install_helper(*packages) do |list, opts| if opts[:version] && list.size != 1 raise ArgumentError, ":version option can only be specified for a single package" end gem = opts[:gem] || self.gem # Why is the "gem" utility such a steaming pile of offal? Lameness include: # - Requires interactive input to install a package, with no way to prevent this # - Repeatedly updates indexes even when there's no reason to, and can't be told to stop # - Doesn't cache packages, insists on downloading them again # - Installs broken packages, often without giving any indication of failure # - Installs broken packages and leaves you to deal with the jagged pieces # - Sometimes fails through exit status, sometimes through output, but not both and not consistently # - Lacks a proper "is this package installed?" feature # - A nightmare to deal with if you want to install your own GEMHOME/GEMPATH # Example of an invalid gem that'll cause the failure I'm trying to avoid below: # package_manager.install("sys-cpu", :with => :gem) # gem options: # -y : Include dependencies, # -E : use /usr/bin/env for installed executables; but only with >= 0.9.4 cmd = "#{gem} install -y" cmd << " --no-ri" if opts[:ri] == false or opts[:docs] == false cmd << " --no-rdoc" if opts[:rdoc] == false or opts[:docs] == false cmd << " --source #{opts[:source]}" if opts[:source] cmd << " --version #{opts[:version]}" if opts[:version] cmd << " "+list.join(" ") cmd << " " << opts[:args] if opts[:args] cmd << " 2>&1" # XXX Try to warn the user that they won't see any output for a while log.info(PNOTE+"Installing Gems, this will take a while...") if writing? and not opts[:quiet] log.info(PEXEC+cmd) return true if preview? uninstall_needed = false begin require 'expect' require 'open4' exitstruct = Open4::popen4(cmd) do |pid, sin, sout, serr| $expect_verbose = opts[:quiet] ? false : true re_success=/Successfully installed/m re_missing=/Could not find.+in any repository/m re_select=/Select which gem to install.+>/m re_failed=/Gem files will remain.+for inspection/m re_refused=/Errno::ECONNREFUSED reading .+?\.gem/m re_all=/#{re_success}|#{re_missing}|#{re_select}|#{re_failed}|#{re_refused}/m while true begin captureded = sout.expect(re_all) rescue NoMethodError log.debug(PNOTE+"Gem quit without closing STDOUT") break end if captureded.nil? log.debug(PNOTE+"Gem quit without emitting STDOUT") break end ### puts "Captureded %s" % captureded.inspect captured = captureded.first if captured.match(re_failed) log.warn(PERROR+"Gem install failed mid-process") uninstall_needed = true break elsif captured.match(re_refused) log.warn(PERROR+"Gem install refused by server!\n#{captured}") break elsif captured.match(re_select) choice = captured.match(/^ (\d+)\. .+?\(ruby\)\s*$/)[1] log.info(PNOTE+"Guessing: #{choice}") sin.puts(choice) end end end rescue Errno::ENOENT => e raise NotImplementedError.new("can't find gem command: #{e}") end if uninstall_needed or not exitstruct.exitstatus.zero? log.error(PERROR+"Gem install failed, trying to uninstall broken pieces: #{list.inspect}") uninstall(list, opts) raise ArgumentError.new("Gem install failed because it's invalid, missing a dependency, or can't talk with Gem server: #{list.inspect}") else # Clear the RubyGems paths cache so it'll see changes. Gem.clear_paths rescue nil unless preview? end end end
See PackageManager#installed?
Special options:
# File lib/automateit/package_manager/gem.rb, line 55 def installed?(*packages) return _installed_helper?(*packages) do |list, opts| if opts[:version] && list.size != 1 raise ArgumentError, ":version option can only be specified for a single package" end gem = opts[:gem] || self.gem cmd = "#{gem} list --local 2>&1" log.debug(PEXEC+cmd) data = `#{cmd}` if opts[:version] package = list.first if match = data.match(/^#{package} \(([^\)]+)\)/m) versions = match[1].split(', ') versions.include?(opts[:version].to_s) ? [package] : [] else [] end else # Gem lists packages out of order, which screws up the # install/uninstall sequence, so we need to put them back in the # order that the user specified. present = data.scan(/^([^\s\(]+)\s+\([^\)]+\)\s*$/).flatten available = [] for package in list available << package if present.include?(package) end available end end end
See PackageManager#not_installed?
# File lib/automateit/package_manager/gem.rb, line 90 def not_installed?(*packages) _not_installed_helper?(*packages) end
:programs => %w(gem),
# File lib/automateit/package_manager/gem.rb, line 34 def setup(*args) super(*args) args, opts = args_and_opts(*args) if opts[:gem] @gem = opts[:gem] else @gem ||= %w(gem gem1.8 gem1.9).inject(nil){|s,v| s ? s : interpreter.which(v)} end end
# File lib/automateit/package_manager/gem.rb, line 197 def uninstall(*packages) return _uninstall_helper(*packages) do |list, opts| gem = opts[:gem] || self.gem # TODO PackageManager::gem#uninstall -- add logic to handle prompts during removal ?? for package in list # gem options: # -x : remove installed executables cmd = "#{gem} uninstall -x #{package} < /dev/null" cmd << " > /dev/null" if opts[:quiet] cmd << " 2>&1" interpreter.sh(cmd) end # Clear the RubyGems paths cache so it'll see changes. Gem.clear_paths rescue nil unless preview? end end