From d687d389872f50fa11cbdd44ab3d68bdd392425b Mon Sep 17 00:00:00 2001 From: dirkpostma Date: Sat, 7 Sep 2024 06:27:23 -0700 Subject: [PATCH] Fix duplicate entries in HEADER_SEARCH_PATHS when running react_native_post_install script (#46262) Summary: In a react native project where USE_FRAMEWORKS is not nil, every time when running `pod install`, duplicate lines are added to `HEADER_SEARCH_PATHS` section of `project.pbxproj`: ``` " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", ``` Note: a popular library that needs `use_frameworks` is react-native-firebase. See https://rnfirebase.io/#altering-cocoapods-to-use-frameworks ## Analyse - `react_native_post_install` calls `ReactNativePodsUtils.update_search_paths(installer)` - when `ENV['USE_FRAMEWORKS'] != nil` then `update_search_paths` calls `add_search_path_if_not_included` - `add_search_path_if_not_included` checks if `"#{new_search_path}"` is already there - if not found it adds `" #{new_search_path}"` _with an extra space_ - next time, it can't find `"#{new_search_path}"` because of the extra space, and adds `" #{new_search_path}"` again ## Changelog: [IOS] [FIXED] - react_native_post_install script no longer adds duplicate entries to HEADER_SEARCH_PATHS Pull Request resolved: https://github.com/facebook/react-native/pull/46262 Test Plan: - create a react native project - add `use_frameworks! :linkage => :static` to `ios/Podfile` (just before `use_react_native`) - run `pod install` - assert no duplicate lines are added to HEADER_SEARCH_PATHS of file `project.pbxproj` Reviewed By: cipolleschi Differential Revision: D61982680 Pulled By: shwanton fbshipit-source-id: 61b566893c551d0813edd6eec2f8352c041c748f --- .../scripts/cocoapods/__tests__/utils-test.rb | 68 +++++++++++++++++++ .../react-native/scripts/cocoapods/utils.rb | 15 +++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index 8d834f53680..a2358cf8336 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -839,6 +839,74 @@ class UtilsTests < Test::Unit::TestCase end end + # ====================================== # + # Test - Add Search Path If Not Included # + # ====================================== # + # Tests for string input + def test_add_search_path_if_not_included_adds_new_path_to_string + current_paths = "/path/to/headers /another/path" + new_path = "/new/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal("/path/to/headers /another/path /new/path", result) + end + + def test_add_search_path_if_not_included_does_not_add_existing_path_to_string + current_paths = "/path/to/headers /another/path" + new_path = "/another/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal("/path/to/headers /another/path", result) + end + + def test_add_search_path_if_not_included_does_not_add_existing_path_with_leading_space_to_string + current_paths = " /path/with/leading/space /another/path" + new_path = "/path/with/leading/space" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal("/path/with/leading/space /another/path", result) + end + + def test_add_search_path_if_not_included_handles_path_with_spaces_in_string + current_paths = "/path/to/headers /another/path" + new_path = '"/path/with spaces/lib"' + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal('/path/to/headers /another/path "/path/with spaces/lib"', result) + end + + # Tests for array input + def test_add_search_path_if_not_included_adds_new_path_to_array + current_paths = ["/path/to/headers", "/another/path"] + new_path = "/new/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal(["/path/to/headers", "/another/path", "/new/path"], result) + end + + def test_add_search_path_if_not_included_does_not_add_existing_path_to_array + current_paths = ["/path/to/headers", "/another/path"] + new_path = "/another/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal(["/path/to/headers", "/another/path"], result) + end + + def test_add_search_path_if_not_included_strips_leading_and_trailing_spaces_in_array + current_paths = ["/path/to/headers", " /another/path"] + new_path = "/another/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal(["/path/to/headers", "/another/path"], result) + end + + def test_add_search_path_if_not_included_handles_path_with_spaces_in_array + current_paths = [" /path/to/headers ", "/another/path"] + new_path = '"/path/with spaces/lib"' + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal(["/path/to/headers", "/another/path", '"/path/with spaces/lib"'], result) + end + + def test_add_search_path_if_not_included_adds_to_empty_array + current_paths = [] + new_path = "/new/path" + result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path) + assert_equal(["/new/path"], result) + end + # =============================================== # # Test - Create Header Search Path For Frameworks # # =============================================== # diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 5b60353ac98..63ef8fc9b23 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -538,10 +538,19 @@ class ReactNativePodsUtils end def self.add_search_path_if_not_included(current_search_paths, new_search_path) - if !current_search_paths.include?(new_search_path) - current_search_paths << " #{new_search_path}" + new_search_path = new_search_path.strip + + if current_search_paths.is_a?(String) + current_search_paths = current_search_paths.strip + return "#{current_search_paths} #{new_search_path}" unless current_search_paths.include?(new_search_path) end - return current_search_paths + + if current_search_paths.is_a?(Array) + current_search_paths = current_search_paths.map(&:strip) + return current_search_paths << new_search_path unless current_search_paths.include?(new_search_path) + end + + current_search_paths end def self.update_header_paths_if_depends_on(target_installation_result, dependency_name, header_paths)