Skip to content

Commit b86d7c5

Browse files
committed
Add the ruby platform to the gem version
Knowing the exact platform of a compiled gem is important to download the correct gem and because different binaries have different hashes. Note that this change makes the gemset platform dependant.
1 parent c5155b9 commit b86d7c5

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

lib/bundix/source.rb

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,35 +92,59 @@ def format_hash(hash)
9292
end
9393

9494
def fetch_local_hash(spec)
95-
spec.source.caches.each do |cache|
96-
path = File.join(cache, "#{spec.full_name}.gem")
97-
next unless File.file?(path)
95+
has_platform = spec.platform && spec.platform != Gem::Platform::RUBY
96+
name_version = "#{spec.name}-#{spec.version}"
97+
filename = has_platform ? "#{name_version}-*" : name_version
98+
99+
paths = spec.source.caches.map(&:to_s)
100+
Dir.glob("{#{paths.join(',')}}/#{filename}.gem").each do |path|
101+
if has_platform
102+
# Find first gem that matches the platform
103+
platform = File.basename(path, '.gem')[(name_version.size + 1)..-1]
104+
next unless Gem::Platform.match(platform)
105+
end
106+
98107
hash = nix_prefetch_url(path)[SHA256_32]
99-
return format_hash(hash) if hash
108+
return format_hash(hash), platform if hash
100109
end
101110

102111
nil
103112
end
104113

105114
def fetch_remotes_hash(spec, remotes)
106115
remotes.each do |remote|
107-
hash = fetch_remote_hash(spec, remote)
108-
return remote, format_hash(hash) if hash
116+
hash, platform = fetch_remote_hash(spec, remote)
117+
return remote, format_hash(hash), platform if hash
109118
end
110119

111120
nil
112121
end
113122

114123
def fetch_remote_hash(spec, remote)
124+
has_platform = spec.platform && spec.platform != Gem::Platform::RUBY
125+
if has_platform
126+
# Fetch remote spec to determine the exact platform
127+
# Note that we can't simply use the local platform; the platform of the gem might differ.
128+
# e.g. universal-darwin-14 covers x86_64-darwin-14
129+
spec = spec_for_dependency(remote, spec.name, spec.version)
130+
return unless spec
131+
end
132+
115133
uri = "#{remote}/gems/#{spec.full_name}.gem"
116134
result = nix_prefetch_url(uri)
117135
return unless result
118-
result[SHA256_32]
136+
137+
return result[SHA256_32], spec.platform&.to_s
119138
rescue => e
120139
puts "ignoring error during fetching: #{e}"
121140
puts e.backtrace
122141
nil
123142
end
143+
144+
def spec_for_dependency(remote, name, version)
145+
sources = Gem::SourceList.from([remote])
146+
Gem::SpecFetcher.new(sources).spec_for_dependency(Gem::Dependency.new(name, version)).first&.first&.first
147+
end
124148
end
125149

126150
class Source < Struct.new(:spec, :fetcher)
@@ -150,11 +174,14 @@ def convert_path
150174

151175
def convert_rubygems
152176
remotes = spec.source.remotes.map{|remote| remote.to_s.sub(/\/+$/, '') }
153-
hash = fetcher.fetch_local_hash(spec)
154-
remote, hash = fetcher.fetch_remotes_hash(spec, remotes) unless hash
177+
hash, platform = fetcher.fetch_local_hash(spec)
178+
remote, hash, platform = fetcher.fetch_remotes_hash(spec, remotes) unless hash
155179
fail "couldn't fetch hash for #{spec.full_name}" unless hash
156180

157181
version = spec.version.to_s
182+
if platform && platform != Gem::Platform::RUBY
183+
version += "-#{platform}"
184+
end
158185

159186
puts "#{hash} => #{spec.name}-#{version}.gem" if $VERBOSE
160187

test/convert.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55

66
class TestConvert < Minitest::Test
77
class PrefetchStub < Bundix::Fetcher
8+
SPECS = {
9+
"sorbet-static" => {
10+
platform: 'java-123',
11+
version: "0.4.4821",
12+
},
13+
}
14+
815
def nix_prefetch_url(*args)
916
format_hash(Digest::SHA256.hexdigest(args.to_s))
1017
end
@@ -18,6 +25,16 @@ def fetch_local_hash(spec)
1825
return nil
1926
end
2027

28+
def spec_for_dependency(remote, name, version)
29+
opts = SPECS[name]
30+
raise "Unexpected spec query: #{name}" unless opts
31+
32+
Gem::Specification.new do |s|
33+
s.name = name
34+
s.version = version
35+
s.platform = Gem::Platform.new(opts[:platform]) if opts[:platform]
36+
end
37+
end
2138
end
2239

2340
def with_gemset(options)
@@ -40,7 +57,7 @@ def test_bundler_dep
4057
) do |gemset|
4158
assert_equal("0.5.0", gemset.dig("bundler-audit", :version))
4259
assert_equal("0.19.4", gemset.dig("thor", :version))
43-
assert_equal("0.4.4821", gemset.dig("sorbet-static", :version))
60+
assert_equal("0.4.4821-java-unknown", gemset.dig("sorbet-static", :version))
4461
end
4562
end
4663
end

0 commit comments

Comments
 (0)