stairs 0.4.0 → 0.4.1
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/.rubocop.yml +4 -0
- data/Guardfile +1 -1
- data/README.md +8 -16
- data/Rakefile +4 -2
- data/lib/stairs/env_adapters/dotenv.rb +4 -0
- data/lib/stairs/env_adapters/rbenv.rb +4 -0
- data/lib/stairs/env_adapters/rvm.rb +4 -0
- data/lib/stairs/step.rb +21 -5
- data/lib/stairs/util/file_mutation.rb +12 -2
- data/lib/stairs/version.rb +1 -1
- data/spec/lib/stairs/env_adapters/dotenv_spec.rb +11 -1
- data/spec/lib/stairs/env_adapters/rbenv_spec.rb +11 -1
- data/spec/lib/stairs/env_adapters/rvm_spec.rb +11 -1
- data/spec/lib/stairs/step_spec.rb +72 -2
- data/spec/lib/stairs/util/file_mutation_spec.rb +50 -4
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: cb094a690ad438125715b25683b2d11f176432ed
         | 
| 4 | 
            +
              data.tar.gz: d3eb3604d83427287293ecac50daf8ed6a5ea841
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 54186ff0a046b2dcbe68fb116a6915ffb7cc350105c0e633e62ff05d37460f705a2c08334c542195ddc1a7b1cfdfb14613aaf60e18f2839f5a7d66d3b381f07c
         | 
| 7 | 
            +
              data.tar.gz: 6c5e729f8a7e3b8df3c5f5b0fe9c20264c9b95e688ba43e435f747cafade1426084cb81029ea59f3b3f3ad570154c43c68b3ac990589bf9d00b4c4e3e343cac4
         | 
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -32,6 +32,10 @@ SpecialGlobalVars: | |
| 32 32 | 
             
            CollectionMethods:
         | 
| 33 33 | 
             
              Enabled: false
         | 
| 34 34 |  | 
| 35 | 
            +
            # Cuz we don't use any fancy characters anyway
         | 
| 36 | 
            +
            Encoding:
         | 
| 37 | 
            +
              Enabled: false
         | 
| 38 | 
            +
             | 
| 35 39 | 
             
            # I just don't care so much about clean specs.. Like short methods and short lines
         | 
| 36 40 | 
             
            AllCops:
         | 
| 37 41 | 
             
              Excludes:
         | 
    
        data/Guardfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -43,8 +43,7 @@ $ rake newb | |
| 43 43 |  | 
| 44 44 | 
             
            ## Defining scripts
         | 
| 45 45 |  | 
| 46 | 
            -
            A script composes many steps that setup a project. | 
| 47 | 
            -
            not yet implemented.
         | 
| 46 | 
            +
            A script composes many steps that setup a project.
         | 
| 48 47 |  | 
| 49 48 | 
             
            ```ruby
         | 
| 50 49 | 
             
            bundle
         | 
| @@ -55,7 +54,7 @@ setup :s3 | |
| 55 54 | 
             
            setup :zencoder, required: false
         | 
| 56 55 |  | 
| 57 56 | 
             
            setup :misc do
         | 
| 58 | 
            -
              env "CHECK_IT", provide | 
| 57 | 
            +
              env "CHECK_IT", provide("Cool check it value")
         | 
| 59 58 | 
             
            end
         | 
| 60 59 |  | 
| 61 60 | 
             
            rake "db:setup"
         | 
| @@ -65,38 +64,30 @@ finish "Just run rails s and sidekiq to get rolling!" | |
| 65 64 |  | 
| 66 65 | 
             
            ### Example CLI
         | 
| 67 66 |  | 
| 68 | 
            -
            Given the above script, the CLI might look like this. | 
| 69 | 
            -
            is desired future functionality (bundle/db tasks, spacing, last words).
         | 
| 67 | 
            +
            Given the above script, the CLI might look like this.
         | 
| 70 68 |  | 
| 71 69 | 
             
            ```
         | 
| 72 70 | 
             
            $ rake newb
         | 
| 73 71 | 
             
            Looks like you're using rbenv to manage environment variables. Is this correct? (Y/N): Y
         | 
| 74 | 
            -
             | 
| 75 72 | 
             
            = Running script setup.rb
         | 
| 76 | 
            -
             | 
| 77 73 | 
             
            == Running bundle
         | 
| 78 74 | 
             
            ...
         | 
| 79 75 | 
             
            == Completed bundle
         | 
| 80 | 
            -
             | 
| 81 76 | 
             
            == Running S3
         | 
| 82 77 | 
             
            AWS access key: 39u39d9u291
         | 
| 83 78 | 
             
            AWS secret: 19jd920i10is0i01i0s01ks0kfknkje
         | 
| 84 79 | 
             
            Do you have an existing bucket? (Y/N): Y
         | 
| 85 80 | 
             
            Bucket name (leave blank for app-dev): my-cool-bucket
         | 
| 86 81 | 
             
            == Completed S3
         | 
| 87 | 
            -
             | 
| 88 82 | 
             
            == Starting Zencoder
         | 
| 89 83 | 
             
            This step is optional, would you like to perform it? (Y/N): N
         | 
| 90 84 | 
             
            == Completed Zencoder
         | 
| 91 | 
            -
             | 
| 92 85 | 
             
            == Starting Misc
         | 
| 93 86 | 
             
            Cool check it value: w00t
         | 
| 94 87 | 
             
            == Completed Misc
         | 
| 95 | 
            -
             | 
| 96 88 | 
             
            == Running db:setup
         | 
| 97 89 | 
             
            ...
         | 
| 98 90 | 
             
            == Completed db:setup
         | 
| 99 | 
            -
             | 
| 100 91 | 
             
            == All done!
         | 
| 101 92 | 
             
            Run rails s and sidekiq to get rolling!
         | 
| 102 93 | 
             
            ```
         | 
| @@ -106,7 +97,7 @@ Run rails s and sidekiq to get rolling! | |
| 106 97 | 
             
            ### Collecting values
         | 
| 107 98 | 
             
            ```ruby
         | 
| 108 99 | 
             
            value = provide "Something"
         | 
| 109 | 
            -
            value = provide "Another", required: false | 
| 100 | 
            +
            value = provide "Another", required: false
         | 
| 110 101 | 
             
            provide "More", default: "a-default"
         | 
| 111 102 | 
             
            ```
         | 
| 112 103 |  | 
| @@ -158,6 +149,7 @@ end | |
| 158 149 | 
             
            #### Using predefined steps (aka plugins)
         | 
| 159 150 | 
             
            ```ruby
         | 
| 160 151 | 
             
            setup :s3
         | 
| 152 | 
            +
            setup :facebook, required: false
         | 
| 161 153 | 
             
            ```
         | 
| 162 154 |  | 
| 163 155 | 
             
            ## Plugins for common setups
         | 
| @@ -175,9 +167,9 @@ setup :s3 | |
| 175 167 |  | 
| 176 168 | 
             
            ### Defining custom plugins
         | 
| 177 169 |  | 
| 178 | 
            -
            Steps inherit from `Stairs::Step`, have a title, | 
| 179 | 
            -
            implement the `run` method. See those included and in the | 
| 180 | 
            -
            extension gems for examples.
         | 
| 170 | 
            +
            Steps inherit from `Stairs::Step` and live in `Stairs::Steps`, have a title,
         | 
| 171 | 
            +
            description, and implement the `run` method. See those included and in the
         | 
| 172 | 
            +
            various extension gems for examples.
         | 
| 181 173 |  | 
| 182 174 | 
             
            ## Contributing
         | 
| 183 175 |  | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/stairs/step.rb
    CHANGED
    
    | @@ -1,8 +1,14 @@ | |
| 1 1 | 
             
            module Stairs
         | 
| 2 2 | 
             
              class Step
         | 
| 3 | 
            +
                attr_reader :options
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(options={})
         | 
| 6 | 
            +
                  @options = options.reverse_merge required: true
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 3 9 | 
             
                def run!
         | 
| 4 10 | 
             
                  stairs_info "== Running #{step_title}"
         | 
| 5 | 
            -
                  run
         | 
| 11 | 
            +
                  run if run_step?
         | 
| 6 12 | 
             
                  stairs_info "== Completed #{step_title}"
         | 
| 7 13 | 
             
                end
         | 
| 8 14 |  | 
| @@ -58,7 +64,12 @@ module Stairs | |
| 58 64 | 
             
                # Set or update env var
         | 
| 59 65 | 
             
                def env(name, value)
         | 
| 60 66 | 
             
                  ENV[name] = value
         | 
| 61 | 
            -
             | 
| 67 | 
            +
             | 
| 68 | 
            +
                  if value
         | 
| 69 | 
            +
                    Stairs.configuration.env_adapter.set name, value
         | 
| 70 | 
            +
                  else
         | 
| 71 | 
            +
                    Stairs.configuration.env_adapter.unset name
         | 
| 72 | 
            +
                  end
         | 
| 62 73 | 
             
                end
         | 
| 63 74 |  | 
| 64 75 | 
             
                # Replace contents of file
         | 
| @@ -74,15 +85,15 @@ module Stairs | |
| 74 85 | 
             
                # Embed a step where step_name is a symbol that can be resolved to a class
         | 
| 75 86 | 
             
                # in Stairs::Steps or a block is provided to be executed in an instance
         | 
| 76 87 | 
             
                # of Step
         | 
| 77 | 
            -
                def setup(step_name, &block)
         | 
| 88 | 
            +
                def setup(step_name, options={}, &block)
         | 
| 78 89 | 
             
                  if block_given?
         | 
| 79 | 
            -
                    Step.new.tap do |step|
         | 
| 90 | 
            +
                    Step.new(options).tap do |step|
         | 
| 80 91 | 
             
                      step.define_singleton_method :run, &block
         | 
| 81 92 | 
             
                      step.step_title = step_name.to_s.titleize
         | 
| 82 93 | 
             
                    end.run!
         | 
| 83 94 | 
             
                  else
         | 
| 84 95 | 
             
                    klass = "Stairs::Steps::#{step_name.to_s.camelize}".constantize
         | 
| 85 | 
            -
                    klass.new.run!
         | 
| 96 | 
            +
                    klass.new(options).run!
         | 
| 86 97 | 
             
                  end
         | 
| 87 98 | 
             
                end
         | 
| 88 99 |  | 
| @@ -97,6 +108,11 @@ module Stairs | |
| 97 108 |  | 
| 98 109 | 
             
                private
         | 
| 99 110 |  | 
| 111 | 
            +
                def run_step?
         | 
| 112 | 
            +
                  return true if options[:required]
         | 
| 113 | 
            +
                  choice "This step is optional, would you like to perform it?"
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 100 116 | 
             
                class Choice
         | 
| 101 117 | 
             
                  # TODO: shouldn't care about case?
         | 
| 102 118 | 
             
                  def initialize(question, choices=%w[Y N], &block)
         | 
| @@ -5,7 +5,7 @@ module Stairs | |
| 5 5 | 
             
                    def replace_or_append(pattern, string, filename)
         | 
| 6 6 | 
             
                      if File.exists? filename
         | 
| 7 7 | 
             
                        contents = File.read filename
         | 
| 8 | 
            -
                        if contents | 
| 8 | 
            +
                        if contents =~ pattern
         | 
| 9 9 | 
             
                          contents.sub! pattern, string
         | 
| 10 10 | 
             
                          write contents, filename
         | 
| 11 11 | 
             
                          return
         | 
| @@ -15,11 +15,21 @@ module Stairs | |
| 15 15 | 
             
                      write_line string, filename
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 |  | 
| 18 | 
            +
                    def remove(pattern, filename)
         | 
| 19 | 
            +
                      return unless File.exists? filename
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      contents = File.read filename
         | 
| 22 | 
            +
                      if contents =~ pattern
         | 
| 23 | 
            +
                        contents.slice!(pattern)
         | 
| 24 | 
            +
                        write contents, filename
         | 
| 25 | 
            +
                      end
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 18 28 | 
             
                    def write_line(string, filename)
         | 
| 19 29 | 
             
                      File.open filename, "a+" do |file|
         | 
| 20 30 | 
             
                        # ensure file ends with newline before appending
         | 
| 21 31 | 
             
                        last_line = file.each_line.reduce("") { |m, l| m = l }
         | 
| 22 | 
            -
                        file.puts "" unless last_line | 
| 32 | 
            +
                        file.puts "" unless last_line == "" || last_line =~ /(.*)\n/
         | 
| 23 33 |  | 
| 24 34 | 
             
                        file.puts string
         | 
| 25 35 | 
             
                      end
         | 
    
        data/lib/stairs/version.rb
    CHANGED
    
    
| @@ -35,4 +35,14 @@ describe Stairs::EnvAdapters::Dotenv do | |
| 35 35 | 
             
                  subject.set(name, value)
         | 
| 36 36 | 
             
                end
         | 
| 37 37 | 
             
              end
         | 
| 38 | 
            -
             | 
| 38 | 
            +
             | 
| 39 | 
            +
              describe "#unset" do
         | 
| 40 | 
            +
                it "delegates to the well tested FileMutation util" do
         | 
| 41 | 
            +
                  Stairs::Util::FileMutation.should_receive(:remove).with(
         | 
| 42 | 
            +
                    Regexp.new("^SOMETHING=(.*)\n"),
         | 
| 43 | 
            +
                    ".env",
         | 
| 44 | 
            +
                  )
         | 
| 45 | 
            +
                  subject.unset "SOMETHING"
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -37,4 +37,14 @@ describe Stairs::EnvAdapters::Rbenv do | |
| 37 37 | 
             
                  subject.set(name, value)
         | 
| 38 38 | 
             
                end
         | 
| 39 39 | 
             
              end
         | 
| 40 | 
            -
             | 
| 40 | 
            +
             | 
| 41 | 
            +
              describe "#unset" do
         | 
| 42 | 
            +
                it "delegates to the well tested FileMutation util" do
         | 
| 43 | 
            +
                  Stairs::Util::FileMutation.should_receive(:remove).with(
         | 
| 44 | 
            +
                    Regexp.new("^SOMETHING=(.*)\n"),
         | 
| 45 | 
            +
                    ".rbenv-vars",
         | 
| 46 | 
            +
                  )
         | 
| 47 | 
            +
                  subject.unset "SOMETHING"
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -37,4 +37,14 @@ describe Stairs::EnvAdapters::RVM do | |
| 37 37 | 
             
                  subject.set(name, value)
         | 
| 38 38 | 
             
                end
         | 
| 39 39 | 
             
              end
         | 
| 40 | 
            -
             | 
| 40 | 
            +
             | 
| 41 | 
            +
              describe "#unset" do
         | 
| 42 | 
            +
                it "delegates to the well tested FileMutation util" do
         | 
| 43 | 
            +
                  Stairs::Util::FileMutation.should_receive(:remove).with(
         | 
| 44 | 
            +
                    Regexp.new("^export SOMETHING=(.*)\n"),
         | 
| 45 | 
            +
                    ".rvmrc",
         | 
| 46 | 
            +
                  )
         | 
| 47 | 
            +
                  subject.unset "SOMETHING"
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -42,6 +42,23 @@ describe Stairs::Step do | |
| 42 42 | 
             
                end
         | 
| 43 43 | 
             
              end
         | 
| 44 44 |  | 
| 45 | 
            +
              describe "options" do
         | 
| 46 | 
            +
                describe "default options" do
         | 
| 47 | 
            +
                  it "is required" do
         | 
| 48 | 
            +
                    expect(subject.options[:required]).to be_true
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                context "with options" do
         | 
| 53 | 
            +
                  let(:options) { { something: "cool" } }
         | 
| 54 | 
            +
                  subject { anon_step.new(options) }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  it "exposes options on the instance" do
         | 
| 57 | 
            +
                    expect(subject.options[:something]).to eq "cool"
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 45 62 | 
             
              describe "#run!" do
         | 
| 46 63 | 
             
                before { subject.stub run: true }
         | 
| 47 64 | 
             
                before { anon_step.title "Step Name" }
         | 
| @@ -60,6 +77,30 @@ describe Stairs::Step do | |
| 60 77 | 
             
                  output = capture_stdout { subject.run! }
         | 
| 61 78 | 
             
                  expect(output).to include "== Completed Step Name"
         | 
| 62 79 | 
             
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                context "when the step is not required" do
         | 
| 82 | 
            +
                  subject { anon_step.new required: false }
         | 
| 83 | 
            +
                  before { subject.stub run: true }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  it "prompts the user to decide if we should run the step" do
         | 
| 86 | 
            +
                    output = follow_prompts("Y") { subject.run! }
         | 
| 87 | 
            +
                    expect(output).to include "This step is optional, would you like to perform it? (Y/N): "
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  context "user says yes" do
         | 
| 91 | 
            +
                    it "runs the step" do
         | 
| 92 | 
            +
                      subject.should_receive :run
         | 
| 93 | 
            +
                      follow_prompts("Y") { subject.run! }
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  context "user says no" do
         | 
| 98 | 
            +
                    it "doesn't run the step" do
         | 
| 99 | 
            +
                      subject.should_not_receive :run
         | 
| 100 | 
            +
                      follow_prompts("N") { subject.run! }
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
                end
         | 
| 63 104 | 
             
              end
         | 
| 64 105 |  | 
| 65 106 | 
             
              describe "#provide" do
         | 
| @@ -214,7 +255,7 @@ describe Stairs::Step do | |
| 214 255 | 
             
                let(:adapter) { double("adapter", set: true) }
         | 
| 215 256 | 
             
                before { Stairs.configuration.env_adapter = adapter }
         | 
| 216 257 |  | 
| 217 | 
            -
                it "delegates to the adapter" do
         | 
| 258 | 
            +
                it "delegates to the adapter's set" do
         | 
| 218 259 | 
             
                  adapter.should_receive(:set).with("NAME", "value")
         | 
| 219 260 | 
             
                  subject.env "NAME", "value"
         | 
| 220 261 | 
             
                end
         | 
| @@ -223,6 +264,13 @@ describe Stairs::Step do | |
| 223 264 | 
             
                  ENV.should_receive(:[]=).with("NAME", "value")
         | 
| 224 265 | 
             
                  subject.env "NAME", "value"
         | 
| 225 266 | 
             
                end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                context "with no value" do
         | 
| 269 | 
            +
                  it "delegates to the adapter's unset" do
         | 
| 270 | 
            +
                    adapter.should_receive(:unset).with("NAME")
         | 
| 271 | 
            +
                    subject.env "NAME", nil
         | 
| 272 | 
            +
                  end
         | 
| 273 | 
            +
                end
         | 
| 226 274 | 
             
              end
         | 
| 227 275 |  | 
| 228 276 | 
             
              describe "#write" do
         | 
| @@ -272,6 +320,16 @@ describe Stairs::Step do | |
| 272 320 | 
             
                    mock_step_class.any_instance.should_receive(:run!)
         | 
| 273 321 | 
             
                    subject.setup :mock_step
         | 
| 274 322 | 
             
                  end
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                  context "with options" do
         | 
| 325 | 
            +
                    let(:options) { { something: "cool" } }
         | 
| 326 | 
            +
                    before { mock_step_class.any_instance.stub run!: true }
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                    it "passes options to the step" do
         | 
| 329 | 
            +
                      mock_step_class.should_receive(:new).with(options).and_call_original
         | 
| 330 | 
            +
                      subject.setup :mock_step, options
         | 
| 331 | 
            +
                    end
         | 
| 332 | 
            +
                  end
         | 
| 275 333 | 
             
                end
         | 
| 276 334 |  | 
| 277 335 | 
             
                context "with a block" do
         | 
| @@ -288,6 +346,18 @@ describe Stairs::Step do | |
| 288 346 | 
             
                    output = capture_stdout { call_method }
         | 
| 289 347 | 
             
                    expect(output).to include "I'm running in Stairs::Step"
         | 
| 290 348 | 
             
                  end
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                  context "with options" do
         | 
| 351 | 
            +
                    let(:options) { { something: "cool" } }
         | 
| 352 | 
            +
                    before { described_class.any_instance.stub run!: true }
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                    it "passes options to the step" do
         | 
| 355 | 
            +
                      instance = subject # Initialize class before asserting against #new
         | 
| 356 | 
            +
             | 
| 357 | 
            +
                      described_class.should_receive(:new).with(options).and_call_original
         | 
| 358 | 
            +
                      subject.setup(:custom_step, options) { true }
         | 
| 359 | 
            +
                    end
         | 
| 360 | 
            +
                  end
         | 
| 291 361 | 
             
                end
         | 
| 292 362 | 
             
              end
         | 
| 293 | 
            -
            end
         | 
| 363 | 
            +
            end
         | 
| @@ -35,6 +35,41 @@ describe Stairs::Util::FileMutation do | |
| 35 35 | 
             
                end
         | 
| 36 36 | 
             
              end
         | 
| 37 37 |  | 
| 38 | 
            +
              describe ".remove" do
         | 
| 39 | 
            +
                before do
         | 
| 40 | 
            +
                  File.open(filename, "w") do |file|
         | 
| 41 | 
            +
                    file.write "VAR_1=hey\nVAR_2=hello\nVAR_3=hi\n"
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                context "when the pattern exists in file" do
         | 
| 46 | 
            +
                  it "removes the match from the file" do
         | 
| 47 | 
            +
                    subject.remove /^VAR_2=(.*)\n/, filename
         | 
| 48 | 
            +
                    expect(File.read(filename)).to eq "VAR_1=hey\nVAR_3=hi\n"
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  context "and is the last line without a trailing newline" do
         | 
| 52 | 
            +
                    before do
         | 
| 53 | 
            +
                      File.open(filename, "w+") do |file|
         | 
| 54 | 
            +
                        file.write "VAR_1=hey\nVAR_2=hello\nVAR_3=hi"
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      it "still matches and removes it" do
         | 
| 58 | 
            +
                        subject.remove /^VAR_3=(.*)\n/, filename
         | 
| 59 | 
            +
                        expect(File.read(filename)).to eq "VAR_1=hey\nVAR_2=hello\n"
         | 
| 60 | 
            +
                      end
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                context "when the pattern does not exist in file" do
         | 
| 66 | 
            +
                  it "leaves the file untouched" do
         | 
| 67 | 
            +
                    subject.remove /^VAR_2=(.*)\n/, filename
         | 
| 68 | 
            +
                    expect(File.read(filename)).to eq "VAR_1=hey\nVAR_3=hi\n"
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 38 73 | 
             
              describe ".write_line" do
         | 
| 39 74 | 
             
                before do
         | 
| 40 75 | 
             
                  File.open(filename, "w") do |file|
         | 
| @@ -51,9 +86,7 @@ describe Stairs::Util::FileMutation do | |
| 51 86 |  | 
| 52 87 | 
             
                context "when there is no newline at the bottom" do
         | 
| 53 88 | 
             
                  before do
         | 
| 54 | 
            -
                    File. | 
| 55 | 
            -
             | 
| 56 | 
            -
                    File.open(filename, "w") do |file|
         | 
| 89 | 
            +
                    File.open(filename, "w+") do |file|
         | 
| 57 90 | 
             
                      file.write("line1\nline2")
         | 
| 58 91 | 
             
                    end
         | 
| 59 92 | 
             
                  end
         | 
| @@ -63,6 +96,19 @@ describe Stairs::Util::FileMutation do | |
| 63 96 | 
             
                    expect(File.read(filename)).to eq "line1\nline2\nline3\n"
         | 
| 64 97 | 
             
                  end
         | 
| 65 98 | 
             
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                context "when the file is empty" do
         | 
| 101 | 
            +
                  before do
         | 
| 102 | 
            +
                    File.open filename, "w+" do |file|
         | 
| 103 | 
            +
                      file.write ""
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  it "writes to the first line of the line" do
         | 
| 108 | 
            +
                    described_class.write_line "line1", filename
         | 
| 109 | 
            +
                    expect(File.read(filename)).to eq "line1\n"
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
                end
         | 
| 66 112 | 
             
              end
         | 
| 67 113 |  | 
| 68 114 | 
             
              describe ".write" do
         | 
| @@ -95,4 +141,4 @@ describe Stairs::Util::FileMutation do | |
| 95 141 | 
             
                  end
         | 
| 96 142 | 
             
                end
         | 
| 97 143 | 
             
              end
         | 
| 98 | 
            -
            end
         | 
| 144 | 
            +
            end
         |