cocoapods 0.13.0 → 0.14.0.rc1
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.
- data/CHANGELOG.md +97 -16
- data/lib/cocoapods.rb +2 -1
- data/lib/cocoapods/command.rb +46 -19
- data/lib/cocoapods/command/install.rb +11 -12
- data/lib/cocoapods/command/linter.rb +3 -1
- data/lib/cocoapods/command/outdated.rb +51 -0
- data/lib/cocoapods/command/push.rb +6 -6
- data/lib/cocoapods/command/setup.rb +1 -1
- data/lib/cocoapods/command/spec.rb +1 -1
- data/lib/cocoapods/command/update.rb +21 -0
- data/lib/cocoapods/config.rb +14 -1
- data/lib/cocoapods/dependency.rb +56 -13
- data/lib/cocoapods/downloader/git.rb +1 -0
- data/lib/cocoapods/downloader/subversion.rb +6 -2
- data/lib/cocoapods/installer.rb +48 -64
- data/lib/cocoapods/local_pod.rb +50 -12
- data/lib/cocoapods/lockfile.rb +267 -0
- data/lib/cocoapods/podfile.rb +4 -0
- data/lib/cocoapods/project.rb +9 -4
- data/lib/cocoapods/resolver.rb +164 -20
- data/lib/cocoapods/specification.rb +11 -13
- data/lib/cocoapods/specification/set.rb +10 -13
- data/lib/cocoapods/version.rb +19 -2
- metadata +7 -4
@@ -0,0 +1,267 @@
|
|
1
|
+
module Pod
|
2
|
+
class Lockfile
|
3
|
+
|
4
|
+
# @return [Lockfile] Returns the Lockfile saved in path.
|
5
|
+
# Returns {nil} If the file can't be loaded.
|
6
|
+
#
|
7
|
+
def self.from_file(path)
|
8
|
+
return nil unless path.exist?
|
9
|
+
hash = YAML.load(File.open(path))
|
10
|
+
lockfile = Lockfile.new(hash)
|
11
|
+
lockfile.defined_in_file = path
|
12
|
+
lockfile
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Lockfile] Generates a lockfile from a {Podfile} and the
|
16
|
+
# list of {Specifications} that were installed.
|
17
|
+
#
|
18
|
+
def self.generate(podfile, specs)
|
19
|
+
Lockfile.new(generate_hash_from_podfile(podfile, specs))
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [String] The file where this Lockfile is defined.
|
23
|
+
#
|
24
|
+
attr_accessor :defined_in_file
|
25
|
+
|
26
|
+
# @return [String] The hash used to initialize the Lockfile.
|
27
|
+
#
|
28
|
+
attr_reader :to_hash
|
29
|
+
|
30
|
+
# @param [Hash] hash A Hash representation of a Lockfile.
|
31
|
+
#
|
32
|
+
def initialize(hash)
|
33
|
+
@to_hash = hash
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Array<String, Hash{String => Array[String]}>] The pods installed
|
37
|
+
# and their dependencies.
|
38
|
+
#
|
39
|
+
def pods
|
40
|
+
@pods ||= to_hash['PODS'] || []
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Array<Dependency>] The Podfile dependencies used during the last
|
44
|
+
# install.
|
45
|
+
#
|
46
|
+
def dependencies
|
47
|
+
@dependencies ||= to_hash['DEPENDENCIES'].map { |dep| dependency_from_string(dep) } || []
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Hash{String => Hash}] A hash where the name of the pods are
|
51
|
+
# the keys and the values are the parameters of an {AbstractExternalSource}
|
52
|
+
# of the dependency that required the pod.
|
53
|
+
#
|
54
|
+
def external_sources
|
55
|
+
@external_sources ||= to_hash["EXTERNAL SOURCES"] || {}
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<String>] The names of the installed Pods.
|
59
|
+
#
|
60
|
+
def pods_names
|
61
|
+
@pods_names ||= pods.map do |pod|
|
62
|
+
pod = pod.keys.first unless pod.is_a?(String)
|
63
|
+
name_and_version_for_pod(pod)[0]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Hash{String => Version}] A Hash containing the name
|
68
|
+
# of the installed Pods as the keys and their corresponding {Version}
|
69
|
+
# as the values.
|
70
|
+
#
|
71
|
+
def pods_versions
|
72
|
+
unless @pods_versions
|
73
|
+
@pods_versions = {}
|
74
|
+
pods.each do |pod|
|
75
|
+
pod = pod.keys.first unless pod.is_a?(String)
|
76
|
+
name, version = name_and_version_for_pod(pod)
|
77
|
+
@pods_versions[name] = version
|
78
|
+
end
|
79
|
+
end
|
80
|
+
@pods_versions
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Dependency] A dependency that describes the exact installed version
|
84
|
+
# of a Pod.
|
85
|
+
#
|
86
|
+
def dependency_for_installed_pod_named(name)
|
87
|
+
version = pods_versions[name]
|
88
|
+
raise Informative, "Attempt to lock a Pod without an known version." unless version
|
89
|
+
dependency = Dependency.new(name, version)
|
90
|
+
if external_source = external_sources[name]
|
91
|
+
dependency.external_source = Dependency::ExternalSources.from_params(dependency.name, external_source)
|
92
|
+
end
|
93
|
+
dependency
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param [String] The string that describes a {Specification} generated
|
97
|
+
# from {Specification#to_s}.
|
98
|
+
#
|
99
|
+
# @example Strings examples
|
100
|
+
# "libPusher"
|
101
|
+
# "libPusher (1.0)"
|
102
|
+
# "libPusher (HEAD based on 1.0)"
|
103
|
+
# "RestKit/JSON"
|
104
|
+
#
|
105
|
+
# @return [String, Version] The name and the version of a
|
106
|
+
# pod.
|
107
|
+
#
|
108
|
+
def name_and_version_for_pod(string)
|
109
|
+
match_data = string.match(/(\S*) \((.*)\)/)
|
110
|
+
name = match_data[1]
|
111
|
+
vers = Version.from_string(match_data[2])
|
112
|
+
[name, vers]
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param [String] The string that describes a {Dependency} generated
|
116
|
+
# from {Dependency#to_s}.
|
117
|
+
#
|
118
|
+
# @example Strings examples
|
119
|
+
# "libPusher"
|
120
|
+
# "libPusher (= 1.0)"
|
121
|
+
# "libPusher (~> 1.0.1)"
|
122
|
+
# "libPusher (> 1.0, < 2.0)"
|
123
|
+
# "libPusher (HEAD)"
|
124
|
+
# "libPusher (from `www.example.com')"
|
125
|
+
# "libPusher (defined in Podfile)"
|
126
|
+
# "RestKit/JSON"
|
127
|
+
#
|
128
|
+
# @return [Dependency] The dependency described by the string.
|
129
|
+
#
|
130
|
+
def dependency_from_string(string)
|
131
|
+
match_data = string.match(/(\S*)( (.*))?/)
|
132
|
+
name = match_data[1]
|
133
|
+
version = match_data[2]
|
134
|
+
version = version.gsub(/[()]/,'') if version
|
135
|
+
case version
|
136
|
+
when nil
|
137
|
+
Dependency.new(name)
|
138
|
+
when /defined in Podfile/
|
139
|
+
# @TODO: store the whole spec?, the version?
|
140
|
+
Dependency.new(name)
|
141
|
+
when /from `(.*)'/
|
142
|
+
external_source_info = external_sources[name]
|
143
|
+
Dependency.new(name, external_source_info)
|
144
|
+
when /HEAD/
|
145
|
+
# @TODO: find a way to serialize from the Downloader the information
|
146
|
+
# necessary to restore a head version.
|
147
|
+
Dependency.new(name, :head)
|
148
|
+
else
|
149
|
+
Dependency.new(name, version)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Analyzes the {Lockfile} and detects any changes applied to the {Podfile}
|
154
|
+
# since the last installation.
|
155
|
+
#
|
156
|
+
# For each Pod, it detects one state among the following:
|
157
|
+
#
|
158
|
+
# - added: Pods that weren't present in the Podfile.
|
159
|
+
# - changed: Pods that were present in the Podfile but changed:
|
160
|
+
# - Pods whose version is not compatible anymore with Podfile,
|
161
|
+
# - Pods that changed their head or external options.
|
162
|
+
# - removed: Pods that were removed form the Podfile.
|
163
|
+
# - unchanged: Pods that are still compatible with Podfile.
|
164
|
+
#
|
165
|
+
# @TODO: detect changes for inline dependencies?
|
166
|
+
#
|
167
|
+
# @return [Hash{Symbol=>Array[Strings]}] A hash where pods are grouped
|
168
|
+
# by the state in which they are.
|
169
|
+
#
|
170
|
+
def detect_changes_with_podfile(podfile)
|
171
|
+
previous_podfile_deps = dependencies.map(&:name)
|
172
|
+
user_installed_pods = pods_names.reject { |name| !previous_podfile_deps.include?(name) }
|
173
|
+
deps_to_install = podfile.dependencies.dup
|
174
|
+
|
175
|
+
result = {}
|
176
|
+
result[:added] = []
|
177
|
+
result[:changed] = []
|
178
|
+
result[:removed] = []
|
179
|
+
result[:unchanged] = []
|
180
|
+
|
181
|
+
user_installed_pods.each do |pod_name|
|
182
|
+
dependency = deps_to_install.find { |d| d.name == pod_name }
|
183
|
+
deps_to_install.delete(dependency)
|
184
|
+
version = pods_versions[pod_name]
|
185
|
+
external_source = Dependency::ExternalSources.from_params(pod_name, external_sources[pod_name])
|
186
|
+
|
187
|
+
if dependency.nil?
|
188
|
+
result[:removed] << pod_name
|
189
|
+
elsif !dependency.match_version?(version) || dependency.external_source != external_source
|
190
|
+
result[:changed] << pod_name
|
191
|
+
else
|
192
|
+
result[:unchanged] << pod_name
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
deps_to_install.each do |dependency|
|
197
|
+
result[:added] << dependency.name
|
198
|
+
end
|
199
|
+
result
|
200
|
+
end
|
201
|
+
|
202
|
+
# @return [void] Writes the Lockfile to {#path}.
|
203
|
+
#
|
204
|
+
def write_to_disk(path)
|
205
|
+
File.open(path, 'w') {|f| f.write(to_yaml) }
|
206
|
+
defined_in_file = path
|
207
|
+
end
|
208
|
+
|
209
|
+
# @return [String] A string useful to represent the Lockfile in a message
|
210
|
+
# presented to the user.
|
211
|
+
#
|
212
|
+
def to_s
|
213
|
+
"Podfile.lock"
|
214
|
+
end
|
215
|
+
|
216
|
+
# @return [String] The YAML representation of the Lockfile, used for
|
217
|
+
# serialization.
|
218
|
+
#
|
219
|
+
def to_yaml
|
220
|
+
to_hash.to_yaml.gsub(/^--- ?\n/,"").gsub(/^([A-Z])/,"\n\\1")
|
221
|
+
end
|
222
|
+
|
223
|
+
# @return [Hash] The Hash representation of the Lockfile generated from
|
224
|
+
# a given Podfile and the list of resolved Specifications.
|
225
|
+
#
|
226
|
+
def self.generate_hash_from_podfile(podfile, specs)
|
227
|
+
hash = {}
|
228
|
+
|
229
|
+
# Get list of [name, dependencies] pairs.
|
230
|
+
pod_and_deps = specs.map do |spec|
|
231
|
+
[spec.to_s, spec.dependencies.map(&:to_s).sort]
|
232
|
+
end.uniq
|
233
|
+
|
234
|
+
# Merge dependencies of iOS and OS X version of the same pod.
|
235
|
+
tmp = {}
|
236
|
+
pod_and_deps.each do |name, deps|
|
237
|
+
if tmp[name]
|
238
|
+
tmp[name].concat(deps).uniq!
|
239
|
+
else
|
240
|
+
tmp[name] = deps
|
241
|
+
end
|
242
|
+
end
|
243
|
+
pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
|
244
|
+
deps.empty? ? name : { name => deps }
|
245
|
+
end
|
246
|
+
hash["PODS"] = pod_and_deps
|
247
|
+
|
248
|
+
hash["DEPENDENCIES"] = podfile.dependencies.map{ |d| d.to_s }.sort
|
249
|
+
|
250
|
+
external_sources = {}
|
251
|
+
deps = podfile.dependencies.select(&:external?).sort{ |d, other| d.name <=> other.name}
|
252
|
+
deps.each{ |d| external_sources[d.name] = d.external_source.params }
|
253
|
+
hash["EXTERNAL SOURCES"] = external_sources unless external_sources.empty?
|
254
|
+
|
255
|
+
checksums = {}
|
256
|
+
specs.select { |spec| !spec.defined_in_file.nil? }.each do |spec|
|
257
|
+
checksum = Digest::SHA1.hexdigest(File.read(spec.defined_in_file))
|
258
|
+
checksum = checksum.encode('UTF-8') if checksum.respond_to?(:encode)
|
259
|
+
checksums[spec.name] = checksum
|
260
|
+
end
|
261
|
+
hash["SPEC CHECKSUMS"] = checksums unless checksums.empty?
|
262
|
+
hash["COCOAPODS"] = VERSION
|
263
|
+
hash
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
data/lib/cocoapods/podfile.rb
CHANGED
data/lib/cocoapods/project.rb
CHANGED
@@ -31,15 +31,20 @@ module Pod
|
|
31
31
|
|
32
32
|
# Shortcut access to the `Pods' PBXGroup.
|
33
33
|
def pods
|
34
|
-
|
34
|
+
@pods ||= groups.where(:name => 'Pods') || groups.new('name' => 'Pods')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shortcut access to the `Local Pods' PBXGroup.
|
38
|
+
def local_pods
|
39
|
+
@local_pods ||= groups.where(:name => 'Local Pods') || groups.new('name' => 'Local Pods')
|
35
40
|
end
|
36
41
|
|
37
42
|
# Adds a group as child to the `Pods' group namespacing subspecs.
|
38
|
-
def add_spec_group(name)
|
39
|
-
groups =
|
43
|
+
def add_spec_group(name, parent_group)
|
44
|
+
groups = parent_group.groups
|
40
45
|
group = nil
|
41
46
|
name.split('/').each do |name|
|
42
|
-
group = groups.
|
47
|
+
group = groups.where(:name => name) || groups.new('name' => name)
|
43
48
|
groups = group.groups
|
44
49
|
end
|
45
50
|
group
|
data/lib/cocoapods/resolver.rb
CHANGED
@@ -4,44 +4,169 @@ module Pod
|
|
4
4
|
class Resolver
|
5
5
|
include Config::Mixin
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# @return [Bool] Whether the resolver should find the pods to install or
|
8
|
+
# the pods to update.
|
9
|
+
#
|
10
|
+
attr_accessor :update_mode
|
11
|
+
|
12
|
+
# @return [Bool] Whether the resolver should update the external specs
|
13
|
+
# in the resolution process.
|
14
|
+
#
|
15
|
+
attr_accessor :update_external_specs
|
16
|
+
|
17
|
+
# @return [Podfile] The Podfile used by the resolver.
|
18
|
+
#
|
19
|
+
attr_reader :podfile
|
20
|
+
|
21
|
+
# @return [Lockfile] The Lockfile used by the resolver.
|
22
|
+
#
|
23
|
+
attr_reader :lockfile
|
24
|
+
|
25
|
+
# @return [Sandbox] The Sandbox used by the resolver to find external
|
26
|
+
# dependencies.
|
27
|
+
#
|
28
|
+
attr_reader :sandbox
|
29
|
+
|
30
|
+
# @return [Array<Strings>] The name of the pods that have an
|
31
|
+
# external source.
|
32
|
+
#
|
33
|
+
attr_reader :pods_from_external_sources
|
34
|
+
|
35
|
+
# @return [Array<Set>] A cache of the sets used to resolve the dependencies.
|
36
|
+
#
|
37
|
+
attr_reader :cached_sets
|
38
|
+
|
39
|
+
# @return [Source::Aggregate] A cache of the sources needed to find the
|
40
|
+
# podspecs.
|
41
|
+
#
|
42
|
+
attr_reader :cached_sources
|
43
|
+
|
44
|
+
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}]
|
45
|
+
# Returns the resolved specifications grouped by target.
|
46
|
+
#
|
47
|
+
attr_reader :specs_by_target
|
48
|
+
|
49
|
+
def initialize(podfile, lockfile, sandbox)
|
50
|
+
@podfile = podfile
|
51
|
+
@lockfile = lockfile
|
52
|
+
@sandbox = sandbox
|
53
|
+
@update_external_specs = true
|
9
54
|
|
10
|
-
def initialize(podfile, sandbox)
|
11
|
-
@podfile = podfile
|
12
|
-
@sandbox = sandbox
|
13
55
|
@cached_sets = {}
|
14
56
|
@cached_sources = Source::Aggregate.new
|
15
|
-
@log_indent = 0;
|
16
57
|
end
|
17
58
|
|
59
|
+
# Identifies the specifications that should be installed according whether
|
60
|
+
# the resolver is in update mode or not.
|
61
|
+
#
|
62
|
+
# @return [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
|
63
|
+
#
|
18
64
|
def resolve
|
19
|
-
@
|
20
|
-
|
65
|
+
@cached_specs = {}
|
66
|
+
@specs_by_target = {}
|
67
|
+
@pods_from_external_sources = []
|
68
|
+
@pods_to_lock = []
|
69
|
+
@log_indent = 0
|
70
|
+
|
71
|
+
if @lockfile
|
72
|
+
puts "\nFinding added, modified or removed dependencies:".green if config.verbose?
|
73
|
+
@pods_by_state = @lockfile.detect_changes_with_podfile(podfile)
|
74
|
+
if config.verbose?
|
75
|
+
@pods_by_state.each do |symbol, pod_names|
|
76
|
+
case symbol
|
77
|
+
when :added
|
78
|
+
mark = "A".green
|
79
|
+
when :changed
|
80
|
+
mark = "M".yellow
|
81
|
+
when :removed
|
82
|
+
mark = "R".red
|
83
|
+
when :unchanged
|
84
|
+
mark = "-"
|
85
|
+
end
|
86
|
+
pod_names.each do |pod_name|
|
87
|
+
puts " #{mark} " << pod_name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
@pods_to_lock = (lockfile.pods_names - @pods_by_state[:added] - @pods_by_state[:changed] - @pods_by_state[:removed]).uniq
|
92
|
+
end
|
21
93
|
|
22
94
|
@podfile.target_definitions.values.each do |target_definition|
|
23
|
-
puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform})".green if config.verbose?
|
95
|
+
puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform}):".green if config.verbose?
|
24
96
|
@loaded_specs = []
|
25
97
|
find_dependency_specs(@podfile, target_definition.dependencies, target_definition)
|
26
|
-
|
98
|
+
@specs_by_target[target_definition] = @cached_specs.values_at(*@loaded_specs).sort_by(&:name)
|
99
|
+
end
|
100
|
+
|
101
|
+
@cached_specs.values.sort_by(&:name)
|
102
|
+
@specs_by_target
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [Array<Specification>] The specifications loaded by the resolver.
|
106
|
+
#
|
107
|
+
def specs
|
108
|
+
@cached_specs.values.uniq
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Bool] Whether a pod should be installed/reinstalled.
|
112
|
+
#
|
113
|
+
def should_install?(name)
|
114
|
+
pods_to_install.include? name
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [Array<Strings>] The name of the pods that should be
|
118
|
+
# installed/reinstalled.
|
119
|
+
#
|
120
|
+
def pods_to_install
|
121
|
+
unless @pods_to_install
|
122
|
+
if lockfile
|
123
|
+
@pods_to_install = specs.select do |spec|
|
124
|
+
spec.version != lockfile.pods_versions[spec.pod_name]
|
125
|
+
end.map(&:name)
|
126
|
+
if update_mode
|
127
|
+
@pods_to_install += specs.select do |spec|
|
128
|
+
spec.version.head? || pods_from_external_sources.include?(spec.pod_name)
|
129
|
+
end.map(&:name)
|
130
|
+
end
|
131
|
+
@pods_to_install += @pods_by_state[:added] + @pods_by_state[:changed]
|
132
|
+
else
|
133
|
+
@pods_to_install = specs.map(&:name)
|
134
|
+
end
|
27
135
|
end
|
136
|
+
@pods_to_install
|
137
|
+
end
|
28
138
|
|
29
|
-
|
30
|
-
|
139
|
+
# @return [Array<Strings>] The name of the pods that were installed
|
140
|
+
# but don't have any dependency anymore. The name of the Pods are
|
141
|
+
# stripped from subspecs.
|
142
|
+
#
|
143
|
+
def removed_pods
|
144
|
+
return [] unless lockfile
|
145
|
+
unless @removed_pods
|
146
|
+
previusly_installed = lockfile.pods_names.map { |pod_name| pod_name.split('/').first }
|
147
|
+
installed = specs.map { |spec| spec.name.split('/').first }
|
148
|
+
@removed_pods = previusly_installed - installed
|
149
|
+
end
|
150
|
+
@removed_pods
|
31
151
|
end
|
32
152
|
|
33
153
|
private
|
34
154
|
|
155
|
+
# @return [Set] The cached set for a given dependency.
|
156
|
+
#
|
35
157
|
def find_cached_set(dependency, platform)
|
36
158
|
set_name = dependency.name.split('/').first
|
37
159
|
@cached_sets[set_name] ||= begin
|
38
160
|
if dependency.specification
|
39
161
|
Specification::Set::External.new(dependency.specification)
|
40
162
|
elsif external_source = dependency.external_source
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
163
|
+
if update_mode && update_external_specs
|
164
|
+
# Always update external sources in update mode.
|
165
|
+
specification = external_source.specification_from_external(@sandbox, platform)
|
166
|
+
else
|
167
|
+
# Don't update external sources in install mode if not needed.
|
168
|
+
specification = external_source.specification_from_sandbox(@sandbox, platform)
|
169
|
+
end
|
45
170
|
set = Specification::Set::External.new(specification)
|
46
171
|
if dependency.subspec_dependency?
|
47
172
|
@cached_sets[dependency.top_level_spec_name] ||= set
|
@@ -53,29 +178,48 @@ module Pod
|
|
53
178
|
end
|
54
179
|
end
|
55
180
|
|
181
|
+
# Resolves the dependencies of a specification and stores them in @cached_specs
|
182
|
+
#
|
183
|
+
# @param [Specification] dependent_specification
|
184
|
+
# @param [Array<Dependency>] dependencies
|
185
|
+
# @param [TargetDefinition] target_definition
|
186
|
+
#
|
187
|
+
# @return [void]
|
188
|
+
#
|
56
189
|
def find_dependency_specs(dependent_specification, dependencies, target_definition)
|
57
190
|
@log_indent += 1
|
58
191
|
dependencies.each do |dependency|
|
192
|
+
# Replace the dependency with a more specific one if the pod is already installed.
|
193
|
+
if !update_mode && @pods_to_lock.include?(dependency.name)
|
194
|
+
dependency = lockfile.dependency_for_installed_pod_named(dependency.name)
|
195
|
+
end
|
196
|
+
|
59
197
|
puts ' ' * @log_indent + "- #{dependency}" if config.verbose?
|
60
198
|
set = find_cached_set(dependency, target_definition.platform)
|
61
|
-
set.required_by(dependent_specification)
|
199
|
+
set.required_by(dependency, dependent_specification.to_s)
|
200
|
+
|
62
201
|
# Ensure we don't resolve the same spec twice for one target
|
63
202
|
unless @loaded_specs.include?(dependency.name)
|
64
203
|
spec = set.specification_by_name(dependency.name)
|
204
|
+
@pods_from_external_sources << spec.pod_name if dependency.external?
|
65
205
|
@loaded_specs << spec.name
|
66
|
-
@
|
206
|
+
@cached_specs[spec.name] = spec
|
67
207
|
# Configure the specification
|
68
208
|
spec.activate_platform(target_definition.platform)
|
69
209
|
spec.version.head = dependency.head?
|
70
210
|
# And recursively load the dependencies of the spec.
|
71
211
|
find_dependency_specs(spec, spec.dependencies, target_definition) if spec.dependencies
|
72
212
|
end
|
73
|
-
validate_platform
|
213
|
+
validate_platform(spec || @cached_specs[dependency.name], target_definition)
|
74
214
|
end
|
75
215
|
@log_indent -= 1
|
76
216
|
end
|
77
217
|
|
78
|
-
|
218
|
+
# Ensures that a spec is compatible with platform of a target.
|
219
|
+
#
|
220
|
+
# @raises If the spec is not supported by the target.
|
221
|
+
#
|
222
|
+
def validate_platform(spec, target)
|
79
223
|
unless spec.available_platforms.any? { |platform| target.platform.supports?(platform) }
|
80
224
|
raise Informative, "[!] The platform of the target `#{target.name}' (#{target.platform}) is not compatible with `#{spec}' which has a minimun requirement of #{spec.available_platforms.join(' - ')}.".red
|
81
225
|
end
|