cocoapods 0.36.4 → 0.37.0.beta.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 +4 -4
- data/CHANGELOG.md +54 -0
- data/LICENSE +8 -2
- data/README.md +37 -16
- data/lib/cocoapods/command/lib.rb +3 -0
- data/lib/cocoapods/command/repo.rb +0 -31
- data/lib/cocoapods/command/repo/list.rb +16 -18
- data/lib/cocoapods/command/spec/lint.rb +3 -0
- data/lib/cocoapods/config.rb +6 -0
- data/lib/cocoapods/downloader.rb +40 -0
- data/lib/cocoapods/downloader/cache.rb +210 -0
- data/lib/cocoapods/downloader/request.rb +90 -0
- data/lib/cocoapods/downloader/response.rb +16 -0
- data/lib/cocoapods/external_sources/abstract_external_source.rb +18 -19
- data/lib/cocoapods/external_sources/path_source.rb +0 -2
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/embed_frameworks_script.rb +2 -2
- data/lib/cocoapods/generator/module_map.rb +17 -2
- data/lib/cocoapods/installer/analyzer.rb +21 -1
- data/lib/cocoapods/installer/pod_source_installer.rb +14 -111
- data/lib/cocoapods/installer/target_installer.rb +4 -0
- data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +23 -2
- data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +36 -6
- data/lib/cocoapods/resolver.rb +3 -6
- data/lib/cocoapods/sandbox.rb +5 -3
- data/lib/cocoapods/sandbox/file_accessor.rb +25 -5
- data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
- data/lib/cocoapods/sandbox/podspec_finder.rb +26 -0
- data/lib/cocoapods/validator.rb +32 -7
- metadata +73 -64
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
module Downloader
|
5
|
+
# This class represents a download request for a given Pod.
|
6
|
+
#
|
7
|
+
class Request
|
8
|
+
# @return [Specification,Nil] The specification for the pod whose download
|
9
|
+
# is being requested.
|
10
|
+
#
|
11
|
+
attr_reader :spec
|
12
|
+
|
13
|
+
# @return [Boolean] Whether this download request is for a released pod.
|
14
|
+
#
|
15
|
+
attr_reader :released_pod
|
16
|
+
alias_method :released_pod?, :released_pod
|
17
|
+
|
18
|
+
# @return [String] The name of the pod whose dowload is being requested.
|
19
|
+
#
|
20
|
+
attr_reader :name
|
21
|
+
|
22
|
+
# @return [Hash<Symbol, String>] The download parameters for this request.
|
23
|
+
#
|
24
|
+
attr_reader :params
|
25
|
+
|
26
|
+
# @return [Boolean] Whether the download request is for a head download.
|
27
|
+
#
|
28
|
+
attr_reader :head
|
29
|
+
alias_method :head?, :head
|
30
|
+
|
31
|
+
# @param [Specification,Nil] spec
|
32
|
+
# see {#spec}
|
33
|
+
#
|
34
|
+
# @param [Boolean] released
|
35
|
+
# see {#released_pod}
|
36
|
+
#
|
37
|
+
# @param [String,Nil] name
|
38
|
+
# see {#name}
|
39
|
+
#
|
40
|
+
# @param [Hash<Symbol,String>,Nil] params
|
41
|
+
# see {#params}
|
42
|
+
#
|
43
|
+
# @param [Boolean] head
|
44
|
+
# see {#head}
|
45
|
+
#
|
46
|
+
def initialize(spec: nil, released: false, name: nil, params: false, head: false)
|
47
|
+
@released_pod = released
|
48
|
+
@spec = spec
|
49
|
+
@params = spec ? (spec.source && spec.source.dup) : params
|
50
|
+
@name = spec ? spec.name : name
|
51
|
+
@head = head
|
52
|
+
|
53
|
+
validate!
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [String] name
|
57
|
+
# the name of the pod being downloaded.
|
58
|
+
#
|
59
|
+
# @param [Hash<#to_s, #to_s>] params
|
60
|
+
# the download parameters of the pod being downloaded.
|
61
|
+
#
|
62
|
+
# @return [String] The slug used to store the files resulting from this
|
63
|
+
# download request.
|
64
|
+
#
|
65
|
+
def slug(name: self.name, params: self.params, spec: self.spec)
|
66
|
+
checksum = spec && spec.checksum && '-' << spec.checksum[0, 5]
|
67
|
+
if released_pod?
|
68
|
+
"Release/#{name}/#{spec.version}#{checksum}"
|
69
|
+
else
|
70
|
+
opts = params.to_a.sort_by(&:first).map { |k, v| "#{k}=#{v}" }.join('-')
|
71
|
+
digest = Digest::MD5.hexdigest(opts)
|
72
|
+
"External/#{name}/#{digest}#{checksum}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# Validates that the given request is well-formed.
|
79
|
+
#
|
80
|
+
# @return [Void]
|
81
|
+
#
|
82
|
+
def validate!
|
83
|
+
raise ArgumentError, 'Requires a name' unless name
|
84
|
+
raise ArgumentError, 'Must give a spec for a released download request' if released_pod? && !spec
|
85
|
+
raise ArgumentError, 'Requires a version if released' if released_pod? && !spec.version
|
86
|
+
raise ArgumentError, 'Requires params' unless params
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Pod
|
2
|
+
module Downloader
|
3
|
+
# A response to a download request.
|
4
|
+
#
|
5
|
+
# @attr [Pathname] location
|
6
|
+
# the location where this downloaded pod is stored on disk.
|
7
|
+
#
|
8
|
+
# @attr [Specification] spec
|
9
|
+
# the specification that describes this downloaded pod.
|
10
|
+
#
|
11
|
+
# @attr [Hash<Symbol, String>] checkout_options
|
12
|
+
# the downloader parameters necessary to recreate this exact download.
|
13
|
+
#
|
14
|
+
Response = Struct.new(:location, :spec, :checkout_options)
|
15
|
+
end
|
16
|
+
end
|
@@ -98,35 +98,31 @@ module Pod
|
|
98
98
|
title = "Pre-downloading: `#{name}` #{description}"
|
99
99
|
UI.titled_section(title, :verbose_prefix => '-> ') do
|
100
100
|
target = sandbox.pod_dir(name)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
unless Pathname(podspec_path).exist?
|
108
|
-
podspec_path = target + "#{name}.podspec.json"
|
109
|
-
json = true
|
110
|
-
end
|
111
|
-
|
112
|
-
store_podspec(sandbox, target + podspec_path, json)
|
101
|
+
download_result = Downloader.download(download_request, target)
|
102
|
+
spec = download_result.spec
|
103
|
+
|
104
|
+
raise Informative, "Unable to find a specification for '#{name}'." unless spec
|
105
|
+
|
106
|
+
store_podspec(sandbox, spec)
|
113
107
|
sandbox.store_pre_downloaded_pod(name)
|
114
|
-
|
115
|
-
source = params
|
116
|
-
else
|
117
|
-
source = downloader.checkout_options
|
118
|
-
end
|
119
|
-
sandbox.store_checkout_source(name, source)
|
108
|
+
sandbox.store_checkout_source(name, download_result.checkout_options)
|
120
109
|
end
|
121
110
|
end
|
122
111
|
|
112
|
+
def download_request
|
113
|
+
Downloader::Request.new(
|
114
|
+
:name => name,
|
115
|
+
:params => params,
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
123
119
|
# Stores the podspec in the sandbox and marks it as from an external
|
124
120
|
# source.
|
125
121
|
#
|
126
122
|
# @param [Sandbox] sandbox
|
127
123
|
# The sandbox where the specification should be stored.
|
128
124
|
#
|
129
|
-
# @param [Pathname, String] spec
|
125
|
+
# @param [Pathname, String, Specification] spec
|
130
126
|
# The path of the specification or its contents.
|
131
127
|
#
|
132
128
|
# @note All the concrete implementations of #{fetch} should invoke this
|
@@ -144,6 +140,9 @@ module Pod
|
|
144
140
|
elsif spec.is_a?(String) && !json
|
145
141
|
spec = Specification.from_string(spec, 'spec.podspec').to_pretty_json
|
146
142
|
json = true
|
143
|
+
elsif spec.is_a?(Specification)
|
144
|
+
spec = spec.to_pretty_json
|
145
|
+
json = true
|
147
146
|
end
|
148
147
|
sandbox.store_podspec(name, spec, true, json)
|
149
148
|
end
|
@@ -3,8 +3,6 @@ module Pod
|
|
3
3
|
# Provides support for fetching a specification file from a path local to
|
4
4
|
# the machine running the installation.
|
5
5
|
#
|
6
|
-
# Works with the {LocalPod::LocalSourcedPod} class.
|
7
|
-
#
|
8
6
|
class PathSource < AbstractExternalSource
|
9
7
|
# @see AbstractExternalSource#fetch
|
10
8
|
#
|
@@ -63,8 +63,8 @@ module Pod
|
|
63
63
|
fi
|
64
64
|
|
65
65
|
# use filter instead of exclude so missing patterns dont' throw errors
|
66
|
-
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" ${source} ${destination}"
|
67
|
-
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" "${source}" "${destination}"
|
66
|
+
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" --filter \"- Modules/\" ${source} ${destination}"
|
67
|
+
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" --filter "- Modules/" "${source}" "${destination}"
|
68
68
|
# Resign the code if required by the build settings to avoid unstable apps
|
69
69
|
if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
|
70
70
|
code_sign "${destination}/$1"
|
@@ -10,10 +10,15 @@ module Pod
|
|
10
10
|
#
|
11
11
|
attr_reader :target
|
12
12
|
|
13
|
+
# @return [Array] the private headers of the module
|
14
|
+
#
|
15
|
+
attr_accessor :private_headers
|
16
|
+
|
13
17
|
# @param [Target] target @see target
|
14
18
|
#
|
15
19
|
def initialize(target)
|
16
20
|
@target = target
|
21
|
+
@private_headers = []
|
17
22
|
end
|
18
23
|
|
19
24
|
# Generates and saves the Info.plist to the given path.
|
@@ -35,14 +40,24 @@ module Pod
|
|
35
40
|
# @return [String]
|
36
41
|
#
|
37
42
|
def generate
|
38
|
-
<<-eos.strip_heredoc
|
43
|
+
result = <<-eos.strip_heredoc
|
39
44
|
framework module #{target.product_module_name} {
|
40
45
|
umbrella header "#{target.umbrella_header_path.basename}"
|
41
46
|
|
42
47
|
export *
|
43
48
|
module * { export * }
|
44
|
-
}
|
45
49
|
eos
|
50
|
+
|
51
|
+
result << "\n#{generate_private_header_exports}" unless private_headers.empty?
|
52
|
+
result << "}\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def generate_private_header_exports
|
58
|
+
private_headers.reduce('') do |string, header|
|
59
|
+
string << %( private header "#{header}"\n)
|
60
|
+
end
|
46
61
|
end
|
47
62
|
end
|
48
63
|
end
|
@@ -55,7 +55,7 @@ module Pod
|
|
55
55
|
|
56
56
|
store_existing_checkout_options
|
57
57
|
fetch_external_sources if allow_fetches
|
58
|
-
@result.specs_by_target = resolve_dependencies
|
58
|
+
@result.specs_by_target = validate_platforms(resolve_dependencies)
|
59
59
|
@result.specifications = generate_specifications
|
60
60
|
@result.targets = generate_targets
|
61
61
|
@result.sandbox_state = generate_sandbox_state
|
@@ -431,6 +431,26 @@ module Pod
|
|
431
431
|
specs_by_target
|
432
432
|
end
|
433
433
|
|
434
|
+
# Warns for any specification that is incompatible with its target.
|
435
|
+
#
|
436
|
+
# @param [Hash{TargetDefinition => Array<Spec>}] specs_by_target
|
437
|
+
# the specifications grouped by target.
|
438
|
+
#
|
439
|
+
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
|
440
|
+
# grouped by target.
|
441
|
+
#
|
442
|
+
def validate_platforms(specs_by_target)
|
443
|
+
specs_by_target.each do |target, specs|
|
444
|
+
specs.each do |spec|
|
445
|
+
unless spec.available_platforms.any? { |p| target.platform.supports?(p) }
|
446
|
+
UI.warn "The platform of the target `#{target.name}` " \
|
447
|
+
"(#{target.platform}) may not be compatible with `#{spec}` which has " \
|
448
|
+
"a minimum requirement of #{spec.available_platforms.join(' - ')}."
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
434
454
|
# Returns the list of all the resolved the resolved specifications.
|
435
455
|
#
|
436
456
|
# @return [Array<Specification>] the list of the specifications.
|
@@ -44,12 +44,6 @@ module Pod
|
|
44
44
|
def install!
|
45
45
|
download_source unless predownloaded? || local?
|
46
46
|
run_prepare_command
|
47
|
-
rescue Informative
|
48
|
-
raise
|
49
|
-
rescue Object
|
50
|
-
UI.notice("Error installing #{root_spec.name}")
|
51
|
-
clean!
|
52
|
-
raise
|
53
47
|
end
|
54
48
|
|
55
49
|
# Cleans the installations if appropriate.
|
@@ -80,32 +74,21 @@ module Pod
|
|
80
74
|
# @return [void]
|
81
75
|
#
|
82
76
|
def download_source
|
83
|
-
|
84
|
-
if head_pod?
|
85
|
-
begin
|
86
|
-
downloader.download_head
|
87
|
-
@specific_source = downloader.checkout_options
|
88
|
-
rescue RuntimeError => e
|
89
|
-
if e.message == 'Abstract method'
|
90
|
-
raise Informative, "The pod '" + root_spec.name + "' does not " \
|
91
|
-
'support the :head option, as it uses a ' + downloader.name +
|
92
|
-
' source. Remove that option to use this pod.'
|
93
|
-
else
|
94
|
-
raise
|
95
|
-
end
|
96
|
-
end
|
97
|
-
else
|
98
|
-
downloader.download
|
99
|
-
unless downloader.options_specific?
|
100
|
-
@specific_source = downloader.checkout_options
|
101
|
-
end
|
102
|
-
end
|
77
|
+
download_result = Downloader.download(download_request, root)
|
103
78
|
|
104
|
-
if specific_source
|
79
|
+
if (@specific_source = download_result.checkout_options) && specific_source != root_spec.source
|
105
80
|
sandbox.store_checkout_source(root_spec.name, specific_source)
|
106
81
|
end
|
107
82
|
end
|
108
83
|
|
84
|
+
def download_request
|
85
|
+
Downloader::Request.new(
|
86
|
+
:spec => root_spec,
|
87
|
+
:released => released?,
|
88
|
+
:head => head_pod?,
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
109
92
|
extend Executable
|
110
93
|
executable :bash
|
111
94
|
|
@@ -135,20 +118,8 @@ module Pod
|
|
135
118
|
# @return [void]
|
136
119
|
#
|
137
120
|
def clean_installation
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
#-----------------------------------------------------------------------#
|
142
|
-
|
143
|
-
public
|
144
|
-
|
145
|
-
# @!group Dependencies
|
146
|
-
|
147
|
-
# @return [Downloader] The downloader to use for the retrieving the
|
148
|
-
# source.
|
149
|
-
#
|
150
|
-
def downloader
|
151
|
-
@downloader ||= Downloader.for_target(root, root_spec.source.dup)
|
121
|
+
cleaner = Sandbox::PodDirCleaner.new(root, specs_by_platform)
|
122
|
+
cleaner.clean!
|
152
123
|
end
|
153
124
|
|
154
125
|
#-----------------------------------------------------------------------#
|
@@ -194,76 +165,8 @@ module Pod
|
|
194
165
|
sandbox.head_pod?(root_spec.name)
|
195
166
|
end
|
196
167
|
|
197
|
-
|
198
|
-
|
199
|
-
private
|
200
|
-
|
201
|
-
# @!group Private helpers
|
202
|
-
|
203
|
-
# @return [Array<Sandbox::FileAccessor>] the file accessors for all the
|
204
|
-
# specifications on their respective platform.
|
205
|
-
#
|
206
|
-
def file_accessors
|
207
|
-
return @file_accessors if @file_accessors
|
208
|
-
@file_accessors = []
|
209
|
-
specs_by_platform.each do |platform, specs|
|
210
|
-
specs.each do |spec|
|
211
|
-
@file_accessors << Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
|
212
|
-
end
|
213
|
-
end
|
214
|
-
@file_accessors
|
215
|
-
end
|
216
|
-
|
217
|
-
# @return [Sandbox::PathList] The path list for this Pod.
|
218
|
-
#
|
219
|
-
def path_list
|
220
|
-
@path_list ||= Sandbox::PathList.new(root)
|
221
|
-
end
|
222
|
-
|
223
|
-
# Finds the absolute paths, including hidden ones, of the files
|
224
|
-
# that are not used by the pod and thus can be safely deleted.
|
225
|
-
#
|
226
|
-
# @note Implementation detail: Don't use `Dir#glob` as there is an
|
227
|
-
# unexplained issue (#568, #572 and #602).
|
228
|
-
#
|
229
|
-
# @todo The paths are down-cased for the comparison as issues similar
|
230
|
-
# to #602 lead the files not being matched and so cleaning all
|
231
|
-
# the files. This solution might create side effects.
|
232
|
-
#
|
233
|
-
# @return [Array<Strings>] The paths that can be deleted.
|
234
|
-
#
|
235
|
-
def clean_paths
|
236
|
-
cached_used = used_files
|
237
|
-
glob_options = File::FNM_DOTMATCH | File::FNM_CASEFOLD
|
238
|
-
files = Pathname.glob(root + '**/*', glob_options).map(&:to_s)
|
239
|
-
|
240
|
-
files.reject! do |candidate|
|
241
|
-
candidate = candidate.downcase
|
242
|
-
candidate.end_with?('.', '..') || cached_used.any? do |path|
|
243
|
-
path = path.downcase
|
244
|
-
path.include?(candidate) || candidate.include?(path)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
files
|
248
|
-
end
|
249
|
-
|
250
|
-
# @return [Array<String>] The absolute path of all the files used by the
|
251
|
-
# specifications (according to their platform) of this Pod.
|
252
|
-
#
|
253
|
-
def used_files
|
254
|
-
files = [
|
255
|
-
file_accessors.map(&:vendored_frameworks),
|
256
|
-
file_accessors.map(&:vendored_libraries),
|
257
|
-
file_accessors.map(&:resource_bundle_files),
|
258
|
-
file_accessors.map(&:license),
|
259
|
-
file_accessors.map(&:prefix_header),
|
260
|
-
file_accessors.map(&:preserve_paths),
|
261
|
-
file_accessors.map(&:readme),
|
262
|
-
file_accessors.map(&:resources),
|
263
|
-
file_accessors.map(&:source_files),
|
264
|
-
]
|
265
|
-
|
266
|
-
files.flatten.compact.map(&:to_s).uniq
|
168
|
+
def released?
|
169
|
+
!local? && !head_pod? && !predownloaded? && sandbox.specification(root_spec.name) != root_spec
|
267
170
|
end
|
268
171
|
|
269
172
|
#-----------------------------------------------------------------------#
|
@@ -107,12 +107,16 @@ module Pod
|
|
107
107
|
# Creates the module map file which ensures that the umbrella header is
|
108
108
|
# recognized with a customized path
|
109
109
|
#
|
110
|
+
# @yield_param [Generator::ModuleMap]
|
111
|
+
# yielded once to configure the private headers
|
112
|
+
#
|
110
113
|
# @return [void]
|
111
114
|
#
|
112
115
|
def create_module_map
|
113
116
|
path = target.module_map_path
|
114
117
|
UI.message "- Generating module map file at #{UI.path(path)}" do
|
115
118
|
generator = Generator::ModuleMap.new(target)
|
119
|
+
yield generator if block_given?
|
116
120
|
generator.save_as(path)
|
117
121
|
add_file_to_support_group(path)
|
118
122
|
|