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
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 {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is INFO message because the end-user is not responsible for the dependencies: of the type definition.

"`#{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
262 changes: 260 additions & 2 deletions test/rbs/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def run_rbs_collection(*commands, bundler:)
rbs_path << (":" + rblib)
end

Open3.capture3({ "RUBYLIB" => rbs_path }, *bundle_exec, "#{__dir__}/../../exe/rbs", "collection", *commands, chdir: Dir.pwd)
Open3.capture3({ "RUBYLIB" => rbs_path }, *bundle_exec, "#{__dir__}/../../exe/rbs", "--log-level=debug", "collection", *commands, chdir: Dir.pwd)
end

if block_given?
Expand All @@ -55,7 +55,11 @@ def bundle_install(*gems)
if gem == :gemspec
"gemspec"
else
"gem '#{gem}'"
if gem.is_a?(Array)
"gem #{gem.map(&:inspect).join(", ")}"
else
"gem '#{gem}'"
end
end
end

Expand Down Expand Up @@ -1288,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 = "[email protected]"
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
Loading