lib/backup/dependency.rb in backup-3.0.27 vs lib/backup/dependency.rb in backup-3.1.0
- old
+ new
@@ -1,108 +1,159 @@
# encoding: utf-8
module Backup
-
##
# A little self-contained gem manager for Backup.
- # Rather than specifying hard dependencies in the gemspec, forcing users
- # to install gems they do not want/need, Backup will notify them when a gem
- # has not been installed, or when the gem's version is incorrect, and provide the
- # command to install the gem. These dependencies are dynamically loaded in the Gemfile
+ # Rather than specifying hard dependencies in the gemspec, forcing users to
+ # install gems they do not want/need, Backup will notify them when a gem has
+ # not been installed, or version is incorrect, and provide the command to
+ # install the gem. These dependencies are dynamically loaded in the Gemfile.
class Dependency
+ DEPENDENCIES = {
+ 'fog' => {
+ :require => 'fog',
+ :version => '~> 1.4',
+ :for => 'Amazon S3, Rackspace Cloud Files (S3, CloudFiles Storages)',
+ :dependencies => ['net-ssh', 'net-scp']
+ },
- ##
- # Returns a hash of dependencies that Backup requires
- # in order to run every available feature
- def self.all
- {
- 'fog' => {
- :require => 'fog',
- :version => '~> 1.4.0',
- :for => 'Amazon S3, Rackspace Cloud Files (S3, CloudFiles Storages)'
- },
+ 'dropbox-sdk' => {
+ :require => 'dropbox_sdk',
+ :version => '~> 1.5.0',
+ :for => 'Dropbox Web Service (Dropbox Storage)'
+ },
- 'dropbox-sdk' => {
- :require => 'dropbox_sdk',
- :version => '~> 1.2.0',
- :for => 'Dropbox Web Service (Dropbox Storage)'
- },
+ 'net-sftp' => {
+ :require => 'net/sftp',
+ :version => ['>= 2.0.0', '<= 2.0.5'],
+ :for => 'SFTP Protocol (SFTP Storage)',
+ :dependencies => 'net-ssh'
+ },
- 'net-sftp' => {
- :require => 'net/sftp',
- :version => '~> 2.0.5',
- :for => 'SFTP Protocol (SFTP Storage)'
- },
+ 'net-scp' => {
+ :require => 'net/scp',
+ :version => ['>= 1.0.0', '<= 1.0.4'],
+ :for => 'SCP Protocol (SCP Storage)',
+ :dependencies => 'net-ssh'
+ },
- 'net-scp' => {
- :require => 'net/scp',
- :version => '~> 1.0.4',
- :for => 'SCP Protocol (SCP Storage)'
- },
+ 'net-ssh' => {
+ :require => 'net/ssh',
+ :version => ['>= 2.3.0', '<= 2.5.2'],
+ :for => 'SSH Protocol (SSH Storage)'
+ },
- 'net-ssh' => {
- :require => 'net/ssh',
- :version => '~> 2.3.0',
- :for => 'SSH Protocol (SSH Storage)'
- },
+ 'mail' => {
+ :require => 'mail',
+ :version => '~> 2.5.0',
+ :for => 'Sending Emails (Mail Notifier)'
+ },
- 'mail' => {
- :require => 'mail',
- :version => '~> 2.4.0',
- :for => 'Sending Emails (Mail Notifier)'
- },
+ 'twitter' => {
+ :require => 'twitter',
+ :version => '~> 4.0',
+ :for => 'Sending Twitter Updates (Twitter Notifier)'
+ },
- 'twitter' => {
- :require => 'twitter',
- :version => '>= 1.7.1',
- :for => 'Sending Twitter Updates (Twitter Notifier)'
- },
+ 'httparty' => {
+ :require => 'httparty',
+ :version => '~> 0.10.2',
+ :for => 'Sending Http Updates (Campfire Notifier)'
+ },
- 'httparty' => {
- :require => 'httparty',
- :version => '~> 0.8.1',
- :for => 'Sending Http Updates'
- },
+ 'prowler' => {
+ :require => 'prowler',
+ :version => '~> 1.3.1',
+ :for => 'Sending iOS push notifications (Prowl Notifier)'
+ },
- 'prowler' => {
- :require => 'prowler',
- :version => '>= 1.3.1',
- :for => 'Sending iOS push notifications (Prowl Notifier)'
- },
+ 'hipchat' => {
+ :require => 'hipchat',
+ :version => '~> 0.7.0',
+ :for => 'Sending notifications to Hipchat'
+ },
- 'hipchat' => {
- :require => 'hipchat',
- :version => '~> 0.4.1',
- :for => 'Sending notifications to Hipchat'
- },
-
- 'parallel' => {
- :require => 'parallel',
- :version => '~> 0.5.12',
- :for => 'Adding concurrency to Cloud-based syncers.'
- }
+ 'parallel' => {
+ :require => 'parallel',
+ :version => '~> 0.6.0',
+ :for => 'Adding concurrency to Cloud-based syncers.'
}
+ }
+
+ class << self
+ def all
+ @all ||= []
+ end
+
+ def find(name)
+ all.select {|dep| dep.name == name }.first
+ end
+
+ def load(name)
+ find(name).load!
+ end
end
- ##
- # Attempts to load the specified gem (by name and version).
- # If the gem with the correct version cannot be found, it'll display a message
- # to the user with instructions on how to install the required gem
- def self.load(name)
- begin
- gem(name, all[name][:version])
- require(all[name][:require])
- rescue LoadError
- Logger.error Errors::Dependency::LoadError.new(<<-EOS)
- Dependency missing
- Dependency required for:
- #{all[name][:for]}
- To install the gem, issue the following command:
- > gem install #{name} -v '#{all[name][:version]}'
- Please try again after installing the missing dependency.
- EOS
- exit 1
+ attr_reader :name, :require_as, :used_for, :requirements
+
+ def initialize(name, options = {})
+ @name = name
+ @require_as = options[:require]
+ @requirements = Array(options[:version])
+ @dependencies = Array(options[:dependencies])
+ @used_for = options[:for]
+ end
+
+ # dependencies should be defined in the order
+ # they should be installed or loaded.
+ def dependencies
+ @dependencies.map {|name| self.class.find(name) }
+ end
+
+ def load!
+ dependencies.each(&:load!)
+
+ gem(name, *requirements)
+ require require_as
+ rescue LoadError
+ raise Errors::Dependency::LoadError, <<-EOS
+ Dependency Missing
+ Gem Name: #{ name }
+ Used for: #{ used_for }
+
+ To install the gem, issue the following command:
+ > backup dependencies --install #{ name }
+ Please try again after installing the missing dependency.
+ EOS
+ end
+
+ def installed?
+ Gem::Specification.find_by_name(name, *requirements)
+ true
+ rescue LoadError
+ false
+ end
+
+ # If multiple version requirements are defined, this tries to find the
+ # version that matches them all. Otherwise, it will fallback to installing
+ # based on the last requirement. This should only be called from the CLI
+ # for `backup dependencies --install <name>`.
+ def install!
+ version = nil
+ if requirements.count > 1
+ begin
+ require 'rubygems/dependency_installer'
+ inst = Gem::DependencyInstaller.new
+ spec, _ = inst.find_spec_by_name_and_version(name, *requirements).first
+ version = spec.version
+ rescue
+ end
end
+ version ||= requirements.last
+ command = "gem install --no-ri --no-rdoc #{ name } -v '#{ version }'"
+ puts "\nLaunching `#{ command }`"
+ exec command
end
+ DEPENDENCIES.each {|name, options| all << new(name, options) }
end
end