geordi 2.10.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +1 -0
 - data/.ruby-version +1 -1
 - data/.travis.yml +8 -2
 - data/CHANGELOG.md +46 -0
 - data/Gemfile +2 -5
 - data/Gemfile.lock +10 -10
 - data/README.md +11 -6
 - data/Rakefile +6 -10
 - data/{bin → exe}/b +0 -0
 - data/{bin → exe}/cap-all +0 -0
 - data/{bin → exe}/console-for +0 -0
 - data/{bin → exe}/cuc +0 -0
 - data/{bin → exe}/cuc-show +0 -0
 - data/{bin → exe}/cuc-vnc-setup +0 -0
 - data/{bin → exe}/deploy-to-production +0 -0
 - data/{bin → exe}/dump-for +0 -0
 - data/{bin → exe}/dumple +0 -0
 - data/{bin → exe}/geordi +0 -0
 - data/{bin → exe}/gitpt +0 -0
 - data/{bin → exe}/launchy_browser +0 -0
 - data/{bin → exe}/load-dump +0 -0
 - data/{bin → exe}/migrate-all +0 -0
 - data/{bin → exe}/rs +0 -0
 - data/{bin → exe}/run_tests +0 -0
 - data/{bin → exe}/shell-for +0 -0
 - data/{bin → exe}/tests +0 -0
 - data/geordi.gemspec +23 -20
 - data/lib/geordi/COMMAND_TEMPLATE +4 -6
 - data/lib/geordi/capistrano_config.rb +20 -17
 - data/lib/geordi/chromedriver_updater.rb +9 -10
 - data/lib/geordi/cli.rb +5 -2
 - data/lib/geordi/commands/_setup_vnc.rb +23 -23
 - data/lib/geordi/commands/apache_site.rb +3 -3
 - data/lib/geordi/commands/bundle_install.rb +3 -3
 - data/lib/geordi/commands/capistrano.rb +5 -6
 - data/lib/geordi/commands/chromedriver_update.rb +0 -9
 - data/lib/geordi/commands/clean.rb +5 -6
 - data/lib/geordi/commands/commit.rb +0 -1
 - data/lib/geordi/commands/console.rb +4 -4
 - data/lib/geordi/commands/create_database_yml.rb +4 -4
 - data/lib/geordi/commands/create_databases.rb +3 -3
 - data/lib/geordi/commands/cucumber.rb +25 -25
 - data/lib/geordi/commands/delete_dumps.rb +12 -12
 - data/lib/geordi/commands/deploy.rb +27 -28
 - data/lib/geordi/commands/drop_databases.rb +13 -15
 - data/lib/geordi/commands/dump.rb +12 -13
 - data/lib/geordi/commands/eurest.rb +2 -2
 - data/lib/geordi/commands/firefox.rb +4 -4
 - data/lib/geordi/commands/migrate.rb +3 -3
 - data/lib/geordi/commands/png_optimize.rb +15 -14
 - data/lib/geordi/commands/rake.rb +3 -3
 - data/lib/geordi/commands/remove_executable_flags.rb +3 -3
 - data/lib/geordi/commands/rspec.rb +11 -11
 - data/lib/geordi/commands/security_update.rb +25 -25
 - data/lib/geordi/commands/server.rb +6 -6
 - data/lib/geordi/commands/setup.rb +8 -8
 - data/lib/geordi/commands/shell.rb +3 -3
 - data/lib/geordi/commands/tests.rb +1 -1
 - data/lib/geordi/commands/unit.rb +3 -3
 - data/lib/geordi/commands/update.rb +7 -7
 - data/lib/geordi/commands/vnc.rb +1 -1
 - data/lib/geordi/commands/with_rake.rb +3 -3
 - data/lib/geordi/commands/yarn_install.rb +3 -3
 - data/lib/geordi/cucumber.rb +35 -36
 - data/lib/geordi/db_cleaner.rb +40 -41
 - data/lib/geordi/dump_loader.rb +6 -5
 - data/lib/geordi/firefox_for_selenium.rb +26 -29
 - data/lib/geordi/gitpt.rb +14 -15
 - data/lib/geordi/interaction.rb +2 -6
 - data/lib/geordi/remote.rb +9 -10
 - data/lib/geordi/util.rb +28 -25
 - data/lib/geordi/version.rb +1 -1
 - metadata +27 -39
 - data/features/commit.feature +0 -17
 - data/features/console.feature +0 -7
 - data/features/cucumber.feature +0 -261
 - data/features/deploy.feature +0 -66
 - data/features/dump.feature +0 -34
 - data/features/firefox.feature +0 -44
 - data/features/server.feature +0 -31
 - data/features/setup.feature +0 -11
 - data/features/shell.feature +0 -78
 - data/features/support/env.rb +0 -8
 - data/features/support/step_definitions/aruba_backport_steps.rb +0 -5
 - data/features/support/step_definitions/miscellaneous_steps.rb +0 -11
 
    
        data/lib/geordi/dump_loader.rb
    CHANGED
    
    | 
         @@ -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 
     | 
    
         
            -
                   
     | 
| 
      
 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, : 
     | 
| 
      
 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(' 
     | 
| 
      
 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  
     | 
| 
      
 19 
     | 
    
         
            +
                  if version && (version != 'system')
         
     | 
| 
       21 
20 
     | 
    
         
             
                    unless FirefoxForSelenium.binary(version).exist?
         
     | 
| 
       22 
     | 
    
         
            -
                      warn "Firefox #{ 
     | 
| 
      
 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 #{ 
     | 
| 
      
 25 
     | 
    
         
            +
                        geordi firefox --setup #{version}
         
     | 
| 
       27 
26 
     | 
    
         
             
                      INSTRUCTIONS
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
                      prompt 
     | 
| 
      
 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 =  
     | 
| 
      
 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)  
     | 
| 
      
 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,  
     | 
| 
      
 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)  
     | 
| 
      
 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 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            -
             
     | 
    
        data/lib/geordi/gitpt.rb
    CHANGED
    
    | 
         @@ -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  
     | 
| 
      
 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. 
     | 
| 
      
 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( 
     | 
| 
      
 38 
     | 
    
         
            +
                  token = highline.ask bold('Your API key:') + ' '
         
     | 
| 
       40 
39 
     | 
    
         
             
                  highline.say "\n"
         
     | 
| 
       41 
40 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  settings = { : 
     | 
| 
      
 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(: 
     | 
| 
      
 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. 
     | 
| 
      
 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  
     | 
| 
      
 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(: 
     | 
| 
      
 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(: 
     | 
| 
      
 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#{ 
     | 
| 
      
 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  
     | 
| 
      
 128 
     | 
    
         
            +
                message << ' - ' << extra if extra != ''
         
     | 
| 
       130 
129 
     | 
    
         | 
| 
       131 
130 
     | 
    
         
             
                Geordi::Util.system! 'git', 'commit', '--allow-empty', '-m', message, *git_args
         
     | 
| 
       132 
131 
     | 
    
         
             
              end
         
     | 
    
        data/lib/geordi/interaction.rb
    CHANGED
    
    | 
         @@ -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)
         
     | 
    
        data/lib/geordi/remote.rb
    CHANGED
    
    | 
         @@ -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 
     | 
    
         
            -
                    : 
     | 
| 
       38 
     | 
    
         
            -
                    : 
     | 
| 
      
 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 #{ 
     | 
| 
      
 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 
     | 
| 
      
 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', "#{ 
     | 
| 
      
 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
         
     | 
    
        data/lib/geordi/util.rb
    CHANGED
    
    | 
         @@ -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 
     | 
| 
      
 12 
     | 
    
         
            +
                  def installing_missing_gems
         
     | 
| 
       14 
13 
     | 
    
         
             
                    yield
         
     | 
| 
       15 
14 
     | 
    
         
             
                  rescue LoadError => error
         
     | 
| 
       16 
15 
     | 
    
         
             
                    error.message =~ /-- (\S+)\Z/
         
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
      
 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 =  
     | 
| 
      
 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/)  
     | 
| 
       25 
     | 
    
         
            -
                    system! install_command, : 
     | 
| 
      
 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! #{ 
     | 
| 
      
 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. 
     | 
| 
      
 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  
     | 
| 
      
 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?  
     | 
| 
      
 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? 
     | 
| 
      
 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? 
     | 
| 
      
 118 
     | 
    
         
            +
                  def cmd_exists?(cmd)
         
     | 
| 
       120 
119 
     | 
    
         
             
                    system("which #{cmd} > /dev/null")
         
     | 
| 
       121 
     | 
    
         
            -
                     
     | 
| 
      
 120 
     | 
    
         
            +
                    $?.exitstatus.zero?
         
     | 
| 
       122 
121 
     | 
    
         
             
                  end
         
     | 
| 
       123 
122 
     | 
    
         | 
| 
       124 
123 
     | 
    
         
             
                  def is_port_open?(port)
         
     | 
| 
       125 
     | 
    
         
            -
                     
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
                     
     | 
| 
       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. 
     | 
| 
      
 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
         
     |