Class: Toys::Utils::Gems

Inherits:
Object
  • Object
show all
Defined in:
lib/toys/utils/gems.rb

Overview

A helper class that activates and installs gems and sets up bundler.

This class is not loaded by default. Before using it directly, you should require "toys/utils/gems"

Defined Under Namespace

Classes: ActivationFailedError, AlreadyBundledError, BundleNotInstalledError, BundlerFailedError, GemfileNotFoundError, GemfileUpdateNeededError, IncompatibleGemSourceError, IncompatibleToysError, InstallFailedError

Constant Summary collapse

DEFAULT_GEMFILE_NAMES =

The gemfile names that are searched by default.

Returns:

  • (Array<String>)
[".gems.rb", "gems.rb", "Gemfile"].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(on_missing: nil, on_conflict: nil, default_confirm: nil, terminal: nil, input: nil, output: nil) ⇒ Gems

Create a new gem activator.

Parameters:

  • on_missing (:confirm, :error, :install) (defaults to: nil)

    What to do if a needed gem is not installed. Possible values:

    • :confirm - prompt the user on whether to install
    • :error - raise an exception
    • :install - just install the gem

    The default is :confirm.

  • on_conflict (:error, :warn, :ignore) (defaults to: nil)

    What to do if bundler has already been run with a different Gemfile. Possible values:

    • :error - raise an exception
    • :ignore - just silently proceed without bundling again
    • :warn - print a warning and proceed without bundling again

    The default is :error.

  • default_confirm (boolean) (defaults to: nil)

    The default confirmation result, if on_missing is set to :confirm. Defaults to true.

  • terminal (Toys::Utils::Terminal) (defaults to: nil)

    Terminal to use (optional)

  • input (IO) (defaults to: nil)

    Input IO (optional, defaults to STDIN)

  • output (IO) (defaults to: nil)

    Output IO (optional, defaults to STDOUT)



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/toys/utils/gems.rb', line 177

def initialize(on_missing: nil,
               on_conflict: nil,
               default_confirm: nil,
               terminal: nil,
               input: nil,
               output: nil)
  require "rubygems"
  unless [nil, :confirm, :install, :error].include?(on_missing)
    raise ::ArgumentError, "Illegal value for on_missing: #{on_missing.inspect}"
  end
  unless [nil, :error, :warn, :ignore].include?(on_conflict)
    raise ::ArgumentError, "Illegal value for on_conflict: #{on_conflict.inspect}"
  end
  unless [nil, true, false].include?(default_confirm)
    raise ::ArgumentError, "Illegal value for default_confirm: #{default_confirm.inspect}"
  end
  @on_missing = on_missing || :confirm
  @on_conflict = on_conflict || :error
  default_confirm = true if default_confirm.nil?
  @default_confirm = default_confirm
  # The terminal passed in is remembered separately from the one this
  # object may later derive from the input and output, so that #with
  # copies the former. Copying a derived terminal would silently defeat
  # an input or output override.
  @param_terminal = terminal
  @terminal = terminal
  @input = input || $stdin
  @output = output || $stdout
end

Class Method Details

.activate(name, *requirements) ⇒ :activated, ...

Activate the given gem. If it is not present, attempt to install it (or inform the user to update the bundle).

Parameters:

  • name (String)

    Name of the gem

  • requirements (String...)

    Version requirements

Returns:

  • (:activated)

    if the gem was activated

  • (:installed)

    if the gem was installed and activated

  • (false)

    if the gem had already been activated

Raises:



148
149
150
# File 'lib/toys/utils/gems.rb', line 148

def self.activate(name, *requirements)
  new.activate(name, *requirements)
end

Instance Method Details

#activate(name, *requirements) ⇒ :activated, ...

Activate the given gem. If it is not present, attempt to install it (or inform the user to update the bundle).

Parameters:

  • name (String)

    Name of the gem

  • requirements (String...)

    Version requirements

Returns:

  • (:activated)

    if the gem was activated

  • (:installed)

    if the gem was installed and activated

  • (false)

    if the gem had already been activated

Raises:



242
243
244
245
246
247
248
# File 'lib/toys/utils/gems.rb', line 242

def activate(name, *requirements)
  Gems.synchronize do
    gem(name, *requirements) ? :activated : false
  rescue ::Gem::LoadError => e
    handle_activation_error(e, name, requirements)
  end
end

#bundle(groups: nil, gemfile_path: nil, search_dirs: nil, gemfile_names: nil, retries: nil) ⇒ :setup, ...

Search for an appropriate Gemfile, and set up the bundle.

Parameters:

  • groups (Array<String>) (defaults to: nil)

    The groups to include in setup. Gems already loaded in this process are always included, whatever groups are requested, because excluding one would remove it from the load path of the running process.

  • gemfile_path (String) (defaults to: nil)

    The path to the Gemfile to use. If nil or not given, the :search_dirs will be searched for a Gemfile.

  • search_dirs (String, Array<String>) (defaults to: nil)

    Directories in which to search for a Gemfile, if gemfile_path is not given. You can provide a single directory or an array of directories.

  • gemfile_names (String, Array<String>) (defaults to: nil)

    File names that are recognized as Gemfiles, when searching because gemfile_path is not given. Defaults to DEFAULT_GEMFILE_NAMES.

  • retries (Integer) (defaults to: nil)

    Number of times to retry bundler operations. Optional.

Returns:

  • (:setup)

    if the bundle was set up with no install needed

  • (:installed)

    if the bundle was installed and set up

  • (:updated)

    if the bundle was updated and set up

  • (false)

    on a bundle conflict if configured not to raise an exception

Raises:



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/toys/utils/gems.rb', line 276

def bundle(groups: nil,
           gemfile_path: nil,
           search_dirs: nil,
           gemfile_names: nil,
           retries: nil)
  Array(search_dirs).each do |dir|
    break if gemfile_path
    gemfile_path = Gems.find_gemfile(dir, gemfile_names: gemfile_names)
  end
  raise GemfileNotFoundError, "Gemfile not found" unless gemfile_path
  gemfile_path = ::File.absolute_path(gemfile_path)
  Gems.synchronize do
    setup_bundle(gemfile_path, Array(groups), retries)
  end
end

#with(**overrides) ⇒ Toys::Utils::Gems

Return a gem activator with the same settings as this one, except for the provided overrides. See the constructor for argument docs. If no non-nil overrides are provided, self is returned.

Parameters:

  • overrides (Hash)

    Overrides. See the constructor for details.

Returns:



215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/toys/utils/gems.rb', line 215

def with(**overrides)
  overrides = overrides.compact
  return self if overrides.empty?
  current_settings = {
    on_missing: @on_missing,
    on_conflict: @on_conflict,
    default_confirm: @default_confirm,
    terminal: @param_terminal,
    input: @input,
    output: @output,
  }
  Gems.new(**current_settings, **overrides)
end