Skip to content

Commit 6a921d0

Browse files
committed
Include all available platforms for a gem in the gemset
gemset attrs stay the same, with the addition of a nativeSources set: ```nix { libv8-node = { groups = ["default"]; nativeSources = [{ platform = "arm64-darwin-20"; remotes = ["https://rubygems.org"]; sha256 = "04qnpw0bm8j82km2whx5zhw59lm8isd3i540g1xfyc0mqw0vynhp"; type = "gem"; } { platform = "x86_64-darwin-20"; remotes = ["https://rubygems.org"]; sha256 = "0r65dwxjrk6s9q4lf1jf7kg344qg3fn8d9r6nad91swmabpzd2bg"; type = "gem"; } { platform = "x86_64-linux"; remotes = ["https://rubygems.org"]; sha256 = "04avzccvrjk4nbi7926cvbdkpkgc6a2m0gyz1s1k4x7q06lkdnnk"; type = "gem"; }]; platforms = []; source = { platform = "ruby"; remotes = ["https://rubygems.org"]; sha256 = "0k2cqxnbm7lm284fa65bf4b18w7k6977mh6anyyai34r43g3vm34"; type = "gem"; }; version = "15.14.0.0"; }; } } ```
1 parent b86d7c5 commit 6a921d0

2 files changed

Lines changed: 31 additions & 8 deletions

File tree

lib/bundix.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,27 @@ def convert
4040
lock = parse_lockfile
4141
dep_cache = build_depcache(lock)
4242

43+
gems = Hash.new { |h, k| h[k] = [] }
44+
4345
# reverse so git comes last
44-
lock.specs.reverse_each.with_object({}) do |spec, gems|
46+
lock.specs.reverse_each do |spec|
4547
gem = find_cached_spec(spec, cache) || convert_spec(spec, cache, dep_cache)
46-
gems.merge!(gem)
47-
48+
gem = gem.values.first # `gem` is a hash with only one value
4849
if spec.dependencies.any?
49-
gems[spec.name]['dependencies'] = spec.dependencies.map(&:name) - ['bundler']
50+
gem['dependencies'] = spec.dependencies.map(&:name) - ['bundler']
5051
end
52+
gems[spec.name] << JSON.load(JSON.dump(gem)) # awful hack to stringify keys
5153
end
54+
55+
gems.map do |name, variants|
56+
# use the plain old ruby gem as the primary source, add other platforms as 'nativeSources'
57+
# If for some reason there's no plain ruby gem, just use the first available platform as the primary source
58+
primary, *others = variants.sort_by do |v|
59+
platform = v["source"]["platform"] || "ruby"
60+
[platform == "ruby" ? 0 : 1, platform]
61+
end
62+
[name, primary.merge("nativeSources" => others.map { |o| o["source"] }.uniq)]
63+
end.to_h
5264
end
5365

5466
def groups(spec, dep_cache)
@@ -100,6 +112,10 @@ def convert_spec(spec, cache, dep_cache)
100112
end
101113

102114
def find_cached_spec(spec, cache)
115+
if spec.platform != "ruby"
116+
puts "TODO: figure out a sane way of dealing with nativeSources from the cache"
117+
return nil
118+
end
103119
name, cached = cache.find{|k, v|
104120
next unless k == spec.name
105121
next unless cached_source = v['source']

lib/bundix/source.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def fetch_local_hash(spec)
101101
if has_platform
102102
# Find first gem that matches the platform
103103
platform = File.basename(path, '.gem')[(name_version.size + 1)..-1]
104-
next unless Gem::Platform.match(platform)
104+
next unless spec.platform =~ platform
105105
end
106106

107107
hash = nix_prefetch_url(path)[SHA256_32]
@@ -126,7 +126,7 @@ def fetch_remote_hash(spec, remote)
126126
# Fetch remote spec to determine the exact platform
127127
# Note that we can't simply use the local platform; the platform of the gem might differ.
128128
# e.g. universal-darwin-14 covers x86_64-darwin-14
129-
spec = spec_for_dependency(remote, spec.name, spec.version)
129+
spec = spec_for_dependency(remote, spec)
130130
return unless spec
131131
end
132132

@@ -141,9 +141,15 @@ def fetch_remote_hash(spec, remote)
141141
nil
142142
end
143143

144-
def spec_for_dependency(remote, name, version)
144+
def spec_for_dependency(remote, dependency)
145145
sources = Gem::SourceList.from([remote])
146-
Gem::SpecFetcher.new(sources).spec_for_dependency(Gem::Dependency.new(name, version)).first&.first&.first
146+
specs, _errors = Gem::SpecFetcher.new(sources).spec_for_dependency(Gem::Dependency.new(dependency.name, dependency.version), false)
147+
specs.each do |spec, source|
148+
return spec if dependency.platform == spec.platform
149+
end
150+
# TODO: When might this happen?
151+
puts 'oh, fallback ' + dependency.platform.to_s
152+
specs.first.first
147153
end
148154
end
149155

@@ -191,6 +197,7 @@ def convert_rubygems
191197
type: 'gem',
192198
remotes: (remote ? [remote] : remotes),
193199
sha256: hash,
200+
platform: platform || "ruby",
194201
},
195202
}
196203
end

0 commit comments

Comments
 (0)