rbs 2.8.1 → 3.0.0.dev.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +1 -1
  3. data/.github/workflows/ruby.yml +9 -6
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +16 -16
  6. data/ext/rbs_extension/constants.c +2 -0
  7. data/ext/rbs_extension/constants.h +1 -0
  8. data/ext/rbs_extension/parser.c +23 -13
  9. data/ext/rbs_extension/ruby_objs.c +15 -3
  10. data/ext/rbs_extension/ruby_objs.h +2 -1
  11. data/lib/rbs/ast/members.rb +49 -15
  12. data/lib/rbs/cli.rb +6 -1
  13. data/lib/rbs/collection/config/lockfile.rb +115 -0
  14. data/lib/rbs/collection/config/lockfile_generator.rb +89 -48
  15. data/lib/rbs/collection/config.rb +11 -39
  16. data/lib/rbs/collection/installer.rb +9 -13
  17. data/lib/rbs/collection/sources/base.rb +2 -2
  18. data/lib/rbs/collection/sources/git.rb +135 -62
  19. data/lib/rbs/collection/sources/rubygems.rb +10 -12
  20. data/lib/rbs/collection/sources/stdlib.rb +10 -13
  21. data/lib/rbs/collection/sources.rb +7 -1
  22. data/lib/rbs/collection.rb +1 -0
  23. data/lib/rbs/definition.rb +1 -1
  24. data/lib/rbs/definition_builder/method_builder.rb +3 -3
  25. data/lib/rbs/definition_builder.rb +449 -572
  26. data/lib/rbs/environment.rb +5 -3
  27. data/lib/rbs/environment_loader.rb +11 -10
  28. data/lib/rbs/locator.rb +2 -2
  29. data/lib/rbs/prototype/helpers.rb +29 -13
  30. data/lib/rbs/prototype/node_usage.rb +99 -0
  31. data/lib/rbs/prototype/rb.rb +3 -2
  32. data/lib/rbs/prototype/rbi.rb +6 -4
  33. data/lib/rbs/prototype/runtime.rb +25 -12
  34. data/lib/rbs/substitution.rb +19 -0
  35. data/lib/rbs/types.rb +1 -5
  36. data/lib/rbs/validator.rb +2 -1
  37. data/lib/rbs/version.rb +1 -1
  38. data/lib/rbs/writer.rb +26 -17
  39. data/lib/rbs.rb +1 -0
  40. data/lib/rdoc_plugin/parser.rb +1 -1
  41. data/schema/members.json +15 -10
  42. data/sig/collection/config/lockfile.rbs +80 -0
  43. data/sig/collection/config/lockfile_generator.rbs +55 -0
  44. data/sig/collection/config.rbs +5 -48
  45. data/sig/collection/installer.rbs +1 -1
  46. data/sig/collection/sources.rbs +66 -29
  47. data/sig/definition_builder.rbs +94 -81
  48. data/sig/environment_loader.rbs +1 -1
  49. data/sig/errors.rbs +21 -0
  50. data/sig/members.rbs +31 -7
  51. data/sig/prototype/node_usage.rbs +20 -0
  52. data/sig/shims/bundler.rbs +13 -0
  53. data/sig/shims/rubygems.rbs +9 -0
  54. data/sig/shims.rbs +0 -22
  55. data/sig/substitution.rbs +6 -0
  56. data/sig/writer.rbs +2 -0
  57. data/stdlib/yaml/0/yaml.rbs +1 -1
  58. metadata +11 -4
@@ -20,93 +20,134 @@ module RBS
20
20
  end
21
21
  end
22
22
 
23
- attr_reader :config, :lock, :gemfile_lock, :lock_path
23
+ attr_reader :config, :lockfile, :gemfile_lock, :existing_lockfile
24
24
 
25
- def self.generate(config_path:, gemfile_lock_path:, with_lockfile: true)
26
- new(config_path: config_path, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile).generate
25
+ def self.generate(config:, gemfile_lock_path:, with_lockfile: true)
26
+ generator = new(config: config, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile)
27
+ generator.generate
28
+ generator.lockfile
27
29
  end
28
30
 
29
- def initialize(config_path:, gemfile_lock_path:, with_lockfile:)
30
- @config = Config.from_path config_path
31
- @lock_path = Config.to_lockfile_path(config_path)
32
- @lock = Config.from_path(lock_path) if lock_path.exist? && with_lockfile
33
- @gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
34
- @gem_queue = []
31
+ def initialize(config:, gemfile_lock_path:, with_lockfile:)
32
+ @config = config
33
+
34
+ lockfile_path = Config.to_lockfile_path(config.config_path)
35
+ lockfile_dir = lockfile_path.parent
36
+
37
+ @lockfile = Lockfile.new(
38
+ lockfile_path: lockfile_path,
39
+ path: config.repo_path_data,
40
+ gemfile_lock_path: gemfile_lock_path.relative_path_from(lockfile_dir)
41
+ )
42
+ config.sources.each do |source|
43
+ case source
44
+ when Sources::Git
45
+ lockfile.sources[source.name] = source
46
+ end
47
+ end
35
48
 
36
- validate_gemfile_lock_path!(lock: lock, gemfile_lock_path: gemfile_lock_path)
49
+ if with_lockfile && lockfile_path.file?
50
+ @existing_lockfile = Lockfile.from_lockfile(lockfile_path: lockfile_path, data: YAML.load_file(lockfile_path.to_s))
51
+ validate_gemfile_lock_path!(lock: @existing_lockfile, gemfile_lock_path: gemfile_lock_path)
52
+ end
37
53
 
38
- config.gemfile_lock_path = gemfile_lock_path
54
+ @gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
39
55
  end
40
56
 
41
57
  def generate
58
+ ignored_gems = config.gems.select {|gem| gem["ignore"] }.map {|gem| gem["name"] }.to_set
59
+
42
60
  config.gems.each do |gem|
43
- @gem_queue.push({ name: gem['name'], version: gem['version'] })
61
+ if Sources::Stdlib.instance.has?(gem["name"], nil) || gem.dig("source", "type") == "stdlib"
62
+ unless ignored_gems.include?(gem["name"])
63
+ assign_stdlib(name: gem["name"], from_gem: nil)
64
+ end
65
+ else
66
+ assign_gem(name: gem["name"], version: gem["version"], ignored_gems: ignored_gems, src_data: gem["source"])
67
+ end
44
68
  end
45
69
 
46
70
  gemfile_lock_gems do |spec|
47
- @gem_queue.push({ name: spec.name, version: spec.version })
71
+ assign_gem(name: spec.name, version: spec.version, ignored_gems: ignored_gems, src_data: nil)
48
72
  end
49
73
 
50
- while gem = @gem_queue.shift
51
- assign_gem(**gem)
52
- end
53
- remove_ignored_gems!
54
-
55
- config.dump_to(lock_path)
56
- config
74
+ lockfile.lockfile_path.write(YAML.dump(lockfile.to_lockfile))
57
75
  end
58
76
 
59
77
  private def validate_gemfile_lock_path!(lock:, gemfile_lock_path:)
60
78
  return unless lock
61
- return unless lock.gemfile_lock_path
62
- return if lock.gemfile_lock_path == gemfile_lock_path
63
-
64
- raise GemfileLockMismatchError.new(expected: lock.gemfile_lock_path, actual: gemfile_lock_path)
79
+ return unless lock.gemfile_lock_fullpath
80
+ unless lock.gemfile_lock_fullpath == gemfile_lock_path
81
+ raise GemfileLockMismatchError.new(expected: lock.gemfile_lock_fullpath, actual: gemfile_lock_path)
82
+ end
65
83
  end
66
84
 
67
- private def assign_gem(name:, version:)
68
- # @type var locked: gem_entry?
69
- locked = lock&.gem(name)
70
- specified = config.gem(name)
85
+ private def assign_gem(name:, version:, ignored_gems:, src_data:)
86
+ return if ignored_gems.include?(name)
87
+ return if lockfile.gems.key?(name)
71
88
 
72
- return if specified&.dig('ignore')
73
- return if specified&.dig('source') # skip if the source is already filled
89
+ # @type var locked: Lockfile::library?
90
+
91
+ if existing_lockfile
92
+ locked = existing_lockfile.gems[name]
93
+ end
74
94
 
75
95
  # If rbs_collection.lock.yaml contain the gem, use it.
76
96
  # Else find the gem from gem_collection.
77
97
  unless locked
78
- source = find_source(name: name)
98
+ source =
99
+ if src_data
100
+ Sources.from_config_entry(src_data)
101
+ else
102
+ find_source(name: name)
103
+ end
79
104
  return unless source
80
105
 
81
106
  installed_version = version
82
- best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => name }))
107
+ best_version = find_best_version(version: installed_version, versions: source.versions(name))
83
108
 
84
109
  locked = {
85
- 'name' => name,
86
- 'version' => best_version.to_s,
87
- 'source' => source.to_lockfile,
110
+ name: name,
111
+ version: best_version.to_s,
112
+ source: source,
88
113
  }
89
114
  end
90
115
 
91
116
  locked or raise
92
117
 
93
- upsert_gem specified, locked
94
- source = Sources.from_config_entry(locked['source'] || raise)
95
- source.dependencies_of(locked)&.each do |dep|
96
- @gem_queue.push({ name: dep['name'], version: nil} )
118
+ lockfile.gems[name] = locked
119
+ source = locked[:source]
120
+
121
+ source.dependencies_of(locked[:name], locked[:version])&.each do |dep|
122
+ assign_stdlib(name: dep["name"], from_gem: name)
97
123
  end
98
124
  end
99
125
 
100
- private def upsert_gem(old, new)
101
- if old
102
- old.merge! new
103
- else
104
- config.add_gem new
126
+ private def assign_stdlib(name:, from_gem:)
127
+ return if lockfile.gems.key?(name)
128
+
129
+ if name == 'rubygems'
130
+ if from_gem
131
+ RBS.logger.warn "`rubygems` has been moved to core library, so it is always loaded. Remove explicit loading `rubygems` from `#{from_gem}`"
132
+ else
133
+ RBS.logger.warn '`rubygems` has been moved to core library, so it is always loaded. Remove explicit loading `rubygems`'
134
+ end
135
+
136
+ return
105
137
  end
106
- end
107
138
 
108
- private def remove_ignored_gems!
109
- config.gems.reject! { |gem| gem['ignore'] }
139
+ source = Sources::Stdlib.instance
140
+ lockfile.gems[name] = { name: name, version: "0", source: source }
141
+
142
+ unless source.has?(name, nil)
143
+ raise "Cannot find `#{name}` from standard libraries"
144
+ end
145
+
146
+ if deps = source.dependencies_of(name, "0")
147
+ deps.each do |dep|
148
+ assign_stdlib(name: dep["name"], from_gem: name)
149
+ end
150
+ end
110
151
  end
111
152
 
112
153
  private def gemfile_lock_gems(&block)
@@ -118,7 +159,7 @@ module RBS
118
159
  private def find_source(name:)
119
160
  sources = config.sources
120
161
 
121
- sources.find { |c| c.has?({ 'name' => name, 'revision' => nil } ) }
162
+ sources.find { |c| c.has?(name, nil) }
122
163
  end
123
164
 
124
165
  private def find_best_version(version:, versions:)
@@ -16,6 +16,8 @@ module RBS
16
16
 
17
17
  PATH = Pathname('rbs_collection.yaml')
18
18
 
19
+ attr_reader :config_path, :data
20
+
19
21
  def self.find_config_path
20
22
  current = Pathname.pwd
21
23
 
@@ -30,18 +32,16 @@ module RBS
30
32
  # Generate a rbs lockfile from Gemfile.lock to `config_path`.
31
33
  # If `with_lockfile` is true, it respects existing rbs lockfile.
32
34
  def self.generate_lockfile(config_path:, gemfile_lock_path:, with_lockfile: true)
33
- LockfileGenerator.generate(config_path: config_path, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile)
35
+ config = from_path(config_path)
36
+ lockfile = LockfileGenerator.generate(config: config, gemfile_lock_path: gemfile_lock_path, with_lockfile: with_lockfile)
37
+
38
+ [config, lockfile]
34
39
  end
35
40
 
36
41
  def self.from_path(path)
37
42
  new(YAML.load(path.read), config_path: path)
38
43
  end
39
44
 
40
- def self.lockfile_of(config_path)
41
- lock_path = to_lockfile_path(config_path)
42
- from_path lock_path if lock_path.exist?
43
- end
44
-
45
45
  def self.to_lockfile_path(config_path)
46
46
  config_path.sub_ext('.lock' + config_path.extname)
47
47
  end
@@ -51,16 +51,16 @@ module RBS
51
51
  @config_path = config_path
52
52
  end
53
53
 
54
- def add_gem(gem)
55
- gems << gem
56
- end
57
-
58
54
  def gem(gem_name)
59
55
  gems.find { |gem| gem['name'] == gem_name }
60
56
  end
61
57
 
62
58
  def repo_path
63
- @config_path.dirname.join @data['path']
59
+ @config_path.dirname.join repo_path_data
60
+ end
61
+
62
+ def repo_path_data
63
+ Pathname(@data["path"])
64
64
  end
65
65
 
66
66
  def sources
@@ -72,37 +72,9 @@ module RBS
72
72
  )
73
73
  end
74
74
 
75
- def dump_to(io)
76
- YAML.dump(@data, io)
77
- end
78
-
79
75
  def gems
80
76
  @data['gems'] ||= []
81
77
  end
82
-
83
- def gemfile_lock_path=(path)
84
- @data['gemfile_lock_path'] = path.relative_path_from(@config_path.dirname).to_s
85
- end
86
-
87
- def gemfile_lock_path
88
- path = @data['gemfile_lock_path']
89
- return unless path
90
- @config_path.dirname.join path
91
- end
92
-
93
- # It raises an error when there are non-available libraries
94
- def check_rbs_availability!
95
- raise CollectionNotAvailable unless repo_path.exist?
96
-
97
- gems.each do |gem|
98
- case gem['source']['type']
99
- when 'git'
100
- meta_path = repo_path.join(gem['name'], gem['version'], Sources::Git::METADATA_FILENAME)
101
- raise CollectionNotAvailable unless meta_path.exist?
102
- raise CollectionNotAvailable unless gem == YAML.load(meta_path.read)
103
- end
104
- end
105
- end
106
78
  end
107
79
  end
108
80
  end
@@ -7,27 +7,23 @@ module RBS
7
7
  attr_reader :stdout
8
8
 
9
9
  def initialize(lockfile_path:, stdout: $stdout)
10
- @lockfile = Config.from_path(lockfile_path)
10
+ @lockfile = Config::Lockfile.from_lockfile(lockfile_path: lockfile_path, data: YAML.load_file(lockfile_path))
11
11
  @stdout = stdout
12
12
  end
13
13
 
14
14
  def install_from_lockfile
15
- install_to = lockfile.repo_path
15
+ install_to = lockfile.fullpath
16
16
  install_to.mkpath
17
- lockfile.gems.each do |config_entry|
18
- source_for(config_entry).install(dest: install_to, config_entry: config_entry, stdout: stdout)
17
+ lockfile.gems.each_value do |gem|
18
+ gem[:source].install(
19
+ dest: install_to,
20
+ name: gem[:name],
21
+ version: gem[:version],
22
+ stdout: stdout
23
+ )
19
24
  end
20
25
  stdout.puts "It's done! #{lockfile.gems.size} gems' RBSs now installed."
21
26
  end
22
-
23
- private def source_for(config_entry)
24
- @source_for ||= {}
25
- key = config_entry['source']
26
- unless key
27
- raise "Cannot find source of '#{config_entry['name']}' gem"
28
- end
29
- @source_for[key] ||= Sources.from_config_entry(key)
30
- end
31
27
  end
32
28
  end
33
29
  end
@@ -4,8 +4,8 @@ module RBS
4
4
  module Collection
5
5
  module Sources
6
6
  module Base
7
- def dependencies_of(config_entry)
8
- manifest = manifest_of(config_entry) or return
7
+ def dependencies_of(name, version)
8
+ manifest = manifest_of(name, version) or return
9
9
  manifest['dependencies']
10
10
  end
11
11
  end
@@ -13,64 +13,78 @@ module RBS
13
13
 
14
14
  class CommandError < StandardError; end
15
15
 
16
- attr_reader :name, :remote, :repo_dir
16
+ attr_reader :name, :remote, :repo_dir, :revision
17
17
 
18
18
  def initialize(name:, revision:, remote:, repo_dir:)
19
19
  @name = name
20
20
  @remote = remote
21
21
  @repo_dir = repo_dir || 'gems'
22
-
23
- setup!(revision: revision)
22
+ @revision = revision
23
+ @need_setup = true
24
24
  end
25
25
 
26
- def has?(config_entry)
27
- gem_name = config_entry['name']
28
- gem_repo_dir.join(gem_name).directory?
26
+ def has?(name, version)
27
+ setup! do
28
+ if version
29
+ (gems_versions[name] || Set[]).include?(version)
30
+ else
31
+ gems_versions.key?(name)
32
+ end
33
+ end
29
34
  end
30
35
 
31
- def versions(config_entry)
32
- gem_name = config_entry['name']
33
- gem_repo_dir.join(gem_name).glob('*/').map { |path| path.basename.to_s }
36
+ def versions(name)
37
+ setup! do
38
+ versions = gems_versions[name] or raise "Git source `#{name}` doesn't have `#{name}`"
39
+ versions.sort
40
+ end
34
41
  end
35
42
 
36
- def install(dest:, config_entry:, stdout:)
37
- gem_name = config_entry['name']
38
- version = config_entry['version'] or raise
39
- gem_dir = dest.join(gem_name, version)
43
+ def install(dest:, name:, version:, stdout:)
44
+ setup!()
45
+
46
+ gem_dir = dest.join(name, version)
40
47
 
41
48
  if gem_dir.directory?
42
- if (prev = YAML.load_file(gem_dir.join(METADATA_FILENAME))) == config_entry
43
- stdout.puts "Using #{format_config_entry(config_entry)}"
49
+ prev = load_metadata(dir: gem_dir)
50
+
51
+ if prev == metadata_content(name: name, version: version)
52
+ stdout.puts "Using #{format_config_entry(name, version)}"
44
53
  else
45
- # @type var prev: RBS::Collection::Config::gem_entry
46
- stdout.puts "Updating to #{format_config_entry(config_entry)} from #{format_config_entry(prev)}"
54
+ stdout.puts "Updating to #{format_config_entry(name, version)} from #{format_config_entry(prev["name"], prev["version"])}"
47
55
  FileUtils.remove_entry_secure(gem_dir.to_s)
48
- _install(dest: dest, config_entry: config_entry)
56
+ _install(dest: dest, name: name, version: version)
49
57
  end
50
58
  else
51
- stdout.puts "Installing #{format_config_entry(config_entry)}"
52
- _install(dest: dest, config_entry: config_entry)
59
+ stdout.puts "Installing #{format_config_entry(name, version)}"
60
+ _install(dest: dest, name: name, version: version)
53
61
  end
54
62
  end
55
63
 
56
- def manifest_of(config_entry)
57
- gem_name = config_entry['name']
58
- version = config_entry['version'] or raise
59
- gem_dir = gem_repo_dir.join(gem_name, version)
60
-
61
- manifest_path = gem_dir.join('manifest.yaml')
62
- YAML.safe_load(manifest_path.read) if manifest_path.exist?
64
+ def manifest_of(name, version)
65
+ setup! do
66
+ path = File.join(repo_dir, name, version, 'manifest.yaml')
67
+ content = git('cat-file', '-p', "#{resolved_revision}:#{path}")
68
+ YAML.safe_load(content)
69
+ rescue CommandError
70
+ if has?(name, version)
71
+ nil
72
+ else
73
+ raise
74
+ end
75
+ end
63
76
  end
64
77
 
65
- private def _install(dest:, config_entry:)
66
- gem_name = config_entry['name']
67
- version = config_entry['version'] or raise
68
- dest = dest.join(gem_name, version)
69
- dest.mkpath
70
- src = gem_repo_dir.join(gem_name, version)
78
+ private def _install(dest:, name:, version:)
79
+ # Should checkout that revision to support symlinks
80
+ git("reset", "--hard", resolved_revision)
71
81
 
72
- cp_r(src, dest)
73
- dest.join(METADATA_FILENAME).write(YAML.dump(config_entry))
82
+ dir = dest.join(name, version)
83
+ dir.mkpath
84
+ src = gem_repo_dir.join(name, version)
85
+
86
+ cp_r(src, dir)
87
+ write_metadata(dir: dir, name: name, version: version)
74
88
  end
75
89
 
76
90
  private def cp_r(src, dest)
@@ -97,40 +111,37 @@ module RBS
97
111
  }
98
112
  end
99
113
 
100
- private def format_config_entry(config_entry)
101
- name = config_entry['name']
102
- v = config_entry['version']
103
-
114
+ private def format_config_entry(name, version)
104
115
  rev = resolved_revision[0..10]
105
116
  desc = "#{name}@#{rev}"
106
117
 
107
- "#{name}:#{v} (#{desc})"
118
+ "#{name}:#{version} (#{desc})"
108
119
  end
109
120
 
110
- private def setup!(revision:)
111
- git_dir.mkpath
112
- if git_dir.join('.git').directory?
113
- if need_to_fetch?(revision)
114
- git 'fetch', 'origin'
115
- end
116
- else
117
- begin
118
- # git v2.27.0 or greater
119
- git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
120
- rescue CommandError
121
- git 'clone', remote, git_dir.to_s, chdir: nil
121
+ private def setup!
122
+ if @need_setup
123
+ git_dir.mkpath
124
+ if git_dir.join('.git').directory?
125
+ if need_to_fetch?(revision)
126
+ git 'fetch', 'origin'
127
+ end
128
+ else
129
+ begin
130
+ # git v2.27.0 or greater
131
+ git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
132
+ rescue CommandError
133
+ git 'clone', remote, git_dir.to_s, chdir: nil
134
+ end
122
135
  end
123
- end
124
136
 
125
- begin
126
- git 'checkout', "origin/#{revision}" # for branch name as `revision`
127
- rescue CommandError
128
- git 'checkout', revision
137
+ @need_setup = false
129
138
  end
139
+
140
+ yield if block_given?
130
141
  end
131
142
 
132
143
  private def need_to_fetch?(revision)
133
- return true unless revision.match?(/\A[a-f0-9]{40}\z/)
144
+ return true unless commit_hash?
134
145
 
135
146
  begin
136
147
  git('cat-file', '-e', revision)
@@ -154,18 +165,31 @@ module RBS
154
165
  git_dir.join @repo_dir
155
166
  end
156
167
 
157
- private def resolved_revision
158
- @resolved_revision ||= resolve_revision
168
+ def resolved_revision
169
+ @resolved_revision ||=
170
+ begin
171
+ if commit_hash?
172
+ revision
173
+ else
174
+ setup! { git('rev-parse', revision).chomp }
175
+ end
176
+ end
159
177
  end
160
178
 
161
- private def resolve_revision
162
- git('rev-parse', 'HEAD').chomp
179
+ private def commit_hash?
180
+ revision.match?(/\A[a-f0-9]{40}\z/)
163
181
  end
164
182
 
165
183
  private def git(*cmd, **opt)
166
184
  sh! 'git', *cmd, **opt
167
185
  end
168
186
 
187
+ private def git?(*cmd, **opt)
188
+ git(*cmd, **opt)
189
+ rescue CommandError
190
+ nil
191
+ end
192
+
169
193
  private def sh!(*cmd, **opt)
170
194
  RBS.logger.debug "$ #{cmd.join(' ')}"
171
195
  opt = { chdir: git_dir }.merge(opt).compact
@@ -175,6 +199,55 @@ module RBS
175
199
  out
176
200
  end
177
201
  end
202
+
203
+ def metadata_content(name:, version:)
204
+ {
205
+ "name" => name,
206
+ "version" => version,
207
+ "source" => to_lockfile
208
+ }
209
+ end
210
+
211
+ def write_metadata(dir:, name:, version:)
212
+ dir.join(METADATA_FILENAME).write(
213
+ YAML.dump(
214
+ metadata_content(name: name, version: version)
215
+ )
216
+ )
217
+ end
218
+
219
+ def load_metadata(dir:)
220
+ # @type var content: Hash[String, untyped]
221
+ content = YAML.load_file(dir.join(METADATA_FILENAME).to_s)
222
+ _ = content.slice("name", "version", "source")
223
+ end
224
+
225
+ private def gems_versions
226
+ @gems_versions ||= begin
227
+ repo_path = Pathname(repo_dir)
228
+
229
+ paths = git('ls-tree', '--full-tree', '-dr', '--name-only', '-z', resolved_revision, File.join(repo_dir, "")).split("\0").map {|line| Pathname(line) }
230
+
231
+ # @type var versions: Hash[String, Set[String]]
232
+ versions = {}
233
+
234
+ paths.each do |full_path|
235
+ path = full_path.relative_path_from(repo_path)
236
+
237
+ gem_name, version = path.descend.take(2)
238
+
239
+ if gem_name
240
+ versions[gem_name.to_s] ||= Set[]
241
+
242
+ if version
243
+ versions[gem_name.to_s] << version.basename.to_s
244
+ end
245
+ end
246
+ end
247
+
248
+ versions
249
+ end
250
+ end
178
251
  end
179
252
  end
180
253
  end
@@ -10,26 +10,24 @@ module RBS
10
10
  include Base
11
11
  include Singleton
12
12
 
13
- def has?(config_entry)
14
- gem_sig_path(config_entry)
13
+ def has?(name, version)
14
+ gem_sig_path(name, version)
15
15
  end
16
16
 
17
- def versions(config_entry)
18
- spec, _ = gem_sig_path(config_entry)
17
+ def versions(name)
18
+ spec, _ = gem_sig_path(name, nil)
19
19
  spec or raise
20
20
  [spec.version.to_s]
21
21
  end
22
22
 
23
- def install(dest:, config_entry:, stdout:)
23
+ def install(dest:, name:, version:, stdout:)
24
24
  # Do nothing because stdlib RBS is available by default
25
- name = config_entry['name']
26
- version = config_entry['version'] or raise
27
- _, from = gem_sig_path(config_entry)
25
+ _, from = gem_sig_path(name, version)
28
26
  stdout.puts "Using #{name}:#{version} (#{from})"
29
27
  end
30
28
 
31
- def manifest_of(config_entry)
32
- _, sig_path = gem_sig_path(config_entry)
29
+ def manifest_of(name, version)
30
+ _, sig_path = gem_sig_path(name, version)
33
31
  sig_path or raise
34
32
  manifest_path = sig_path.join('manifest.yaml')
35
33
  YAML.safe_load(manifest_path.read) if manifest_path.exist?
@@ -41,8 +39,8 @@ module RBS
41
39
  }
42
40
  end
43
41
 
44
- private def gem_sig_path(config_entry)
45
- RBS::EnvironmentLoader.gem_sig_path(config_entry['name'], config_entry['version'])
42
+ private def gem_sig_path(name, version)
43
+ RBS::EnvironmentLoader.gem_sig_path(name, version)
46
44
  end
47
45
  end
48
46
  end