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,366 @@
|
|
1
|
+
require 'active_support/multibyte/unicode'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
# Stores the global configuration of CocoaPods.
|
5
|
+
#
|
6
|
+
class Config
|
7
|
+
# The default settings for the configuration.
|
8
|
+
#
|
9
|
+
# Users can specify custom settings in `~/.cocoapods/config.yaml`.
|
10
|
+
# An example of the contents of this file might look like:
|
11
|
+
#
|
12
|
+
# ---
|
13
|
+
# skip_repo_update: true
|
14
|
+
# new_version_message: false
|
15
|
+
#
|
16
|
+
DEFAULTS = {
|
17
|
+
:verbose => false,
|
18
|
+
:silent => false,
|
19
|
+
:skip_download_cache => !ENV['COCOAPODS_SKIP_CACHE'].nil?,
|
20
|
+
|
21
|
+
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
|
22
|
+
|
23
|
+
:cache_root => Pathname.new(Dir.home) + 'Library/Caches/CocoaPods',
|
24
|
+
}
|
25
|
+
|
26
|
+
# Applies the given changes to the config for the duration of the given
|
27
|
+
# block.
|
28
|
+
#
|
29
|
+
# @param [Hash<#to_sym,Object>] changes
|
30
|
+
# the changes to merge temporarily with the current config
|
31
|
+
#
|
32
|
+
# @yield [] is called while the changes are applied
|
33
|
+
#
|
34
|
+
def with_changes(changes)
|
35
|
+
old = {}
|
36
|
+
changes.keys.each do |key|
|
37
|
+
key = key.to_sym
|
38
|
+
old[key] = send(key) if respond_to?(key)
|
39
|
+
end
|
40
|
+
configure_with(changes)
|
41
|
+
yield if block_given?
|
42
|
+
ensure
|
43
|
+
configure_with(old)
|
44
|
+
end
|
45
|
+
|
46
|
+
public
|
47
|
+
|
48
|
+
#-------------------------------------------------------------------------#
|
49
|
+
|
50
|
+
# @!group UI
|
51
|
+
|
52
|
+
# @return [Bool] Whether CocoaPods should provide detailed output about the
|
53
|
+
# performed actions.
|
54
|
+
#
|
55
|
+
attr_accessor :verbose
|
56
|
+
alias_method :verbose?, :verbose
|
57
|
+
|
58
|
+
# @return [Bool] Whether CocoaPods should produce not output.
|
59
|
+
#
|
60
|
+
attr_accessor :silent
|
61
|
+
alias_method :silent?, :silent
|
62
|
+
|
63
|
+
# @return [Bool] Whether CocoaPods is allowed to run as root.
|
64
|
+
#
|
65
|
+
attr_accessor :allow_root
|
66
|
+
alias_method :allow_root?, :allow_root
|
67
|
+
|
68
|
+
# @return [Bool] Whether a message should be printed when a new version of
|
69
|
+
# CocoaPods is available.
|
70
|
+
#
|
71
|
+
attr_accessor :new_version_message
|
72
|
+
alias_method :new_version_message?, :new_version_message
|
73
|
+
|
74
|
+
#-------------------------------------------------------------------------#
|
75
|
+
|
76
|
+
# @!group Installation
|
77
|
+
|
78
|
+
# @return [Bool] Whether the installer should skip the download cache.
|
79
|
+
#
|
80
|
+
attr_accessor :skip_download_cache
|
81
|
+
alias_method :skip_download_cache?, :skip_download_cache
|
82
|
+
|
83
|
+
public
|
84
|
+
|
85
|
+
#-------------------------------------------------------------------------#
|
86
|
+
|
87
|
+
# @!group Cache
|
88
|
+
|
89
|
+
# @return [Pathname] The directory where CocoaPods should cache remote data
|
90
|
+
# and other expensive to compute information.
|
91
|
+
#
|
92
|
+
attr_accessor :cache_root
|
93
|
+
|
94
|
+
def cache_root
|
95
|
+
@cache_root.mkpath unless @cache_root.exist?
|
96
|
+
@cache_root
|
97
|
+
end
|
98
|
+
|
99
|
+
public
|
100
|
+
|
101
|
+
#-------------------------------------------------------------------------#
|
102
|
+
|
103
|
+
# @!group Initialization
|
104
|
+
|
105
|
+
def initialize(use_user_settings = true)
|
106
|
+
configure_with(DEFAULTS)
|
107
|
+
|
108
|
+
unless ENV['CP_HOME_DIR'].nil?
|
109
|
+
@cache_root = home_dir + 'cache'
|
110
|
+
end
|
111
|
+
|
112
|
+
if use_user_settings && user_settings_file.exist?
|
113
|
+
require 'yaml'
|
114
|
+
user_settings = YAML.load_file(user_settings_file)
|
115
|
+
configure_with(user_settings)
|
116
|
+
end
|
117
|
+
|
118
|
+
unless ENV['CP_CACHE_DIR'].nil?
|
119
|
+
@cache_root = Pathname.new(ENV['CP_CACHE_DIR']).expand_path
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def verbose
|
124
|
+
@verbose && !silent
|
125
|
+
end
|
126
|
+
|
127
|
+
public
|
128
|
+
|
129
|
+
#-------------------------------------------------------------------------#
|
130
|
+
|
131
|
+
# @!group Paths
|
132
|
+
|
133
|
+
# @return [Pathname] the directory where repos, templates and configuration
|
134
|
+
# files are stored.
|
135
|
+
#
|
136
|
+
def home_dir
|
137
|
+
@home_dir ||= Pathname.new(ENV['CP_HOME_DIR'] || '~/.cocoapods').expand_path
|
138
|
+
end
|
139
|
+
|
140
|
+
# @return [Pathname] the directory where the CocoaPods sources are stored.
|
141
|
+
#
|
142
|
+
def repos_dir
|
143
|
+
@repos_dir ||= Pathname.new(ENV['CP_REPOS_DIR'] || (home_dir + 'repos')).expand_path
|
144
|
+
end
|
145
|
+
|
146
|
+
attr_writer :repos_dir
|
147
|
+
|
148
|
+
# @return [Source::Manager] the source manager for the spec repos in `repos_dir`
|
149
|
+
#
|
150
|
+
def sources_manager
|
151
|
+
return @sources_manager if @sources_manager && @sources_manager.repos_dir == repos_dir
|
152
|
+
@sources_manager = Source::Manager.new(repos_dir)
|
153
|
+
end
|
154
|
+
|
155
|
+
# @return [Pathname] the directory where the CocoaPods templates are stored.
|
156
|
+
#
|
157
|
+
def templates_dir
|
158
|
+
@templates_dir ||= Pathname.new(ENV['CP_TEMPLATES_DIR'] || (home_dir + 'templates')).expand_path
|
159
|
+
end
|
160
|
+
|
161
|
+
# @return [Pathname] the root of the CocoaPods installation where the
|
162
|
+
# Podfile is located.
|
163
|
+
#
|
164
|
+
def installation_root
|
165
|
+
@installation_root ||= begin
|
166
|
+
current_dir = Pathname.new(Dir.pwd.unicode_normalize(:nfkc))
|
167
|
+
current_path = current_dir
|
168
|
+
until current_path.root?
|
169
|
+
if podfile_path_in_dir(current_path)
|
170
|
+
installation_root = current_path
|
171
|
+
unless current_path == current_dir
|
172
|
+
UI.puts("[in #{current_path}]")
|
173
|
+
end
|
174
|
+
break
|
175
|
+
else
|
176
|
+
current_path = current_path.parent
|
177
|
+
end
|
178
|
+
end
|
179
|
+
installation_root || current_dir
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
attr_writer :installation_root
|
184
|
+
alias_method :project_root, :installation_root
|
185
|
+
|
186
|
+
# @return [Pathname] The root of the sandbox.
|
187
|
+
#
|
188
|
+
def sandbox_root
|
189
|
+
@sandbox_root ||= installation_root + 'Pods'
|
190
|
+
end
|
191
|
+
|
192
|
+
attr_writer :sandbox_root
|
193
|
+
alias_method :project_pods_root, :sandbox_root
|
194
|
+
|
195
|
+
# @return [Sandbox] The sandbox of the current project.
|
196
|
+
#
|
197
|
+
def sandbox
|
198
|
+
@sandbox ||= Sandbox.new(sandbox_root)
|
199
|
+
end
|
200
|
+
|
201
|
+
# @return [Podfile] The Podfile to use for the current execution.
|
202
|
+
# @return [Nil] If no Podfile is available.
|
203
|
+
#
|
204
|
+
def podfile
|
205
|
+
@podfile ||= Podfile.from_file(podfile_path) if podfile_path
|
206
|
+
end
|
207
|
+
attr_writer :podfile
|
208
|
+
|
209
|
+
# @return [Lockfile] The Lockfile to use for the current execution.
|
210
|
+
# @return [Nil] If no Lockfile is available.
|
211
|
+
#
|
212
|
+
def lockfile
|
213
|
+
@lockfile ||= Lockfile.from_file(lockfile_path) if lockfile_path
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns the path of the Podfile.
|
217
|
+
#
|
218
|
+
# @note The Podfile can be named either `CocoaPods.podfile.yaml`,
|
219
|
+
# `CocoaPods.podfile` or `Podfile`. The first two are preferred as
|
220
|
+
# they allow to specify an OS X UTI.
|
221
|
+
#
|
222
|
+
# @return [Pathname]
|
223
|
+
# @return [Nil]
|
224
|
+
#
|
225
|
+
def podfile_path
|
226
|
+
@podfile_path ||= podfile_path_in_dir(installation_root)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Returns the path of the Lockfile.
|
230
|
+
#
|
231
|
+
# @note The Lockfile is named `Podfile.lock`.
|
232
|
+
#
|
233
|
+
def lockfile_path
|
234
|
+
@lockfile_path ||= installation_root + 'Podfile.lock'
|
235
|
+
end
|
236
|
+
|
237
|
+
# Returns the path of the default Podfile pods.
|
238
|
+
#
|
239
|
+
# @note The file is expected to be named Podfile.default
|
240
|
+
#
|
241
|
+
# @return [Pathname]
|
242
|
+
#
|
243
|
+
def default_podfile_path
|
244
|
+
@default_podfile_path ||= templates_dir + 'Podfile.default'
|
245
|
+
end
|
246
|
+
|
247
|
+
# Returns the path of the default Podfile test pods.
|
248
|
+
#
|
249
|
+
# @note The file is expected to be named Podfile.test
|
250
|
+
#
|
251
|
+
# @return [Pathname]
|
252
|
+
#
|
253
|
+
def default_test_podfile_path
|
254
|
+
@default_test_podfile_path ||= templates_dir + 'Podfile.test'
|
255
|
+
end
|
256
|
+
|
257
|
+
# @return [Pathname] The file to use to cache the search data.
|
258
|
+
#
|
259
|
+
def search_index_file
|
260
|
+
cache_root + 'search_index.json'
|
261
|
+
end
|
262
|
+
|
263
|
+
private
|
264
|
+
|
265
|
+
#-------------------------------------------------------------------------#
|
266
|
+
|
267
|
+
# @!group Private helpers
|
268
|
+
|
269
|
+
# @return [Pathname] The path of the file which contains the user settings.
|
270
|
+
#
|
271
|
+
def user_settings_file
|
272
|
+
home_dir + 'config.yaml'
|
273
|
+
end
|
274
|
+
|
275
|
+
# Sets the values of the attributes with the given hash.
|
276
|
+
#
|
277
|
+
# @param [Hash{String,Symbol => Object}] values_by_key
|
278
|
+
# The values of the attributes grouped by key.
|
279
|
+
#
|
280
|
+
# @return [void]
|
281
|
+
#
|
282
|
+
def configure_with(values_by_key)
|
283
|
+
return unless values_by_key
|
284
|
+
values_by_key.each do |key, value|
|
285
|
+
if key.to_sym == :cache_root
|
286
|
+
value = Pathname.new(value).expand_path
|
287
|
+
end
|
288
|
+
instance_variable_set("@#{key}", value)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# @return [Array<String>] The filenames that the Podfile can have ordered
|
293
|
+
# by priority.
|
294
|
+
#
|
295
|
+
PODFILE_NAMES = [
|
296
|
+
'CocoaPods.podfile.yaml',
|
297
|
+
'CocoaPods.podfile',
|
298
|
+
'Podfile',
|
299
|
+
'Podfile.rb',
|
300
|
+
].freeze
|
301
|
+
|
302
|
+
public
|
303
|
+
|
304
|
+
# Returns the path of the Podfile in the given dir if any exists.
|
305
|
+
#
|
306
|
+
# @param [Pathname] dir
|
307
|
+
# The directory where to look for the Podfile.
|
308
|
+
#
|
309
|
+
# @return [Pathname] The path of the Podfile.
|
310
|
+
# @return [Nil] If not Podfile was found in the given dir
|
311
|
+
#
|
312
|
+
def podfile_path_in_dir(dir)
|
313
|
+
PODFILE_NAMES.each do |filename|
|
314
|
+
candidate = dir + filename
|
315
|
+
if candidate.file?
|
316
|
+
return candidate
|
317
|
+
end
|
318
|
+
end
|
319
|
+
nil
|
320
|
+
end
|
321
|
+
|
322
|
+
# Excludes the given dir from Time Machine backups.
|
323
|
+
#
|
324
|
+
# @param [Pathname] dir
|
325
|
+
# The directory to exclude from Time Machine backups.
|
326
|
+
#
|
327
|
+
# @return [void]
|
328
|
+
#
|
329
|
+
def exclude_from_backup(dir)
|
330
|
+
return if Gem.win_platform?
|
331
|
+
system('tmutil', 'addexclusion', dir.to_s, %i(out err) => File::NULL)
|
332
|
+
end
|
333
|
+
|
334
|
+
public
|
335
|
+
|
336
|
+
#-------------------------------------------------------------------------#
|
337
|
+
|
338
|
+
# @!group Singleton
|
339
|
+
|
340
|
+
# @return [Config] the current config instance creating one if needed.
|
341
|
+
#
|
342
|
+
def self.instance
|
343
|
+
@instance ||= new
|
344
|
+
end
|
345
|
+
|
346
|
+
# Sets the current config instance. If set to nil the config will be
|
347
|
+
# recreated when needed.
|
348
|
+
#
|
349
|
+
# @param [Config, Nil] the instance.
|
350
|
+
#
|
351
|
+
# @return [void]
|
352
|
+
#
|
353
|
+
class << self
|
354
|
+
attr_writer :instance
|
355
|
+
end
|
356
|
+
|
357
|
+
# Provides support for accessing the configuration instance in other
|
358
|
+
# scopes.
|
359
|
+
#
|
360
|
+
module Mixin
|
361
|
+
def config
|
362
|
+
Config.instance
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods/sources_manager'
|
@@ -0,0 +1,322 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
module Downloader
|
6
|
+
# The class responsible for managing Pod downloads, transparently caching
|
7
|
+
# them in a cache directory.
|
8
|
+
#
|
9
|
+
class Cache
|
10
|
+
# @return [Pathname] The root directory where this cache store its
|
11
|
+
# downloads.
|
12
|
+
#
|
13
|
+
attr_reader :root
|
14
|
+
|
15
|
+
# Initialize a new instance
|
16
|
+
#
|
17
|
+
# @param [Pathname,String] root
|
18
|
+
# see {#root}
|
19
|
+
#
|
20
|
+
def initialize(root)
|
21
|
+
@root = Pathname(root)
|
22
|
+
ensure_matching_version
|
23
|
+
end
|
24
|
+
|
25
|
+
# Downloads the Pod from the given `request`
|
26
|
+
#
|
27
|
+
# @param [Request] request
|
28
|
+
# the request to be downloaded.
|
29
|
+
#
|
30
|
+
# @return [Response] the response from downloading `request`
|
31
|
+
#
|
32
|
+
def download_pod(request)
|
33
|
+
cached_pod(request) || uncached_pod(request)
|
34
|
+
rescue Informative
|
35
|
+
raise
|
36
|
+
rescue
|
37
|
+
UI.puts("\n[!] Error installing #{request.name}".red)
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Hash<String, Hash<Symbol, String>>]
|
42
|
+
# A hash whose keys are the pod name
|
43
|
+
# And values are a hash with the following keys:
|
44
|
+
# :spec_file : path to the spec file
|
45
|
+
# :name : name of the pod
|
46
|
+
# :version : pod version
|
47
|
+
# :release : boolean to tell if that's a release pod
|
48
|
+
# :slug : the slug path where the pod cache is located
|
49
|
+
#
|
50
|
+
def cache_descriptors_per_pod
|
51
|
+
specs_dir = root + 'Specs'
|
52
|
+
release_specs_dir = specs_dir + 'Release'
|
53
|
+
return {} unless specs_dir.exist?
|
54
|
+
|
55
|
+
spec_paths = specs_dir.find.select { |f| f.fnmatch('*.podspec.json') }
|
56
|
+
spec_paths.reduce({}) do |hash, spec_path|
|
57
|
+
spec = Specification.from_file(spec_path)
|
58
|
+
hash[spec.name] ||= []
|
59
|
+
is_release = spec_path.to_s.start_with?(release_specs_dir.to_s)
|
60
|
+
request = Downloader::Request.new(:spec => spec, :released => is_release)
|
61
|
+
hash[spec.name] << {
|
62
|
+
:spec_file => spec_path,
|
63
|
+
:name => spec.name,
|
64
|
+
:version => spec.version,
|
65
|
+
:release => is_release,
|
66
|
+
:slug => root + request.slug,
|
67
|
+
}
|
68
|
+
hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Convenience method for acquiring a shared lock to safely read from the
|
73
|
+
# cache. See `Cache.lock` for more details.
|
74
|
+
#
|
75
|
+
# @param [Pathname] location
|
76
|
+
# the path to require a lock for.
|
77
|
+
#
|
78
|
+
# @param [block] &block
|
79
|
+
# the block to execute inside the lock.
|
80
|
+
#
|
81
|
+
# @return [void]
|
82
|
+
#
|
83
|
+
def self.read_lock(location, &block)
|
84
|
+
Cache.lock(location, File::LOCK_SH, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convenience method for acquiring an exclusive lock to safely write to
|
88
|
+
# the cache. See `Cache.lock` for more details.
|
89
|
+
#
|
90
|
+
# @param [Pathname] location
|
91
|
+
# the path to require a lock for.
|
92
|
+
#
|
93
|
+
# @param [block] &block
|
94
|
+
# the block to execute inside the lock.
|
95
|
+
#
|
96
|
+
# @return [void]
|
97
|
+
#
|
98
|
+
def self.write_lock(location, &block)
|
99
|
+
Cache.lock(location, File::LOCK_EX, &block)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Creates a .lock file at `location`, aquires a lock of type
|
103
|
+
# `lock_type`, checks that it is valid, and executes passed block while
|
104
|
+
# holding on to that lock. Afterwards, the .lock file is deleted, which is
|
105
|
+
# why validation of the lock is necessary, as you might have a lock on a
|
106
|
+
# file that doesn't exist on the filesystem anymore.
|
107
|
+
#
|
108
|
+
# @param [Pathname] location
|
109
|
+
# the path to require a lock for.
|
110
|
+
#
|
111
|
+
# @param [locking_constant] lock_type
|
112
|
+
# the type of lock, either exclusive (File::LOCK_EX) or shared
|
113
|
+
# (File::LOCK_SH).
|
114
|
+
#
|
115
|
+
# @return [void]
|
116
|
+
#
|
117
|
+
def self.lock(location, lock_type)
|
118
|
+
raise ArgumentError, 'no block given' unless block_given?
|
119
|
+
lockfile = "#{location}.lock"
|
120
|
+
f = nil
|
121
|
+
loop do
|
122
|
+
f.close if f
|
123
|
+
f = File.open(lockfile, File::CREAT, 0o644)
|
124
|
+
f.flock(lock_type)
|
125
|
+
break if Cache.valid_lock?(f, lockfile)
|
126
|
+
end
|
127
|
+
begin
|
128
|
+
yield location
|
129
|
+
ensure
|
130
|
+
if lock_type == File::LOCK_SH
|
131
|
+
f.flock(File::LOCK_EX)
|
132
|
+
File.delete(lockfile) if Cache.valid_lock?(f, lockfile)
|
133
|
+
else
|
134
|
+
File.delete(lockfile)
|
135
|
+
end
|
136
|
+
f.close
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Checks that the lock is on a file that still exists on the filesystem.
|
141
|
+
#
|
142
|
+
# @param [File] file
|
143
|
+
# the actual file that we have a lock for.
|
144
|
+
#
|
145
|
+
# @param [String] filename
|
146
|
+
# the filename of the file that we have a lock for.
|
147
|
+
#
|
148
|
+
# @return [Boolean]
|
149
|
+
# true if `filename` still exists and is the same file as `file`
|
150
|
+
#
|
151
|
+
def self.valid_lock?(file, filename)
|
152
|
+
file.stat.ino == File.stat(filename).ino
|
153
|
+
rescue Errno::ENOENT
|
154
|
+
false
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
# Ensures the cache on disk was created with the same CocoaPods version as
|
160
|
+
# is currently running.
|
161
|
+
#
|
162
|
+
# @return [Void]
|
163
|
+
#
|
164
|
+
def ensure_matching_version
|
165
|
+
version_file = root + 'VERSION'
|
166
|
+
version = version_file.read.strip if version_file.file?
|
167
|
+
|
168
|
+
root.rmtree if version != Pod::VERSION && root.exist?
|
169
|
+
root.mkpath
|
170
|
+
|
171
|
+
version_file.open('w') { |f| f << Pod::VERSION }
|
172
|
+
end
|
173
|
+
|
174
|
+
# @param [Request] request
|
175
|
+
# the request to be downloaded.
|
176
|
+
#
|
177
|
+
# @param [Hash<Symbol,String>] slug_opts
|
178
|
+
# the download options that should be used in constructing the
|
179
|
+
# cache slug for this request.
|
180
|
+
#
|
181
|
+
# @return [Pathname] The path for the Pod downloaded from the given
|
182
|
+
# `request`.
|
183
|
+
#
|
184
|
+
def path_for_pod(request, slug_opts = {})
|
185
|
+
root + request.slug(**slug_opts)
|
186
|
+
end
|
187
|
+
|
188
|
+
# @param [Request] request
|
189
|
+
# the request to be downloaded.
|
190
|
+
#
|
191
|
+
# @param [Hash<Symbol,String>] slug_opts
|
192
|
+
# the download options that should be used in constructing the
|
193
|
+
# cache slug for this request.
|
194
|
+
#
|
195
|
+
# @return [Pathname] The path for the podspec downloaded from the given
|
196
|
+
# `request`.
|
197
|
+
#
|
198
|
+
def path_for_spec(request, slug_opts = {})
|
199
|
+
path = root + 'Specs' + request.slug(**slug_opts)
|
200
|
+
Pathname.new(path.to_path + '.podspec.json')
|
201
|
+
end
|
202
|
+
|
203
|
+
# @param [Request] request
|
204
|
+
# the request to be downloaded.
|
205
|
+
#
|
206
|
+
# @return [Response] The download response for the given `request` that
|
207
|
+
# was found in the download cache.
|
208
|
+
#
|
209
|
+
def cached_pod(request)
|
210
|
+
cached_spec = cached_spec(request)
|
211
|
+
path = path_for_pod(request)
|
212
|
+
|
213
|
+
return unless cached_spec && path.directory?
|
214
|
+
spec = request.spec || cached_spec
|
215
|
+
Response.new(path, spec, request.params)
|
216
|
+
end
|
217
|
+
|
218
|
+
# @param [Request] request
|
219
|
+
# the request to be downloaded.
|
220
|
+
#
|
221
|
+
# @return [Specification] The cached specification for the given
|
222
|
+
# `request`.
|
223
|
+
#
|
224
|
+
def cached_spec(request)
|
225
|
+
path = path_for_spec(request)
|
226
|
+
path.file? && Specification.from_file(path)
|
227
|
+
rescue JSON::ParserError
|
228
|
+
nil
|
229
|
+
end
|
230
|
+
|
231
|
+
# @param [Request] request
|
232
|
+
# the request to be downloaded.
|
233
|
+
#
|
234
|
+
# @return [Response] The download response for the given `request` that
|
235
|
+
# was not found in the download cache.
|
236
|
+
#
|
237
|
+
def uncached_pod(request)
|
238
|
+
in_tmpdir do |target|
|
239
|
+
result, podspecs = download(request, target)
|
240
|
+
result.location = nil
|
241
|
+
|
242
|
+
podspecs.each do |name, spec|
|
243
|
+
destination = path_for_pod(request, :name => name, :params => result.checkout_options)
|
244
|
+
copy_and_clean(target, destination, spec)
|
245
|
+
write_spec(spec, path_for_spec(request, :name => name, :params => result.checkout_options))
|
246
|
+
if request.name == name
|
247
|
+
result.location = destination
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
result
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def download(request, target)
|
256
|
+
Downloader.download_request(request, target)
|
257
|
+
end
|
258
|
+
|
259
|
+
# Performs the given block inside a temporary directory,
|
260
|
+
# which is removed at the end of the block's scope.
|
261
|
+
#
|
262
|
+
# @return [Object] The return value of the given block
|
263
|
+
#
|
264
|
+
def in_tmpdir(&blk)
|
265
|
+
tmpdir = Pathname(Dir.mktmpdir)
|
266
|
+
blk.call(tmpdir)
|
267
|
+
ensure
|
268
|
+
FileUtils.remove_entry(tmpdir, :force => true) if tmpdir && tmpdir.exist?
|
269
|
+
end
|
270
|
+
|
271
|
+
# Copies the `source` directory to `destination`, cleaning the directory
|
272
|
+
# of any files unused by `spec`.
|
273
|
+
#
|
274
|
+
# @param [Pathname] source
|
275
|
+
#
|
276
|
+
# @param [Pathname] destination
|
277
|
+
#
|
278
|
+
# @param [Specification] spec
|
279
|
+
#
|
280
|
+
# @return [Void]
|
281
|
+
#
|
282
|
+
def copy_and_clean(source, destination, spec)
|
283
|
+
specs_by_platform = group_subspecs_by_platform(spec)
|
284
|
+
destination.parent.mkpath
|
285
|
+
Cache.write_lock(destination) do
|
286
|
+
FileUtils.rm_rf(destination)
|
287
|
+
FileUtils.cp_r(source, destination)
|
288
|
+
Pod::Installer::PodSourcePreparer.new(spec, destination).prepare!
|
289
|
+
Sandbox::PodDirCleaner.new(destination, specs_by_platform).clean!
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def group_subspecs_by_platform(spec)
|
294
|
+
specs_by_platform = {}
|
295
|
+
[spec, *spec.recursive_subspecs].each do |ss|
|
296
|
+
ss.available_platforms.each do |platform|
|
297
|
+
specs_by_platform[platform] ||= []
|
298
|
+
specs_by_platform[platform] << ss
|
299
|
+
end
|
300
|
+
end
|
301
|
+
specs_by_platform
|
302
|
+
end
|
303
|
+
|
304
|
+
# Writes the given `spec` to the given `path`.
|
305
|
+
#
|
306
|
+
# @param [Specification] spec
|
307
|
+
# the specification to be written.
|
308
|
+
#
|
309
|
+
# @param [Pathname] path
|
310
|
+
# the path the specification is to be written to.
|
311
|
+
#
|
312
|
+
# @return [Void]
|
313
|
+
#
|
314
|
+
def write_spec(spec, path)
|
315
|
+
path.dirname.mkpath
|
316
|
+
Cache.write_lock(path) do
|
317
|
+
path.open('w') { |f| f.write spec.to_pretty_json }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|