cocoapods-tt 0.0.1

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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-tt/command/native/install.rb +56 -0
  3. data/lib/cocoapods-tt/command/native/update.rb +157 -0
  4. data/lib/cocoapods-tt/command/tt/make.rb +92 -0
  5. data/lib/cocoapods-tt/command/tt.rb +115 -0
  6. data/lib/cocoapods-tt/command.rb +1 -0
  7. data/lib/cocoapods-tt/gem_version.rb +3 -0
  8. data/lib/cocoapods-tt/native/command.rb +185 -0
  9. data/lib/cocoapods-tt/native/config.rb +366 -0
  10. data/lib/cocoapods-tt/native/core_overrides.rb +1 -0
  11. data/lib/cocoapods-tt/native/downloader/cache.rb +322 -0
  12. data/lib/cocoapods-tt/native/downloader/request.rb +86 -0
  13. data/lib/cocoapods-tt/native/downloader/response.rb +16 -0
  14. data/lib/cocoapods-tt/native/downloader.rb +192 -0
  15. data/lib/cocoapods-tt/native/executable.rb +247 -0
  16. data/lib/cocoapods-tt/native/external_sources/abstract_external_source.rb +205 -0
  17. data/lib/cocoapods-tt/native/external_sources/downloader_source.rb +30 -0
  18. data/lib/cocoapods-tt/native/external_sources/path_source.rb +55 -0
  19. data/lib/cocoapods-tt/native/external_sources/podspec_source.rb +54 -0
  20. data/lib/cocoapods-tt/native/external_sources.rb +57 -0
  21. data/lib/cocoapods-tt/native/gem_version.rb +5 -0
  22. data/lib/cocoapods-tt/native/generator/acknowledgements/markdown.rb +44 -0
  23. data/lib/cocoapods-tt/native/generator/acknowledgements/plist.rb +94 -0
  24. data/lib/cocoapods-tt/native/generator/acknowledgements.rb +107 -0
  25. data/lib/cocoapods-tt/native/generator/app_target_helper.rb +363 -0
  26. data/lib/cocoapods-tt/native/generator/bridge_support.rb +22 -0
  27. data/lib/cocoapods-tt/native/generator/constant.rb +19 -0
  28. data/lib/cocoapods-tt/native/generator/copy_dsyms_script.rb +56 -0
  29. data/lib/cocoapods-tt/native/generator/copy_resources_script.rb +223 -0
  30. data/lib/cocoapods-tt/native/generator/copy_xcframework_script.rb +227 -0
  31. data/lib/cocoapods-tt/native/generator/dummy_source.rb +31 -0
  32. data/lib/cocoapods-tt/native/generator/embed_frameworks_script.rb +196 -0
  33. data/lib/cocoapods-tt/native/generator/file_list.rb +39 -0
  34. data/lib/cocoapods-tt/native/generator/header.rb +103 -0
  35. data/lib/cocoapods-tt/native/generator/info_plist_file.rb +128 -0
  36. data/lib/cocoapods-tt/native/generator/module_map.rb +99 -0
  37. data/lib/cocoapods-tt/native/generator/prefix_header.rb +60 -0
  38. data/lib/cocoapods-tt/native/generator/script_phase_constants.rb +100 -0
  39. data/lib/cocoapods-tt/native/generator/umbrella_header.rb +46 -0
  40. data/lib/cocoapods-tt/native/hooks_manager.rb +132 -0
  41. data/lib/cocoapods-tt/native/installer/analyzer/analysis_result.rb +87 -0
  42. data/lib/cocoapods-tt/native/installer/analyzer/locking_dependency_analyzer.rb +103 -0
  43. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant.rb +87 -0
  44. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant_set.rb +175 -0
  45. data/lib/cocoapods-tt/native/installer/analyzer/podfile_dependency_cache.rb +55 -0
  46. data/lib/cocoapods-tt/native/installer/analyzer/sandbox_analyzer.rb +268 -0
  47. data/lib/cocoapods-tt/native/installer/analyzer/specs_state.rb +108 -0
  48. data/lib/cocoapods-tt/native/installer/analyzer/target_inspection_result.rb +58 -0
  49. data/lib/cocoapods-tt/native/installer/analyzer/target_inspector.rb +258 -0
  50. data/lib/cocoapods-tt/native/installer/analyzer.rb +1204 -0
  51. data/lib/cocoapods-tt/native/installer/base_install_hooks_context.rb +135 -0
  52. data/lib/cocoapods-tt/native/installer/installation_options.rb +195 -0
  53. data/lib/cocoapods-tt/native/installer/pod_source_installer.rb +224 -0
  54. data/lib/cocoapods-tt/native/installer/pod_source_preparer.rb +77 -0
  55. data/lib/cocoapods-tt/native/installer/podfile_validator.rb +168 -0
  56. data/lib/cocoapods-tt/native/installer/post_install_hooks_context.rb +9 -0
  57. data/lib/cocoapods-tt/native/installer/post_integrate_hooks_context.rb +9 -0
  58. data/lib/cocoapods-tt/native/installer/pre_install_hooks_context.rb +51 -0
  59. data/lib/cocoapods-tt/native/installer/pre_integrate_hooks_context.rb +9 -0
  60. data/lib/cocoapods-tt/native/installer/project_cache/project_cache.rb +11 -0
  61. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analysis_result.rb +53 -0
  62. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analyzer.rb +200 -0
  63. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_version.rb +43 -0
  64. data/lib/cocoapods-tt/native/installer/project_cache/project_installation_cache.rb +103 -0
  65. data/lib/cocoapods-tt/native/installer/project_cache/project_metadata_cache.rb +73 -0
  66. data/lib/cocoapods-tt/native/installer/project_cache/target_cache_key.rb +176 -0
  67. data/lib/cocoapods-tt/native/installer/project_cache/target_metadata.rb +74 -0
  68. data/lib/cocoapods-tt/native/installer/sandbox_dir_cleaner.rb +105 -0
  69. data/lib/cocoapods-tt/native/installer/sandbox_header_paths_installer.rb +45 -0
  70. data/lib/cocoapods-tt/native/installer/source_provider_hooks_context.rb +34 -0
  71. data/lib/cocoapods-tt/native/installer/target_uuid_generator.rb +34 -0
  72. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +179 -0
  73. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator.rb +815 -0
  74. data/lib/cocoapods-tt/native/installer/user_project_integrator.rb +280 -0
  75. data/lib/cocoapods-tt/native/installer/xcode/multi_pods_project_generator.rb +82 -0
  76. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +66 -0
  77. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_installer.rb +192 -0
  78. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/app_host_installer.rb +154 -0
  79. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/file_references_installer.rb +329 -0
  80. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +195 -0
  81. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_installer.rb +1239 -0
  82. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_integrator.rb +312 -0
  83. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pods_project_writer.rb +90 -0
  84. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/project_generator.rb +120 -0
  85. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installation_result.rb +140 -0
  86. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer.rb +257 -0
  87. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer_helper.rb +110 -0
  88. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator.rb +291 -0
  89. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator_result.rb +54 -0
  90. data/lib/cocoapods-tt/native/installer/xcode/single_pods_project_generator.rb +38 -0
  91. data/lib/cocoapods-tt/native/installer/xcode/target_validator.rb +170 -0
  92. data/lib/cocoapods-tt/native/installer/xcode.rb +11 -0
  93. data/lib/cocoapods-tt/native/installer.rb +1044 -0
  94. data/lib/cocoapods-tt/native/native_target_extension.rb +60 -0
  95. data/lib/cocoapods-tt/native/open-uri.rb +33 -0
  96. data/lib/cocoapods-tt/native/podfile.rb +13 -0
  97. data/lib/cocoapods-tt/native/project.rb +544 -0
  98. data/lib/cocoapods-tt/native/resolver/lazy_specification.rb +88 -0
  99. data/lib/cocoapods-tt/native/resolver/resolver_specification.rb +41 -0
  100. data/lib/cocoapods-tt/native/resolver.rb +600 -0
  101. data/lib/cocoapods-tt/native/sandbox/file_accessor.rb +532 -0
  102. data/lib/cocoapods-tt/native/sandbox/headers_store.rb +163 -0
  103. data/lib/cocoapods-tt/native/sandbox/path_list.rb +242 -0
  104. data/lib/cocoapods-tt/native/sandbox/pod_dir_cleaner.rb +71 -0
  105. data/lib/cocoapods-tt/native/sandbox/podspec_finder.rb +23 -0
  106. data/lib/cocoapods-tt/native/sandbox.rb +470 -0
  107. data/lib/cocoapods-tt/native/sources_manager.rb +221 -0
  108. data/lib/cocoapods-tt/native/target/aggregate_target.rb +558 -0
  109. data/lib/cocoapods-tt/native/target/build_settings.rb +1385 -0
  110. data/lib/cocoapods-tt/native/target/pod_target.rb +1168 -0
  111. data/lib/cocoapods-tt/native/target.rb +378 -0
  112. data/lib/cocoapods-tt/native/user_interface/error_report.rb +204 -0
  113. data/lib/cocoapods-tt/native/user_interface/inspector_reporter.rb +102 -0
  114. data/lib/cocoapods-tt/native/user_interface.rb +463 -0
  115. data/lib/cocoapods-tt/native/validator.rb +1170 -0
  116. data/lib/cocoapods-tt/native/version_metadata.rb +26 -0
  117. data/lib/cocoapods-tt/native/xcode/framework_paths.rb +54 -0
  118. data/lib/cocoapods-tt/native/xcode/linkage_analyzer.rb +22 -0
  119. data/lib/cocoapods-tt/native/xcode/xcframework/xcframework_slice.rb +138 -0
  120. data/lib/cocoapods-tt/native/xcode/xcframework.rb +99 -0
  121. data/lib/cocoapods-tt/native/xcode.rb +7 -0
  122. data/lib/cocoapods-tt.rb +1 -0
  123. data/lib/cocoapods_plugin.rb +17 -0
  124. metadata +193 -0
@@ -0,0 +1,470 @@
1
+ require 'fileutils'
2
+
3
+ module Pod
4
+ # The sandbox provides support for the directory that CocoaPods uses for an
5
+ # installation. In this directory the Pods projects, the support files and
6
+ # the sources of the Pods are stored.
7
+ #
8
+ # CocoaPods assumes to have control of the sandbox.
9
+ #
10
+ # Once completed the sandbox will have the following file structure:
11
+ #
12
+ # Pods
13
+ # |
14
+ # +-- Headers
15
+ # | +-- Private
16
+ # | | +-- [Pod Name]
17
+ # | +-- Public
18
+ # | +-- [Pod Name]
19
+ # |
20
+ # +-- Local Podspecs
21
+ # | +-- External Sources
22
+ # | +-- Normal Sources
23
+ # |
24
+ # +-- Target Support Files
25
+ # | +-- [Target Name]
26
+ # | +-- Pods-acknowledgements.markdown
27
+ # | +-- Pods-acknowledgements.plist
28
+ # | +-- Pods-dummy.m
29
+ # | +-- Pods-prefix.pch
30
+ # | +-- Pods.xcconfig
31
+ # |
32
+ # +-- [Pod Name]
33
+ # |
34
+ # +-- Manifest.lock
35
+ # |
36
+ # +-- Pods.xcodeproj
37
+ # (if installation option 'generate_multiple_pod_projects' is enabled)
38
+ # |
39
+ # +-- PodTarget1.xcodeproj
40
+ # |
41
+ # ...
42
+ # |
43
+ # +-- PodTargetN.xcodeproj
44
+ #
45
+ #
46
+ class Sandbox
47
+ autoload :FileAccessor, 'cocoapods/sandbox/file_accessor'
48
+ autoload :HeadersStore, 'cocoapods/sandbox/headers_store'
49
+ autoload :PathList, 'cocoapods/sandbox/path_list'
50
+ autoload :PodDirCleaner, 'cocoapods/sandbox/pod_dir_cleaner'
51
+ autoload :PodspecFinder, 'cocoapods/sandbox/podspec_finder'
52
+
53
+ # @return [Pathname] the root of the sandbox.
54
+ #
55
+ attr_reader :root
56
+
57
+ # @return [HeadersStore] the header directory for the user targets.
58
+ #
59
+ attr_reader :public_headers
60
+
61
+ # Initialize a new instance
62
+ #
63
+ # @param [String, Pathname] root @see #root
64
+ #
65
+ def initialize(root)
66
+ FileUtils.mkdir_p(root)
67
+ @root = Pathname.new(root).realpath
68
+ @public_headers = HeadersStore.new(self, 'Public', :public)
69
+ @predownloaded_pods = []
70
+ @checkout_sources = {}
71
+ @development_pods = {}
72
+ @pods_with_absolute_path = []
73
+ @stored_podspecs = {}
74
+ end
75
+
76
+ # @return [Lockfile] the manifest which contains the information about the
77
+ # installed pods or `nil` if one is not present.
78
+ #
79
+ def manifest
80
+ @manifest ||= begin
81
+ Lockfile.from_file(manifest_path) if manifest_path.exist?
82
+ end
83
+ end
84
+
85
+ # Removes the files of the Pod with the given name from the sandbox.
86
+ #
87
+ # @return [void]
88
+ #
89
+ def clean_pod(name)
90
+ root_name = Specification.root_name(name)
91
+ unless local?(root_name)
92
+ path = pod_dir(name)
93
+ path.rmtree if path.exist?
94
+ end
95
+ podspec_path = specification_path(name)
96
+ podspec_path.rmtree if podspec_path
97
+ pod_target_project_path = pod_target_project_path(name)
98
+ pod_target_project_path.rmtree if pod_target_project_path.exist?
99
+ end
100
+
101
+ # Prepares the sandbox for a new installation removing any file that will
102
+ # be regenerated and ensuring that the directories exists.
103
+ #
104
+ def prepare
105
+ FileUtils.mkdir_p(headers_root)
106
+ FileUtils.mkdir_p(sources_root)
107
+ FileUtils.mkdir_p(specifications_root)
108
+ FileUtils.mkdir_p(target_support_files_root)
109
+ end
110
+
111
+ # @return [String] a string representation suitable for debugging.
112
+ #
113
+ def inspect
114
+ "#<#{self.class}> with root #{root}"
115
+ end
116
+
117
+ #-------------------------------------------------------------------------#
118
+
119
+ public
120
+
121
+ # @!group Paths
122
+
123
+ # @return [Pathname] the path of the manifest.
124
+ #
125
+ def manifest_path
126
+ root + 'Manifest.lock'
127
+ end
128
+
129
+ # @return [Pathname] the path of the Pods project.
130
+ #
131
+ def project_path
132
+ root + 'Pods.xcodeproj'
133
+ end
134
+
135
+ # @return [Pathname] the path of the installation cache.
136
+ #
137
+ def project_installation_cache_path
138
+ root.join('.project_cache', 'installation_cache.yaml')
139
+ end
140
+
141
+ # @return [Pathname] the path of the metadata cache.
142
+ #
143
+ def project_metadata_cache_path
144
+ root.join('.project_cache', 'metadata_cache.yaml')
145
+ end
146
+
147
+ # @return [Pathname] the path of the version cache.
148
+ #
149
+ def project_version_cache_path
150
+ root.join('.project_cache', 'version')
151
+ end
152
+
153
+ # @param [String] pod_target_name
154
+ # Name of the pod target used to generate the path of its Xcode project.
155
+ #
156
+ # @return [Pathname] the path of the project for a pod target.
157
+ #
158
+ def pod_target_project_path(pod_target_name)
159
+ root + "#{pod_target_name}.xcodeproj"
160
+ end
161
+
162
+ # Returns the path for the directory where the support files of
163
+ # a target are stored.
164
+ #
165
+ # @param [String] name
166
+ # The name of the target.
167
+ #
168
+ # @return [Pathname] the path of the support files.
169
+ #
170
+ def target_support_files_dir(name)
171
+ target_support_files_root + name
172
+ end
173
+
174
+ # Returns the path where the Pod with the given name is stored, taking into
175
+ # account whether the Pod is locally sourced.
176
+ #
177
+ # @param [String] name
178
+ # The name of the Pod.
179
+ #
180
+ # @return [Pathname] the path of the Pod.
181
+ #
182
+ def pod_dir(name)
183
+ root_name = Specification.root_name(name)
184
+ if local?(root_name)
185
+ Pathname.new(development_pods[root_name].dirname)
186
+ else
187
+ sources_root + root_name
188
+ end
189
+ end
190
+
191
+ # Returns true if the path as originally specified was absolute.
192
+ #
193
+ # @param [String] name
194
+ #
195
+ # @return [Bool] true if originally absolute
196
+ #
197
+ def local_path_was_absolute?(name)
198
+ @pods_with_absolute_path.include? name
199
+ end
200
+
201
+ # @return [Pathname] The directory where headers are stored.
202
+ #
203
+ def headers_root
204
+ root + 'Headers'
205
+ end
206
+
207
+ # @return [Pathname] The directory where the downloaded sources of
208
+ # the Pods are stored.
209
+ #
210
+ def sources_root
211
+ root
212
+ end
213
+
214
+ # @return [Pathname] the path for the directory where the
215
+ # specifications are stored.
216
+ #
217
+ def specifications_root
218
+ root + 'Local Podspecs'
219
+ end
220
+
221
+ # @return [Pathname] The directory where the files generated by
222
+ # CocoaPods to support the umbrella targets are stored.
223
+ #
224
+ def target_support_files_root
225
+ root + 'Target Support Files'
226
+ end
227
+
228
+ #-------------------------------------------------------------------------#
229
+
230
+ public
231
+
232
+ # @!group Specification store
233
+
234
+ # Returns the specification for the Pod with the given name.
235
+ #
236
+ # @param [String] name
237
+ # the name of the Pod for which the specification is requested.
238
+ #
239
+ # @return [Specification] the specification if the file is found.
240
+ #
241
+ def specification(name)
242
+ @stored_podspecs[name] ||= if file = specification_path(name)
243
+ original_path = development_pods[name]
244
+ Specification.from_file(original_path || file)
245
+ end
246
+ end
247
+
248
+ # Returns the path of the specification for the Pod with the
249
+ # given name, if one is stored.
250
+ #
251
+ # @param [String] name
252
+ # the name of the Pod for which the podspec file is requested.
253
+ #
254
+ # @return [Pathname] the path or nil.
255
+ # @return [Nil] if the podspec is not stored.
256
+ #
257
+ def specification_path(name)
258
+ name = Specification.root_name(name)
259
+ path = specifications_root + "#{name}.podspec"
260
+ if path.exist?
261
+ path
262
+ else
263
+ path = specifications_root + "#{name}.podspec.json"
264
+ if path.exist?
265
+ path
266
+ end
267
+ end
268
+ end
269
+
270
+ # Stores a specification in the `Local Podspecs` folder.
271
+ #
272
+ # @param [String] name
273
+ # the name of the pod
274
+ #
275
+ # @param [String, Pathname, Specification] podspec
276
+ # The contents of the specification (String) or the path to a
277
+ # podspec file (Pathname).
278
+ #
279
+ # @return [void]
280
+ #
281
+ #
282
+ def store_podspec(name, podspec, _external_source = false, json = false)
283
+ file_name = json ? "#{name}.podspec.json" : "#{name}.podspec"
284
+ output_path = specifications_root + file_name
285
+
286
+ spec =
287
+ case podspec
288
+ when String
289
+ Sandbox.update_changed_file(output_path, podspec)
290
+ Specification.from_file(output_path)
291
+ when Pathname
292
+ unless podspec.exist?
293
+ raise Informative, "No podspec found for `#{name}` in #{podspec}"
294
+ end
295
+ FileUtils.copy(podspec, output_path)
296
+ Specification.from_file(podspec)
297
+ when Specification
298
+ raise ArgumentError, 'can only store Specification objects as json' unless json
299
+ Sandbox.update_changed_file(output_path, podspec.to_pretty_json)
300
+ podspec.dup
301
+ else
302
+ raise ArgumentError, "Unknown type for podspec: #{podspec.inspect}"
303
+ end
304
+
305
+ # we force the file to be the file in the sandbox, so specs that have been serialized to
306
+ # json maintain a consistent checksum.
307
+ # this is safe to do because `spec` is always a clean instance
308
+ spec.defined_in_file = output_path
309
+
310
+ unless spec.name == name
311
+ raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
312
+ end
313
+ @stored_podspecs[spec.name] = spec
314
+ end
315
+
316
+ #-------------------------------------------------------------------------#
317
+
318
+ public
319
+
320
+ # @!group Pods information
321
+
322
+ # Marks a Pod as pre-downloaded
323
+ #
324
+ # @param [String] name
325
+ # The name of the Pod.
326
+ #
327
+ # @return [void]
328
+ #
329
+ def store_pre_downloaded_pod(name)
330
+ root_name = Specification.root_name(name)
331
+ predownloaded_pods << root_name
332
+ end
333
+
334
+ # @return [Array<String>] The names of the pods that have been
335
+ # pre-downloaded from an external source.
336
+ #
337
+ attr_reader :predownloaded_pods
338
+
339
+ # Checks if a Pod has been pre-downloaded by the resolver in order to fetch
340
+ # the podspec.
341
+ #
342
+ # @param [String] name
343
+ # The name of the Pod.
344
+ #
345
+ # @return [Bool] Whether the Pod has been pre-downloaded.
346
+ #
347
+ def predownloaded?(name)
348
+ root_name = Specification.root_name(name)
349
+ predownloaded_pods.include?(root_name)
350
+ end
351
+
352
+ #--------------------------------------#
353
+
354
+ # Stores the local path of a Pod.
355
+ #
356
+ # @param [String] name
357
+ # The name of the Pod.
358
+ #
359
+ # @param [Hash] source
360
+ # The hash which contains the options as returned by the
361
+ # downloader.
362
+ #
363
+ # @return [void]
364
+ #
365
+ def store_checkout_source(name, source)
366
+ root_name = Specification.root_name(name)
367
+ checkout_sources[root_name] = source
368
+ end
369
+
370
+ # Removes the checkout source of a Pod.
371
+ #
372
+ # @param [String] name
373
+ # The name of the Pod.
374
+ #
375
+ # @return [void]
376
+ #
377
+ def remove_checkout_source(name)
378
+ root_name = Specification.root_name(name)
379
+ checkout_sources.delete(root_name)
380
+ end
381
+
382
+ # Removes local podspec a Pod.
383
+ #
384
+ # @param [String] name
385
+ # The name of the Pod.
386
+ #
387
+ # @return [void]
388
+ #
389
+ def remove_local_podspec(name)
390
+ local_podspec = specification_path(name)
391
+ FileUtils.rm(local_podspec) if local_podspec
392
+ end
393
+
394
+ # @return [Hash{String=>Hash}] The options necessary to recreate the exact
395
+ # checkout of a given Pod grouped by its name.
396
+ #
397
+ attr_reader :checkout_sources
398
+
399
+ #--------------------------------------#
400
+
401
+ # Stores the local path of a Pod.
402
+ #
403
+ # @param [String] name
404
+ # The name of the Pod.
405
+ #
406
+ # @param [Pathname, String] path
407
+ # The path to the local Podspec
408
+ #
409
+ # @param [Bool] was_absolute
410
+ # True if the specified local path was absolute.
411
+ #
412
+ # @return [void]
413
+ #
414
+ def store_local_path(name, path, was_absolute = false)
415
+ root_name = Specification.root_name(name)
416
+ path = Pathname.new(path) unless path.is_a?(Pathname)
417
+ development_pods[root_name] = path
418
+ @pods_with_absolute_path << root_name if was_absolute
419
+ end
420
+
421
+ # @return [Hash{String=>Pathname}] The path of the Pods' podspecs with a local source
422
+ # grouped by their root name.
423
+ #
424
+ attr_reader :development_pods
425
+
426
+ # Checks if a Pod is locally sourced?
427
+ #
428
+ # @param [String] name
429
+ # The name of the Pod.
430
+ #
431
+ # @return [Bool] Whether the Pod is locally sourced.
432
+ #
433
+ def local?(name)
434
+ !local_podspec(name).nil?
435
+ end
436
+
437
+ # @param [String] name
438
+ # The name of a locally specified Pod
439
+ #
440
+ # @return [Pathname] Path to the local Podspec of the Pod
441
+ #
442
+ def local_podspec(name)
443
+ root_name = Specification.root_name(name)
444
+ development_pods[root_name]
445
+ end
446
+
447
+ # @!group Convenience Methods
448
+
449
+ # Writes a file if it does not exist or if its contents have changed.
450
+ #
451
+ # @param [Pathname] path
452
+ # The path to read from and write to.
453
+ #
454
+ # @param [String] contents
455
+ # The contents to write if they do not match or the file does not exist.
456
+ #
457
+ # @return [void]
458
+ #
459
+ def self.update_changed_file(path, contents)
460
+ if path.exist?
461
+ content_stream = StringIO.new(contents)
462
+ identical = File.open(path, 'rb') { |f| FileUtils.compare_stream(f, content_stream) }
463
+ return if identical
464
+ end
465
+ File.open(path, 'w') { |f| f.write(contents) }
466
+ end
467
+
468
+ #-------------------------------------------------------------------------#
469
+ end
470
+ end
@@ -0,0 +1,221 @@
1
+ require 'cocoapods-core/source'
2
+ require 'cocoapods/open-uri'
3
+ require 'netrc'
4
+ require 'set'
5
+ require 'rest'
6
+ require 'yaml'
7
+
8
+ module Pod
9
+ class Source
10
+ class Manager
11
+ # Returns the source whose {Source#url} is equal to `url`, adding the repo
12
+ # in a manner similarly to `pod repo add` if it is not found.
13
+ #
14
+ # @raise If no source with the given `url` could be created,
15
+ #
16
+ # @return [Source] The source whose {Source#url} is equal to `url`,
17
+ #
18
+ # @param [String] url
19
+ # The URL of the source.
20
+ #
21
+ def find_or_create_source_with_url(url)
22
+ source_with_url(url) || create_source_with_url(url)
23
+ end
24
+
25
+ # Adds the source whose {Source#url} is equal to `url`,
26
+ # in a manner similarly to `pod repo add` if it is not found.
27
+ #
28
+ # @raise If no source with the given `url` could be created,
29
+ #
30
+ # @return [Source] The source whose {Source#url} is equal to `url`,
31
+ #
32
+ # @param [String] url
33
+ # The URL of the source.
34
+ #
35
+ def create_source_with_url(url)
36
+ name = name_for_url(url)
37
+ is_cdn = cdn_url?(url)
38
+
39
+ # Hack to ensure that `repo add` output is shown.
40
+ previous_title_level = UI.title_level
41
+ UI.title_level = 0
42
+
43
+ begin
44
+ if is_cdn
45
+ Command::Repo::AddCDN.parse([name, url]).run
46
+ else
47
+ Command::Repo::Add.parse([name, url]).run
48
+ end
49
+ rescue Informative => e
50
+ message = "Unable to add a source with url `#{url}` " \
51
+ "named `#{name}`.\n"
52
+ message << "(#{e})\n" if Config.instance.verbose?
53
+ message << 'You can try adding it manually in ' \
54
+ "`#{Config.instance.repos_dir}` or via `pod repo add`."
55
+ raise Informative, message
56
+ ensure
57
+ UI.title_level = previous_title_level
58
+ end
59
+ source = source_with_url(url)
60
+
61
+ raise "Unable to create a source with URL #{url}" unless source
62
+
63
+ source
64
+ end
65
+
66
+ # Determines whether `url` is a CocoaPods CDN URL.
67
+ #
68
+ # @return [Boolean] whether `url` is a CocoaPods CDN URL,
69
+ #
70
+ # @param [String] url
71
+ # The URL of the source.
72
+ #
73
+ def cdn_url?(url)
74
+ return false unless url =~ %r{^https?:\/\/}
75
+
76
+ uri_options = {}
77
+
78
+ netrc_info = Netrc.read
79
+ uri = URI.parse(url)
80
+ return false unless uri.userinfo.nil?
81
+
82
+ netrc_host = uri.host
83
+ credentials = netrc_info[netrc_host]
84
+ uri_options[:http_basic_authentication] = credentials if credentials
85
+
86
+ response = OpenURI.open_uri(url.chomp('/') + '/CocoaPods-version.yml', uri_options)
87
+ response_hash = YAML.load(response.read) # rubocop:disable Security/YAMLLoad
88
+ response_hash.is_a?(Hash) && !Source::Metadata.new(response_hash).latest_cocoapods_version.nil?
89
+ rescue Psych::SyntaxError, ::OpenURI::HTTPError, SocketError
90
+ return false
91
+ rescue => e
92
+ raise Informative, "Couldn't determine repo type for URL: `#{url}`: #{e}"
93
+ end
94
+
95
+ # Returns the source whose {Source#name} or {Source#url} is equal to the
96
+ # given `name_or_url`.
97
+ #
98
+ # @return [Source] The source whose {Source#name} or {Source#url} is equal to the
99
+ # given `name_or_url`.
100
+ #
101
+ # @param [String] name_or_url
102
+ # The name or the URL of the source.
103
+ #
104
+ def source_with_name_or_url(name_or_url)
105
+ all.find { |s| s.name == name_or_url } ||
106
+ find_or_create_source_with_url(name_or_url)
107
+ end
108
+
109
+ # @return [Pathname] The path where the search index should be stored.
110
+ #
111
+ def search_index_path
112
+ @search_index_path ||= Config.instance.search_index_file
113
+ end
114
+
115
+ # @!group Updating Sources
116
+
117
+ # Updates the local clone of the spec-repo with the given name or of all
118
+ # the git repos if the name is omitted.
119
+ #
120
+ # @param [String] source_name
121
+ #
122
+ # @param [Bool] show_output
123
+ #
124
+ # @return [void]
125
+ #
126
+ def update(source_name = nil, show_output = false)
127
+ if source_name
128
+ sources = [updateable_source_named(source_name)]
129
+ else
130
+ sources = updateable_sources
131
+ end
132
+
133
+ changed_spec_paths = {}
134
+
135
+ # Do not perform an update if the repos dir has not been setup yet.
136
+ return unless repos_dir.exist?
137
+
138
+ # Create the Spec_Lock file if needed and lock it so that concurrent
139
+ # repo updates do not cause each other to fail
140
+ File.open("#{repos_dir}/Spec_Lock", File::CREAT) do |f|
141
+ f.flock(File::LOCK_EX)
142
+ sources.each do |source|
143
+ UI.section "Updating spec repo `#{source.name}`" do
144
+ changed_source_paths = source.update(show_output)
145
+ changed_spec_paths[source] = changed_source_paths if changed_source_paths.count > 0
146
+ source.verify_compatibility!
147
+ end
148
+ end
149
+ end
150
+ # Perform search index update operation in background.
151
+ update_search_index_if_needed_in_background(changed_spec_paths)
152
+ end
153
+
154
+ # Adds the provided source to the list of sources
155
+ #
156
+ # @param [Source] source the source to add
157
+ #
158
+ def add_source(source)
159
+ all << source unless all.any? { |s| s.url == source || s.name == source.name }
160
+ end
161
+ end
162
+
163
+ extend Executable
164
+ executable :git
165
+
166
+ def repo_git(args, include_error: false)
167
+ Executable.capture_command('git', ['-C', repo] + args,
168
+ :capture => include_error ? :merge : :out,
169
+ :env => {
170
+ 'GIT_CONFIG' => nil,
171
+ 'GIT_DIR' => nil,
172
+ 'GIT_WORK_TREE' => nil,
173
+ }
174
+ ).
175
+ first.strip
176
+ end
177
+
178
+ def update_git_repo(show_output = false)
179
+ Config.instance.with_changes(:verbose => show_output) do
180
+ args = %W(-C #{repo} fetch origin)
181
+ args.push('--progress') if show_output
182
+ git!(args)
183
+ current_branch = git!(%W(-C #{repo} rev-parse --abbrev-ref HEAD)).strip
184
+ git!(%W(-C #{repo} reset --hard origin/#{current_branch}))
185
+ end
186
+ rescue
187
+ raise Informative, 'CocoaPods was not able to update the ' \
188
+ "`#{name}` repo. If this is an unexpected issue " \
189
+ 'and persists you can inspect it running ' \
190
+ '`pod repo update --verbose`'
191
+ end
192
+ end
193
+
194
+ class TrunkSource
195
+ def verify_compatibility!
196
+ super
197
+ latest_cocoapods_version = metadata.latest_cocoapods_version && Gem::Version.create(metadata.latest_cocoapods_version)
198
+ return unless Config.instance.new_version_message? &&
199
+ latest_cocoapods_version &&
200
+ latest_cocoapods_version > Gem::Version.new(Pod::VERSION)
201
+
202
+ rc = latest_cocoapods_version.prerelease?
203
+ install_message = !Pathname(__FILE__).dirname.writable? ? 'sudo ' : ''
204
+ install_message << 'gem install cocoapods'
205
+ install_message << ' --pre' if rc
206
+ message = [
207
+ '',
208
+ "CocoaPods #{latest_cocoapods_version} is available.".green,
209
+ "To update use: `#{install_message}`".green,
210
+ ("[!] This is a test version we'd love you to try.".yellow if rc),
211
+ '',
212
+ 'For more information, see https://blog.cocoapods.org ' \
213
+ 'and the CHANGELOG for this version at ' \
214
+ "https://github.com/CocoaPods/CocoaPods/releases/tag/#{latest_cocoapods_version}".green,
215
+ '',
216
+ '',
217
+ ].compact.join("\n")
218
+ UI.puts(message)
219
+ end
220
+ end
221
+ end