GemInstaller.initialize()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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