77require 'rexml/document'
88require 'open3' # [macOS]
99require 'json' # [macOS]
10+ require 'tmpdir' # [macOS]
1011
1112HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git"
1213ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE"
@@ -177,8 +178,18 @@ def podspec_source_build_from_github_tag(react_native_path)
177178end
178179
179180def 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]
182193end
183194
184195def podspec_source_download_prebuild_release_tarball ( react_native_path , version )
@@ -201,6 +212,51 @@ def artifacts_dir()
201212 return File . join ( Pod ::Config . instance . project_pods_root , "hermes-engine-artifacts" )
202213end
203214
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+
204260def hermestag_file ( react_native_path )
205261 return File . join ( react_native_path , "sdks" , ".hermesversion" )
206262end
@@ -240,15 +296,20 @@ def resolve_url_redirects(url)
240296 return ( `curl -Ls -o /dev/null -w %{url_effective} \" #{ url } \" ` )
241297end
242298
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." )
252313end
253314# macOS]
254315
0 commit comments