cocoapods-square-stable 0.19.3

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1296 -0
  3. data/LICENSE +20 -0
  4. data/README.md +94 -0
  5. data/bin/pod +16 -0
  6. data/bin/sandbox-pod +120 -0
  7. data/lib/cocoapods.rb +77 -0
  8. data/lib/cocoapods/command.rb +116 -0
  9. data/lib/cocoapods/command/help.rb +23 -0
  10. data/lib/cocoapods/command/inter_process_communication.rb +178 -0
  11. data/lib/cocoapods/command/list.rb +77 -0
  12. data/lib/cocoapods/command/outdated.rb +56 -0
  13. data/lib/cocoapods/command/podfile_info.rb +91 -0
  14. data/lib/cocoapods/command/project.rb +88 -0
  15. data/lib/cocoapods/command/push.rb +172 -0
  16. data/lib/cocoapods/command/repo.rb +145 -0
  17. data/lib/cocoapods/command/search.rb +61 -0
  18. data/lib/cocoapods/command/setup.rb +134 -0
  19. data/lib/cocoapods/command/spec.rb +590 -0
  20. data/lib/cocoapods/config.rb +231 -0
  21. data/lib/cocoapods/downloader.rb +59 -0
  22. data/lib/cocoapods/executable.rb +118 -0
  23. data/lib/cocoapods/external_sources.rb +363 -0
  24. data/lib/cocoapods/file_list.rb +36 -0
  25. data/lib/cocoapods/gem_version.rb +7 -0
  26. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  27. data/lib/cocoapods/generator/acknowledgements/markdown.rb +40 -0
  28. data/lib/cocoapods/generator/acknowledgements/plist.rb +64 -0
  29. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  30. data/lib/cocoapods/generator/copy_resources_script.rb +54 -0
  31. data/lib/cocoapods/generator/dummy_source.rb +22 -0
  32. data/lib/cocoapods/generator/prefix_header.rb +82 -0
  33. data/lib/cocoapods/generator/target_environment_header.rb +86 -0
  34. data/lib/cocoapods/generator/xcconfig.rb +185 -0
  35. data/lib/cocoapods/hooks/installer_representation.rb +134 -0
  36. data/lib/cocoapods/hooks/library_representation.rb +94 -0
  37. data/lib/cocoapods/hooks/pod_representation.rb +74 -0
  38. data/lib/cocoapods/installer.rb +571 -0
  39. data/lib/cocoapods/installer/analyzer.rb +559 -0
  40. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +253 -0
  41. data/lib/cocoapods/installer/file_references_installer.rb +179 -0
  42. data/lib/cocoapods/installer/pod_source_installer.rb +248 -0
  43. data/lib/cocoapods/installer/target_installer.rb +379 -0
  44. data/lib/cocoapods/installer/user_project_integrator.rb +180 -0
  45. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +224 -0
  46. data/lib/cocoapods/library.rb +202 -0
  47. data/lib/cocoapods/open_uri.rb +24 -0
  48. data/lib/cocoapods/project.rb +209 -0
  49. data/lib/cocoapods/resolver.rb +212 -0
  50. data/lib/cocoapods/sandbox.rb +343 -0
  51. data/lib/cocoapods/sandbox/file_accessor.rb +217 -0
  52. data/lib/cocoapods/sandbox/headers_store.rb +96 -0
  53. data/lib/cocoapods/sandbox/path_list.rb +208 -0
  54. data/lib/cocoapods/sources_manager.rb +276 -0
  55. data/lib/cocoapods/user_interface.rb +304 -0
  56. data/lib/cocoapods/user_interface/error_report.rb +101 -0
  57. data/lib/cocoapods/validator.rb +350 -0
  58. metadata +238 -0
@@ -0,0 +1,559 @@
1
+ module Pod
2
+ class Installer
3
+
4
+ # Analyzes the Podfile, the Lockfile, and the sandbox manifest to generate
5
+ # the information relative to a CocoaPods installation.
6
+ #
7
+ class Analyzer
8
+
9
+ include Config::Mixin
10
+
11
+ autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
12
+
13
+ # @return [Sandbox] The sandbox where the Pods should be installed.
14
+ #
15
+ attr_reader :sandbox
16
+
17
+ # @return [Podfile] The Podfile specification that contains the
18
+ # information of the Pods that should be installed.
19
+ #
20
+ attr_reader :podfile
21
+
22
+ # @return [Lockfile] The Lockfile that stores the information about the
23
+ # Pods previously installed on any machine.
24
+ #
25
+ attr_reader :lockfile
26
+
27
+ # @param [Sandbox] sandbox @see sandbox
28
+ # @param [Podfile] podfile @see podfile
29
+ # @param [Lockfile] lockfile @see lockfile
30
+ #
31
+ def initialize(sandbox, podfile, lockfile = nil)
32
+ @sandbox = sandbox
33
+ @podfile = podfile
34
+ @lockfile = lockfile
35
+
36
+ @update_mode = false
37
+ @allow_pre_downloads = true
38
+ end
39
+
40
+ # Performs the analysis.
41
+ #
42
+ # The Podfile and the Lockfile provide the information necessary to
43
+ # compute which specification should be installed. The manifest of the
44
+ # sandbox returns which specifications are installed.
45
+ #
46
+ # @return [AnalysisResult]
47
+ #
48
+ def analyze(allow_fetches = true)
49
+ update_repositories_if_needed if allow_fetches
50
+ @result = AnalysisResult.new
51
+ @result.podfile_state = generate_podfile_state
52
+ @locked_dependencies = generate_version_locking_dependencies
53
+
54
+ @result.libraries = generated_libraries
55
+ fetch_external_sources if allow_fetches
56
+ @result.specs_by_target = resolve_dependencies
57
+ @result.specifications = generate_specifications
58
+ @result.sandbox_state = generate_sandbox_state
59
+ @result
60
+ end
61
+
62
+ attr_accessor :result
63
+
64
+ # @return [Bool] Whether an installation should be performed or this
65
+ # CocoaPods project is already up to date.
66
+ #
67
+ def needs_install?
68
+ analysis_result = analyze(false)
69
+ podfile_needs_install?(analysis_result) || sandbox_needs_install?(analysis_result)
70
+ end
71
+
72
+ # @return [Bool] Whether the podfile has changes respect to the lockfile.
73
+ #
74
+ def podfile_needs_install?(analysis_result)
75
+ state = analysis_result.podfile_state
76
+ needing_install = state.added + state.changed + state.deleted
77
+ !needing_install.empty?
78
+ end
79
+
80
+ # @return [Bool] Whether the sandbox is in synch with the lockfile.
81
+ #
82
+ def sandbox_needs_install?(analysis_result)
83
+ state = analysis_result.sandbox_state
84
+ needing_install = state.added + state.changed + state.deleted
85
+ !needing_install.empty?
86
+ end
87
+
88
+ #-----------------------------------------------------------------------#
89
+
90
+ # @!group Configuration
91
+
92
+ # @return [Bool] Whether the version of the dependencies which did non
93
+ # change in the Podfile should be locked.
94
+ #
95
+ attr_accessor :update_mode
96
+ alias_method :update_mode?, :update_mode
97
+
98
+ # @return [Bool] Whether the analysis allows pre-downloads and thus
99
+ # modifications to the sandbox.
100
+ #
101
+ # @note This flag should not be used in installations.
102
+ #
103
+ # @note This is used by the `pod outdated` command to prevent
104
+ # modification of the sandbox in the resolution process.
105
+ #
106
+ attr_accessor :allow_pre_downloads
107
+ alias_method :allow_pre_downloads?, :allow_pre_downloads
108
+
109
+ #-----------------------------------------------------------------------#
110
+
111
+ private
112
+
113
+ # @!group Analysis steps
114
+
115
+ # Compares the {Podfile} with the {Lockfile} in order to detect which
116
+ # dependencies should be locked.
117
+ #
118
+ # @return [SpecsState] the states of the Podfile specs.
119
+ #
120
+ # @note As the target definitions share the same sandbox they should have
121
+ # the same version of a Pod. For this reason this method returns
122
+ # the name of the Pod (root name of the dependencies) and doesn't
123
+ # group them by target definition.
124
+ #
125
+ # @todo [CocoaPods > 0.18] If there isn't a Lockfile all the Pods should
126
+ # be marked as added.
127
+ #
128
+ def generate_podfile_state
129
+ if lockfile
130
+ pods_state = nil
131
+ UI.section "Finding Podfile changes" do
132
+ pods_by_state = lockfile.detect_changes_with_podfile(podfile)
133
+ pods_by_state.dup.each do |state, full_names|
134
+ pods_by_state[state] = full_names.map { |fn| Specification.root_name(fn) }
135
+ end
136
+ pods_state = SpecsState.new(pods_by_state)
137
+ pods_state.print
138
+ end
139
+ pods_state
140
+ else
141
+ state = SpecsState.new
142
+ state.added.concat(podfile.dependencies.map(&:root_name).uniq)
143
+ state
144
+ end
145
+ end
146
+
147
+ # Updates the source repositories unless the config indicates to skip it.
148
+ #
149
+ # @return [void]
150
+ #
151
+ def update_repositories_if_needed
152
+ unless config.skip_repo_update?
153
+ UI.section 'Updating spec repositories' do
154
+ SourcesManager.update
155
+ end
156
+ end
157
+ end
158
+
159
+ # Creates the models that represent the libraries generated by CocoaPods.
160
+ #
161
+ # @note The libraries are generated before the resolution process
162
+ # because it might be necessary to infer the platform from the
163
+ # user targets, which in turns requires to identify the user
164
+ # project.
165
+ #
166
+ # @note The specification of the libraries are added in the
167
+ # {#resolve_dependencies} step.
168
+ #
169
+ # @return [Array<Libraries>] the generated libraries.
170
+ #
171
+ def generated_libraries
172
+ libraries = []
173
+ podfile.target_definition_list.each do |target_definition|
174
+ lib = Library.new(target_definition)
175
+ lib.support_files_root = sandbox.library_support_files_dir(lib.name)
176
+
177
+ if config.integrate_targets?
178
+ project_path = compute_user_project_path(target_definition)
179
+ user_project = Xcodeproj::Project.new(project_path)
180
+ targets = compute_user_project_targets(target_definition, user_project)
181
+
182
+ lib.user_project_path = project_path
183
+ lib.client_root = project_path.dirname
184
+ lib.user_target_uuids = targets.map(&:uuid)
185
+ lib.user_build_configurations = compute_user_build_configurations(target_definition, targets)
186
+ lib.platform = compute_platform_for_target_definition(target_definition, targets)
187
+ else
188
+ unless target_definition.platform
189
+ raise Informative, "It is necessary to specify the platform in the Podfile if not integrating."
190
+ end
191
+ lib.client_root = config.installation_root
192
+ lib.user_target_uuids = []
193
+ lib.user_build_configurations = {}
194
+ lib.platform = target_definition.platform
195
+ end
196
+ libraries << lib
197
+ end
198
+ libraries
199
+ end
200
+
201
+ # Generates dependencies that require the specific version of the Pods
202
+ # that haven't changed in the {Lockfile}.
203
+ #
204
+ # These dependencies are passed to the {Resolver}, unless the installer
205
+ # is in update mode, to prevent it from upgrading the Pods that weren't
206
+ # changed in the {Podfile}.
207
+ #
208
+ # @return [Array<Dependency>] the dependencies generate by the lockfile
209
+ # that prevent the resolver to update a Pod.
210
+ #
211
+ def generate_version_locking_dependencies
212
+ if update_mode?
213
+ []
214
+ else
215
+ result.podfile_state.unchanged.map do |pod|
216
+ lockfile.dependency_to_lock_pod_named(pod)
217
+ end
218
+ end
219
+ end
220
+
221
+ # Fetches the podspecs of external sources if modifications to the
222
+ # sandbox are allowed.
223
+ #
224
+ # @note In update mode all the external sources are refreshed while in
225
+ # normal mode they are refreshed only if added or changed in the
226
+ # Podfile. Moreover, in normal specifications for unchanged Pods
227
+ # which are missing or are generated from an local source are
228
+ # fetched as well.
229
+ #
230
+ # @note It is possible to perform this step before the resolution
231
+ # process because external sources identify a single specific
232
+ # version (checkout). If the other dependencies are not
233
+ # compatible with the version reported by the podspec of the
234
+ # external source the resolver will raise.
235
+ #
236
+ # @return [void]
237
+ #
238
+ # TODO Specs
239
+ #
240
+ def fetch_external_sources
241
+ return unless allow_pre_downloads?
242
+ deps_to_fetch = []
243
+ deps_to_fetch_if_needed = []
244
+ deps_with_external_source = podfile.dependencies.select { |dep| dep.external_source }
245
+ if update_mode?
246
+ deps_to_fetch = deps_with_external_source
247
+ else
248
+ pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
249
+ deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) }
250
+ deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) }
251
+ deps_to_fetch += deps_to_fetch_if_needed.select { |dep| sandbox.specification(dep.root_name).nil? || !dep.external_source[:local].nil? || !dep.external_source[:path].nil? }
252
+ end
253
+
254
+ unless deps_to_fetch.empty?
255
+ UI.section "Fetching external sources" do
256
+ deps_to_fetch.uniq.sort.each do |dependency|
257
+ source = ExternalSources.from_dependency(dependency, podfile.defined_in_file)
258
+ source.fetch(sandbox)
259
+ end
260
+ end
261
+ end
262
+ end
263
+
264
+ # Converts the Podfile in a list of specifications grouped by target.
265
+ #
266
+ # @note In this step the specs are added to the libraries.
267
+ #
268
+ # @note As some dependencies might have external sources the resolver
269
+ # is aware of the {Sandbox} and interacts with it to download the
270
+ # podspecs of the external sources. This is necessary because the
271
+ # resolver needs their specifications to analyze their
272
+ # dependencies.
273
+ #
274
+ # @note The specifications of the external sources which are added,
275
+ # modified or removed need to deleted from the sandbox before the
276
+ # resolution process. Otherwise the resolver might use an
277
+ # incorrect specification instead of pre-downloading it.
278
+ #
279
+ # @note In update mode the resolver is set to always update the specs
280
+ # from external sources.
281
+ #
282
+ # @return [Hash{TargetDefinition => Array<Spec>}] the specifications
283
+ # grouped by target.
284
+ #
285
+ def resolve_dependencies
286
+ specs_by_target = nil
287
+
288
+ UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do
289
+ resolver = Resolver.new(sandbox, podfile, locked_dependencies)
290
+ specs_by_target = resolver.resolve
291
+ end
292
+
293
+ specs_by_target.each do |target_definition, specs|
294
+ lib = result.libraries.find { |l| l.target_definition == target_definition}
295
+ lib.specs = specs
296
+ end
297
+
298
+ specs_by_target
299
+ end
300
+
301
+ # Returns the list of all the resolved the resolved specifications.
302
+ #
303
+ # @return [Array<Specification>] the list of the specifications.
304
+ #
305
+ def generate_specifications
306
+ result.specs_by_target.values.flatten.uniq
307
+ end
308
+
309
+ # Computes the state of the sandbox respect to the resolved
310
+ # specifications.
311
+ #
312
+ # @return [SpecsState] the representation of the state of the manifest
313
+ # specifications.
314
+ #
315
+ def generate_sandbox_state
316
+ sandbox_state = nil
317
+ UI.section "Comparing resolved specification to the sandbox manifest" do
318
+ sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode, lockfile)
319
+ sandbox_state = sandbox_analyzer.analyze
320
+ sandbox_state.print
321
+ end
322
+ sandbox_state
323
+ end
324
+
325
+ #-----------------------------------------------------------------------#
326
+
327
+ # @!group Analysis internal products
328
+
329
+ # @return [Array<Dependency>] the dependencies generate by the lockfile
330
+ # that prevent the resolver to update a Pod.
331
+ #
332
+ attr_reader :locked_dependencies
333
+
334
+ #-----------------------------------------------------------------------#
335
+
336
+ private
337
+
338
+ # @!group Analysis sub-steps
339
+
340
+ # Returns the path of the user project that the {TargetDefinition}
341
+ # should integrate.
342
+ #
343
+ # @raise If the project is implicit and there are multiple projects.
344
+ #
345
+ # @raise If the path doesn't exits.
346
+ #
347
+ # @return [Pathname] the path of the user project.
348
+ #
349
+ def compute_user_project_path(target_definition)
350
+ if target_definition.user_project_path
351
+ path = config.installation_root + target_definition.user_project_path
352
+ path = "#{path}.xcodeproj" unless File.extname(path) == '.xcodeproj'
353
+ path = Pathname.new(path)
354
+ unless path.exist?
355
+ raise Informative, "Unable to find the Xcode project " \
356
+ "`#{path}` for the target `#{target_definition.label}`."
357
+ end
358
+
359
+ else
360
+ xcodeprojs = Pathname.glob(config.installation_root + '*.xcodeproj')
361
+ if xcodeprojs.size == 1
362
+ path = xcodeprojs.first
363
+ else
364
+ raise Informative, "Could not automatically select an Xcode project. " \
365
+ "Specify one in your Podfile like so:\n\n" \
366
+ " xcodeproj 'path/to/Project.xcodeproj'\n"
367
+ end
368
+ end
369
+ path
370
+ end
371
+
372
+ # Returns a list of the targets from the project of {TargetDefinition}
373
+ # that needs to be integrated.
374
+ #
375
+ # @note The method first looks if there is a target specified with
376
+ # the `link_with` option of the {TargetDefinition}. Otherwise
377
+ # it looks for the target that has the same name of the target
378
+ # definition. Finally if no target was found the first
379
+ # encountered target is returned (it is assumed to be the one
380
+ # to integrate in simple projects).
381
+ #
382
+ # @note This will only return targets that do **not** already have
383
+ # the Pods library in their frameworks build phase.
384
+ #
385
+ #
386
+ def compute_user_project_targets(target_definition, user_project)
387
+ if link_with = target_definition.link_with
388
+ targets = native_targets(user_project).select { |t| link_with.include?(t.name) }
389
+ raise Informative, "Unable to find the targets named `#{link_with.to_sentence}` to link with target definition `#{target_definition.name}`" if targets.empty?
390
+ elsif target_definition.link_with_first_target?
391
+ targets = [ native_targets(user_project).first ].compact
392
+ raise Informative, "Unable to find a target" if targets.empty?
393
+ else
394
+ target = native_targets(user_project).find { |t| t.name == target_definition.name.to_s }
395
+ targets = [ target ].compact
396
+ raise Informative, "Unable to find a target named `#{target_definition.name.to_s}`" if targets.empty?
397
+ end
398
+ targets
399
+ end
400
+
401
+ # @return [Array<PBXNativeTarget>] Returns the user’s targets, excluding
402
+ # aggregate targets.
403
+ #
404
+ def native_targets(user_project)
405
+ user_project.targets.reject do |target|
406
+ target.is_a? Xcodeproj::Project::Object::PBXAggregateTarget
407
+ end
408
+ end
409
+
410
+ # @return [Hash{String=>Symbol}] A hash representing the user build
411
+ # configurations where each key corresponds to the name of a
412
+ # configuration and its value to its type (`:debug` or `:release`).
413
+ #
414
+ def compute_user_build_configurations(target_definition, user_targets)
415
+ if user_targets
416
+ user_targets.map { |t| t.build_configurations.map(&:name) }.flatten.inject({}) do |hash, name|
417
+ unless name == 'Debug' || name == 'Release'
418
+ hash[name] = :release
419
+ end
420
+ hash
421
+ end.merge(target_definition.build_configurations || {})
422
+ else
423
+ target_definition.build_configurations || {}
424
+ end
425
+ end
426
+
427
+ # @return [Platform] The platform for the library.
428
+ #
429
+ # @note This resolves to the lowest deployment target across the user
430
+ # targets.
431
+ #
432
+ # @todo Is assigning the platform to the target definition the best way
433
+ # to go?
434
+ #
435
+ def compute_platform_for_target_definition(target_definition, user_targets)
436
+ return target_definition.platform if target_definition.platform
437
+ name = nil
438
+ deployment_target = nil
439
+
440
+ user_targets.each do |target|
441
+ name ||= target.platform_name
442
+ raise Informative, "Targets with different platforms" unless name == target.platform_name
443
+ if !deployment_target || deployment_target > Version.new(target.deployment_target)
444
+ deployment_target = Version.new(target.deployment_target)
445
+ end
446
+ end
447
+
448
+ target_definition.set_platform(name, deployment_target)
449
+ Platform.new(name, deployment_target)
450
+ end
451
+
452
+ #-----------------------------------------------------------------------#
453
+
454
+ class AnalysisResult
455
+
456
+ # @return [SpecsState] the states of the Podfile specs.
457
+ #
458
+ attr_accessor :podfile_state
459
+
460
+ # @return [Hash{TargetDefinition => Array<Spec>}] the specifications
461
+ # grouped by target.
462
+ #
463
+ attr_accessor :specs_by_target
464
+
465
+ # @return [Array<Specification>] the specifications of the resolved
466
+ # version of Pods that should be installed.
467
+ #
468
+ attr_accessor :specifications
469
+
470
+ # @return [SpecsState] the states of the {Sandbox} respect the resolved
471
+ # specifications.
472
+ #
473
+ attr_accessor :sandbox_state
474
+
475
+ # @return [Array<Library>] the libraries generated by the target
476
+ # definitions.
477
+ #
478
+ attr_accessor :libraries
479
+
480
+ end
481
+
482
+ #-----------------------------------------------------------------------#
483
+
484
+ # This class represents the state of a collection of Pods.
485
+ #
486
+ # @note The names of the pods stored by this class are always the **root**
487
+ # name of the specification.
488
+ #
489
+ # @note The motivation for this class is to ensure that the names of the
490
+ # subspecs are added instead of the name of the Pods.
491
+ #
492
+ class SpecsState
493
+
494
+ # @param [Hash{Symbol=>String}] pods_by_state
495
+ # The **root** name of the pods grouped by their state
496
+ # (`:added`, `:removed`, `:changed` or `:unchanged`).
497
+ #
498
+ def initialize(pods_by_state = nil)
499
+ @added = []
500
+ @deleted = []
501
+ @changed = []
502
+ @unchanged = []
503
+
504
+ if pods_by_state
505
+ @added = pods_by_state[:added] || []
506
+ @deleted = pods_by_state[:removed] || []
507
+ @changed = pods_by_state[:changed] || []
508
+ @unchanged = pods_by_state[:unchanged] || []
509
+ end
510
+ end
511
+
512
+ # @return [Array<String>] the names of the pods that were added.
513
+ #
514
+ attr_accessor :added
515
+
516
+ # @return [Array<String>] the names of the pods that were changed.
517
+ #
518
+ attr_accessor :changed
519
+
520
+ # @return [Array<String>] the names of the pods that were deleted.
521
+ #
522
+ attr_accessor :deleted
523
+
524
+ # @return [Array<String>] the names of the pods that were unchanged.
525
+ #
526
+ attr_accessor :unchanged
527
+
528
+ # Displays the state of each pod.
529
+ #
530
+ # @return [void]
531
+ #
532
+ def print
533
+ added .sort.each { |pod| UI.message("A".green + " #{pod}", '', 2) }
534
+ deleted .sort.each { |pod| UI.message("R".red + " #{pod}", '', 2) }
535
+ changed .sort.each { |pod| UI.message("M".yellow + " #{pod}", '', 2) }
536
+ unchanged.sort.each { |pod| UI.message("-" + " #{pod}", '', 2) }
537
+ end
538
+
539
+ # Adds the name of a Pod to the give state.
540
+ #
541
+ # @param [String]
542
+ # the name of the Pod.
543
+ #
544
+ # @param [Symbol]
545
+ # the state of the Pod.
546
+ #
547
+ # @raise If there is an attempt to add the name of a subspec.
548
+ #
549
+ # @return [void]
550
+ #
551
+ def add_name(name, state)
552
+ raise "[Bug] Attempt to add subspec to the pods state" if name.include?('/')
553
+ self.send(state) << name
554
+ end
555
+
556
+ end
557
+ end
558
+ end
559
+ end