@@ -92,35 +92,59 @@ def format_hash(hash)
92
92
end
93
93
94
94
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
+
98
107
hash = nix_prefetch_url ( path ) [ SHA256_32 ]
99
- return format_hash ( hash ) if hash
108
+ return format_hash ( hash ) , platform if hash
100
109
end
101
110
102
111
nil
103
112
end
104
113
105
114
def fetch_remotes_hash ( spec , remotes )
106
115
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
109
118
end
110
119
111
120
nil
112
121
end
113
122
114
123
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
+
115
133
uri = "#{ remote } /gems/#{ spec . full_name } .gem"
116
134
result = nix_prefetch_url ( uri )
117
135
return unless result
118
- result [ SHA256_32 ]
136
+
137
+ return result [ SHA256_32 ] , spec . platform &.to_s
119
138
rescue => e
120
139
puts "ignoring error during fetching: #{ e } "
121
140
puts e . backtrace
122
141
nil
123
142
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
124
148
end
125
149
126
150
class Source < Struct . new ( :spec , :fetcher )
@@ -150,11 +174,14 @@ def convert_path
150
174
151
175
def convert_rubygems
152
176
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
155
179
fail "couldn't fetch hash for #{ spec . full_name } " unless hash
156
180
157
181
version = spec . version . to_s
182
+ if platform && platform != Gem ::Platform ::RUBY
183
+ version += "-#{ platform } "
184
+ end
158
185
159
186
puts "#{ hash } => #{ spec . name } -#{ version } .gem" if $VERBOSE
160
187
0 commit comments