geordi 2.10.1 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +8 -2
  5. data/CHANGELOG.md +46 -0
  6. data/Gemfile +2 -5
  7. data/Gemfile.lock +10 -10
  8. data/README.md +11 -6
  9. data/Rakefile +6 -10
  10. data/{bin → exe}/b +0 -0
  11. data/{bin → exe}/cap-all +0 -0
  12. data/{bin → exe}/console-for +0 -0
  13. data/{bin → exe}/cuc +0 -0
  14. data/{bin → exe}/cuc-show +0 -0
  15. data/{bin → exe}/cuc-vnc-setup +0 -0
  16. data/{bin → exe}/deploy-to-production +0 -0
  17. data/{bin → exe}/dump-for +0 -0
  18. data/{bin → exe}/dumple +0 -0
  19. data/{bin → exe}/geordi +0 -0
  20. data/{bin → exe}/gitpt +0 -0
  21. data/{bin → exe}/launchy_browser +0 -0
  22. data/{bin → exe}/load-dump +0 -0
  23. data/{bin → exe}/migrate-all +0 -0
  24. data/{bin → exe}/rs +0 -0
  25. data/{bin → exe}/run_tests +0 -0
  26. data/{bin → exe}/shell-for +0 -0
  27. data/{bin → exe}/tests +0 -0
  28. data/geordi.gemspec +23 -20
  29. data/lib/geordi/COMMAND_TEMPLATE +4 -6
  30. data/lib/geordi/capistrano_config.rb +20 -17
  31. data/lib/geordi/chromedriver_updater.rb +9 -10
  32. data/lib/geordi/cli.rb +5 -2
  33. data/lib/geordi/commands/_setup_vnc.rb +23 -23
  34. data/lib/geordi/commands/apache_site.rb +3 -3
  35. data/lib/geordi/commands/bundle_install.rb +3 -3
  36. data/lib/geordi/commands/capistrano.rb +5 -6
  37. data/lib/geordi/commands/chromedriver_update.rb +0 -9
  38. data/lib/geordi/commands/clean.rb +5 -6
  39. data/lib/geordi/commands/commit.rb +0 -1
  40. data/lib/geordi/commands/console.rb +4 -4
  41. data/lib/geordi/commands/create_database_yml.rb +4 -4
  42. data/lib/geordi/commands/create_databases.rb +3 -3
  43. data/lib/geordi/commands/cucumber.rb +25 -25
  44. data/lib/geordi/commands/delete_dumps.rb +12 -12
  45. data/lib/geordi/commands/deploy.rb +27 -28
  46. data/lib/geordi/commands/drop_databases.rb +13 -15
  47. data/lib/geordi/commands/dump.rb +12 -13
  48. data/lib/geordi/commands/eurest.rb +2 -2
  49. data/lib/geordi/commands/firefox.rb +4 -4
  50. data/lib/geordi/commands/migrate.rb +3 -3
  51. data/lib/geordi/commands/png_optimize.rb +15 -14
  52. data/lib/geordi/commands/rake.rb +3 -3
  53. data/lib/geordi/commands/remove_executable_flags.rb +3 -3
  54. data/lib/geordi/commands/rspec.rb +11 -11
  55. data/lib/geordi/commands/security_update.rb +25 -25
  56. data/lib/geordi/commands/server.rb +6 -6
  57. data/lib/geordi/commands/setup.rb +8 -8
  58. data/lib/geordi/commands/shell.rb +3 -3
  59. data/lib/geordi/commands/tests.rb +1 -1
  60. data/lib/geordi/commands/unit.rb +3 -3
  61. data/lib/geordi/commands/update.rb +7 -7
  62. data/lib/geordi/commands/vnc.rb +1 -1
  63. data/lib/geordi/commands/with_rake.rb +3 -3
  64. data/lib/geordi/commands/yarn_install.rb +3 -3
  65. data/lib/geordi/cucumber.rb +35 -36
  66. data/lib/geordi/db_cleaner.rb +40 -41
  67. data/lib/geordi/dump_loader.rb +6 -5
  68. data/lib/geordi/firefox_for_selenium.rb +26 -29
  69. data/lib/geordi/gitpt.rb +14 -15
  70. data/lib/geordi/interaction.rb +2 -6
  71. data/lib/geordi/remote.rb +9 -10
  72. data/lib/geordi/util.rb +28 -25
  73. data/lib/geordi/version.rb +1 -1
  74. metadata +27 -39
  75. data/features/commit.feature +0 -17
  76. data/features/console.feature +0 -7
  77. data/features/cucumber.feature +0 -261
  78. data/features/deploy.feature +0 -66
  79. data/features/dump.feature +0 -34
  80. data/features/firefox.feature +0 -44
  81. data/features/server.feature +0 -31
  82. data/features/setup.feature +0 -11
  83. data/features/shell.feature +0 -78
  84. data/features/support/env.rb +0 -8
  85. data/features/support/step_definitions/aruba_backport_steps.rb +0 -5
  86. data/features/support/step_definitions/miscellaneous_steps.rb +0 -11
@@ -5,7 +5,6 @@ require 'geordi/util'
5
5
 
6
6
  module Geordi
7
7
  class DumpLoader
8
- include Geordi::Interaction
9
8
 
10
9
  def initialize(file)
11
10
  @dump_file = file
@@ -14,7 +13,9 @@ module Geordi
14
13
  def development_database_config
15
14
  require 'yaml'
16
15
 
17
- @config ||= YAML::load(ERB.new(File.read('config/database.yml')).result)
16
+ evaluated_config_file = ERB.new(File.read('config/database.yml')).result
17
+ # Allow aliases and a special set of classes like symbols and time objects
18
+ @config ||= YAML.safe_load(evaluated_config_file, [Symbol, Time], [], true)
18
19
  @config['development']
19
20
  end
20
21
  alias_method :config, :development_database_config
@@ -47,16 +48,16 @@ module Geordi
47
48
  available_dumps = Dir.glob(dumps_glob).sort
48
49
 
49
50
  HighLine.new.choose(*available_dumps) do |menu|
50
- menu.hidden('') { fail 'Abort.' }
51
+ menu.hidden('') { Interaction.fail 'Abort.' }
51
52
  end
52
53
  end
53
54
  end
54
55
 
55
56
  def load
56
- note 'Source file: ' + dump_file
57
+ Interaction.note 'Source file: ' + dump_file
57
58
 
58
59
  source_command = send("#{config['adapter']}_command")
59
- Util.system! source_command, :fail_message => "An error occured loading #{File.basename(dump_file)}"
60
+ Util.system! source_command, fail_message: "An error occured loading #{File.basename(dump_file)}"
60
61
  end
61
62
 
62
63
  end
@@ -1,13 +1,12 @@
1
1
  require 'pathname'
2
2
  require 'tempfile'
3
- require File.expand_path('../interaction', __FILE__)
3
+ require File.expand_path('interaction', __dir__)
4
4
 
5
5
  module Geordi
6
6
  module FirefoxForSelenium
7
- extend Geordi::Interaction
8
7
 
9
8
  FIREFOX_FOR_SELENIUM_BASE_PATH = Pathname.new('~/bin/firefoxes').expand_path
10
- FIREFOX_FOR_SELENIUM_PROFILE_NAME = 'firefox-for-selenium'
9
+ FIREFOX_FOR_SELENIUM_PROFILE_NAME = 'firefox-for-selenium'.freeze
11
10
  FIREFOX_VERSION_FILE = Pathname.new('.firefox-version')
12
11
 
13
12
  def self.install(version)
@@ -17,16 +16,16 @@ module Geordi
17
16
  def self.path_from_config
18
17
  version = FIREFOX_VERSION_FILE.exist? && File.read(FIREFOX_VERSION_FILE).strip
19
18
 
20
- if version and version != 'system'
19
+ if version && (version != 'system')
21
20
  unless FirefoxForSelenium.binary(version).exist?
22
- warn "Firefox #{ version } not found"
21
+ Interaction.warn "Firefox #{version} not found"
23
22
 
24
- note strip_heredoc(<<-INSTRUCTIONS)
23
+ Interaction.note Util.strip_heredoc(<<-INSTRUCTIONS)
25
24
  Install it with
26
- geordi firefox --setup #{ version }
25
+ geordi firefox --setup #{version}
27
26
  INSTRUCTIONS
28
27
 
29
- prompt 'Run tests anyway?', 'n', /y|yes/ or fail 'Cancelled.'
28
+ Interaction.prompt('Run tests anyway?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
30
29
  end
31
30
 
32
31
  path(version)
@@ -37,7 +36,7 @@ module Geordi
37
36
  FIREFOX_FOR_SELENIUM_BASE_PATH.join(version)
38
37
  end
39
38
 
40
- def self.binary(version, name = "firefox")
39
+ def self.binary(version, name = 'firefox')
41
40
  path(version).join(name)
42
41
  end
43
42
 
@@ -46,13 +45,12 @@ module Geordi
46
45
 
47
46
  if path
48
47
  ENV['PATH'] = "#{path}:#{ENV['PATH']}"
49
- note 'Firefox for Selenium set up'
48
+ Interaction.note 'Firefox for Selenium set up'
50
49
  end
51
50
  end
52
51
 
53
52
 
54
53
  class Installer
55
- include Geordi::Interaction
56
54
 
57
55
  def initialize(version)
58
56
  @version = version
@@ -72,7 +70,7 @@ module Geordi
72
70
  private
73
71
 
74
72
  def execute_command(cmd)
75
- system(cmd) or raise "Error while executing command: #{cmd}"
73
+ system(cmd) || raise("Error while executing command: #{cmd}")
76
74
  end
77
75
 
78
76
  def run_firefox_for_selenium(args = '')
@@ -92,13 +90,13 @@ module Geordi
92
90
  end
93
91
 
94
92
  def original_binary
95
- FirefoxForSelenium.binary(@version, "firefox-original")
93
+ FirefoxForSelenium.binary(@version, 'firefox-original')
96
94
  end
97
95
 
98
96
  def say_hello
99
97
  execute_command('clear')
100
98
 
101
- puts strip_heredoc(<<-HELLO)
99
+ puts Util.strip_heredoc(<<-HELLO)
102
100
  Whenever Firefox updates, Selenium breaks. This is annoying. This
103
101
  script will help you create an unchanging version of Firefox for your
104
102
  Selenium tests.
@@ -117,31 +115,31 @@ module Geordi
117
115
  - It will live in #{path}
118
116
  HELLO
119
117
 
120
- prompt "Press ENTER when you're ready to begin."
118
+ Interaction.prompt "Press ENTER when you're ready to begin."
121
119
  end
122
120
 
123
121
  def check_if_run_before
124
122
  if original_binary.exist?
125
- note 'This version seems to be already installed.'
126
- prompt 'Press ENTER to continue anyway or press CTRL+C to abort.'
123
+ Interaction.note 'This version seems to be already installed.'
124
+ Interaction.prompt 'Press ENTER to continue anyway or press CTRL+C to abort.'
127
125
  end
128
126
  end
129
127
 
130
128
  def download_firefox
131
129
  path.mkpath
132
130
 
133
- puts strip_heredoc(<<-INSTRUCTION)
131
+ puts Util.strip_heredoc(<<-INSTRUCTION)
134
132
  Please download an old version of Firefox from: #{download_url}
135
133
  Unpack it with: tar xjf firefox-#{@version}.tar.bz2 -C #{path} --strip-components=1
136
134
  Now #{path.join('firefox')} should be the firefox binary, not a directory.
137
135
  INSTRUCTION
138
- prompt 'Continue?'
136
+ Interaction.prompt 'Continue?'
139
137
 
140
- File.file?(binary) or raise "Could not find #{binary}"
138
+ File.file?(binary) || raise("Could not find #{binary}")
141
139
  end
142
140
 
143
141
  def create_separate_profile
144
- note "Creating a separate profile named '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}' so your own profile will be safe..."
142
+ Interaction.note "Creating a separate profile named '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}' so your own profile will be safe..."
145
143
  # don't use the patched firefox binary for this, we don't want to give
146
144
  # a -p option here
147
145
  execute_command("PATH=#{path}:$PATH firefox -no-remote -CreateProfile #{FIREFOX_FOR_SELENIUM_PROFILE_NAME}")
@@ -149,14 +147,14 @@ module Geordi
149
147
  end
150
148
 
151
149
  def patch_old_firefox
152
- note "Patching #{binary} so it uses the new profile and never re-uses windows from other Firefoxes..."
150
+ Interaction.note "Patching #{binary} so it uses the new profile and never re-uses windows from other Firefoxes..."
153
151
  execute_command("mv #{binary} #{original_binary}")
154
152
  execute_command("mv #{binary}-bin #{original_binary}-bin")
155
153
  patched_binary = Tempfile.new('firefox')
156
- patched_binary.write strip_heredoc(<<-PATCH)
154
+ patched_binary.write Util.strip_heredoc(<<-PATCH)
157
155
  #!/usr/bin/env ruby
158
156
  exec('#{original_binary}', '-no-remote', '-P', '#{FIREFOX_FOR_SELENIUM_PROFILE_NAME}', *ARGV)
159
- PATCH
157
+ PATCH
160
158
  patched_binary.close
161
159
  execute_command("mv #{patched_binary.path} #{binary}")
162
160
  execute_command("chmod +x #{binary}")
@@ -164,7 +162,7 @@ module Geordi
164
162
  end
165
163
 
166
164
  def configure_old_firefox
167
- puts strip_heredoc(<<-INSTRUCTION)
165
+ puts Util.strip_heredoc(<<-INSTRUCTION)
168
166
  You will now have to do some manual configuration.
169
167
 
170
168
  This script will open the patched copy of Firefox when you press ENTER.
@@ -178,15 +176,15 @@ module Geordi
178
176
  Firefox profile
179
177
  INSTRUCTION
180
178
 
181
- prompt 'Will open the patched copy of Firefox now'
179
+ Interaction.prompt 'Will open the patched copy of Firefox now'
182
180
  run_firefox_for_selenium
183
181
  end
184
182
 
185
183
  def kkthxbb
186
- success "Congratulations, you're done!"
184
+ Interaction.success "Congratulations, you're done!"
187
185
 
188
186
  puts
189
- puts strip_heredoc(<<-INSTRUCTION)
187
+ puts Util.strip_heredoc(<<-INSTRUCTION)
190
188
  Your patched copy of Firefox will be used when you run Cucumber using
191
189
  the cucumber script that comes with the geordi gem. If you cannot use
192
190
  `geordi cucumber`, but still need the test browser set up, you can use:
@@ -200,4 +198,3 @@ module Geordi
200
198
  end
201
199
  end
202
200
  end
203
-
@@ -1,11 +1,10 @@
1
1
  class Gitpt
2
- include Geordi::Interaction
3
2
  require 'yaml'
4
3
  require 'highline'
5
4
  require 'tracker_api'
6
5
 
7
- SETTINGS_FILE_NAME = '.gitpt'
8
- PROJECT_IDS_FILE_NAME = '.pt_project_id'
6
+ SETTINGS_FILE_NAME = '.gitpt'.freeze
7
+ PROJECT_IDS_FILE_NAME = '.pt_project_id'.freeze
9
8
 
10
9
  def initialize
11
10
  self.highline = HighLine.new
@@ -13,7 +12,7 @@ class Gitpt
13
12
  end
14
13
 
15
14
  def run(git_args)
16
- warn <<-WARNING if !Geordi::Util.staged_changes?
15
+ Geordi::Interaction.warn <<-WARNING unless Geordi::Util.staged_changes?
17
16
  No staged changes. Will create an empty commit.
18
17
  WARNING
19
18
 
@@ -30,16 +29,16 @@ No staged changes. Will create an empty commit.
30
29
  def read_settings
31
30
  file_path = File.join(ENV['HOME'], SETTINGS_FILE_NAME)
32
31
 
33
- unless File.exists?(file_path)
32
+ unless File.exist?(file_path)
34
33
  highline.say HighLine::RESET
35
34
  highline.say "Welcome to #{bold 'gitpt'}.\n\n"
36
35
 
37
36
  highline.say highlight('Your settings are missing or invalid.')
38
37
  highline.say "Please configure your Pivotal Tracker access.\n\n"
39
- token = highline.ask bold("Your API key:") + " "
38
+ token = highline.ask bold('Your API key:') + ' '
40
39
  highline.say "\n"
41
40
 
42
- settings = { :token => token }
41
+ settings = { token: token }
43
42
  File.open(file_path, 'w') do |file|
44
43
  file.write settings.to_yaml
45
44
  end
@@ -49,7 +48,7 @@ No staged changes. Will create an empty commit.
49
48
  end
50
49
 
51
50
  def build_client(settings)
52
- TrackerApi::Client.new(:token => settings.fetch(:token))
51
+ TrackerApi::Client.new(token: settings.fetch(:token))
53
52
  end
54
53
 
55
54
  def load_projects
@@ -60,14 +59,14 @@ No staged changes. Will create an empty commit.
60
59
  def read_project_ids
61
60
  file_path = PROJECT_IDS_FILE_NAME
62
61
 
63
- if File.exists?(file_path)
62
+ if File.exist?(file_path)
64
63
  project_ids = File.read('.pt_project_id').split(/[\s]+/).map(&:to_i)
65
64
  end
66
65
 
67
- if project_ids and project_ids.size > 0
66
+ if project_ids && (project_ids.size > 0)
68
67
  project_ids
69
68
  else
70
- warn "Sorry, I could not find a project ID in #{file_path} :("
69
+ Geordi::Interaction.warn "Sorry, I could not find a project ID in #{file_path} :("
71
70
  puts
72
71
 
73
72
  puts "Please put at least one Pivotal Tracker project id into #{file_path} in this directory."
@@ -79,19 +78,19 @@ No staged changes. Will create an empty commit.
79
78
  def applicable_stories
80
79
  projects = load_projects
81
80
  projects.collect do |project|
82
- project.stories(:filter => 'state:started,finished,rejected')
81
+ project.stories(filter: 'state:started,finished,rejected')
83
82
  end.flatten
84
83
  end
85
84
 
86
85
  def choose_story
87
86
  if Geordi::Util.testing?
88
- return OpenStruct.new(:id => 12, :name => 'Test Story')
87
+ return OpenStruct.new(id: 12, name: 'Test Story')
89
88
  end
90
89
 
91
90
  loading_message = 'Connecting to Pivotal Tracker ...'
92
91
  print(loading_message)
93
92
  stories = applicable_stories
94
- reset_loading_message = "\r#{ ' ' * (loading_message.length + stories.length)}\r"
93
+ reset_loading_message = "\r#{' ' * (loading_message.length + stories.length)}\r"
95
94
 
96
95
  highline.choose do |menu|
97
96
  menu.header = 'Choose a story'
@@ -126,7 +125,7 @@ No staged changes. Will create an empty commit.
126
125
 
127
126
  def create_commit(message, *git_args)
128
127
  extra = highline.ask("\nAdd an optional message").strip
129
- message << ' - ' << extra if (extra != "")
128
+ message << ' - ' << extra if extra != ''
130
129
 
131
130
  Geordi::Util.system! 'git', 'commit', '--allow-empty', '-m', message, *git_args
132
131
  end
@@ -3,6 +3,8 @@
3
3
  module Geordi
4
4
  module Interaction
5
5
 
6
+ module_function
7
+
6
8
  # Start your command by `announce`-ing what you're about to do
7
9
  def announce(text)
8
10
  message = "\n# #{text}"
@@ -42,12 +44,6 @@ module Geordi
42
44
  puts "\e[32m#{message}\e[0m" # green
43
45
  end
44
46
 
45
- def strip_heredoc(string)
46
- leading_whitespace = (string.match(/\A( +)[^ ]+/) || [])[1]
47
- string.gsub! /^#{leading_whitespace}/, '' if leading_whitespace
48
- string
49
- end
50
-
51
47
  # Returns the user's input.
52
48
  # If agreement_regex is given, returns whether the input matches the regex.
53
49
  def prompt(text, default = nil, agreement_regex = nil)
@@ -6,9 +6,8 @@ require 'pathname'
6
6
 
7
7
  module Geordi
8
8
  class Remote
9
- include Geordi::Interaction
10
9
 
11
- REMOTE_DUMP_PATH = '~/dumps/dump_for_download.dump'
10
+ REMOTE_DUMP_PATH = '~/dumps/dump_for_download.dump'.freeze
12
11
 
13
12
  def initialize(stage)
14
13
  @stage = stage
@@ -34,8 +33,8 @@ module Geordi
34
33
  def dump(options = {})
35
34
  # Generate dump on the server
36
35
  shell options.merge({
37
- :remote_command => "dumple #{@config.env} --for_download",
38
- :select_server => nil # Dump must be generated on the primary server
36
+ remote_command: "dumple #{@config.env} --for_download",
37
+ select_server: nil, # Dump must be generated on the primary server
39
38
  })
40
39
 
41
40
  destination_directory = File.join(@config.root, 'tmp')
@@ -43,17 +42,17 @@ module Geordi
43
42
  destination_path = File.join(destination_directory, "#{@stage}.dump")
44
43
  relative_destination = Pathname.new(destination_path).relative_path_from Pathname.new(@config.root)
45
44
 
46
- note "Downloading remote dump to #{relative_destination} ..."
45
+ Interaction.note "Downloading remote dump to #{relative_destination} ..."
47
46
  server = @config.primary_server
48
- Util.system! "scp -C #{ @config.user(server) }@#{ server }:#{REMOTE_DUMP_PATH} #{destination_path}"
47
+ Util.system! "scp -C #{@config.user(server)}@#{server}:#{REMOTE_DUMP_PATH} #{destination_path}"
49
48
 
50
- success "Dumped the #{@stage} database to #{relative_destination}."
49
+ Interaction.success "Dumped the #{@stage} database to #{relative_destination}."
51
50
 
52
51
  destination_path
53
52
  end
54
53
 
55
54
  def console(options = {})
56
- shell(options.merge :remote_command => Util.console_command(@config.env))
55
+ shell(options.merge(remote_command: Util.console_command(@config.env)))
57
56
  end
58
57
 
59
58
  def shell(options = {})
@@ -62,8 +61,8 @@ module Geordi
62
61
  remote_command = "cd #{@config.remote_root} && #{@config.shell}"
63
62
  remote_command << " -c '#{options[:remote_command]}'" if options[:remote_command]
64
63
 
65
- note 'Connecting to ' + server.to_s
66
- Util.system! 'ssh', "#{ @config.user(server) }@#{ server }", '-t', remote_command
64
+ Interaction.note 'Connecting to ' + server.to_s
65
+ Util.system! 'ssh', "#{@config.user(server)}@#{server}", '-t', remote_command
67
66
  end
68
67
 
69
68
  end
@@ -4,29 +4,28 @@ require 'socket'
4
4
  module Geordi
5
5
  class Util
6
6
  class << self
7
- include Geordi::Interaction
8
7
 
9
8
  # Geordi commands sometimes require external gems. However, we don't want
10
9
  # all employed gems as runtime dependencies because that would
11
10
  # unnecessarily slow down all commands.
12
11
  # Thus, we have this handy method here.
13
- def installing_missing_gems(&block)
12
+ def installing_missing_gems
14
13
  yield
15
14
  rescue LoadError => error
16
15
  error.message =~ /-- (\S+)\Z/
17
- $1 or raise # could not extract a gem name from the error message, re-raise the error
16
+ Regexp.last_match(1) || raise # could not extract a gem name from the error message, re-raise the error
18
17
 
19
- gem_name = $1.strip.split('/').first
18
+ gem_name = Regexp.last_match(1).strip.split('/').first
20
19
  install_command = 'gem install ' + gem_name
21
20
 
22
21
  # install missing gem
23
- warn 'Probably missing gem: ' + gem_name
24
- prompt('Install it now?', 'y', /y|yes/) or fail 'Missing Gems.'
25
- system! install_command, :show_cmd => true
22
+ Interaction.warn 'Probably missing gem: ' + gem_name
23
+ Interaction.prompt('Install it now?', 'y', /y|yes/) || Interaction.fail('Missing Gems.')
24
+ system! install_command, show_cmd: true
26
25
 
27
26
  # retry
28
27
  Gem.clear_paths
29
- note 'Retrying ...'
28
+ Interaction.note 'Retrying ...'
30
29
  require gem_name
31
30
  retry
32
31
  end
@@ -39,27 +38,27 @@ module Geordi
39
38
  # @option fail_message: The text to print on command failure
40
39
  def system!(*commands)
41
40
  options = commands.last.is_a?(Hash) ? commands.pop : {}
42
- note_cmd commands.join(' ') if options[:show_cmd]
41
+ Interaction.note_cmd commands.join(' ') if options[:show_cmd]
43
42
 
44
43
  if options[:confirm]
45
- prompt('Run this now?', 'n', /y|yes/) or fail('Cancelled.')
44
+ Interaction.prompt('Run this now?', 'n', /y|yes/) or Interaction.fail('Cancelled.')
46
45
  end
47
46
 
48
47
  if testing?
49
- puts "Util.system! #{ commands.join ', ' }"
48
+ puts "Util.system! #{commands.join ', '}"
50
49
  else
51
50
  # Remove Geordi's Bundler environment when running commands.
52
51
  success = if !defined?(Bundler)
53
52
  system(*commands)
54
53
  elsif Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('2.1.2')
55
- Bundler.with_unbundled_env do
54
+ Bundler.with_original_env do
56
55
  system(*commands)
57
56
  end
58
57
  else
59
58
  Bundler.clean_system(*commands)
60
59
  end
61
60
 
62
- success or fail(options[:fail_message] || 'Something went wrong.')
61
+ success || Interaction.fail(options[:fail_message] || 'Something went wrong.')
63
62
  end
64
63
  end
65
64
 
@@ -94,7 +93,7 @@ module Geordi
94
93
  ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
95
94
  else
96
95
  statuses = `git status --porcelain`.split("\n")
97
- statuses.any? { |l| l.start_with? 'A' }
96
+ statuses.any? { |l| l.start_with? /[A-Z]/i }
98
97
  end
99
98
  end
100
99
 
@@ -107,7 +106,7 @@ module Geordi
107
106
  # try to guess user's favorite cli text editor
108
107
  def decide_texteditor
109
108
  %w[/usr/bin/editor vi].each do |texteditor|
110
- if cmd_exists? texteditor and texteditor.start_with? '$'
109
+ if cmd_exists?(texteditor) && texteditor.start_with?('$')
111
110
  return ENV[texteditor[1..-1]]
112
111
  elsif cmd_exists? texteditor
113
112
  return texteditor
@@ -116,19 +115,17 @@ module Geordi
116
115
  end
117
116
 
118
117
  # check if given cmd is executable. Absolute path or command in $PATH allowed.
119
- def cmd_exists? cmd
118
+ def cmd_exists?(cmd)
120
119
  system("which #{cmd} > /dev/null")
121
- return $?.exitstatus.zero?
120
+ $?.exitstatus.zero?
122
121
  end
123
122
 
124
123
  def is_port_open?(port)
125
- begin
126
- socket = TCPSocket.new('127.0.0.1', port)
127
- socket.close
128
- return true
129
- rescue Errno::ECONNREFUSED
130
- return false
131
- end
124
+ socket = TCPSocket.new('127.0.0.1', port)
125
+ socket.close
126
+ true
127
+ rescue Errno::ECONNREFUSED
128
+ false
132
129
  end
133
130
 
134
131
  # splint lines e.g. read from a file into lines and clean those up
@@ -162,13 +159,19 @@ module Geordi
162
159
  end
163
160
 
164
161
  def file_containing?(file, regex)
165
- File.exists?(file) and File.read(file).scan(regex).any?
162
+ File.exist?(file) && File.read(file).scan(regex).any?
166
163
  end
167
164
 
168
165
  def testing?
169
166
  !!ENV['GEORDI_TESTING']
170
167
  end
171
168
 
169
+ def strip_heredoc(string)
170
+ leading_whitespace = (string.match(/\A( +)[^ ]+/) || [])[1]
171
+ string.gsub! /^#{leading_whitespace}/, '' if leading_whitespace
172
+ string
173
+ end
174
+
172
175
  private
173
176
 
174
177
  def bundle_list