cocoapods 1.10.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +571 -7
  3. data/README.md +10 -11
  4. data/bin/sandbox-pod +1 -1
  5. data/lib/cocoapods/command/lib/lint.rb +4 -1
  6. data/lib/cocoapods/command/outdated.rb +12 -1
  7. data/lib/cocoapods/command/repo/push.rb +20 -0
  8. data/lib/cocoapods/command/setup.rb +2 -2
  9. data/lib/cocoapods/command/spec/cat.rb +3 -1
  10. data/lib/cocoapods/command/spec/create.rb +1 -0
  11. data/lib/cocoapods/command/spec/lint.rb +4 -1
  12. data/lib/cocoapods/command/spec/which.rb +3 -1
  13. data/lib/cocoapods/command/spec.rb +18 -9
  14. data/lib/cocoapods/config.rb +8 -7
  15. data/lib/cocoapods/downloader/cache.rb +98 -6
  16. data/lib/cocoapods/downloader.rb +4 -2
  17. data/lib/cocoapods/executable.rb +1 -1
  18. data/lib/cocoapods/external_sources/abstract_external_source.rb +1 -1
  19. data/lib/cocoapods/external_sources/path_source.rb +1 -1
  20. data/lib/cocoapods/external_sources/podspec_source.rb +1 -1
  21. data/lib/cocoapods/gem_version.rb +1 -1
  22. data/lib/cocoapods/generator/acknowledgements.rb +13 -1
  23. data/lib/cocoapods/generator/app_target_helper.rb +8 -4
  24. data/lib/cocoapods/generator/copy_dsyms_script.rb +4 -4
  25. data/lib/cocoapods/generator/copy_resources_script.rb +2 -1
  26. data/lib/cocoapods/generator/copy_xcframework_script.rb +52 -70
  27. data/lib/cocoapods/generator/embed_frameworks_script.rb +4 -3
  28. data/lib/cocoapods/generator/info_plist_file.rb +1 -1
  29. data/lib/cocoapods/generator/script_phase_constants.rb +1 -0
  30. data/lib/cocoapods/installer/analyzer/analysis_result.rb +3 -3
  31. data/lib/cocoapods/installer/analyzer/pod_variant.rb +1 -1
  32. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +38 -10
  33. data/lib/cocoapods/installer/analyzer.rb +21 -13
  34. data/lib/cocoapods/installer/base_install_hooks_context.rb +19 -4
  35. data/lib/cocoapods/installer/installation_options.rb +11 -0
  36. data/lib/cocoapods/installer/pod_source_downloader.rb +159 -0
  37. data/lib/cocoapods/installer/pod_source_installer.rb +10 -36
  38. data/lib/cocoapods/installer/podfile_validator.rb +2 -2
  39. data/lib/cocoapods/installer/pre_integrate_hooks_context.rb +9 -0
  40. data/lib/cocoapods/installer/project_cache/project_cache_analyzer.rb +14 -7
  41. data/lib/cocoapods/installer/project_cache/project_installation_cache.rb +15 -2
  42. data/lib/cocoapods/installer/project_cache/target_cache_key.rb +48 -7
  43. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +150 -9
  44. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +11 -3
  45. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +62 -9
  46. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +6 -19
  47. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +86 -59
  48. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +48 -6
  49. data/lib/cocoapods/installer/xcode/pods_project_generator/project_generator.rb +3 -1
  50. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +2 -2
  51. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +8 -5
  52. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +9 -3
  53. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +37 -2
  54. data/lib/cocoapods/installer/xcode/target_validator.rb +1 -1
  55. data/lib/cocoapods/installer.rb +150 -34
  56. data/lib/cocoapods/native_target_extension.rb +1 -1
  57. data/lib/cocoapods/open-uri.rb +1 -1
  58. data/lib/cocoapods/project.rb +8 -8
  59. data/lib/cocoapods/resolver/resolver_specification.rb +1 -1
  60. data/lib/cocoapods/resolver.rb +7 -7
  61. data/lib/cocoapods/sandbox/file_accessor.rb +67 -11
  62. data/lib/cocoapods/sandbox/headers_store.rb +3 -1
  63. data/lib/cocoapods/sandbox/path_list.rb +2 -2
  64. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +1 -1
  65. data/lib/cocoapods/sandbox.rb +48 -12
  66. data/lib/cocoapods/sources_manager.rb +18 -9
  67. data/lib/cocoapods/target/aggregate_target.rb +23 -1
  68. data/lib/cocoapods/target/build_settings.rb +67 -22
  69. data/lib/cocoapods/target/pod_target.rb +49 -24
  70. data/lib/cocoapods/target.rb +1 -1
  71. data/lib/cocoapods/user_interface.rb +6 -2
  72. data/lib/cocoapods/validator.rb +58 -22
  73. data/lib/cocoapods/version_metadata.rb +1 -1
  74. data/lib/cocoapods/xcode/xcframework/xcframework_slice.rb +22 -7
  75. data/lib/cocoapods/xcode/xcframework.rb +9 -4
  76. data/lib/cocoapods.rb +2 -0
  77. metadata +35 -27
@@ -64,20 +64,26 @@ module Pod
64
64
 
65
65
  #{Pod::Generator::ScriptPhaseConstants::RSYNC_PROTECT_TMP_FILES}
66
66
 
67
+ #{variant_for_slice}
68
+
69
+ #{archs_for_slice}
70
+
67
71
  copy_dir()
68
72
  {
69
73
  local source="$1"
70
74
  local destination="$2"
71
75
 
72
76
  # Use filter instead of exclude so missing patterns don't throw errors.
73
- echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}\\" \\"${destination}\\""
74
- rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}" "${destination}"
77
+ echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}*\\" \\"${destination}\\""
78
+ rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}"/* "${destination}"
75
79
  }
76
80
 
77
81
  SELECT_SLICE_RETVAL=""
78
82
 
79
83
  select_slice() {
80
- local paths=("$@")
84
+ local xcframework_name="$1"
85
+ xcframework_name="${xcframework_name##*/}"
86
+ local paths=("${@:2}")
81
87
  # Locate the correct slice of the .xcframework for the current architectures
82
88
  local target_path=""
83
89
 
@@ -93,29 +99,15 @@ select_slice() {
93
99
  fi
94
100
  for i in ${!paths[@]}; do
95
101
  local matched_all_archs="1"
96
- for target_arch in $target_archs
97
- do
98
- if ! [[ "${paths[$i]}" == *"$target_variant"* ]]; then
99
- matched_all_archs="0"
100
- break
101
- fi
102
-
103
- # Verifies that the path contains the variant string (simulator or maccatalyst) if the variant is set.
104
- if [[ -z "$target_variant" && ("${paths[$i]}" == *"simulator"* || "${paths[$i]}" == *"maccatalyst"*) ]]; then
102
+ local slice_archs="$(archs_for_slice "${xcframework_name}/${paths[$i]}")"
103
+ local slice_variant="$(variant_for_slice "${xcframework_name}/${paths[$i]}")"
104
+ for target_arch in $target_archs; do
105
+ if ! [[ "${slice_variant}" == "$target_variant" ]]; then
105
106
  matched_all_archs="0"
106
107
  break
107
108
  fi
108
109
 
109
- # This regex matches all possible variants of the arch in the folder name:
110
- # Let's say the folder name is: ios-armv7_armv7s_arm64_arm64e/CoconutLib.framework
111
- # We match the following: -armv7_, _armv7s_, _arm64_ and _arm64e/.
112
- # If we have a specific variant: ios-i386_x86_64-simulator/CoconutLib.framework
113
- # We match the following: -i386_ and _x86_64-
114
- # When the .xcframework wraps a static library, the folder name does not include
115
- # any .framework. In that case, the folder name can be: ios-arm64_armv7
116
- # We also match _armv7$ to handle that case.
117
- local target_arch_regex="[_\\-]${target_arch}([\\/_\\-]|$)"
118
- if ! [[ "${paths[$i]}" =~ $target_arch_regex ]]; then
110
+ if ! echo "${slice_archs}" | tr " " "\\n" | grep -F -q -x "$target_arch"; then
119
111
  matched_all_archs="0"
120
112
  break
121
113
  fi
@@ -130,60 +122,17 @@ select_slice() {
130
122
  done
131
123
  }
132
124
 
133
- install_library() {
134
- local source="$1"
135
- local name="$2"
136
- local destination="#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/${name}"
137
-
138
- # Libraries can contain headers, module maps, and a binary, so we'll copy everything in the folder over
139
-
140
- local source="$binary"
141
- echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" \\"${source}/*\\" \\"${destination}\\""
142
- rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" "${source}/*" "${destination}"
143
- }
144
-
145
- # Copies a framework to derived data for use in later build phases
146
- install_framework()
147
- {
148
- local source="$1"
149
- local name="$2"
150
- local destination="#{Pod::Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/${name}"
151
-
152
- if [ ! -d "$destination" ]; then
153
- mkdir -p "$destination"
154
- fi
155
-
156
- copy_dir "$source" "$destination"
157
- echo "Copied $source to $destination"
158
- }
159
-
160
- install_xcframework_library() {
161
- local basepath="$1"
162
- local name="$2"
163
- local paths=("$@")
164
-
165
- # Locate the correct slice of the .xcframework for the current architectures
166
- select_slice "${paths[@]}"
167
- local target_path="$SELECT_SLICE_RETVAL"
168
- if [[ -z "$target_path" ]]; then
169
- echo "warning: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)."
170
- return
171
- fi
172
-
173
- install_framework "$basepath/$target_path" "$name"
174
- }
175
-
176
125
  install_xcframework() {
177
126
  local basepath="$1"
178
127
  local name="$2"
179
128
  local package_type="$3"
180
- local paths=("$@")
129
+ local paths=("${@:4}")
181
130
 
182
131
  # Locate the correct slice of the .xcframework for the current architectures
183
- select_slice "${paths[@]}"
132
+ select_slice "${basepath}" "${paths[@]}"
184
133
  local target_path="$SELECT_SLICE_RETVAL"
185
134
  if [[ -z "$target_path" ]]; then
186
- echo "warning: [CP] Unable to find matching .xcframework slice in '${paths[@]}' for the current build architectures ($ARCHS)."
135
+ echo "warning: [CP] $(basename ${basepath}): Unable to find matching slice in '${paths[@]}' for the current build architectures ($ARCHS) and platform (${EFFECTIVE_PLATFORM_NAME-${PLATFORM_NAME}})."
187
136
  return
188
137
  fi
189
138
  local source="$basepath/$target_path"
@@ -195,7 +144,6 @@ install_xcframework() {
195
144
  fi
196
145
 
197
146
  copy_dir "$source/" "$destination"
198
-
199
147
  echo "Copied $source to $destination"
200
148
  }
201
149
 
@@ -218,7 +166,7 @@ install_xcframework() {
218
166
  def install_xcframework_args(xcframework, slices)
219
167
  root = xcframework.path
220
168
  args = [shell_escape("${PODS_ROOT}/#{root.relative_path_from(sandbox_root)}")]
221
- args << shell_escape(xcframework.name)
169
+ args << shell_escape(xcframework.target_name)
222
170
  is_framework = xcframework.build_type.framework?
223
171
  args << shell_escape(is_framework ? 'framework' : 'library')
224
172
  slices.each do |slice|
@@ -227,6 +175,40 @@ install_xcframework() {
227
175
  args.join(' ')
228
176
  end
229
177
 
178
+ def variant_for_slice
179
+ script = ''
180
+ script << "variant_for_slice()\n"
181
+ script << "{\n"
182
+ script << " case \"$1\" in\n"
183
+ xcframeworks.each do |xcframework|
184
+ root = xcframework.path
185
+ xcframework.slices.each do |slice|
186
+ script << " #{shell_escape(root.basename.join(slice.path.dirname.relative_path_from(root)))})\n"
187
+ script << " echo \"#{slice.platform_variant}\"\n"
188
+ script << " ;;\n"
189
+ end
190
+ end
191
+ script << " esac\n"
192
+ script << '}'
193
+ end
194
+
195
+ def archs_for_slice
196
+ script = ''
197
+ script << "archs_for_slice()\n"
198
+ script << "{\n"
199
+ script << " case \"$1\" in\n"
200
+ xcframeworks.each do |xcframework|
201
+ root = xcframework.path
202
+ xcframework.slices.each do |slice|
203
+ script << " #{shell_escape(root.basename.join(slice.path.dirname.relative_path_from(root)))})\n"
204
+ script << " echo \"#{slice.supported_archs.sort.join(' ')}\"\n"
205
+ script << " ;;\n"
206
+ end
207
+ end
208
+ script << " esac\n"
209
+ script << '}'
210
+ end
211
+
230
212
  class << self
231
213
  # @param [Pathname] xcframework_path
232
214
  # the base path of the .xcframework bundle
@@ -63,7 +63,7 @@ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
63
63
  mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
64
64
 
65
65
  COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
66
- SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
66
+ SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
67
67
  BCSYMBOLMAP_DIR="BCSymbolMaps"
68
68
 
69
69
 
@@ -83,7 +83,7 @@ install_framework()
83
83
 
84
84
  if [ -L "${source}" ]; then
85
85
  echo "Symlinked..."
86
- source="$(readlink "${source}")"
86
+ source="$(readlink -f "${source}")"
87
87
  fi
88
88
 
89
89
  if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then
@@ -159,8 +159,9 @@ code_sign_if_enabled() {
159
159
  end
160
160
  xcframeworks_by_config.each do |config, xcframeworks|
161
161
  xcframeworks.select { |xcf| xcf.build_type.dynamic_framework? }.each do |xcframework|
162
+ target_name = xcframework.target_name
162
163
  name = xcframework.name
163
- contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{name}/#{name}.framework"\n)
164
+ contents_by_config[config] << %( install_framework "#{Target::BuildSettings::XCFRAMEWORKS_BUILD_DIR_VARIABLE}/#{target_name}/#{name}.framework"\n)
164
165
  end
165
166
  end
166
167
  script << "\n" unless contents_by_config.empty?
@@ -112,7 +112,7 @@ module Pod
112
112
  'CFBundleSignature' => '????',
113
113
  'CFBundleVersion' => '${CURRENT_PROJECT_VERSION}',
114
114
  'NSPrincipalClass' => '',
115
- 'CFBundleDevelopmentRegion' => 'en',
115
+ 'CFBundleDevelopmentRegion' => '${PODS_DEVELOPMENT_LANGUAGE}',
116
116
  }
117
117
 
118
118
  info['CFBundleExecutable'] = '${EXECUTABLE_NAME}' if bundle_package_type != :bndl
@@ -79,6 +79,7 @@ install_dsym() {
79
79
  rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}"
80
80
  else
81
81
  # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing.
82
+ mkdir -p "${DWARF_DSYM_FOLDER_PATH}"
82
83
  touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM"
83
84
  fi
84
85
  fi
@@ -59,14 +59,14 @@ module Pod
59
59
  end
60
60
  end
61
61
 
62
- # @return [Bool] Whether an installation should be performed or this
62
+ # @return [Boolean] Whether an installation should be performed or this
63
63
  # CocoaPods project is already up to date.
64
64
  #
65
65
  def needs_install?
66
66
  podfile_needs_install? || sandbox_needs_install?
67
67
  end
68
68
 
69
- # @return [Bool] Whether the podfile has changes respect to the lockfile.
69
+ # @return [Boolean] Whether the podfile has changes respect to the lockfile.
70
70
  #
71
71
  def podfile_needs_install?
72
72
  state = podfile_state
@@ -74,7 +74,7 @@ module Pod
74
74
  needing_install > 0
75
75
  end
76
76
 
77
- # @return [Bool] Whether the sandbox is in synch with the lockfile.
77
+ # @return [Boolean] Whether the sandbox is in synch with the lockfile.
78
78
  #
79
79
  def sandbox_needs_install?
80
80
  state = sandbox_state
@@ -56,7 +56,7 @@ module Pod
56
56
  # @note Non library specs are intentionally not included as part of the equality for pod variants since a pod
57
57
  # variant should not be affected by the number of test nor app specs included.
58
58
  #
59
- # @return [Bool] whether the {PodVariant} is equal to another taking all all their attributes into account
59
+ # @return [Boolean] whether the {PodVariant} is equal to another taking all all their attributes into account
60
60
  #
61
61
  def ==(other)
62
62
  self.class == other.class &&
@@ -31,12 +31,16 @@ module Pod
31
31
  #
32
32
  attr_reader :sandbox
33
33
 
34
+ # @return [Podfile] The Podfile to analyze dependencies.
35
+ #
36
+ attr_reader :podfile
37
+
34
38
  # @return [Array<Specifications>] The specifications returned by the
35
39
  # resolver.
36
40
  #
37
41
  attr_reader :specs
38
42
 
39
- # @return [Bool] Whether the installation is performed in update mode.
43
+ # @return [Boolean] Whether the installation is performed in update mode.
40
44
  #
41
45
  attr_reader :update_mode
42
46
 
@@ -45,11 +49,13 @@ module Pod
45
49
  # Init a new SandboxAnalyzer
46
50
  #
47
51
  # @param [Sandbox] sandbox @see sandbox
52
+ # @param [Podfile] podfile @see podfile
48
53
  # @param [Array<Specifications>] specs @see specs
49
- # @param [Bool] update_mode @see update_mode
54
+ # @param [Boolean] update_mode @see update_mode
50
55
  #
51
- def initialize(sandbox, specs, update_mode)
56
+ def initialize(sandbox, podfile, specs, update_mode)
52
57
  @sandbox = sandbox
58
+ @podfile = podfile
53
59
  @specs = specs
54
60
  @update_mode = update_mode
55
61
  end
@@ -86,8 +92,8 @@ module Pod
86
92
  # @return [Symbol] The state
87
93
  #
88
94
  def pod_state(pod)
89
- return :added if pod_added?(pod)
90
95
  return :deleted if pod_deleted?(pod)
96
+ return :added if pod_added?(pod)
91
97
  return :changed if pod_changed?(pod)
92
98
  :unchanged
93
99
  end
@@ -99,11 +105,11 @@ module Pod
99
105
  # @param [String] pod
100
106
  # the name of the Pod.
101
107
  #
102
- # @return [Bool] Whether the Pod is added.
108
+ # @return [Boolean] Whether the Pod is added.
103
109
  #
104
110
  def pod_added?(pod)
105
111
  return true if resolved_pods.include?(pod) && !sandbox_pods.include?(pod)
106
- return true if !folder_exist?(pod) && !sandbox.local?(pod)
112
+ return true if !sandbox.local?(pod) && !folder_exist?(pod)
107
113
  false
108
114
  end
109
115
 
@@ -113,7 +119,7 @@ module Pod
113
119
  # @param [String] pod
114
120
  # the name of the Pod.
115
121
  #
116
- # @return [Bool] Whether the Pod is deleted.
122
+ # @return [Boolean] Whether the Pod is deleted.
117
123
  #
118
124
  def pod_deleted?(pod)
119
125
  return true if !resolved_pods.include?(pod) && sandbox_pods.include?(pod)
@@ -132,13 +138,15 @@ module Pod
132
138
  # @param [String] pod
133
139
  # the name of the Pod.
134
140
  #
135
- # @return [Bool] Whether the Pod is changed.
141
+ # @return [Boolean] Whether the Pod is changed.
136
142
  #
137
143
  def pod_changed?(pod)
138
144
  spec = root_spec(pod)
139
145
  return true if spec.version != sandbox_version(pod)
140
146
  return true if spec.checksum != sandbox_checksum(pod)
141
147
  return true if resolved_spec_names(pod) != sandbox_spec_names(pod)
148
+ podfile_dep = podfile_dependency(pod)&.tap { |dep| dep.podspec_repo = nil }
149
+ return true if podfile_dep != sandbox_dependency(pod)
142
150
  return true if sandbox.predownloaded?(pod)
143
151
  return true if folder_empty?(pod)
144
152
  false
@@ -161,14 +169,14 @@ module Pod
161
169
  # @return [Array<String>] The name of the resolved Pods.
162
170
  #
163
171
  def resolved_pods
164
- specs.map { |spec| spec.root.name }.uniq
172
+ @resolved_pods ||= specs.map { |spec| spec.root.name }.uniq
165
173
  end
166
174
 
167
175
  # @return [Array<String>] The name of the Pods stored in the sandbox
168
176
  # manifest.
169
177
  #
170
178
  def sandbox_pods
171
- sandbox_manifest.pod_names.map { |name| Specification.root_name(name) }.uniq
179
+ @sandbox_pods ||= sandbox_manifest.pod_names.map { |name| Specification.root_name(name) }.uniq
172
180
  end
173
181
 
174
182
  # @return [Array<String>] The name of the resolved specifications
@@ -223,6 +231,26 @@ module Pod
223
231
  sandbox_manifest.checksum(pod)
224
232
  end
225
233
 
234
+ # @return [Dependency, nil] The dependency with the given name stored in the sandbox.
235
+ #
236
+ # @param [String] pod
237
+ # the name of the Pod.
238
+ #
239
+ def sandbox_dependency(pod)
240
+ sandbox_manifest.dependencies.find { |d| d.name == pod }
241
+ end
242
+
243
+ #--------------------------------------#
244
+
245
+ # @return [Dependency, nil] The dependency with the given name from the podfile.
246
+ #
247
+ # @param [String] pod
248
+ # the name of the Pod.
249
+ #
250
+ def podfile_dependency(pod)
251
+ podfile.dependencies.find { |d| d.name == pod }
252
+ end
253
+
226
254
  #--------------------------------------#
227
255
 
228
256
  def folder_exist?(pod)
@@ -35,7 +35,7 @@ module Pod
35
35
  #
36
36
  attr_reader :podfile
37
37
 
38
- # @return [Lockfile] The Lockfile, if available, that stores the information about the Pods previously installed.
38
+ # @return [Lockfile, nil] The Lockfile, if available, that stores the information about the Pods previously installed.
39
39
  #
40
40
  attr_reader :lockfile
41
41
 
@@ -43,7 +43,7 @@ module Pod
43
43
  #
44
44
  attr_reader :plugin_sources
45
45
 
46
- # @return [Bool] Whether the analysis has dependencies and thus sources must be configured.
46
+ # @return [Boolean] Whether the analysis has dependencies and thus sources must be configured.
47
47
  #
48
48
  # @note This is used by the `pod lib lint` command to prevent update of specs when not needed.
49
49
  #
@@ -67,7 +67,7 @@ module Pod
67
67
  #
68
68
  # @param [Sandbox] sandbox @see #sandbox
69
69
  # @param [Podfile] podfile @see #podfile
70
- # @param [Lockfile] lockfile @see #lockfile
70
+ # @param [Lockfile, nil] lockfile @see #lockfile
71
71
  # @param [Array<Source>] plugin_sources @see #plugin_sources
72
72
  # @param [Boolean] has_dependencies @see #has_dependencies
73
73
  # @param [Hash, Boolean, nil] pods_to_update @see #pods_to_update
@@ -84,6 +84,7 @@ module Pod
84
84
  @installation_options = podfile.installation_options
85
85
  @podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
86
86
  @sources_manager = sources_manager
87
+ @path_lists = {}
87
88
  @result = nil
88
89
  end
89
90
 
@@ -93,7 +94,7 @@ module Pod
93
94
  # compute which specification should be installed. The manifest of the
94
95
  # sandbox returns which specifications are installed.
95
96
  #
96
- # @param [Bool] allow_fetches
97
+ # @param [Boolean] allow_fetches
97
98
  # whether external sources may be fetched
98
99
  #
99
100
  # @return [AnalysisResult]
@@ -125,7 +126,7 @@ module Pod
125
126
  validate_platforms(resolver_specs_by_target)
126
127
  specifications = generate_specifications(resolver_specs_by_target)
127
128
  aggregate_targets, pod_targets = generate_targets(resolver_specs_by_target, target_inspections)
128
- sandbox_state = generate_sandbox_state(specifications)
129
+ sandbox_state = generate_sandbox_state(specifications)
129
130
  specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
130
131
  hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
131
132
  end
@@ -193,7 +194,7 @@ module Pod
193
194
 
194
195
  # @!group Configuration
195
196
 
196
- # @return [Bool] Whether the version of the dependencies which did not
197
+ # @return [Boolean] Whether the version of the dependencies which did not
197
198
  # change in the Podfile should be locked.
198
199
  #
199
200
  def update_mode?
@@ -565,12 +566,11 @@ module Pod
565
566
  pod_targets_by_build_config = Hash.new([].freeze)
566
567
  build_configurations.each { |config| pod_targets_by_build_config[config] = [] }
567
568
 
569
+ dependencies_by_root_name = @podfile_dependency_cache.target_definition_dependencies(target_definition).group_by(&:root_name)
570
+
568
571
  pod_targets_by_target_definition[target_definition].each do |pod_target|
569
572
  pod_name = pod_target.pod_name
570
-
571
- dependencies = @podfile_dependency_cache.target_definition_dependencies(target_definition).select do |dependency|
572
- Specification.root_name(dependency.name) == pod_name
573
- end
573
+ dependencies = dependencies_by_root_name[pod_name] || []
574
574
 
575
575
  build_configurations.each do |configuration_name|
576
576
  whitelists = dependencies.map do |dependency|
@@ -714,7 +714,12 @@ module Pod
714
714
  dependencies.map do |root_spec, deps|
715
715
  pod_targets_by_name[root_spec.name].find do |t|
716
716
  next false if t.platform.symbolic_name != target.platform.symbolic_name ||
717
- t.build_as_framework? != target.build_as_framework? # rather than target type or requires_frameworks? since we want to group by what was specified in that _target definition_
717
+ # In the case of variants we must ensure that the platform this target is meant for is the same
718
+ # as the one we are interested in.
719
+ t.target_definitions.first.platform != target.target_definitions.first.platform ||
720
+ # rather than target type or requires_frameworks? since we want to group by what was specified in that
721
+ # _target definition_.
722
+ t.build_as_framework? != target.build_as_framework?
718
723
  spec_names = t.specs.map(&:name)
719
724
  deps.all? { |dep| spec_names.include?(dep.name) }
720
725
  end
@@ -826,7 +831,10 @@ module Pod
826
831
  def create_file_accessors(specs, platform)
827
832
  name = specs.first.name
828
833
  pod_root = sandbox.pod_dir(name)
829
- path_list = Sandbox::PathList.new(pod_root)
834
+ path_list = @path_lists.fetch(pod_root) do |root|
835
+ path_list = Sandbox::PathList.new(root)
836
+ @path_lists[root] = path_list
837
+ end
830
838
  specs.map do |spec|
831
839
  Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
832
840
  end
@@ -1115,7 +1123,7 @@ module Pod
1115
1123
  def generate_sandbox_state(specifications)
1116
1124
  sandbox_state = nil
1117
1125
  UI.section 'Comparing resolved specification to the sandbox manifest' do
1118
- sandbox_analyzer = SandboxAnalyzer.new(sandbox, specifications, update_mode?)
1126
+ sandbox_analyzer = SandboxAnalyzer.new(sandbox, podfile, specifications, update_mode?)
1119
1127
  sandbox_state = sandbox_analyzer.analyze
1120
1128
  sandbox_state.print
1121
1129
  end
@@ -16,6 +16,10 @@ module Pod
16
16
  #
17
17
  attr_reader :pods_project
18
18
 
19
+ # @return [Array<Pod::Project>] the subprojects nested under pods_project.
20
+ #
21
+ attr_reader :pod_target_subprojects
22
+
19
23
  # @return [Array<UmbrellaTargetDescription>] The list of
20
24
  # the CocoaPods umbrella targets generated by the installer.
21
25
  #
@@ -26,12 +30,14 @@ module Pod
26
30
  # @param [Sandbox] sandbox see #sandbox
27
31
  # @param [String] sandbox_root see #sandbox_root
28
32
  # @param [Xcodeproj::Project] pods_project see #pods_project
33
+ # @param [Array<Xcodeproj::Project>] pod_target_subprojects see #pod_target_subprojects
29
34
  # @param [Array<UmbrellaTargetDescription>] umbrella_targets see #umbrella_targets
30
35
  #
31
- def initialize(sandbox, sandbox_root, pods_project, umbrella_targets)
36
+ def initialize(sandbox, sandbox_root, pods_project, pod_target_subprojects, umbrella_targets)
32
37
  @sandbox = sandbox
33
38
  @sandbox_root = sandbox_root
34
39
  @pods_project = pods_project
40
+ @pod_target_subprojects = pod_target_subprojects
35
41
  @umbrella_targets = umbrella_targets
36
42
  end
37
43
 
@@ -43,6 +49,9 @@ module Pod
43
49
  # @param [Project] pods_project
44
50
  # The pods project.
45
51
  #
52
+ # @param [Project] pod_target_subprojects
53
+ # The subprojects nested under pods_project.
54
+ #
46
55
  # @param [Array<AggregateTarget>] aggregate_targets
47
56
  # The aggregate targets, which will been presented by an adequate
48
57
  # {UmbrellaTargetDescription} in the generated context.
@@ -50,7 +59,7 @@ module Pod
50
59
  # @return [HooksContext] Convenience class method to generate the
51
60
  # static context.
52
61
  #
53
- def self.generate(sandbox, pods_project, aggregate_targets)
62
+ def self.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
54
63
  umbrella_targets_descriptions = aggregate_targets.map do |umbrella|
55
64
  user_project = umbrella.user_project
56
65
  user_targets = umbrella.user_targets
@@ -61,7 +70,13 @@ module Pod
61
70
  UmbrellaTargetDescription.new(user_project, user_targets, specs, platform_name, platform_deployment_target, cocoapods_target_label)
62
71
  end
63
72
 
64
- new(sandbox, sandbox.root.to_s, pods_project, umbrella_targets_descriptions)
73
+ new(sandbox, sandbox.root.to_s, pods_project, pod_target_subprojects, umbrella_targets_descriptions)
74
+ end
75
+
76
+ # @return [Array<Pod::Project>] all projects generated during installation
77
+ #
78
+ def generated_projects
79
+ [pods_project] + pod_target_subprojects
65
80
  end
66
81
 
67
82
  # Pure data class which describes an umbrella target.
@@ -82,7 +97,7 @@ module Pod
82
97
  #
83
98
  attr_reader :specs
84
99
 
85
- # @return [Symbol] The platform (either `:ios`, `:watchos`, `:tvos`, or `:osx`).
100
+ # @return [Symbol] The platform (either `:ios`, `:watchos`, `:tvos`, `:visionos`, or `:osx`).
86
101
  #
87
102
  attr_reader :platform_name
88
103
 
@@ -190,6 +190,17 @@ module Pod
190
190
  # Whether to skip generating the `Pods.xcodeproj` and perform only dependency resolution and downloading.
191
191
  #
192
192
  option :skip_pods_project_generation, false
193
+
194
+ # Whether to download pods in parallel before beginning the installation process
195
+ #
196
+ option :parallel_pod_downloads, false
197
+
198
+ # The size of the thread pool to use when downloading pods in parallel. Only takes effect when
199
+ # `parallel_pod_downloads` is `true`.
200
+ #
201
+ # Default: 40
202
+ #
203
+ option(:parallel_pod_download_thread_pool_size, 40, :boolean => false)
193
204
  end
194
205
  end
195
206
  end