1# Copyright 2018-present 650 Industries. All rights reserved.
2
3module Expo
4  class ReactImportPatcher
5
6    public def initialize(installer, options)
7      @root = installer.sandbox.root
8      @module_dirs = get_module_dirs(installer)
9      @options = options
10    end
11
12    public def run!
13      args = [
14        'node',
15        '--eval',
16        'require(\'expo-modules-autolinking\')(process.argv.slice(1))',
17        'patch-react-imports',
18        '--pods-root',
19        File.expand_path(@root),
20      ]
21
22      if @options[:dry_run]
23        args.append('--dry-run')
24      end
25
26      @module_dirs.each do |dir|
27        args.append(File.expand_path(dir))
28      end
29      Pod::UI.message "Executing ReactImportsPatcher node command: #{Shellwords.join(args)}"
30
31      time_begin = Process.clock_gettime(Process::CLOCK_MONOTONIC)
32      system(*args)
33      elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_begin
34      Pod::UI.info "expo_patch_react_imports! took #{elapsed_time.round(4)} seconds to transform files."
35    end
36
37    private def get_module_dirs(installer)
38      unless installer.pods_project
39        Pod::UI.message '`pods_project` not found. This is expected when `:incremental_installation` is enabled in your project\'s Podfile.'
40        return []
41      end
42
43      result = []
44      installer.pods_project.development_pods.children.each do |pod|
45        if pod.is_a?(Xcodeproj::Project::Object::PBXFileReference) && pod.path.end_with?('.xcodeproj')
46          # Support generate_multiple_pod_projects or use_frameworks!
47          project = Xcodeproj::Project.open(File.join(installer.sandbox.root, pod.path))
48          groups = project.groups.select { |group| !(['Dependencies', 'Frameworks', 'Products'].include? group.name) }
49          groups.each do |group|
50            result.append(group.real_path.to_s)
51          end
52        else
53          result.append(pod.real_path.to_s)
54        end
55      end
56
57      return result.select { |dir|
58        # Exclude known dirs unnecessary to patch and reduce processing time
59        !dir.include?('/react-native/') &&
60        !dir.end_with?('/react-native') &&
61        !dir.include?('/expo-')
62      }
63    end
64
65  end # class ReactImportPatcher
66end # module Expo
67