Skip to content

Commit

Permalink
Implement mutex_m support
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Dec 4, 2024
1 parent 554679d commit 383026d
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 8 deletions.
4 changes: 2 additions & 2 deletions lib/rbs/collection/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ def repo_path_data
def sources
@sources ||= [
Sources::Rubygems.instance,
Sources::Stdlib.instance,
*@data['sources'].map { |c| Sources.from_config_entry(c, base_directory: @config_path.dirname) }
*@data['sources'].map { |c| Sources.from_config_entry(c, base_directory: @config_path.dirname) },
Sources::Stdlib.instance
]
end

Expand Down
39 changes: 34 additions & 5 deletions lib/rbs/collection/config/lockfile_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module RBS
module Collection
class Config
class LockfileGenerator
ALUMNI_STDLIBS = { "mutex_m" => ">= 0.3.0" }

class GemfileLockMismatchError < StandardError
def initialize(expected:, actual:)
@expected = expected
Expand Down Expand Up @@ -58,9 +60,10 @@ def initialize(config:, definition:, with_lockfile:)

def generate
config.gems.each do |gem|
if Sources::Stdlib.instance.has?(gem["name"], nil) || gem.dig("source", "type") == "stdlib"
case
when gem.dig("source", "type") == "stdlib"
unless gem.fetch("ignore", false)
assign_stdlib(name: gem["name"], from_gem: nil)
assign_stdlib(name: gem["name"])
end
else
assign_gem(name: gem["name"], version: gem["version"])
Expand Down Expand Up @@ -113,6 +116,11 @@ def generate
find_source(name: name)
end

if source.is_a?(Sources::Stdlib)
assign_stdlib(name: name)
return
end

if source
installed_version = version
best_version = find_best_version(version: installed_version, versions: source.versions(name))
Expand Down Expand Up @@ -149,16 +157,37 @@ def generate
end
end

private def assign_stdlib(name:, from_gem:)
private def assign_stdlib(name:, from_gem: nil)
return if lockfile.gems.key?(name)

case name
when 'rubygems', 'set'
msg = "`#{name}` has been moved to core library, so it is always loaded. Remove explicit loading `#{name}`"
msg << " from `#{from_gem}`" if from_gem
RBS.logger.warn msg

msg << "."
return
when *ALUMNI_STDLIBS.keys
version = ALUMNI_STDLIBS.fetch(name)
if from_gem
# From `dependencies:` of a `manifest.yaml` of a gem
source = find_source(name: name) or raise
if source.is_a?(Sources::Stdlib)
RBS.logger.warn {
"`#{name}` is included in the RBS dependencies of `#{from_gem}`, but the type definition as a stdlib in rbs-gem is deprecated. Add `#{name}` (#{version}) to the dependency of your Ruby program to use the gem-bundled type definition."
}
else
RBS.logger.info {
"`#{name}` is included in the RBS dependencies of `#{from_gem}`, but the type definition as a stdlib in rbs-gem is deprecated. Delete `#{name}` from the RBS dependencies of `#{from_gem}`."
}
assign_gem(name: name, version: nil)
return
end
else
# From `gems:` of a `rbs_collection.yaml`
RBS.logger.warn {
"`#{name}` as a stdlib in rbs-gem is deprecated. Add `#{name}` (#{version}) to the dependency of your Ruby program to use the gem-bundled type definition."
}
end
end

source = Sources::Stdlib.instance
Expand Down
10 changes: 9 additions & 1 deletion sig/collection/config/lockfile_generator.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ module RBS
module Collection
class Config
class LockfileGenerator
# Name of stdlibs that was rbs-bundled stdlib but is now a gem.
#
ALUMNI_STDLIBS: Hash[String, String]

class GemfileLockMismatchError < StandardError
@expected: Pathname

Expand Down Expand Up @@ -43,7 +47,11 @@ module RBS
#
def assign_gem: (name: String, version: String?, ?skip: bool) -> void

def assign_stdlib: (name: String, from_gem: String?) -> void
# Assign a gem from stdlib to lockfile
#
# `from_gem` is a String when the stdlib is assigned through the `dependencies:` in `manifest.yaml` of a gem.
#
def assign_stdlib: (name: String, ?from_gem: String) -> void

# Find a source of a gem from ones registered in `config.sources`
#
Expand Down
254 changes: 254 additions & 0 deletions test/rbs/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,260 @@ def test_collection_install_gemspec
end
end

def test_collection_install__mutex_m__config__bundled
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
gems:
- name: mutex_m
YAML

bundle_install(["mutex_m", ">= 0.3.0"])
_stdout, stderr = run_rbs_collection("install", bundler: true)

refute_match(/`mutex_m` as a stdlib in rbs-gem is deprecated./, stderr)

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Rubygems, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__config__no_bundled
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
gems:
- name: mutex_m
YAML

bundle_install(["mutex_m", "0.2.0"])
_stdout, stderr = run_rbs_collection("install", bundler: true)

assert_include stderr, '`mutex_m` as a stdlib in rbs-gem is deprecated.'
assert_include stderr, 'Add `mutex_m` (>= 0.3.0) to the dependency of your Ruby program to use the gem-bundled type definition.'

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Stdlib, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__config__stdlib_source
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
gems:
- name: mutex_m
source:
type: stdlib
YAML

bundle_install
_stdout, stderr = run_rbs_collection("install", bundler: true)

assert_include stderr, '`mutex_m` as a stdlib in rbs-gem is deprecated.'
assert_include stderr, 'Add `mutex_m` (>= 0.3.0) to the dependency of your Ruby program to use the gem-bundled type definition.'

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Stdlib, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__bundled
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
YAML

bundle_install(["mutex_m", ">= 0.3.0"])
_stdout, stderr = run_rbs_collection("install", bundler: true)

refute_match(/`mutex_m` as a stdlib in rbs-gem is deprecated./, stderr)

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Rubygems, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__no_bundled
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
YAML

bundle_install(["mutex_m", "0.2.0"])
_stdout, stderr = run_rbs_collection("install", bundler: true)

assert_include stderr, '`mutex_m` as a stdlib in rbs-gem is deprecated.'
assert_include stderr, 'Add `mutex_m` (>= 0.3.0) to the dependency of your Ruby program to use the gem-bundled type definition.'

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Stdlib, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__dependency_no_bundled
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- type: local
path: repo
path: #{dir.join('gem_rbs_collection')}
YAML

(dir/"repo/true_string/0").mkpath
(dir/"repo/true_string/0/manifest.yaml").write(<<~YAML)
dependencies:
- name: mutex_m
YAML

bundle_install("true_string") # true_string is a soutaro's gem that doesn't have sig directory

_stdout, stderr = run_rbs_collection("install", bundler: true)

assert_include stderr, '`mutex_m` is included in the RBS dependencies of `true_string`, but the type definition as a stdlib in rbs-gem is deprecated.'
assert_include stderr, 'Add `mutex_m` (>= 0.3.0) to the dependency of your Ruby program to use the gem-bundled type definition.'

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Stdlib, lockfile.gems["mutex_m"][:source]
end
end
end

def test_collection_install__mutex_m__rbs_dependency_and__gem_dependency
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
dir = Pathname(dir)

(dir/"gem").mkpath
(dir/"gem/hola.gemspec").write(<<~RUBY)
Gem::Specification.new do |s|
s.name = "hola"
s.version = "0.0.0"
s.summary = "Hola!"
s.description = "A simple hello world gem"
s.authors = ["Nick Quaranto"]
s.email = "nick@quaran.to"
s.files = ["lib/hola.rb", "sig/hola.rbs"]
s.homepage =
"https://rubygems.org/gems/hola"
s.license = "MIT"
s.add_runtime_dependency "mutex_m", ">= 0.3.0"
end
RUBY
(dir/"gem/sig").mkpath
(dir/"gem/sig/manifest.yaml").write(<<~YAML)
dependencies:
- name: mutex_m
YAML

bundle_install(["hola", { path: "gem" }])

(dir + RBS::Collection::Config::PATH).write(<<~YAML)
sources:
- name: ruby/gem_rbs_collection
remote: https://github.com/ruby/gem_rbs_collection.git
revision: b4d3b346d9657543099a35a1fd20347e75b8c523
repo_dir: gems
path: #{dir.join('gem_rbs_collection')}
YAML

_stdout, stderr = run_rbs_collection("install", bundler: true)

assert_include stderr, '`mutex_m` is included in the RBS dependencies of `hola`, but the type definition as a stdlib in rbs-gem is deprecated.'
assert_include stderr, 'Delete `mutex_m` from the RBS dependencies of `hola`.'

lockfile = RBS::Collection::Config::Lockfile.from_lockfile(
lockfile_path: dir + "rbs_collection.lock.yaml",
data: YAML.safe_load((dir + "rbs_collection.lock.yaml").read)
)

assert_instance_of RBS::Collection::Sources::Rubygems, lockfile.gems["mutex_m"][:source]
end
end
end

def test_subtract
Dir.mktmpdir do |dir|
dir = Pathname(dir)
Expand Down

0 comments on commit 383026d

Please sign in to comment.