Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
spoom (1.7.9)
spoom (1.7.10)
erubi (>= 1.10.0)
prism (>= 0.28.0)
rbi (>= 0.3.3)
Expand Down
33 changes: 33 additions & 0 deletions lib/spoom/bundler_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# typed: strict
# frozen_string_literal: true

module Spoom
module BundlerHelper
extend T::Sig

class << self
# Generate a gem requirement for the given gem name, using that gem's version in the "real" current bundle.
#
# This ensures that any child Spoom::Contexts use predictable gem versions,
# without having to manually specify them and bump them to stay in sync with Spoom's real Gemfile.
Comment on lines +9 to +12
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this explanation be clear to someone who didn't already understand what's going on here?

#
# Given `"foo"`, returns a string like 'gem "foo", "= 1.2.3"', suitable for inserting into a Gemfile.
#: (String) -> String
def gem_requirement_from_real_bundle(gem_name)
specs = Bundler.load.gems[gem_name]

if specs.nil? || specs.empty?
raise "Did not find gem #{gem_name.inspect} in the current bundle"
elsif specs.count > 1
raise <<~MSG
Found multiple versions of #{gem_name.inspect} in the current bundle:
#{specs.sort_by(&:version).map { |spec| " - #{spec.name} #{spec.version}" }.join("\n")}
MSG
else
spec = specs.first
%(gem "#{spec.name}", "= #{spec.version}")
end
end
end
end
end
11 changes: 7 additions & 4 deletions lib/spoom/cli/srb/sigs.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# typed: true
# frozen_string_literal: true

require "spoom/bundler_helper"

module Spoom
module Cli
module Srb
Expand Down Expand Up @@ -142,13 +144,14 @@ class Module; include T::Sig; end
# Now we create a new context to import our modified gem and run tapioca
say("Running Tapioca...")
tapioca_context = Spoom::Context.mktmp!
tapioca_context.write!("Gemfile", <<~RB)
tapioca_context.write_gemfile!(<<~GEMFILE)
source "https://rubygems.org"

gem "rbs", ">= 4.0.0.dev.4"
gem "tapioca"
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("rbs")}
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("tapioca")}

gem "#{spec.name}", path: "#{copy_context.absolute_path}"
RB
GEMFILE
exec(tapioca_context, "bundle install")
exec(tapioca_context, "bundle exec tapioca gem #{spec.name} --no-doc --no-loc --no-file-header")

Expand Down
2 changes: 1 addition & 1 deletion lib/spoom/context/bundle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def gemfile_lock_specs
return {} unless file?("Gemfile.lock")

parser = Bundler::LockfileParser.new(read_gemfile_lock)
parser.specs.map { |spec| [spec.name, spec] }.to_h
parser.specs.to_h { |spec| [spec.name, spec] }
end

# Get `gem` version from the `Gemfile.lock` content
Expand Down
2 changes: 1 addition & 1 deletion lib/spoom/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# frozen_string_literal: true

module Spoom
VERSION = "1.7.9"
VERSION = "1.7.10"
end
7 changes: 7 additions & 0 deletions rbi/spoom.rbi
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ module Spoom
end
end

module Spoom::BundlerHelper
class << self
sig { params(gem_name: ::String).returns(::String) }
def gem_requirement_from_real_bundle(gem_name); end
end
end

module Spoom::Cli; end

class Spoom::Cli::Deadcode < ::Thor
Expand Down
21 changes: 21 additions & 0 deletions test/spoom/bundler_helper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# typed: true
# frozen_string_literal: true

require "test_helper"

module Spoom
class BundlerHelperTest < Minitest::Test
def test_gem_requirement_from_real_bundle_returns_gem_requirement_string
gem_from_spoom_bundle = "tapioca"
gem_requirement = BundlerHelper.gem_requirement_from_real_bundle(gem_from_spoom_bundle)

assert_match(/^gem "#{gem_from_spoom_bundle}", "= .+"$/, gem_requirement)
end

def test_raises_if_gem_not_found_in_bundle
assert_raises(RuntimeError) do
BundlerHelper.gem_requirement_from_real_bundle("not-real")
end
end
end
end
6 changes: 3 additions & 3 deletions test/spoom/context/sorbet_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_context_run_srb_from_bundle
context.write_gemfile!(<<~GEMFILE)
source "https://rubygems.org"

gem "sorbet"
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet")}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we really care which version of Sorbet gets installed in these tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so either, but I'd rather not have to worry about it.

GEMFILE
context.bundle("config set --local path $GEM_HOME")
context.bundle_install!
Expand Down Expand Up @@ -67,7 +67,7 @@ def test_context_run_srb_from_path
context.write_gemfile!(<<~GEMFILE)
source "https://rubygems.org"

gem "sorbet"
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet")}
GEMFILE
context.bundle_install!

Expand Down Expand Up @@ -163,7 +163,7 @@ def test_context_srb_version_return_version_string
context.write_gemfile!(<<~GEMFILE)
source "https://rubygems.org"

gem "sorbet"
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet")}
GEMFILE
context.bundle_install!

Expand Down
4 changes: 2 additions & 2 deletions test/spoom/deadcode/plugins_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def test_deadcode_plugins_with_sorbet
plugins = plugins_classes_for_gemfile(<<~GEMFILE)
source "https://rubygems.org"

gem "sorbet"
gem "sorbet-runtime"
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet")}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I don't think we really care about which version we use

#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet-runtime")}
GEMFILE

assert_equal(
Expand Down
24 changes: 16 additions & 8 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,29 @@ def new_project(name = nil)
# Default Gemfile contents requiring only Spoom
#: -> String
def spoom_gemfile
<<~GEMFILE
source("https://rubygems.org")

gemspec name: "spoom", path: "#{SPOOM_PATH}"
gem "tapioca"
gem "sorbet-static-and-runtime", "#{Sorbet::GEM_VERSION}"
gem "json", "2.7.2"
GEMFILE
Spoom::TestHelper.default_spoom_test_gemfile
end

# Replace all sorbet-like version "0.5.5888" in `test` by "X.X.XXXX"
#: (String text) -> String
def censor_sorbet_version(text)
text.gsub(/\d\.\d\.\d{4,5}/, "X.X.XXXX")
end

class << self
#: -> String
def default_spoom_test_gemfile
@default_spoom_test_gemfile ||= <<~GEMFILE #: String?
source("https://rubygems.org")

gemspec name: "spoom", path: "#{SPOOM_PATH}"

#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("tapioca")}
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("sorbet-static-and-runtime")}
#{Spoom::BundlerHelper.gem_requirement_from_real_bundle("json")}
GEMFILE
end
end
end
end

Expand Down