Class: Wagons::Installer

Inherits:
Object show all
Defined in:
lib/wagons/installer.rb

Overview

Helper class to install wagons into the current application. Wagons are searched for in the system gem repository.

If you want to use the #install method, add “gem ‘open4’” to your Gemfile.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeInstaller

Returns a new instance of Installer.



10
11
12
# File 'lib/wagons/installer.rb', line 10

def initialize
  @include_version_in_wagonfile = true
end

Instance Attribute Details

#include_version_in_wagonfileObject

Returns the value of attribute include_version_in_wagonfile.



8
9
10
# File 'lib/wagons/installer.rb', line 8

def include_version_in_wagonfile
  @include_version_in_wagonfile
end

Instance Method Details

#availableObject

Most recent gem specifications of all wagons available in GEM_HOME.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/wagons/installer.rb', line 20

def available
  return @available if defined?(@available)

  # only keep most recent version in @available
  @available = []
  load_available_specs.each do |spec|
    if prev = @available.find { |w| w.name == spec.name }
      if prev.version < spec.version
        @available.delete(prev)
        @available << spec
      end
    else
      @available << spec
    end
  end
  @available
end

#available_spec(name) ⇒ Object

Get the gem specification of an available wagon with the given name. Return nil if not found.



90
91
92
# File 'lib/wagons/installer.rb', line 90

def available_spec(name)
  available.find { |s| s.name == name }
end

#check_app_requirement(specs) ⇒ Object

Check if the app requirement of the given gem specifications are met by the current app version. Returns nil if everything is fine or a array with error messages.



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/wagons/installer.rb', line 128

def check_app_requirement(specs)
  missing = []
  specs.each do |spec|
    if wagon = wagon_class(spec)
      unless wagon.app_requirement.satisfied_by?(Wagons.app_version)
        missing << "#{spec} requires application version #{wagon.app_requirement}"
      end
    end
  end

  missing
end

#check_dependencies(specs) ⇒ Object

Check if all wagon dependencies of the given gem specifications are met by the installed wagons. Returns nil if everything is fine or a string with error messages.



116
117
118
119
120
121
122
123
# File 'lib/wagons/installer.rb', line 116

def check_dependencies(specs)
  missing = check_app_requirement(specs)

  present = exclude_specs(installed, specs)
  future = present + specs

  check_all_dependencies(specs, future, missing)
end

#check_protected(specs) ⇒ Object

Checks if the wagons for given gem specifications are protected. Returns nil if everything is fine or a string with error messages.



151
152
153
154
155
156
157
158
# File 'lib/wagons/installer.rb', line 151

def check_protected(specs)
  protected = []
  specs.each do |spec|
    msg = Wagons.find(spec.name).protect?
    protected << msg if msg.is_a?(String)
  end
  protected.join("\n").presence
end

#check_uninstalled_dependencies(specs) ⇒ Object

Check if the wagon dependencies of the remaining wagons would still be met after the given gem specifications are uninstalled. Returns nil if everything is fine or a string with error messages.



144
145
146
147
# File 'lib/wagons/installer.rb', line 144

def check_uninstalled_dependencies(specs)
  present = exclude_specs(installed, specs)
  check_all_dependencies(present, present)
end

#exclude_specs(full, to_be_excluded) ⇒ Object

Removes all gem specifications with the same name in to_be_excluded from full. Versions are ignored.



172
173
174
# File 'lib/wagons/installer.rb', line 172

def exclude_specs(full, to_be_excluded)
  full.clone.delete_if { |s| to_be_excluded.find { |d| s.name == d.name } }
end

#install(names) ⇒ Object

Install or update the wagons with the given names. I.e., adds the given wagon names to the Wagonfile and runs rake wagon:setup. After that, the application MUST be restarted to load the new wagons. Returns nil if everything is fine or a string with error messages. This method requires open4.



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/wagons/installer.rb', line 57

def install(names)
  change_internal(names, :check_dependencies) do |specs|
    content = File.read(wagonfile) rescue ''
    wagonfile_update(specs)

    begin
      setup_wagons(specs)
    rescue => e
      wagonfile_write(content)
      raise e
    end
  end
end

#installedObject

Gem specifications of all installed wagons.



15
16
17
# File 'lib/wagons/installer.rb', line 15

def installed
  @installed ||= Wagons.all.map(&:gemspec)
end

#installed_spec(name) ⇒ Object

Get the gem specification of the installed wagon with the given name. Return nil if not found.



84
85
86
# File 'lib/wagons/installer.rb', line 84

def installed_spec(name)
  installed.find { |s| s.name == name }
end

#not_installedObject

Most recent gem specifications of available, but not installed (in any version) wagons.



39
40
41
# File 'lib/wagons/installer.rb', line 39

def not_installed
  exclude_specs(available, installed)
end

#specs_from_names(names) ⇒ Object

List of available gem specifications with the given names. Raises an error if a name cannot be found.



162
163
164
165
166
167
168
# File 'lib/wagons/installer.rb', line 162

def specs_from_names(names)
  names.map do |name|
    spec = available_spec(name)
    fail "#{name} was not found" if spec.nil?
    spec
  end
end

#uninstall(names) ⇒ Object

Remove the wagons with the given names. I.e., reverts the migrations of the given wagon names if the wagon is not protected and removes the entries from the Wagonfile. Returns nil if everything is fine or a string with error messages.



75
76
77
78
79
80
# File 'lib/wagons/installer.rb', line 75

def uninstall(names)
  change_internal(names, :check_uninstalled_dependencies, :check_protected) do |specs|
    remove_wagons(specs)
    wagonfile_remove(specs)
  end
end

#updatesObject

Most recent gem specifications of available and installed (in an older version) wagons.



44
45
46
47
48
49
50
# File 'lib/wagons/installer.rb', line 44

def updates
  available.select do |spec|
    if wagon = installed_spec(spec.name)
      wagon.version < spec.version
    end
  end
end

#wagon_class(spec) ⇒ Object

The wagon class of the given spec.



182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/wagons/installer.rb', line 182

def wagon_class(spec)
  @wagon_classes ||= {}
  return @wagon_classes[spec] if @wagon_classes.key?(spec)

  clazz = nil
  file = File.join(spec.gem_dir, 'lib', spec.name, 'wagon.rb')
  if File.exist?(file)
    require file
    clazz = "#{spec.name.camelize}::Wagon".constantize
  else
    fail "#{spec.name} wagon class not found in #{file}"
  end
  @wagon_classes[spec] = clazz
end

#wagonfileObject

Wagonfile



177
178
179
# File 'lib/wagons/installer.rb', line 177

def wagonfile
  Rails.root.join('Wagonfile')
end

#wagonfile_remove(specs) ⇒ Object

Remove the given gem specifications from the Wagonfile.



107
108
109
110
111
# File 'lib/wagons/installer.rb', line 107

def wagonfile_remove(specs)
  wagonfile_edit(specs) do |spec, content|
    content.sub(gem_declaration_regexp(spec.name), '')
  end
end

#wagonfile_update(specs) ⇒ Object

Update the Wagonfile with the given gem specifications.



95
96
97
98
99
100
101
102
103
104
# File 'lib/wagons/installer.rb', line 95

def wagonfile_update(specs)
  wagonfile_edit(specs) do |spec, content|
    declaration = "gem '#{spec.name}'"
    declaration += ", '#{spec.version}'" if include_version_in_wagonfile
    unless content.sub!(gem_declaration_regexp(spec.name), declaration)
      content += "\n#{declaration}"
    end
    content
  end
end