Skip to content

Enhancement for gem env #9883

Description

@forthrin

The following rewrite of show_environment suggests improvements of gem env output.

Feedback on further improvements or alternative angles appreciated.

Feature Benefits
Outputs YAML (near already) Can parse, pipe to yq for colors, etc.
Checks file presence Helpful in bug reports
Replaces Dir.home with ~ Redaction / Privacy
Centralizes formatting DRY

Example output

RubyGems Environment:
  Version:
    - 4.0.20
  Platforms:
    - ruby
    - arm64-darwin-25
  Configuration:
    update_sources: true
    verbose: true
    backtrace: true
    bulk_threshold: 1000
    gem: --no-document
  Sources:
    - https://rubygems.org/
  Dependencies:
    Ruby version: 4.0.7 (2026-09-15 patchlevel 0) [arm64-darwin25]
    Ruby executable: /opt/homebrew/opt/ruby/bin/ruby
    Git executable: /usr/bin/git
  Directories:
    Global install: /opt/homebrew/lib/ruby/gems/4.0.0
    # Global config: /opt/homebrew/Cellar/ruby/4.0.7/etc
    Executable: /opt/homebrew/lib/ruby/gems/4.0.0/bin
    # User install: ~/.local/share/gem/ruby/4.0.0
    Spec cache: ~/.cache/gem/specs
    # Credentials: ~/.local/share/gem/credentials
  Gem path:
    - /opt/homebrew/lib/ruby/gems/4.0.0
    # - ~/.local/share/gem/ruby/4.0.0
    - /opt/homebrew/Cellar/ruby/4.0.7/lib/ruby/gems/4.0.0
  Shell path:
    - /opt/homebrew/bin
    - /opt/homebrew/sbin
    - /opt/homebrew/opt/ruby/bin
    - /usr/bin
    - /bin
    - /usr/sbin
    - /sbin
    - /opt/homebrew/lib/ruby/gems/4.0.0/bin

Code

  def exist(value)
    case value
    when %r{^/}
      File.stat(value)
    end
    ''
  rescue Errno::ENOENT
    '# '
  end

  def tree(items)
    items.flat_map do |group, items|
      items.compact.map do |item|
        item = [item].flatten
        line = exist(item.last) + (item.one? ? '- ' : '') + item.join(': ')
        line.prepend('    ').gsub(Dir.home, '~')
      end.prepend(format('  %s:', group))
    end
  end

  def show_environment # :nodoc:
    config = {}
    Gem.configuration.each do |name, value|
      config[name] = name == 'gemcutter_key' ? value.gsub(/./, '*') : value
    end
    {
      'Version' => [Gem::VERSION],
      'Platforms' => Gem.platforms.map(&:to_s),
      'Configuration' => config,
      'Sources' => Gem.sources.to_a,
      'Dependencies' => {
        'Ruby version' => "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]",
        'Ruby executable' => Gem.ruby,
        'Git executable' => git_path
      },
      'Directories' => {
        'Global install' => Gem.dir,
        'Global config' => Gem::ConfigFile::SYSTEM_CONFIG_PATH,
        'Executable' => Gem.bindir,
        'User install' => Gem.user_dir,
        'Prefix' => Gem.prefix,
        'Spec cache' => Gem.spec_cache_dir,
        'Credentials' => Gem.configuration.credentials_path
      },
      'Gem path' => ([Gem.dir] + Gem.path).uniq,
      'Shell path' => ENV['PATH'].split(File::PATH_SEPARATOR)
    }.then { tree(it).prepend('RubyGems Environment:').join("\n") }
  end

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions