rbs 2.8.4 → 3.0.0.dev.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -28
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +16 -16
  5. data/Rakefile +1 -9
  6. data/ext/rbs_extension/constants.c +2 -0
  7. data/ext/rbs_extension/constants.h +1 -0
  8. data/ext/rbs_extension/extconf.rb +1 -1
  9. data/ext/rbs_extension/parser.c +23 -13
  10. data/ext/rbs_extension/ruby_objs.c +15 -3
  11. data/ext/rbs_extension/ruby_objs.h +2 -1
  12. data/lib/rbs/ast/members.rb +49 -15
  13. data/lib/rbs/cli.rb +6 -1
  14. data/lib/rbs/collection/config/lockfile.rb +115 -0
  15. data/lib/rbs/collection/config/lockfile_generator.rb +89 -48
  16. data/lib/rbs/collection/config.rb +11 -39
  17. data/lib/rbs/collection/installer.rb +9 -13
  18. data/lib/rbs/collection/sources/base.rb +2 -2
  19. data/lib/rbs/collection/sources/git.rb +135 -62
  20. data/lib/rbs/collection/sources/rubygems.rb +10 -12
  21. data/lib/rbs/collection/sources/stdlib.rb +10 -13
  22. data/lib/rbs/collection/sources.rb +7 -1
  23. data/lib/rbs/collection.rb +1 -0
  24. data/lib/rbs/definition.rb +1 -1
  25. data/lib/rbs/definition_builder/method_builder.rb +3 -3
  26. data/lib/rbs/definition_builder.rb +449 -572
  27. data/lib/rbs/environment.rb +5 -3
  28. data/lib/rbs/environment_loader.rb +11 -10
  29. data/lib/rbs/locator.rb +2 -2
  30. data/lib/rbs/prototype/helpers.rb +29 -13
  31. data/lib/rbs/prototype/node_usage.rb +99 -0
  32. data/lib/rbs/prototype/rb.rb +3 -2
  33. data/lib/rbs/prototype/rbi.rb +6 -4
  34. data/lib/rbs/prototype/runtime.rb +25 -12
  35. data/lib/rbs/substitution.rb +19 -0
  36. data/lib/rbs/types.rb +1 -5
  37. data/lib/rbs/validator.rb +2 -1
  38. data/lib/rbs/version.rb +1 -1
  39. data/lib/rbs/writer.rb +26 -17
  40. data/lib/rbs.rb +1 -0
  41. data/lib/rdoc_plugin/parser.rb +1 -1
  42. data/rbs.gemspec +1 -1
  43. data/schema/members.json +15 -10
  44. data/sig/collection/config/lockfile.rbs +80 -0
  45. data/sig/collection/config/lockfile_generator.rbs +55 -0
  46. data/sig/collection/config.rbs +5 -48
  47. data/sig/collection/installer.rbs +1 -1
  48. data/sig/collection/sources.rbs +66 -29
  49. data/sig/definition_builder.rbs +94 -81
  50. data/sig/environment_loader.rbs +1 -1
  51. data/sig/errors.rbs +21 -0
  52. data/sig/members.rbs +31 -7
  53. data/sig/prototype/node_usage.rbs +20 -0
  54. data/sig/shims/bundler.rbs +13 -0
  55. data/sig/shims/rubygems.rbs +9 -0
  56. data/sig/shims.rbs +0 -22
  57. data/sig/substitution.rbs +6 -0
  58. data/sig/writer.rbs +2 -0
  59. data/steep/Gemfile +3 -0
  60. data/steep/Gemfile.lock +61 -0
  61. metadata +13 -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