Skip to content

Commit

Permalink
Merge pull request #808 from pocke/Add_manifest_yaml_for_collection_t…
Browse files Browse the repository at this point in the history
…o_specify_stdlib_dependencies

Add manifest.yaml for collection to specify stdlib dependencies
  • Loading branch information
pocke authored Dec 16, 2021
2 parents 75b10f4 + 2518857 commit 02d2a4f
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 36 deletions.
24 changes: 23 additions & 1 deletion docs/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* `git(1)`
* `Gemfile.lock`


## Usage

### Setup
Expand Down Expand Up @@ -65,9 +64,13 @@ Finally the third party RBSs are available! `rbs` commands, such as `rbs validat

## Configuration

### `rbs_collection.yaml`

Configure `rbs collection` with editing `rbs_collection.yaml`.

```yaml
# rbs_collection.yaml

# Download sources.
# You can add own collection git repository.
sources:
Expand All @@ -92,6 +95,25 @@ gems:
ignore: true
```
### `manifest.yaml`

If you are a gem maintainer, you can write `manifest.yaml`.
You need to put the file if the gem has implicit dependencies, which don't appear in `Gemfile.lock`. You have to write standard libraries' dependencies in most cases.
For example:

```yaml
# manifest.yaml
dependencies:
# If your gem depends on pathname but the gemspec doesn't include pathname,
# you need to write the following.
- name: pathname
```

If the gem's RBS is managed with [ruby/gem_rbs_collection](https://github.com/ruby/gem_rbs_collection), put it as `gems/GEM_NAME/VERSION/manifest.yaml`. For example, `gems/activesupport/6.0/manifest.yaml`.
If the gem's RBS is included in the gem package, put it as `sig/manifest.yaml`.


## Files / Directories

* `rbs_collection.yaml`
Expand Down
44 changes: 26 additions & 18 deletions lib/rbs/collection/config/lockfile_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,54 @@ def initialize(config_path:, gemfile_lock_path:, with_lockfile:)
@lock_path = Config.to_lockfile_path(config_path)
@lock = Config.from_path(lock_path) if lock_path.exist? && with_lockfile
@gemfile_lock = Bundler::LockfileParser.new(gemfile_lock_path.read)
@gem_queue = []
end

def generate
config.gems.each do |gem|
assign_gem(gem_name: gem['name'], version: gem['version'])
@gem_queue.push({ name: gem['name'], version: gem['version'] })
end

gemfile_lock_gems do |spec|
assign_gem(gem_name: spec.name, version: spec.version)
@gem_queue.push({ name: spec.name, version: spec.version })
end

while gem = @gem_queue.shift
assign_gem(**gem)
end
remove_ignored_gems!

config.dump_to(lock_path)
config
end

private def assign_gem(gem_name:, version:)
locked = lock&.gem(gem_name)
specified = config.gem(gem_name)
private def assign_gem(name:, version:)
locked = lock&.gem(name)
specified = config.gem(name)

return if specified&.dig('ignore')
return if specified&.dig('source') # skip if the source is already filled

if locked
# If rbs_collection.lock.yaml contain the gem, use it.
upsert_gem specified, locked
else
# Find the gem from gem_collection.
source = find_source(gem_name: gem_name)
# If rbs_collection.lock.yaml contain the gem, use it.
# Else find the gem from gem_collection.
unless locked
source = find_source(name: name)
return unless source

installed_version = version
best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => gem_name }))
# @type var new_content: RBS::Collection::Config::gem_entry
new_content = {
'name' => gem_name,
best_version = find_best_version(version: installed_version, versions: source.versions({ 'name' => name }))
locked = {
'name' => name,
'version' => best_version.to_s,
'source' => source.to_lockfile,
}
upsert_gem specified, new_content
end

upsert_gem specified, locked
source = Sources.from_config_entry(locked['source'])
manifest = source.manifest_of(locked) or return
manifest['dependencies']&.each do |dep|
@gem_queue.push({ name: dep['name'], version: nil} )
end
end

Expand All @@ -76,10 +84,10 @@ def generate
end
end

private def find_source(gem_name:)
private def find_source(name:)
sources = config.sources

sources.find { |c| c.has?({ 'name' => gem_name, 'revision' => nil } ) }
sources.find { |c| c.has?({ 'name' => name, 'revision' => nil } ) }
end

private def find_best_version(version:, versions:)
Expand Down
9 changes: 9 additions & 0 deletions lib/rbs/collection/sources/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ def install(dest:, config_entry:, stdout:)
end
end

def manifest_of(config_entry)
gem_name = config_entry['name']
version = config_entry['version'] or raise
gem_dir = gem_repo_dir.join(gem_name, version)

manifest_path = gem_dir.join('manifest.yaml')
YAML.safe_load(manifest_path.read) if manifest_path.exist?
end

private def _install(dest:, config_entry:)
gem_name = config_entry['name']
version = config_entry['version'] or raise
Expand Down
7 changes: 7 additions & 0 deletions lib/rbs/collection/sources/rubygems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ def install(dest:, config_entry:, stdout:)
stdout.puts "Using #{name}:#{version} (#{from})"
end

def manifest_of(config_entry)
_, sig_path = gem_sig_path(config_entry)
sig_path or raise
manifest_path = sig_path.join('manifest.yaml')
YAML.safe_load(manifest_path.read) if manifest_path.exist?
end

def to_lockfile
{
'type' => 'rubygems',
Expand Down
6 changes: 6 additions & 0 deletions lib/rbs/collection/sources/stdlib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ def install(dest:, config_entry:, stdout:)
stdout.puts "Using #{name}:#{version} (#{from})"
end

def manifest_of(config_entry)
version = config_entry['version'] or raise
manifest_path = gem_dir(config_entry).join(version, 'manifest.yaml')
YAML.safe_load(manifest_path.read) if manifest_path.exist?
end

def to_lockfile
{
'type' => 'stdlib',
Expand Down
9 changes: 9 additions & 0 deletions sig/collection/collections.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ module RBS
def versions: (Config::gem_entry) -> Array[String]
def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
def to_lockfile: () -> source_entry
def manifest_of: (Config::gem_entry) -> manifest_entry?
end

type source_entry = Git::source_entry
| Stdlib::source_entry
| Rubygems::source_entry
type manifest_entry = {
"dependencies" => Array[{"name" => String}]?,
}

class Git
METADATA_FILENAME: String
Expand Down Expand Up @@ -42,6 +46,8 @@ module RBS

def to_lockfile: () -> source_entry

def manifest_of: (Config::gem_entry) -> manifest_entry?

private

def _install: (dest: Pathname , config_entry: Config::gem_entry) -> void
Expand Down Expand Up @@ -86,6 +92,8 @@ module RBS

def to_lockfile: () -> source_entry

def manifest_of: (Config::gem_entry) -> manifest_entry?

private

def gem_dir: (Config::gem_entry) -> Pathname
Expand All @@ -104,6 +112,7 @@ module RBS
def versions: (Config::gem_entry) -> Array[String]
def install: (dest: Pathname, config_entry: Config::gem_entry, stdout: CLI::_IO) -> void
def to_lockfile: () -> source_entry
def manifest_of: (Config::gem_entry) -> manifest_entry?

private

Expand Down
4 changes: 2 additions & 2 deletions sig/collection/config.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ module RBS

private

def assign_gem: (gem_name: String, version: String?) -> void
def assign_gem: (name: String, version: String?) -> void

def upsert_gem: (gem_entry? old, gem_entry new) -> void

def gemfile_lock_gems: () { (untyped) -> void } -> void

def remove_ignored_gems!: () -> void

def find_source: (gem_name: String) -> untyped
def find_source: (name: String) -> untyped

def find_best_version: (version: String?, versions: Array[String]) -> Gem::Version
end
Expand Down
2 changes: 2 additions & 0 deletions stdlib/bigdecimal-math/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: bigdecimal
2 changes: 2 additions & 0 deletions stdlib/csv/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: forwardable
2 changes: 2 additions & 0 deletions stdlib/logger/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: monitor
2 changes: 2 additions & 0 deletions stdlib/net-http/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: uri
2 changes: 2 additions & 0 deletions stdlib/openssl/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: socket
2 changes: 2 additions & 0 deletions stdlib/prime/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: singleton
3 changes: 3 additions & 0 deletions stdlib/resolv/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies:
- name: socket
- name: timeout
3 changes: 3 additions & 0 deletions stdlib/yaml/0/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies:
- name: dbm
- name: pstore
2 changes: 2 additions & 0 deletions test/assets/test-gem/sig/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
- name: pathname
Loading

0 comments on commit 02d2a4f

Please sign in to comment.