Class: Pod::Installer::Xcode::PodsProjectGenerator::FileReferencesInstaller

Inherits:
Object
  • Object
show all
Defined in:
lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb

Overview

Controller class responsible of installing the file references of the specifications in the Pods project.

Constant Summary collapse

LOCALIZATION_REGION_FILEPATTERN_REGEX =

Regex for extracting the region portion of a localized file path. Ex. Resources/en.lproj --> en

/(\/|^)(?<region>[^\/]*?)\.lproj(\/|$)/

Instance Attribute Summary collapse

Installation Steps collapse

Private Helpers collapse

Instance Method Summary collapse

Constructor Details

#initialize(sandbox, pod_targets, pods_project, preserve_pod_file_structure = false) ⇒ FileReferencesInstaller

Initialize a new instance

Parameters:

  • sandbox (Sandbox)

    @see #sandbox

  • pod_targets (Array<PodTarget>)

    @see #pod_targets

  • pods_project (Project)

    @see #pods_project

  • preserve_pod_file_structure (Boolean) (defaults to: false)

    @see #preserve_pod_file_structure



35
36
37
38
39
40
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 35

def initialize(sandbox, pod_targets, pods_project, preserve_pod_file_structure = false)
  @sandbox = sandbox
  @pod_targets = pod_targets
  @pods_project = pods_project
  @preserve_pod_file_structure = preserve_pod_file_structure
end

Instance Attribute Details

#pod_targetsArray<PodTarget> (readonly)

Returns The pod targets of the installation.

Returns:

  • (Array<PodTarget>)

    The pod targets of the installation.



18
19
20
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 18

def pod_targets
  @pod_targets
end

#pods_projectProject (readonly)

Returns The project to install the file references into.

Returns:

  • (Project)

    The project to install the file references into.



22
23
24
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 22

def pods_project
  @pods_project
end

#preserve_pod_file_structureBoolean (readonly)

Returns add support for preserving the file structure of externally sourced pods, in addition to local pods.

Returns:

  • (Boolean)

    add support for preserving the file structure of externally sourced pods, in addition to local pods.



26
27
28
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 26

def preserve_pod_file_structure
  @preserve_pod_file_structure
end

#sandboxSandbox (readonly)

Returns The sandbox of the installation.

Returns:

  • (Sandbox)

    The sandbox of the installation.



14
15
16
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 14

def sandbox
  @sandbox
end

Instance Method Details

#add_developer_filesObject (private)



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 138

def add_developer_files
  UI.message '- Adding development pod helper files' do
    file_accessors.each do |file_accessor|
      pod_name = file_accessor.spec.name
      next unless sandbox.local?(pod_name)
      root_name = Specification.root_name(pod_name)
      paths = file_accessor.developer_files
      next if paths.empty?
      group = pods_project.group_for_spec(root_name, :developer)
      paths.each do |path|
        ref = pods_project.add_file_reference(path, group, false)
        if path.extname == '.podspec'
          pods_project.mark_ruby_file_ref(ref)
        end
      end
    end
  end
end

#add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil, reflect_file_system_structure = false) ⇒ Array<PBXFileReference> (private)

Adds file references to the list of the paths returned by the file accessor with the given key to the given group of the Pods project.

Parameters:

  • file_accessor_key (Symbol)

    The method of the file accessor which would return the list of the paths.

  • group_key (Symbol) (defaults to: nil)

    The key of the group of the Pods project.

  • reflect_file_system_structure (Boolean) (defaults to: false)

    Whether organizing a local pod's files in subgroups inside the pod's group is allowed.

Returns:

  • (Array<PBXFileReference>)

    the added file references



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 216

def add_file_accessors_paths_to_pods_group(file_accessor_key, group_key = nil, reflect_file_system_structure = false)
  file_accessors.flat_map do |file_accessor|
    paths = file_accessor.send(file_accessor_key)
    paths = allowable_project_paths(paths)
    next [] if paths.empty?

    pod_name = file_accessor.spec.name
    preserve_pod_file_structure_flag = (sandbox.local?(pod_name) || preserve_pod_file_structure) && reflect_file_system_structure
    base_path = preserve_pod_file_structure_flag ? common_path(paths) : nil
    actual_group_key = preserve_pod_file_structure_flag ? nil : group_key
    group = pods_project.group_for_spec(pod_name, actual_group_key)
    paths.map do |path|
      pods_project.add_file_reference(path, group, preserve_pod_file_structure_flag, base_path)
    end
  end
end

#add_frameworks_bundlesvoid (private)

This method returns an undefined value.

Adds the bundled frameworks to the Pods project



107
108
109
110
111
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 107

def add_frameworks_bundles
  UI.message '- Adding frameworks' do
    add_file_accessors_paths_to_pods_group(:vendored_frameworks, :frameworks)
  end
end

#add_known_regions(file_references) ⇒ Object (private)

Adds the known localization regions to the root of the project

Parameters:

  • file_references (Array<PBXFileReferences>)

    the resource file references



317
318
319
320
321
322
323
324
325
326
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 317

def add_known_regions(file_references)
  pattern = LOCALIZATION_REGION_FILEPATTERN_REGEX
  regions = file_references.map do |ref|
    if (match = ref.path.to_s.match(pattern))
      match[:region]
    end
  end.compact

  pods_project.root_object.known_regions = (pods_project.root_object.known_regions | regions).sort
end

#add_resourcesvoid (private)

Note:

The source files are grouped by Pod and in turn by subspec (recursively) in the resources group.

This method returns an undefined value.

Adds the resources of the Pods to the Pods project.



130
131
132
133
134
135
136
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 130

def add_resources
  UI.message '- Adding resources' do
    refs = add_file_accessors_paths_to_pods_group(:resources, :resources, true)
    refs.concat add_file_accessors_paths_to_pods_group(:resource_bundle_files, :resources, true)
    add_known_regions(refs)
  end
end

#add_source_files_referencesvoid (private)

Note:

The source files are grouped by Pod and in turn by subspec (recursively).

This method returns an undefined value.

Adds the source files of the Pods to the Pods project.



97
98
99
100
101
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 97

def add_source_files_references
  UI.message '- Adding source files' do
    add_file_accessors_paths_to_pods_group(:source_files, nil, true)
  end
end

#add_vendored_librariesvoid (private)

This method returns an undefined value.

Adds the bundled libraries to the Pods project



117
118
119
120
121
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 117

def add_vendored_libraries
  UI.message '- Adding libraries' do
    add_file_accessors_paths_to_pods_group(:vendored_libraries, :frameworks)
  end
end

#allowable_project_paths(paths) ⇒ Array<Pathname> (private)

Filters a list of paths down to those paths which can be added to the Xcode project. Some paths are intermediates and only their children should be added, while some paths are treated as bundles and their children should not be added directly.

Parameters:

  • paths (Array<Pathname>)

    The paths to files or directories on disk.

Returns:

  • (Array<Pathname>)

    The paths which can be added to the Xcode project



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 243

def allowable_project_paths(paths)
  lproj_paths = Set.new
  lproj_paths_with_files = Set.new

  # Remove all file ref under .docc folder, but preserve the .docc folder
  paths = merge_to_docc_folder(paths)

  allowable_paths = paths.select do |path|
    path_str = path.to_s

    # We add the directory for a Core Data model, but not the items in it.
    next if path_str =~ /.*\.xcdatamodeld\/.+/i

    # We add the directory for a Core Data migration mapping, but not the items in it.
    next if path_str =~ /.*\.xcmappingmodel\/.+/i

    # We add the directory for an asset catalog, but not the items in it.
    next if path_str =~ /.*\.xcassets\/.+/i

    if path_str =~ /\.lproj(\/|$)/i
      # If the element is an .lproj directory then save it and potentially
      # add it later if we don't find any contained items.
      if path_str =~ /\.lproj$/i && path.directory?
        lproj_paths << path
        next
      end

      # Collect the paths for the .lproj directories that contain files.
      lproj_path = /(^.*\.lproj)\/.*/i.match(path_str)[1]
      lproj_paths_with_files << Pathname(lproj_path)

      # Directories nested within an .lproj directory are added as file
      # system references so their contained items are not added directly.
      next if path.dirname.dirname == lproj_path
    end

    true
  end

  # Only add the path for the .lproj directories that do not have anything
  # within them added as well. This generally happens if the glob within the
  # resources directory was not a recursive glob.
  allowable_paths + lproj_paths.subtract(lproj_paths_with_files).to_a
end

#common_path(paths) ⇒ Pathname (private)

Returns a Pathname of the nearest parent from which all the given paths descend. Converts each Pathname to a list of path components and finds the longest common prefix

Parameters:

  • paths (Array<Pathname>)

    The paths to files or directories on disk. Must be absolute paths

Returns:

  • (Pathname)

    Pathname of the nearest parent shared by paths, or nil if none exists



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 296

def common_path(paths)
  return nil if paths.empty?
  strs = paths.map do |path|
    unless path.absolute?
      raise ArgumentError, "Paths must be absolute #{path}"
    end
    path.dirname.to_s
  end
  min, max = strs.minmax
  min = min.split('/')
  max = max.split('/')
  idx = min.size.times { |i| break i if min[i] != max[i] }
  result = Pathname.new(min[0...idx].join('/'))
  # Don't consider "/" a common path
  return result unless result.to_s == '' || result.to_s == '/'
end

#file_accessorsArray<Sandbox::FileAccessor> (private)

Returns The file accessors for all the specs platform combinations.

Returns:



196
197
198
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 196

def file_accessors
  @file_accessors ||= pod_targets.flat_map(&:file_accessors).compact
end

#install!void

This method returns an undefined value.

Installs the file references.



46
47
48
49
50
51
52
53
54
55
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 46

def install!
  refresh_file_accessors
  prepare_pod_groups
  add_source_files_references
  add_frameworks_bundles
  add_vendored_libraries
  add_resources
  add_developer_files unless sandbox.development_pods.empty?
  link_headers
end

This method returns an undefined value.

Creates the link to the headers of the Pod in the sandbox.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 161

def link_headers
  UI.message '- Linking headers' do
    pod_targets.each do |pod_target|
      # When integrating Pod as frameworks, built Pods are built into
      # frameworks, whose headers are included inside the built
      # framework. Those headers do not need to be linked from the
      # sandbox.
      next if pod_target.build_as_framework? && pod_target.should_build?

      pod_target_header_mappings = pod_target.header_mappings_by_file_accessor.values
      pod_target_header_mappings.each do |header_mappings|
        header_mappings.each do |namespaced_path, files|
          pod_target.build_headers.add_files(namespaced_path, files)
        end
      end

      public_header_mappings = pod_target.public_header_mappings_by_file_accessor.values
      public_header_mappings.each do |header_mappings|
        header_mappings.each do |namespaced_path, files|
          sandbox.public_headers.add_files(namespaced_path, files)
        end
      end
    end
  end
end

#prepare_pod_groupsObject (private)

Prepares the main groups to which all files will be added for the respective target



79
80
81
82
83
84
85
86
87
88
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 79

def prepare_pod_groups
  file_accessors.each do |file_accessor|
    pod_name = file_accessor.spec.name
    next unless sandbox.local?(pod_name)
    root_name = Specification.root_name(pod_name)
    path = file_accessor.root
    group = pods_project.group_for_spec(root_name)
    group.set_path(path) unless group.path == path
  end
end

#refresh_file_accessorsvoid (private)

Note:

The contents of the file accessors are modified by the clean step of the #PodSourceInstaller and by the pre install hooks.

This method returns an undefined value.

Reads the file accessors contents from the file system.



70
71
72
73
74
75
# File 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb', line 70

def refresh_file_accessors
  file_accessors.reject do |file_accessor|
    pod_name = file_accessor.spec.name
    sandbox.local?(pod_name)
  end.map(&:path_list).uniq.each(&:read_file_system)
end