module ExtendedBundler::Errors
Constants
- HOMEPAGE
- NATIVE_EXTENSION_MSG
- VERSION
Public Class Methods
Registers the plugin and adds all needed hooks Will call troubleshoot via the `after-install` hook if the install does not succeed
# File lib/extended_bundler/errors.rb, line 25 def register return if defined?(@registered) && @registered @registered = true Bundler::Plugin.add_hook('after-install') do |spec_install| troubleshoot(spec_install) if spec_install.state != :installed end Bundler::Plugin.add_hook('before-install-all') do |_d| # This hook makes bundler load the plugin # Because the plugin is loaded before everything, our after-install hook is registered end end
Troubleshoots a failed installation Will return if we have no handlers for this gem, otherwise finds a handler to match against Each YAML file is assumed to have an array of hashes with 3 keys in each hash
-
versions : either `all` or a hash with min/max indicating the versions of the gem this applies to
-
matching : An array of strings that will be used (as a regex) to match against the error message
-
message : A message to tell the user instead of the original stack trace
This works by finding all potential “handlers” for a given gem and finding one that matches the version and has an output (in matching) that matches the message. If it does match, it will replace the error message and provide step by step instructions on how to proceed
@param spec_install [Bundler::ParallelInstaller::SpecInstallation] a SpecInstallation object from Bundler
# File lib/extended_bundler/errors.rb, line 51 def troubleshoot(spec_install) path = handler_path(spec_install.name) return nil unless File.exist?(path) troubleshooted = false yaml = YAML.load_file(path) yaml.each do |handler| next unless version_match?(spec_install.spec.version, handler['versions']) next unless handler['matching'].any? { |m| spec_install.error =~ Regexp.new(m) } spec_install.error = build_error(spec_install, handler) troubleshooted = true end if !troubleshooted && spec_install.error.include?('Failed to build gem native extension') spec_install.error = spec_install.error + "\n\n" + NATIVE_EXTENSION_MSG end end
Private Class Methods
# File lib/extended_bundler/errors.rb, line 91 def build_error(spec_install, handler) body = message(handler) # If we can pull out the original logs, add those to the message if log = spec_install.error.match(/Results logged to (?<message>.*)/) body += "\n{{bold:Original Logs are available at:}}\n" + log[:message] end # Otherwise just format what we have title = "#{spec_install.name} (#{spec_install.spec.version.to_s}) could not be installed" lines = [ "{{bold:#{title}}}", ("━" * title.length), body.lines.map(&:chomp) ].flatten formatted_lines = lines.map { |l| "{{red:┃}} #{l}".strip } ExtendedBundler::Errors::Formatter.new(formatted_lines.join("\n")).format end
# File lib/extended_bundler/errors.rb, line 114 def handler_path(gem_name) File.expand_path("../handlers/#{gem_name}.yml", __FILE__) end
# File lib/extended_bundler/errors.rb, line 105 def message(handler) # Grab the LANG environment variable # Assume it's in Posix compliant ISO 15897 format (which is approx lang_region.encoding). # Grab the lang out of that. If for some reason this isn't available, default back to # English on any issue. iso_15897_posix_lang = ENV.fetch('LANG', 'en').split('_').first handler['messages'][iso_15897_posix_lang] || handler['messages']['en'] end
# File lib/extended_bundler/errors.rb, line 71 def version_match?(spec_version, matching_versions) # Valid versions are either the string `all` or a hash with min/max return true if matching_versions == 'all' # Validate the matching versions are correct (Hash) unless matching_versions.is_a?(Hash) return ArgumentError, 'matching key must be "all" or a hash with min/max' end # If we don't specify a minimum, we can just start from 0 min = Gem::Version.new(matching_versions.fetch('min', '0')) # If we don't specify a max, we just dont compare against a max if matching_versions['max'] max = Gem::Version.new(matching_versions['max']) return spec_version >= min && spec_version <= max end spec_version > min end