Class: Geordi::Util

Inherits:
Object
  • Object
show all
Extended by:
Interaction
Defined in:
lib/geordi/util.rb

Class Method Summary collapse

Methods included from Interaction

announce, fail, note, note_cmd, prompt, strip_heredoc, success, warn

Class Method Details

.cmd_exists?(cmd) ⇒ Boolean

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

Returns:

  • (Boolean)


119
120
121
122
# File 'lib/geordi/util.rb', line 119

def cmd_exists?(cmd)
  system("which #{cmd} > /dev/null")
  $CHILD_STATUS.exitstatus.zero?
end

.console_command(environment) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/geordi/util.rb', line 66

def console_command(environment)
  if gem_major_version('rails') == 2
    'script/console ' + environment
  elsif gem_major_version('rails') == 3
    'bundle exec rails console ' + environment
  else
    "bundle exec rails console -e #{environment}"
  end
end

.current_branchObject



84
85
86
87
88
89
90
# File 'lib/geordi/util.rb', line 84

def current_branch
  if testing?
    'master'
  else
    `git rev-parse --abbrev-ref HEAD`.strip
  end
end

.decide_texteditorObject

try to guess user’s favorite cli text editor



108
109
110
111
112
113
114
115
116
# File 'lib/geordi/util.rb', line 108

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_targetsObject



101
102
103
104
105
# File 'lib/geordi/util.rb', line 101

def deploy_targets
  Dir['config/deploy/*'].map do |f|
    File.basename f, '.rb' # Filename without .rb extension
  end
end

.file_containing?(file, regex) ⇒ Boolean

Returns:

  • (Boolean)


162
163
164
# File 'lib/geordi/util.rb', line 162

def file_containing?(file, regex)
  File.exist?(file) && File.read(file).scan(regex).any?
end

.gem_available?(gem) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/geordi/util.rb', line 137

def gem_available?(gem)
  !!gem_version(gem)
end

.gem_major_version(gem) ⇒ Object

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



143
144
145
146
# File 'lib/geordi/util.rb', line 143

def gem_major_version(gem)
  gem_version = gem_version(gem)
  gem_version && gem_version.segments[0]
end

.gem_version(gem) ⇒ Object

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



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/geordi/util.rb', line 150

def gem_version(gem)
  # Lines look like `* will_paginate (2.3.15)` or `railslts-version (2.3.18.16 7f51cc7)`
  bundle_list.split("\n").each do |line|
    matches = line.match(/\* #{gem} \(([\d\.]+)/)
    next if matches.nil? || matches[1].nil?

    return Gem::Version.new(matches[1])
  end

  nil
end

.installing_missing_gemsObject

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.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 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
  warn 'Probably missing gem: ' + gem_name
  prompt('Install it now?', 'y', /y|yes/) || raise('Missing Gems.')
  system! install_command, show_cmd: true

  # retry
  Gem.clear_paths
  note 'Retrying ...'
  require gem_name
  retry
end

.is_port_open?(port) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
127
128
129
130
# File 'lib/geordi/util.rb', line 124

def is_port_open?(port)
  socket = TCPSocket.new('127.0.0.1', port)
  socket.close
  true
rescue Errno::ECONNREFUSED
  false
end

.server_commandObject



76
77
78
79
80
81
82
# File 'lib/geordi/util.rb', line 76

def server_command
  if gem_major_version('rails') == 2
    'script/server ""'
  else
    'bundle exec rails server'
  end
end

.staged_changes?Boolean

Returns:

  • (Boolean)


92
93
94
95
96
97
98
99
# File 'lib/geordi/util.rb', line 92

def staged_changes?
  if testing?
    ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
  else
    statuses = `git status --porcelain`.split("\n")
    statuses.any? { |l| l.start_with? /[A-Z]/i }
  end
end

.stripped_lines(input_string) ⇒ Object

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



133
134
135
# File 'lib/geordi/util.rb', line 133

def stripped_lines(input_string)
  input_string.lines.map(&:chomp).map(&:strip)
end

.system!(*commands) ⇒ Object

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

Parameters:

  • show_cmd: (Hash)

    a customizable set of options

  • confirm: (Hash)

    a customizable set of options

  • fail_message: (Hash)

    a customizable set of options



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/geordi/util.rb', line 40

def system!(*commands)
  options = commands.last.is_a?(Hash) ? commands.pop : {}
  note_cmd commands.join(' ') if options[:show_cmd]

  if options[:confirm]
    prompt('Run this now?', 'n', /y|yes/) || raise('Cancelled.')
  end

  if testing?
    puts "Util.system! #{commands.join ', '}"
  else
    # Remove Geordi's Bundler environment when running commands.
    success = if !defined?(Bundler)
      system(*commands)
    elsif Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.1.2')
      Bundler.with_original_env do
        system(*commands)
      end
    else
      Bundler.clean_system(*commands)
    end

    success || raise(options[:fail_message] || 'Something went wrong.')
  end
end

.testing?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/geordi/util.rb', line 166

def testing?
  !!ENV['GEORDI_TESTING']
end