Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gemfile variables #223

Merged
merged 10 commits into from
May 16, 2024
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ customizations include:
- heading: a string that by default adds "# This file was generated by Appraisal" to the top of each Gemfile, (the string will be commented for you)
- single_quotes: a boolean that controls if strings are single quoted in each Gemfile, defaults to false

You can also provide variables for substitution in the heading, based on each appraisal. Currently supported variables:
- `%{appraisal}`: Becomes the name of each appraisal, e.g. `rails-3`
- `%{gemfile}`: Becomes the filename of each gemfile, e.g. `rails-3.gemfile`
- `%{gemfile_path}`: Becomes the full path of each gemfile, e.g. `/path/to/project/gemfiles/rails-3.gemfile`
- `%{lockfile}`: Becomes the filename of each lockfile, e.g. `rails-3.gemfile.lock`
- `%{lockfile_path}`: Becomes the full path of each lockfile, e.g. `/path/to/project/gemfiles/rails-3.gemfile.lock`
- `%{relative_gemfile_path}`: Becomes the relative path of each gemfile, e.g. `gemfiles/rails-3.gemfile`
- `%{relative_lockfile_path}`: Becomes the relative path of each lockfile, e.g. `gemfiles/rails-3.gemfile.lock`

### Example Usage

**Appraisals**
Expand All @@ -169,8 +178,8 @@ customize_gemfiles do
heading: <<~HEADING
frozen_string_literal: true

File has been generated by Appraisal, do NOT modify it directly!
See the conventions at https://example.com/
`%{gemfile}` has been generated by Appraisal, do NOT modify it or `%{lockfile}` directly!
Make the changes to the "%{appraisal}" block in `Appraisals` instead. See the conventions at https://example.com/
joe-sharp marked this conversation as resolved.
Show resolved Hide resolved
HEADING
}
end
Expand All @@ -184,8 +193,8 @@ Using the `Appraisals` file defined above, this is what the resulting `Gemfile`
```ruby
# frozen_string_literal: true

# File has been generated by Appraisal, do NOT modify it directly!
# See the conventions at https://example.com/
# `rails-3.gemfile` has been generated by Appraisal, do NOT modify it or `rails-3.gemfile.lock` directly!
# Make the changes to the "rails-3" block in `Appraisals` instead. See the conventions at https://example.com/

gem 'rails', '3.2.14'
```
Expand Down
3 changes: 2 additions & 1 deletion lib/appraisal/appraisal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def git_source(*args, &block)

def write_gemfile
File.open(gemfile_path, "w") do |file|
signature = Customize.heading || "This file was generated by Appraisal"
signature =
Customize.heading(self) || "This file was generated by Appraisal"
file.puts([comment_lines(signature), quoted_gemfile].join("\n\n"))
end
end
Expand Down
20 changes: 19 additions & 1 deletion lib/appraisal/customize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,30 @@ def initialize(heading: nil, single_quotes: false)
@@single_quotes = single_quotes
end

def self.heading
def self.heading(gemfile)
@@heading ||= nil
customize(@@heading, gemfile)
end

def self.single_quotes
@@single_quotes ||= false
end

def self.customize(heading, gemfile)
return nil unless heading

format(
heading.to_s,
appraisal: gemfile.send("clean_name"),
gemfile: gemfile.send("gemfile_name"),
gemfile_path: gemfile.gemfile_path,
lockfile: "#{gemfile.send('gemfile_name')}.lock",
lockfile_path: gemfile.send("lockfile_path"),
relative_gemfile_path: gemfile.relative_gemfile_path,
relative_lockfile_path: "#{gemfile.relative_gemfile_path}.lock",
)
end

private_class_method :customize
end
end
141 changes: 131 additions & 10 deletions spec/appraisal/customize_spec.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,139 @@
require "spec_helper"
require "appraisal/appraisal"
require "appraisal/customize"

describe Appraisal::Customize do
it "has defaults" do
expect(described_class.heading).to eq nil
expect(described_class.single_quotes).to eq false
expect { described_class.new }.to_not(change do
[described_class.heading, described_class.single_quotes]
end)
let(:appraisal) { Appraisal::Appraisal.new("test", "Gemfile") }
let(:single_line_heading) { "This file was generated with a custom heading!" }
let(:multi_line_heading) do
<<~HEADING
frozen_string_literal: true

This file was generated with a custom heading!
HEADING
end
let(:subject) { described_class.new }
let(:single_line_subject) do
described_class.new(heading: single_line_heading)
end
let(:multi_line_single_quotes_subject) do
described_class.new(heading: multi_line_heading, single_quotes: true)
end

describe ".heading" do
it "returns nil if no heading is set" do
subject
expect(described_class.heading(appraisal)).to eq(nil)
end

it "returns the heading if set" do
single_line_subject
expect(described_class.heading(appraisal)).to eq(single_line_heading)
end

it "returns the heading without an trailing newline" do
multi_line_single_quotes_subject
expect(described_class.heading(appraisal)).to eq(multi_line_heading.chomp)
expect(described_class.heading(appraisal)).to_not end_with("\n")
end
end

describe ".single_quotes" do
it "returns false if not set" do
subject
expect(described_class.single_quotes).to eq(false)
end

it "returns true if set" do
multi_line_single_quotes_subject
expect(described_class.single_quotes).to eq(true)
end
end

it "can override defaults" do
described_class.new(single_quotes: true, heading: "foo")
expect(described_class.heading).to eq "foo"
expect(described_class.single_quotes).to eq true
describe ".customize" do
let(:appraisal_name) { "test" }
let(:gemfile) { "test.gemfile" }
let(:lockfile) { "#{gemfile}.lock" }
let(:gemfile_relative_path) { "gemfiles/#{gemfile}" }
let(:lockfile_relative_path) { "gemfiles/#{lockfile}" }
let(:gemfile_full_path) { "/path/to/project/#{gemfile_relative_path}" }
let(:lockfile_full_path) { "/path/to/project/#{lockfile_relative_path}" }
before do
allow(appraisal).to receive(:gemfile_name).and_return(gemfile)
allow(appraisal).to receive(:gemfile_path).and_return(gemfile_full_path)
allow(appraisal).to receive(:lockfile_path).and_return(lockfile_full_path)
allow(appraisal).to receive(:relative_gemfile_path).
and_return(gemfile_relative_path)
end

it "returns nil if no heading is set" do
subject
expect(described_class.send(:customize, nil, appraisal)).to eq(nil)
end

it "returns the heading unchanged" do
single_line_subject
expect(described_class.send(
:customize,
single_line_heading,
appraisal,
)).to eq(single_line_heading)
end

it "returns the heading with the appraisal name" do
expect(described_class.send(
:customize,
"Appraisal: %{appraisal}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Appraisal: #{appraisal_name}")
end

it "returns the heading with the gemfile name" do
expect(described_class.send(
:customize,
"Gemfile: %{gemfile}", # rubocop:disable Style/FormatStringToken
appraisal,
)).to eq("Gemfile: #{gemfile}")
end

it "returns the heading with the gemfile path" do
expect(described_class.send(
:customize,
"Gemfile: %{gemfile_path}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Gemfile: #{gemfile_full_path}")
end

it "returns the heading with the lockfile name" do
expect(described_class.send(
:customize,
"Lockfile: %{lockfile}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Lockfile: #{lockfile}")
end

it "returns the heading with the lockfile path" do
expect(described_class.send(
:customize,
"Lockfile: %{lockfile_path}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Lockfile: #{lockfile_full_path}")
end

it "returns the heading with the relative gemfile path" do
expect(described_class.send(
:customize,
"Gemfile: %{relative_gemfile_path}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Gemfile: #{gemfile_relative_path}")
end

it "returns the heading with the relative lockfile path" do
expect(described_class.send(
:customize,
"Gemfile: %{relative_lockfile_path}", # rubocop:disable Style/FormatStringToken, Metrics/LineLength
appraisal,
)).to eq("Gemfile: #{lockfile_relative_path}")
end
end
end