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.
- checksums.yaml +7 -0
- data/lib/cocoapods-tt/command/native/install.rb +56 -0
- data/lib/cocoapods-tt/command/native/update.rb +157 -0
- data/lib/cocoapods-tt/command/tt/make.rb +92 -0
- data/lib/cocoapods-tt/command/tt.rb +115 -0
- data/lib/cocoapods-tt/command.rb +1 -0
- data/lib/cocoapods-tt/gem_version.rb +3 -0
- data/lib/cocoapods-tt/native/command.rb +185 -0
- data/lib/cocoapods-tt/native/config.rb +366 -0
- data/lib/cocoapods-tt/native/core_overrides.rb +1 -0
- data/lib/cocoapods-tt/native/downloader/cache.rb +322 -0
- data/lib/cocoapods-tt/native/downloader/request.rb +86 -0
- data/lib/cocoapods-tt/native/downloader/response.rb +16 -0
- data/lib/cocoapods-tt/native/downloader.rb +192 -0
- data/lib/cocoapods-tt/native/executable.rb +247 -0
- data/lib/cocoapods-tt/native/external_sources/abstract_external_source.rb +205 -0
- data/lib/cocoapods-tt/native/external_sources/downloader_source.rb +30 -0
- data/lib/cocoapods-tt/native/external_sources/path_source.rb +55 -0
- data/lib/cocoapods-tt/native/external_sources/podspec_source.rb +54 -0
- data/lib/cocoapods-tt/native/external_sources.rb +57 -0
- data/lib/cocoapods-tt/native/gem_version.rb +5 -0
- data/lib/cocoapods-tt/native/generator/acknowledgements/markdown.rb +44 -0
- data/lib/cocoapods-tt/native/generator/acknowledgements/plist.rb +94 -0
- data/lib/cocoapods-tt/native/generator/acknowledgements.rb +107 -0
- data/lib/cocoapods-tt/native/generator/app_target_helper.rb +363 -0
- data/lib/cocoapods-tt/native/generator/bridge_support.rb +22 -0
- data/lib/cocoapods-tt/native/generator/constant.rb +19 -0
- data/lib/cocoapods-tt/native/generator/copy_dsyms_script.rb +56 -0
- data/lib/cocoapods-tt/native/generator/copy_resources_script.rb +223 -0
- data/lib/cocoapods-tt/native/generator/copy_xcframework_script.rb +227 -0
- data/lib/cocoapods-tt/native/generator/dummy_source.rb +31 -0
- data/lib/cocoapods-tt/native/generator/embed_frameworks_script.rb +196 -0
- data/lib/cocoapods-tt/native/generator/file_list.rb +39 -0
- data/lib/cocoapods-tt/native/generator/header.rb +103 -0
- data/lib/cocoapods-tt/native/generator/info_plist_file.rb +128 -0
- data/lib/cocoapods-tt/native/generator/module_map.rb +99 -0
- data/lib/cocoapods-tt/native/generator/prefix_header.rb +60 -0
- data/lib/cocoapods-tt/native/generator/script_phase_constants.rb +100 -0
- data/lib/cocoapods-tt/native/generator/umbrella_header.rb +46 -0
- data/lib/cocoapods-tt/native/hooks_manager.rb +132 -0
- data/lib/cocoapods-tt/native/installer/analyzer/analysis_result.rb +87 -0
- data/lib/cocoapods-tt/native/installer/analyzer/locking_dependency_analyzer.rb +103 -0
- data/lib/cocoapods-tt/native/installer/analyzer/pod_variant.rb +87 -0
- data/lib/cocoapods-tt/native/installer/analyzer/pod_variant_set.rb +175 -0
- data/lib/cocoapods-tt/native/installer/analyzer/podfile_dependency_cache.rb +55 -0
- data/lib/cocoapods-tt/native/installer/analyzer/sandbox_analyzer.rb +268 -0
- data/lib/cocoapods-tt/native/installer/analyzer/specs_state.rb +108 -0
- data/lib/cocoapods-tt/native/installer/analyzer/target_inspection_result.rb +58 -0
- data/lib/cocoapods-tt/native/installer/analyzer/target_inspector.rb +258 -0
- data/lib/cocoapods-tt/native/installer/analyzer.rb +1204 -0
- data/lib/cocoapods-tt/native/installer/base_install_hooks_context.rb +135 -0
- data/lib/cocoapods-tt/native/installer/installation_options.rb +195 -0
- data/lib/cocoapods-tt/native/installer/pod_source_installer.rb +224 -0
- data/lib/cocoapods-tt/native/installer/pod_source_preparer.rb +77 -0
- data/lib/cocoapods-tt/native/installer/podfile_validator.rb +168 -0
- data/lib/cocoapods-tt/native/installer/post_install_hooks_context.rb +9 -0
- data/lib/cocoapods-tt/native/installer/post_integrate_hooks_context.rb +9 -0
- data/lib/cocoapods-tt/native/installer/pre_install_hooks_context.rb +51 -0
- data/lib/cocoapods-tt/native/installer/pre_integrate_hooks_context.rb +9 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_cache.rb +11 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analysis_result.rb +53 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analyzer.rb +200 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_cache_version.rb +43 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_installation_cache.rb +103 -0
- data/lib/cocoapods-tt/native/installer/project_cache/project_metadata_cache.rb +73 -0
- data/lib/cocoapods-tt/native/installer/project_cache/target_cache_key.rb +176 -0
- data/lib/cocoapods-tt/native/installer/project_cache/target_metadata.rb +74 -0
- data/lib/cocoapods-tt/native/installer/sandbox_dir_cleaner.rb +105 -0
- data/lib/cocoapods-tt/native/installer/sandbox_header_paths_installer.rb +45 -0
- data/lib/cocoapods-tt/native/installer/source_provider_hooks_context.rb +34 -0
- data/lib/cocoapods-tt/native/installer/target_uuid_generator.rb +34 -0
- data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +179 -0
- data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator.rb +815 -0
- data/lib/cocoapods-tt/native/installer/user_project_integrator.rb +280 -0
- data/lib/cocoapods-tt/native/installer/xcode/multi_pods_project_generator.rb +82 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +66 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_installer.rb +192 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/app_host_installer.rb +154 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/file_references_installer.rb +329 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +195 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_installer.rb +1239 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_integrator.rb +312 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pods_project_writer.rb +90 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/project_generator.rb +120 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installation_result.rb +140 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer.rb +257 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer_helper.rb +110 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator.rb +291 -0
- data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator_result.rb +54 -0
- data/lib/cocoapods-tt/native/installer/xcode/single_pods_project_generator.rb +38 -0
- data/lib/cocoapods-tt/native/installer/xcode/target_validator.rb +170 -0
- data/lib/cocoapods-tt/native/installer/xcode.rb +11 -0
- data/lib/cocoapods-tt/native/installer.rb +1044 -0
- data/lib/cocoapods-tt/native/native_target_extension.rb +60 -0
- data/lib/cocoapods-tt/native/open-uri.rb +33 -0
- data/lib/cocoapods-tt/native/podfile.rb +13 -0
- data/lib/cocoapods-tt/native/project.rb +544 -0
- data/lib/cocoapods-tt/native/resolver/lazy_specification.rb +88 -0
- data/lib/cocoapods-tt/native/resolver/resolver_specification.rb +41 -0
- data/lib/cocoapods-tt/native/resolver.rb +600 -0
- data/lib/cocoapods-tt/native/sandbox/file_accessor.rb +532 -0
- data/lib/cocoapods-tt/native/sandbox/headers_store.rb +163 -0
- data/lib/cocoapods-tt/native/sandbox/path_list.rb +242 -0
- data/lib/cocoapods-tt/native/sandbox/pod_dir_cleaner.rb +71 -0
- data/lib/cocoapods-tt/native/sandbox/podspec_finder.rb +23 -0
- data/lib/cocoapods-tt/native/sandbox.rb +470 -0
- data/lib/cocoapods-tt/native/sources_manager.rb +221 -0
- data/lib/cocoapods-tt/native/target/aggregate_target.rb +558 -0
- data/lib/cocoapods-tt/native/target/build_settings.rb +1385 -0
- data/lib/cocoapods-tt/native/target/pod_target.rb +1168 -0
- data/lib/cocoapods-tt/native/target.rb +378 -0
- data/lib/cocoapods-tt/native/user_interface/error_report.rb +204 -0
- data/lib/cocoapods-tt/native/user_interface/inspector_reporter.rb +102 -0
- data/lib/cocoapods-tt/native/user_interface.rb +463 -0
- data/lib/cocoapods-tt/native/validator.rb +1170 -0
- data/lib/cocoapods-tt/native/version_metadata.rb +26 -0
- data/lib/cocoapods-tt/native/xcode/framework_paths.rb +54 -0
- data/lib/cocoapods-tt/native/xcode/linkage_analyzer.rb +22 -0
- data/lib/cocoapods-tt/native/xcode/xcframework/xcframework_slice.rb +138 -0
- data/lib/cocoapods-tt/native/xcode/xcframework.rb +99 -0
- data/lib/cocoapods-tt/native/xcode.rb +7 -0
- data/lib/cocoapods-tt.rb +1 -0
- data/lib/cocoapods_plugin.rb +17 -0
- 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
|