7
7
require 'rexml/document'
8
8
require 'open3' # [macOS]
9
9
require 'json' # [macOS]
10
+ require 'tmpdir' # [macOS]
10
11
11
12
HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git"
12
13
ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE"
@@ -177,8 +178,18 @@ def podspec_source_build_from_github_tag(react_native_path)
177
178
end
178
179
179
180
def podspec_source_build_from_github_main ( )
180
- hermes_log ( "Using the latest commit from main." )
181
- return { :git => HERMES_GITHUB_URL , :commit => `git ls-remote #{ HERMES_GITHUB_URL } main | cut -f 1` . strip }
181
+ # hermes_log("Using the latest commit from main.")
182
+ # return {:git => HERMES_GITHUB_URL, :commit => `git ls-remote #{HERMES_GITHUB_URL} main | cut -f 1`.strip}
183
+
184
+ # [macOS
185
+ # The logic for this is a bit different on macOS.
186
+ # Since react-native-macos lags slightly behind facebook/react-native, we can't always use
187
+ # the latest Hermes commit because Hermes and JSI don't always guarantee backwards compatibility.
188
+ # Instead, we take the commit hash of Hermes at the time of the merge base with facebook/react-native.
189
+ commit = hermes_commit_at_merge_base ( )
190
+ hermes_log ( "Using Hermes commit from the merge base with facebook/react-native: #{ commit } " )
191
+ return { :git => HERMES_GITHUB_URL , :commit => commit }
192
+ # macOS]
182
193
end
183
194
184
195
def podspec_source_download_prebuild_release_tarball ( react_native_path , version )
@@ -201,6 +212,51 @@ def artifacts_dir()
201
212
return File . join ( Pod ::Config . instance . project_pods_root , "hermes-engine-artifacts" )
202
213
end
203
214
215
+ # [macOS
216
+ def hermes_commit_at_merge_base ( )
217
+ # We don't need ls-remote because react-native-macos is a fork of facebook/react-native
218
+ fetch_result = `git fetch -q https://github.com/facebook/react-native.git`
219
+ if $?. exitstatus != 0
220
+ abort <<-EOS
221
+ [Hermes] Failed to fetch facebook/react-native into the local repository.
222
+ EOS
223
+ end
224
+
225
+ merge_base = `git merge-base FETCH_HEAD HEAD` . strip
226
+ if merge_base . empty?
227
+ abort <<-EOS
228
+ [Hermes] Unable to find the merge base between our HEAD and upstream's HEAD.
229
+ EOS
230
+ end
231
+
232
+ timestamp = `git show -s --format=%ci #{ merge_base } ` . strip
233
+ if timestamp . empty?
234
+ abort <<-EOS
235
+ [Hermes] Unable to extract the timestamp for the merge base (#{ merge_base } ).
236
+ EOS
237
+ end
238
+
239
+ commit = nil
240
+ Dir . mktmpdir do |tmpdir |
241
+ hermes_git_dir = File . join ( tmpdir , "hermes.git" )
242
+ # Unfortunately we can't use git rev-list on HERMES_GITHUB_URL directly since we're not in that repo.
243
+ # Instead, we create a shallow clone to avoid downloading the entire history.
244
+ `git clone -q --bare --shallow-since="#{ timestamp } " #{ HERMES_GITHUB_URL } "#{ hermes_git_dir } "`
245
+ `git --git-dir="#{ hermes_git_dir } " fetch -q --deepen=1`
246
+
247
+ # If all goes well, this will be the commit hash of Hermes at the time of the merge base
248
+ commit = `git --git-dir="#{ hermes_git_dir } " rev-list -1 --before="#{ timestamp } " HEAD` . strip
249
+ if commit . empty?
250
+ abort <<-EOS
251
+ [Hermes] Unable to find the Hermes commit hash at time #{ timestamp } .
252
+ EOS
253
+ end
254
+ end
255
+
256
+ return commit
257
+ end
258
+ # macOS]
259
+
204
260
def hermestag_file ( react_native_path )
205
261
return File . join ( react_native_path , "sdks" , ".hermesversion" )
206
262
end
@@ -240,15 +296,20 @@ def resolve_url_redirects(url)
240
296
return ( `curl -Ls -o /dev/null -w %{url_effective} \" #{ url } \" ` )
241
297
end
242
298
243
- # [macOS react-native-macos does not publish macos specific hermes artifacts
244
- # so we attempt to find the latest patch version of the iOS artifacts and use that
245
- def findLastestVersionWithArtifact ( version )
246
- # See https://central.sonatype.org/search/rest-api-guide/ for details on query params
247
- versionWithoutPatch = "#{ version . match ( /^(\d +\. \d +)/ ) } "
248
- res , = Open3 . capture3 ( "curl -s https://search.maven.org/solrsearch/select?q=g:com.facebook.react+AND+a:react-native-artifacts+AND+v:#{ versionWithoutPatch } .*&core=gav&rows=1&wt=json" )
249
- wt = JSON . parse ( res )
250
- response = wt [ 'response' ]
251
- return response [ 'docs' ] [ 0 ] [ 'v' ] unless response [ 'numFound' ] == 0
299
+ # [macOS
300
+ # Tries to find a suitable Hermes version for a given react-native-macos package.
301
+ # For stable branches, we prefer this to be specified as a peer dependency.
302
+ def findMatchingHermesVersion ( package )
303
+ if package [ 'version' ] == "1000.0.0"
304
+ # The main branch builds from source, so skip this check
305
+ return nil
306
+ end
307
+
308
+ if package [ 'peerDependencies' ]
309
+ return package [ 'peerDependencies' ] [ 'react-native' ]
310
+ end
311
+
312
+ hermes_log ( "No matching Hermes version found. Defaulting to main branch, which may be unreliable." )
252
313
end
253
314
# macOS]
254
315
0 commit comments