1
|
1 |
|
require_relative "../output" |
2
|
1 |
|
require_relative "exceptions" |
3
|
1 |
|
require_relative "exception_suppressor" |
4
|
|
|
|
5
|
1 |
|
module Resume |
6
|
1 |
|
module CLI |
7
|
|
|
# Module concerned with the installation and dependency checking |
8
|
|
|
# of Ruby gems on to the system in order to generate the resume. |
9
|
|
|
# |
10
|
|
|
# @author Paul Fioravanti |
11
|
1 |
|
class GemInstaller |
12
|
1 |
|
extend Forwardable |
13
|
|
|
|
14
|
|
|
# @!attribute gems [r] |
15
|
|
|
# @return [Hash] The hash of gems to install. |
16
|
1 |
|
attr_reader :gems |
17
|
|
|
|
18
|
1 |
|
def self.gem_already_installed?(name, version) |
19
|
3 |
|
Gem::Specification.find_by_name(name).version == |
20
|
|
|
Gem::Version.new(version) |
21
|
|
|
end |
22
|
1 |
|
private_class_method :gem_already_installed? |
23
|
|
|
|
24
|
|
|
# Initialises a new instance of a Gem Installer. |
25
|
|
|
# |
26
|
|
|
# @param gems [Hash] |
27
|
|
|
# A hash containing the gem dependencies for the resume. |
28
|
|
|
# @return [GemInstaller] |
29
|
|
|
# The gem installer object. |
30
|
1 |
|
def initialize(gems) |
31
|
10 |
|
@gems = gems |
32
|
|
|
end |
33
|
|
|
|
34
|
|
|
# Audits the local system to see if the necessary gems are installed. |
35
|
|
|
# |
36
|
|
|
# @return [Hash] The list of remaining gem dependencies to install. |
37
|
1 |
|
def audit_gem_dependencies |
38
|
3 |
|
gems.each do |name, version| |
39
|
|
|
# if gem not installed: leave in the gems list |
40
|
4 |
|
ExceptionSuppressor.suppress(Gem::LoadError, -> { next }) do |
41
|
3 |
|
if self.class.__send__(:gem_already_installed?, name, version) |
42
|
|
|
# remove dependency to install |
43
|
1 |
|
self.gems -= [[name, version]] |
44
|
|
|
end |
45
|
|
|
end |
46
|
|
|
end |
47
|
|
|
end |
48
|
|
|
|
49
|
|
|
# Outputs the name and version of the gems that must be installed |
50
|
|
|
# in order to generate the resume. |
51
|
|
|
# |
52
|
|
|
# @return [Hash] The list of dependencies to install. |
53
|
1 |
|
def output_gem_dependencies |
54
|
2 |
|
return if gems.none? |
55
|
|
|
|
56
|
1 |
|
Output.warning(:ruby_gems) |
57
|
1 |
|
gems.each do |name, version| |
58
|
1 |
|
Output.plain(:gem_name_and_version, name: name, version: version) |
59
|
|
|
end |
60
|
|
|
end |
61
|
|
|
|
62
|
|
|
# Attempts to install gem dependencies and reports back on |
63
|
|
|
# whether it was successful. |
64
|
|
|
# |
65
|
|
|
# @raise [NetworkConnectionError] |
66
|
|
|
# if an internet connection is unavailable to download gems. |
67
|
|
|
# @return [true] |
68
|
|
|
# if gem dependencies were successfully installed. |
69
|
|
|
# @return [false] |
70
|
|
|
# if gem dependencies were not successfully installed. |
71
|
1 |
|
def gems_successfully_installed? |
72
|
5 |
|
return true if gems.none? |
73
|
|
|
|
74
|
4 |
|
Output.plain(:installing_ruby_gems) |
75
|
4 |
|
gems.all? do |gem_name, version| |
76
|
4 |
|
Kernel.system("gem", "install", gem_name, "-v", version) |
77
|
|
|
end |
78
|
|
|
rescue SocketError, Errno::ECONNREFUSED |
79
|
2 |
|
raise NetworkConnectionError |
80
|
|
|
ensure |
81
|
|
|
# Reset dir and path values so just-installed gems can |
82
|
|
|
# be required, but also have this here so that the |
83
|
|
|
# return value for this method is a boolean |
84
|
5 |
|
Gem.clear_paths |
85
|
|
|
end |
86
|
|
|
|
87
|
1 |
|
private |
88
|
|
|
|
89
|
1 |
|
attr_writer :gems |
90
|
|
|
end |
91
|
|
|
end |
92
|
|
|
end |
93
|
|
|
|