Parent

Class/Module Index [+]

Quicksearch

Nanoc::CLI::ErrorHandler

Catches errors and prints nice diagnostic messages, then exits.

@api private

Constants

GEM_NAMES

A hash that contains the name of the gem for a given required file. If a `require` fails, the gem name is looked up in this hash.

Public Class Methods

disable() click to toggle source

Disables error handling. This is used by the test cases to prevent error from being handled by the CLI while tests are running.

@api private

# File lib/nanoc/cli/error_handler.rb, line 33
def self.disable
  @disabled = true
end
enable() click to toggle source

Re-enables error handling after it was disabled. This is used by the test cases to prevent error from being handled by the CLI while tests are running.

@api private

# File lib/nanoc/cli/error_handler.rb, line 42
def self.enable
  @disabled = false
end
handle_while(params = {}, &block) click to toggle source

Enables error handling in the given block.

@option params [Nanoc::CLI::Command, nil] command The command that is

currently being executed, or nil if there is none

@return [void]

# File lib/nanoc/cli/error_handler.rb, line 21
def self.handle_while(params = {}, &block)
  if @disabled
    yield
  else
    new(params).handle_while(&block)
  end
end
new(params = {}) click to toggle source

@option params [Nanoc::CLI::Command, nil] command The command that is

currently being executed, or nil if there is none
# File lib/nanoc/cli/error_handler.rb, line 11
def initialize(params = {})
  @command = params[:command]
end

Public Instance Methods

handle_while(&block) click to toggle source

Enables error handling in the given block. This method should not be called directly; use {Nanoc::CLI::ErrorHandler.handle_while} instead.

@return [void]

@api private

# File lib/nanoc/cli/error_handler.rb, line 52
def handle_while(&block)
  # Set exit handler
  %( INT TERM ).each do |signal|
    Signal.trap(signal) do
      puts
      exit!(0)
    end
  end

  # Set stack trace dump handler
  if !defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby'
    begin
      Signal.trap('USR1') do
        puts 'Caught USR1; dumping a stack trace'
        puts caller.map { |i| "  #{i}" }.join("\n")
      end
    rescue ArgumentError
    end
  end

  # Run
  yield
rescue Nanoc::Errors::GenericTrivial => e
  $stderr.puts "Error: #{e.message}"
  exit(1)
rescue Interrupt
  exit(1)
rescue StandardError, ScriptError => e
  print_error(e)
  exit(1)
end
write_compact_error(error, stream) click to toggle source

Writes a compact representation of the error, suitable for a terminal, on the given stream (probably stderr).

@param [Error] error The error that should be described

@param [IO] stream The stream to write the description too

@api private

@return [void]

# File lib/nanoc/cli/error_handler.rb, line 120
def write_compact_error(error, stream)
  # Header
  stream.puts
  stream.puts 'Captain! We’ve been hit!'

  # Sections
  write_error_message(stream, error)
  write_compilation_stack(stream, error)
  write_stack_trace(stream, error)

  # Issue link
  write_issue_link(stream)
end
write_verbose_error(error, stream) click to toggle source

Writes a verbose representation of the error on the given stream.

@param [Error] error The error that should be described

@param [IO] stream The stream to write the description too

@api private

@return [void]

# File lib/nanoc/cli/error_handler.rb, line 143
def write_verbose_error(error, stream)
  # Header
  stream.puts "Crashlog created at #{Time.now}"

  # Sections
  write_error_message(stream, error, :verbose => true)
  write_compilation_stack(stream, error, :verbose => true)
  write_stack_trace(stream, error, :verbose => true)
  write_version_information(stream,        :verbose => true)
  write_system_information(stream,        :verbose => true)
  write_installed_gems(stream,        :verbose => true)
  write_environment(stream,        :verbose => true)
  write_gemfile_lock(stream,        :verbose => true)
  write_load_paths(stream,        :verbose => true)
end

Protected Instance Methods

compiler() click to toggle source

@return [Nanoc::Compiler] The compiler for the current site

# File lib/nanoc/cli/error_handler.rb, line 174
def compiler
  site && site.compiler
end
debug?() click to toggle source

@return [Boolean] true if debug output is enabled, false if not

@see Nanoc::CLI.debug?

# File lib/nanoc/cli/error_handler.rb, line 164
def debug?
  Nanoc::CLI.debug?
end
gems_and_versions() click to toggle source

@return [Hash<String, Array>] A hash containing the gem names as keys and gem versions as value

# File lib/nanoc/cli/error_handler.rb, line 184
def gems_and_versions
  gems = {}
  Gem::Specification.find_all.sort_by { |s| [ s.name, s.version ] }.each do |spec|
    gems[spec.name] ||= []
    gems[spec.name] << spec.version.to_s
  end
  gems
end
resolution_for(error) click to toggle source

Attempts to find a resolution for the given error, or nil if no resolution can be automatically obtained.

@param [Error] error The error to find a resolution for

@return [String] The resolution for the given error

# File lib/nanoc/cli/error_handler.rb, line 232
def resolution_for(error)
  case error
  when LoadError
    # Get gem name
    matches = error.message.match(/(no such file to load|cannot load such file) -- ([^\s]+)/)
    return nil if matches.nil?
    gem_name = GEM_NAMES[matches[2]]

    # Build message
    if gem_name
      if self.using_bundler?
        'Make sure the gem is added to Gemfile and run `bundle install`.'
      else
        "Install the '#{gem_name}' gem using `gem install #{gem_name}`."
      end
    end
  when RuntimeError
    if error.message =~ /^can't modify frozen/
      "You attempted to modify immutable data. Some data, such as "            "item/layout attributes and raw item/layout content, can not "            "be modified once compilation has started. (This was "            "unintentionally possible in 3.1.x and before, but has been "            "disabled in 3.2.x in order to allow compiler optimisations.)"
    end
  end
end
site() click to toggle source

@return [Nanoc::Site] The site that is currently being processed

# File lib/nanoc/cli/error_handler.rb, line 169
def site
  @command && @command.site
end
stack() click to toggle source

@return [Array] The current compilation stack

# File lib/nanoc/cli/error_handler.rb, line 179
def stack
  (compiler && compiler.stack) || []
end
using_bundler?() click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 259
def using_bundler?
  defined?(Bundler) && Bundler::SharedHelpers.in_bundle?
end
write_compilation_stack(stream, error, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 281
def write_compilation_stack(stream, error, params = {})
  write_section_header(stream, 'Compilation stack', params)

  if stack.empty?
    stream.puts '  (empty)'
  else
    stack.reverse.each do |obj|
      if obj.is_a?(Nanoc::ItemRep)
        stream.puts "  - [item]   #{obj.item.identifier} (rep #{obj.name})"
      else # layout
        stream.puts "  - [layout] #{obj.identifier}"
      end
    end
  end
end
write_environment(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 338
def write_environment(stream, params = {})
  write_section_header(stream, 'Environment', params)
  ENV.sort.each do |e|
    stream.puts "#{e.first} => #{e.last.inspect}"
  end
end
write_error_message(stream, error, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 273
def write_error_message(stream, error, params = {})
  write_section_header(stream, 'Message', params)

  stream.puts "#{error.class}: #{error.message}"
  resolution = resolution_for(error)
  stream.puts "#{resolution}" if resolution
end
write_gemfile_lock(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 345
def write_gemfile_lock(stream, params = {})
  if File.exist?('Gemfile.lock')
    write_section_header(stream, 'Gemfile.lock', params)
    stream.puts File.read('Gemfile.lock')
  end
end
write_installed_gems(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 331
def write_installed_gems(stream, params = {})
  write_section_header(stream, 'Installed gems', params)
  gems_and_versions.each do |g|
    stream.puts "  #{g.first} #{g.last.join(', ')}"
  end
end
write_load_paths(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 352
def write_load_paths(stream, params = {})
  write_section_header(stream, 'Load paths', params)
  $LOAD_PATH.each_with_index do |i, index|
    stream.puts "  #{index}. #{i}"
  end
end
write_section_header(stream, title, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 263
def write_section_header(stream, title, params = {})
  stream.puts
  if params[:verbose]
    stream.puts '===== ' + title.upcase + ':'
  else
    stream.puts "\e[1m\e[31m" + title + ':' + "\e[0m"
  end
  stream.puts
end
write_stack_trace(stream, error, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 297
def write_stack_trace(stream, error, params = {})
  is_verbose = params.fetch(:verbose, false)

  write_section_header(stream, 'Stack trace', params)

  count = is_verbose ? -1 : 10
  error.backtrace[0...count].each_with_index do |item, index|
    stream.puts "  #{index}. #{item}"
  end
  if !is_verbose && error.backtrace.size > count
    stream.puts "  ... #{error.backtrace.size - count} more lines omitted. See full crash log for details."
  end
end
write_system_information(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 324
def write_system_information(stream, params = {})
  uname = `uname -a`
  write_section_header(stream, 'System information', params)
  stream.puts uname
rescue Errno::ENOENT
end
write_version_information(stream, params = {}) click to toggle source
# File lib/nanoc/cli/error_handler.rb, line 319
def write_version_information(stream, params = {})
  write_section_header(stream, 'Version information', params)
  stream.puts Nanoc.version_information
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.