class Geordi::Util

Public Class Methods

binstub_or_fallback(executable) click to toggle source
# File lib/geordi/util.rb, line 85
def binstub_or_fallback(executable)
  binstub_file = "bin/#{executable}"

  File.exist?(binstub_file) ? binstub_file : "bundle exec #{executable}"
end
cmd_exists?(cmd) click to toggle source

check if given cmd is executable. Absolute path or command in $PATH allowed.

# File lib/geordi/util.rb, line 152
def cmd_exists?(cmd)
  system("which #{cmd} > /dev/null")
  $?.exitstatus.zero?
end
console_command(environment) click to toggle source
# File lib/geordi/util.rb, line 91
def console_command(environment)
  if gem_major_version('rails') == 2
    "script/console #{environment}"
  elsif gem_major_version('rails') == 3
    "#{binstub_or_fallback('rails')} console #{environment}"
  else
    use_multiline = if irb_version >= Gem::Version.new('1.2') && ruby_version < Gem::Version.new('3.0')
      Interaction.note 'Using --nomultiline switch for faster pasting'
      '--nomultiline'
    end

    irb_flags = [use_multiline, Settings.new.irb_flags].join(' ').strip
    irb_flags.prepend('-- ') unless irb_flags.empty?

    "#{binstub_or_fallback('rails')} console -e #{environment} #{irb_flags}"
  end
end
cucumber_path?(path) click to toggle source
# File lib/geordi/util.rb, line 213
def cucumber_path?(path)
  %r{(^|\/)features|\.feature($|:)}.match?(path)
end
current_branch() click to toggle source
# File lib/geordi/util.rb, line 117
def current_branch
  if testing?
    'master'
  else
    `git rev-parse --abbrev-ref HEAD`.strip
  end
end
decide_texteditor() click to toggle source

try to guess user’s favorite cli text editor

# File lib/geordi/util.rb, line 141
def decide_texteditor
  %w[/usr/bin/editor vi].each do |texteditor|
    if cmd_exists?(texteditor) && texteditor.start_with?('$')
      return ENV[texteditor[1..-1]]
    elsif cmd_exists? texteditor
      return texteditor
    end
  end
end
deploy_targets() click to toggle source
# File lib/geordi/util.rb, line 134
def deploy_targets
  Dir['config/deploy/*'].map do |f|
    File.basename f, '.rb' # Filename without .rb extension
  end
end
file_containing?(file, regex) click to toggle source
# File lib/geordi/util.rb, line 190
def file_containing?(file, regex)
  File.exist?(file) && File.read(file).scan(regex).any?
end
gem_available?(gem) click to toggle source
# File lib/geordi/util.rb, line 170
def gem_available?(gem)
  !!gem_version(gem)
end
gem_major_version(gem) click to toggle source

Get the major version or for the given gem by parsing the Gemfile.lock. Returns nil if the gem is not used.

# File lib/geordi/util.rb, line 176
def gem_major_version(gem)
  gem_version = gem_version(gem)
  gem_version && gem_version.segments[0]
end
gem_version(gem) click to toggle source

Get the version for the given gem by parsing Gemfile.lock. Returns nil if the gem is not used.

# File lib/geordi/util.rb, line 183
def gem_version(gem)
  lock_file = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile))
  spec = lock_file.specs.detect { |spec| spec.name == gem }

  spec && spec.version
end
installing_missing_gems() { || ... } click to toggle source

Geordi commands sometimes require external gems. However, we don’t want all employed gems as runtime dependencies because that would unnecessarily slow down all commands. Thus, we have this handy method here.

# File lib/geordi/util.rb, line 13
def installing_missing_gems
  yield
rescue LoadError => error
  error.message =~ /-- (\S+)\Z/
  Regexp.last_match(1) || raise # could not extract a gem name from the error message, re-raise the error

  gem_name = Regexp.last_match(1).strip.split('/').first
  install_command = 'gem install ' + gem_name

  # install missing gem
  Interaction.warn 'Probably missing gem: ' + gem_name
  Interaction.prompt('Install it now?', 'y', /y|yes/) || Interaction.fail('Missing Gems.')
  Util.run!(install_command, show_cmd: true)

  # retry
  Gem.clear_paths
  Interaction.note 'Retrying ...'
  require gem_name
  retry
end
irb_version() click to toggle source
# File lib/geordi/util.rb, line 198
def irb_version
  version_string = if testing?
    ENV['GEORDI_TESTING_IRB_VERSION']
  else
    `irb --version`[/irb (\d+\.\d+\.\d+)/, 1]
  end

  Gem::Version.new(version_string)
end
is_port_open?(port) click to toggle source
# File lib/geordi/util.rb, line 157
def is_port_open?(port)
  socket = TCPSocket.new('127.0.0.1', port)
  socket.close
  true
rescue Errno::ECONNREFUSED
  false
end
rspec_path?(path) click to toggle source
# File lib/geordi/util.rb, line 217
def rspec_path?(path)
  %r{(^|\/)spec|_spec\.rb($|:)}.match?(path)
end
ruby_version() click to toggle source
# File lib/geordi/util.rb, line 208
def ruby_version
  version_string = testing? ? ENV['GEORDI_TESTING_RUBY_VERSION'] : RUBY_VERSION
  Gem::Version.new(version_string)
end
run!(command, show_cmd: false, confirm: false, fail_message: 'Something went wrong.', exec: false) click to toggle source

Run a command with a clean environment. Print an error message and exit if the command fails.

show_cmd: Whether to print the command confirm: Whether to ask for confirmation before running it fail_message: The text to print on command failure exec: Whether to run the command with ‘exec` instead of `system`

# File lib/geordi/util.rb, line 41
def run!(command, show_cmd: false, confirm: false, fail_message: 'Something went wrong.', exec: false)
  # Disable shell features for arrays https://stackoverflow.com/questions/13338147/ruby-system-method-arguments
  # Conversion: ['ls *', 'some arg'] => ['ls', '*', 'some arg']
  # If you need shell features, you need to pass in a String instead of an array.
  if command.is_a?(Array)
    real_command, *arguments = *command
    command = [real_command.split(' '), arguments].flatten
    show_command = command
  else
    show_command = [command]
  end

  if show_cmd
    # Join with spaces for better readability and copy-pasting
    Interaction.note_cmd show_command.join(' ')
  end

  if confirm
    Interaction.prompt('Run this now?', 'n', /y|yes/) or Interaction.fail('Cancelled.')
  end

  if testing?
    # Join with commas for precise argument distinction
    puts "Util.run!#{' (exec)' if exec} #{show_command.join(', ')}"
  else
    method = exec ? :exec : :system

    # Remove Geordi's Bundler environment when running commands.
    success = if !defined?(Bundler)
      Kernel.public_send(method, *command)
    elsif Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('1.17.3')
      Bundler.with_original_env do
        Kernel.public_send(method, *command)
      end
    else
      method = exec ? :clean_exec : :clean_system
      Bundler.public_send(method, *command)
    end

    # This part will never be reached when `exec` is true
    success || Interaction.fail(fail_message)
  end
end
server_command() click to toggle source
# File lib/geordi/util.rb, line 109
def server_command
  if gem_major_version('rails') == 2
    'script/server ""'
  else
    "#{binstub_or_fallback('rails')} server"
  end
end
staged_changes?() click to toggle source
# File lib/geordi/util.rb, line 125
def staged_changes?
  if testing?
    ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
  else
    statuses = `git status --porcelain`.split("\n")
    statuses.any? { |l| /^[A-Z]/i =~ l }
  end
end
stripped_lines(input_string) click to toggle source

splint lines e.g. read from a file into lines and clean those up

# File lib/geordi/util.rb, line 166
def stripped_lines(input_string)
  input_string.lines.map(&:chomp).map(&:strip)
end
testing?() click to toggle source
# File lib/geordi/util.rb, line 194
def testing?
  !!ENV['GEORDI_TESTING']
end