cocoapods 1.2.1 → 1.3.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +89 -1
- data/lib/cocoapods/command/lib/lint.rb +3 -0
- data/lib/cocoapods/command/repo/push.rb +1 -1
- data/lib/cocoapods/command/spec/lint.rb +3 -0
- data/lib/cocoapods/gem_version.rb +1 -1
- data/lib/cocoapods/generator/copy_resources_script.rb +11 -11
- data/lib/cocoapods/generator/embed_frameworks_script.rb +18 -6
- data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +6 -66
- data/lib/cocoapods/generator/xcconfig/pod_xcconfig.rb +16 -3
- data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +102 -6
- data/lib/cocoapods/installer.rb +17 -76
- data/lib/cocoapods/installer/analyzer.rb +48 -44
- data/lib/cocoapods/installer/xcode.rb +1 -0
- data/lib/cocoapods/installer/xcode/pods_project_generator.rb +22 -9
- data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +11 -5
- data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +78 -5
- data/lib/cocoapods/installer/xcode/target_validator.rb +126 -0
- data/lib/cocoapods/project.rb +5 -0
- data/lib/cocoapods/resolver.rb +1 -1
- data/lib/cocoapods/resolver/lazy_specification.rb +2 -2
- data/lib/cocoapods/sandbox.rb +23 -0
- data/lib/cocoapods/target/pod_target.rb +72 -5
- data/lib/cocoapods/validator.rb +101 -46
- metadata +9 -8
@@ -0,0 +1,126 @@
|
|
1
|
+
module Pod
|
2
|
+
class Installer
|
3
|
+
class Xcode
|
4
|
+
# The {Xcode::TargetValidator} ensures that the pod and aggregate target
|
5
|
+
# configuration is valid for installation.
|
6
|
+
#
|
7
|
+
class TargetValidator
|
8
|
+
# @return [Array<AggregateTarget>] The aggregate targets that should be
|
9
|
+
# validated.
|
10
|
+
#
|
11
|
+
attr_reader :aggregate_targets
|
12
|
+
|
13
|
+
# @return [Array<PodTarget>] The pod targets that should be validated.
|
14
|
+
#
|
15
|
+
attr_reader :pod_targets
|
16
|
+
|
17
|
+
# Create a new TargetValidator with aggregate and pod targets to
|
18
|
+
# validate.
|
19
|
+
#
|
20
|
+
# @param [Array<AggregateTarget>] aggregate_targets
|
21
|
+
# The aggregate targets to validate.
|
22
|
+
#
|
23
|
+
# @param [Array<PodTarget>] pod_targets
|
24
|
+
# The pod targets to validate.
|
25
|
+
#
|
26
|
+
def initialize(aggregate_targets, pod_targets)
|
27
|
+
@aggregate_targets = aggregate_targets
|
28
|
+
@pod_targets = pod_targets
|
29
|
+
end
|
30
|
+
|
31
|
+
# Perform the validation steps for the provided aggregate and pod
|
32
|
+
# targets.
|
33
|
+
#
|
34
|
+
def validate!
|
35
|
+
verify_no_duplicate_framework_and_library_names
|
36
|
+
verify_no_static_framework_transitive_dependencies
|
37
|
+
verify_no_pods_used_with_multiple_swift_versions
|
38
|
+
verify_framework_usage
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def verify_no_duplicate_framework_and_library_names
|
44
|
+
aggregate_targets.each do |aggregate_target|
|
45
|
+
aggregate_target.user_build_configurations.keys.each do |config|
|
46
|
+
pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
|
47
|
+
file_accessors = pod_targets.flat_map(&:file_accessors)
|
48
|
+
|
49
|
+
frameworks = file_accessors.flat_map(&:vendored_frameworks).uniq.map(&:basename)
|
50
|
+
frameworks += pod_targets.select { |pt| pt.should_build? && pt.requires_frameworks? }.map(&:product_module_name)
|
51
|
+
verify_no_duplicate_names(frameworks, aggregate_target.label, 'frameworks')
|
52
|
+
|
53
|
+
libraries = file_accessors.flat_map(&:vendored_libraries).uniq.map(&:basename)
|
54
|
+
libraries += pod_targets.select { |pt| pt.should_build? && !pt.requires_frameworks? }.map(&:product_name)
|
55
|
+
verify_no_duplicate_names(libraries, aggregate_target.label, 'libraries')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def verify_no_duplicate_names(names, label, type)
|
61
|
+
duplicates = names.map { |n| n.to_s.downcase }.group_by { |f| f }.select { |_, v| v.size > 1 }.keys
|
62
|
+
|
63
|
+
unless duplicates.empty?
|
64
|
+
raise Informative, "The '#{label}' target has " \
|
65
|
+
"#{type} with conflicting names: #{duplicates.to_sentence}."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def verify_no_static_framework_transitive_dependencies
|
70
|
+
aggregate_targets.each do |aggregate_target|
|
71
|
+
next unless aggregate_target.requires_frameworks?
|
72
|
+
|
73
|
+
aggregate_target.user_build_configurations.keys.each do |config|
|
74
|
+
pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
|
75
|
+
|
76
|
+
dependencies = pod_targets.select(&:should_build?).flat_map(&:dependencies)
|
77
|
+
dependended_upon_targets = pod_targets.select { |t| dependencies.include?(t.pod_name) && !t.should_build? }
|
78
|
+
|
79
|
+
static_libs = dependended_upon_targets.flat_map(&:file_accessors).flat_map(&:vendored_static_artifacts)
|
80
|
+
unless static_libs.empty?
|
81
|
+
raise Informative, "The '#{aggregate_target.label}' target has " \
|
82
|
+
"transitive dependencies that include static binaries: (#{static_libs.to_sentence})"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def verify_no_pods_used_with_multiple_swift_versions
|
89
|
+
error_message_for_target = lambda do |target|
|
90
|
+
"#{target.name} (Swift #{target.swift_version})"
|
91
|
+
end
|
92
|
+
swift_pod_targets = pod_targets.select(&:uses_swift?)
|
93
|
+
error_messages = swift_pod_targets.map do |pod_target|
|
94
|
+
swift_target_definitions = pod_target.target_definitions.reject { |target| target.swift_version.blank? }
|
95
|
+
next if swift_target_definitions.empty? || swift_target_definitions.uniq(&:swift_version).count == 1
|
96
|
+
target_errors = swift_target_definitions.map(&error_message_for_target).join(', ')
|
97
|
+
"- #{pod_target.name} required by #{target_errors}"
|
98
|
+
end.compact
|
99
|
+
|
100
|
+
unless error_messages.empty?
|
101
|
+
raise Informative, 'The following pods are integrated into targets ' \
|
102
|
+
"that do not have the same Swift version:\n\n#{error_messages.join("\n")}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def verify_framework_usage
|
107
|
+
aggregate_targets.each do |aggregate_target|
|
108
|
+
next if aggregate_target.requires_frameworks?
|
109
|
+
|
110
|
+
aggregate_target.user_build_configurations.keys.each do |config|
|
111
|
+
pod_targets = aggregate_target.pod_targets_for_build_configuration(config)
|
112
|
+
|
113
|
+
swift_pods = pod_targets.select(&:uses_swift?)
|
114
|
+
unless swift_pods.empty?
|
115
|
+
raise Informative, 'Pods written in Swift can only be integrated as frameworks; ' \
|
116
|
+
'add `use_frameworks!` to your Podfile or target to opt into using it. ' \
|
117
|
+
"The Swift #{swift_pods.size == 1 ? 'Pod being used is' : 'Pods being used are'}: " +
|
118
|
+
swift_pods.map(&:name).to_sentence
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/cocoapods/project.rb
CHANGED
data/lib/cocoapods/resolver.rb
CHANGED
@@ -305,7 +305,7 @@ module Pod
|
|
305
305
|
find_cached_set(dependency).
|
306
306
|
all_specifications(installation_options.warn_for_multiple_pod_sources).
|
307
307
|
select { |s| requirement.satisfied_by? s.version }.
|
308
|
-
map { |s| s.subspec_by_name(dependency.name, false) }.
|
308
|
+
map { |s| s.subspec_by_name(dependency.name, false, true) }.
|
309
309
|
compact.
|
310
310
|
reverse
|
311
311
|
end
|
@@ -18,11 +18,11 @@ module Pod
|
|
18
18
|
specification.respond_to?(method, include_all)
|
19
19
|
end
|
20
20
|
|
21
|
-
def subspec_by_name(name = nil, raise_if_missing = true)
|
21
|
+
def subspec_by_name(name = nil, raise_if_missing = true, include_test_specifications = false)
|
22
22
|
if !name || name == self.name
|
23
23
|
self
|
24
24
|
else
|
25
|
-
specification.subspec_by_name(name, raise_if_missing)
|
25
|
+
specification.subspec_by_name(name, raise_if_missing, include_test_specifications)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
data/lib/cocoapods/sandbox.rb
CHANGED
@@ -386,5 +386,28 @@ module Pod
|
|
386
386
|
end
|
387
387
|
|
388
388
|
#-------------------------------------------------------------------------#
|
389
|
+
|
390
|
+
public
|
391
|
+
|
392
|
+
# @!group Pods Helpers
|
393
|
+
|
394
|
+
# Creates the file accessors for the given Pod Targets.
|
395
|
+
#
|
396
|
+
# @param [Array<PodTarget>] pod_targets
|
397
|
+
# The Pod Targets to create file accessors for.
|
398
|
+
#
|
399
|
+
def create_file_accessors(pod_targets)
|
400
|
+
pod_targets.each do |pod_target|
|
401
|
+
pod_root = pod_dir(pod_target.root_spec.name)
|
402
|
+
path_list = PathList.new(pod_root)
|
403
|
+
file_accessors = pod_target.specs.map do |spec|
|
404
|
+
FileAccessor.new(path_list, spec.consumer(pod_target.platform))
|
405
|
+
end
|
406
|
+
pod_target.file_accessors ||= []
|
407
|
+
pod_target.file_accessors.concat(file_accessors)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
#-------------------------------------------------------------------------#
|
389
412
|
end
|
390
413
|
end
|
@@ -28,6 +28,16 @@ module Pod
|
|
28
28
|
#
|
29
29
|
attr_accessor :dependent_targets
|
30
30
|
|
31
|
+
# @return [Array<PodTarget>] the targets that this target has a test dependency
|
32
|
+
# upon.
|
33
|
+
#
|
34
|
+
attr_accessor :test_dependent_targets
|
35
|
+
|
36
|
+
# return [Array<PBXNativeTarget>] the test target generated in the Pods project for
|
37
|
+
# this library or `nil` if there is no test target created.
|
38
|
+
#
|
39
|
+
attr_accessor :test_native_targets
|
40
|
+
|
31
41
|
# @param [Array<Specification>] specs @see #specs
|
32
42
|
# @param [Array<TargetDefinition>] target_definitions @see #target_definitions
|
33
43
|
# @param [Sandbox] sandbox @see #sandbox
|
@@ -46,7 +56,9 @@ module Pod
|
|
46
56
|
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private')
|
47
57
|
@file_accessors = []
|
48
58
|
@resource_bundle_targets = []
|
59
|
+
@test_native_targets = []
|
49
60
|
@dependent_targets = []
|
61
|
+
@test_dependent_targets = []
|
50
62
|
@build_config_cache = {}
|
51
63
|
end
|
52
64
|
|
@@ -133,7 +145,7 @@ module Pod
|
|
133
145
|
#
|
134
146
|
attr_accessor :file_accessors
|
135
147
|
|
136
|
-
# @return [Array<
|
148
|
+
# @return [Array<PBXNativeTarget>] the resource bundle targets belonging
|
137
149
|
# to this target.
|
138
150
|
attr_reader :resource_bundle_targets
|
139
151
|
|
@@ -157,7 +169,7 @@ module Pod
|
|
157
169
|
specs.map { |spec| spec.consumer(platform) }
|
158
170
|
end
|
159
171
|
|
160
|
-
# @return [Boolean] Whether the target uses Swift code
|
172
|
+
# @return [Boolean] Whether the target uses Swift code.
|
161
173
|
#
|
162
174
|
def uses_swift?
|
163
175
|
return @uses_swift if defined? @uses_swift
|
@@ -168,6 +180,52 @@ module Pod
|
|
168
180
|
end
|
169
181
|
end
|
170
182
|
|
183
|
+
# @return [Boolean] Whether the target has any tests specifications.
|
184
|
+
#
|
185
|
+
def contains_test_specifications?
|
186
|
+
specs.any?(&:test_specification?)
|
187
|
+
end
|
188
|
+
|
189
|
+
# @return [Array<Symbol>] All of the test supported types within this target.
|
190
|
+
#
|
191
|
+
def supported_test_types
|
192
|
+
specs.select(&:test_specification?).map(&:test_type).uniq
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the corresponding native target to use based on the provided specification.
|
196
|
+
# This is used to figure out whether to add a source file into the library native target or any of the
|
197
|
+
# test native targets.
|
198
|
+
#
|
199
|
+
# @param [Specification] spec
|
200
|
+
# The specifcation to base from in order to find the native target.
|
201
|
+
#
|
202
|
+
# @return [PBXNativeTarget] the native target to use or `nil` if none is found.
|
203
|
+
#
|
204
|
+
def native_target_for_spec(spec)
|
205
|
+
return native_target unless spec.test_specification?
|
206
|
+
test_native_targets.find do |native_target|
|
207
|
+
native_target.symbol_type == product_type_for_test_type(spec.test_type)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns the corresponding native product type to use given the test type.
|
212
|
+
# This is primarily used when creating the native targets in order to produce the correct test bundle target
|
213
|
+
# based on the type of tests included.
|
214
|
+
#
|
215
|
+
# @param [Symbol] test_type
|
216
|
+
# The test type to map to provided by the test specification DSL.
|
217
|
+
#
|
218
|
+
# @return [Symbol] The native product type to use.
|
219
|
+
#
|
220
|
+
def product_type_for_test_type(test_type)
|
221
|
+
case test_type
|
222
|
+
when :unit
|
223
|
+
:unit_test_bundle
|
224
|
+
else
|
225
|
+
raise Informative, "Unknown test type `#{test_type}`."
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
171
229
|
# @return [Specification] The root specification for the target.
|
172
230
|
#
|
173
231
|
def root_spec
|
@@ -189,6 +247,15 @@ module Pod
|
|
189
247
|
"#{label}-#{bundle_name}"
|
190
248
|
end
|
191
249
|
|
250
|
+
# @param [Symbol] test_type
|
251
|
+
# The test type to use for producing the test label.
|
252
|
+
#
|
253
|
+
# @return [String] The derived name of the test target.
|
254
|
+
#
|
255
|
+
def test_target_label(test_type)
|
256
|
+
"#{label}-#{test_type.capitalize}-Tests"
|
257
|
+
end
|
258
|
+
|
192
259
|
# @return [Array<String>] The names of the Pods on which this target
|
193
260
|
# depends.
|
194
261
|
#
|
@@ -234,7 +301,7 @@ module Pod
|
|
234
301
|
|
235
302
|
if whitelists.empty?
|
236
303
|
@build_config_cache[key] = true
|
237
|
-
|
304
|
+
true
|
238
305
|
elsif whitelists.count == 1
|
239
306
|
@build_config_cache[key] = whitelists.first
|
240
307
|
whitelists.first
|
@@ -258,7 +325,7 @@ module Pod
|
|
258
325
|
|
259
326
|
if whitelists.empty?
|
260
327
|
@inhibit_warnings = false
|
261
|
-
|
328
|
+
false
|
262
329
|
elsif whitelists.count == 1
|
263
330
|
@inhibit_warnings = whitelists.first
|
264
331
|
whitelists.first
|
@@ -268,7 +335,7 @@ module Pod
|
|
268
335
|
'settings to inhibit warnings. CocoaPods does not currently ' \
|
269
336
|
'support different settings and will fall back to your preference ' \
|
270
337
|
'set in the root target definition.'
|
271
|
-
|
338
|
+
podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
|
272
339
|
end
|
273
340
|
end
|
274
341
|
|
data/lib/cocoapods/validator.rb
CHANGED
@@ -28,8 +28,12 @@ module Pod
|
|
28
28
|
# the Source URLs to use in creating a {Podfile}.
|
29
29
|
#
|
30
30
|
def initialize(spec_or_path, source_urls)
|
31
|
-
@source_urls = source_urls.map { |url| config.sources_manager.source_with_name_or_url(url) }.map(&:url)
|
32
31
|
@linter = Specification::Linter.new(spec_or_path)
|
32
|
+
@source_urls = if @linter.spec && @linter.spec.dependencies.empty?
|
33
|
+
[]
|
34
|
+
else
|
35
|
+
source_urls.map { |url| config.sources_manager.source_with_name_or_url(url) }.map(&:url)
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
#-------------------------------------------------------------------------#
|
@@ -68,7 +72,7 @@ module Pod
|
|
68
72
|
a_spec = spec
|
69
73
|
if spec && @only_subspec
|
70
74
|
subspec_name = @only_subspec.start_with?(spec.root.name) ? @only_subspec : "#{spec.root.name}/#{@only_subspec}"
|
71
|
-
a_spec = spec.subspec_by_name(subspec_name)
|
75
|
+
a_spec = spec.subspec_by_name(subspec_name, true, true)
|
72
76
|
@subspec_name = a_spec.name
|
73
77
|
end
|
74
78
|
|
@@ -142,15 +146,8 @@ module Pod
|
|
142
146
|
reasons << 'all results apply only to public specs, but you can use ' \
|
143
147
|
'`--private` to ignore them if linting the specification for a private pod'
|
144
148
|
end
|
145
|
-
|
146
|
-
|
147
|
-
'Swift 3.0 by default, if you are using a different version of ' \
|
148
|
-
'swift you can use a `.swift-version` file to set the version for ' \
|
149
|
-
"your Pod. For example to use Swift 2.3, run: \n" \
|
150
|
-
' `echo "2.3" > .swift-version`'
|
151
|
-
else
|
152
|
-
reasons.to_sentence
|
153
|
-
end
|
149
|
+
|
150
|
+
reasons.to_sentence
|
154
151
|
end
|
155
152
|
|
156
153
|
#-------------------------------------------------------------------------#
|
@@ -189,10 +186,14 @@ module Pod
|
|
189
186
|
#
|
190
187
|
attr_accessor :only_subspec
|
191
188
|
|
192
|
-
# @return [Bool] Whether the validator should validate all subspecs
|
189
|
+
# @return [Bool] Whether the validator should validate all subspecs.
|
193
190
|
#
|
194
191
|
attr_accessor :no_subspecs
|
195
192
|
|
193
|
+
# @return [Bool] Whether the validator should skip building and running tests.
|
194
|
+
#
|
195
|
+
attr_accessor :skip_tests
|
196
|
+
|
196
197
|
# @return [Bool] Whether frameworks should be used for the installation.
|
197
198
|
#
|
198
199
|
attr_accessor :use_frameworks
|
@@ -245,7 +246,7 @@ module Pod
|
|
245
246
|
# @return [Pathname] the temporary directory used by the linter.
|
246
247
|
#
|
247
248
|
def validation_dir
|
248
|
-
Pathname(Dir.
|
249
|
+
@validation_dir ||= Pathname(Dir.mktmpdir(['CocoaPods-Lint-', "-#{spec.name}"]))
|
249
250
|
end
|
250
251
|
|
251
252
|
# @return [String] the SWIFT_VERSION to use for validation.
|
@@ -290,6 +291,10 @@ module Pod
|
|
290
291
|
# Perform analysis for a given spec (or subspec)
|
291
292
|
#
|
292
293
|
def perform_extensive_analysis(spec)
|
294
|
+
if spec.test_specification?
|
295
|
+
error('spec', "Validating a test spec (`#{spec.name}`) is not supported.")
|
296
|
+
return false
|
297
|
+
end
|
293
298
|
validate_homepage(spec)
|
294
299
|
validate_screenshots(spec)
|
295
300
|
validate_social_media_url(spec)
|
@@ -304,9 +309,11 @@ module Pod
|
|
304
309
|
download_pod
|
305
310
|
check_file_patterns
|
306
311
|
install_pod
|
312
|
+
validate_dot_swift_version
|
307
313
|
add_app_project_import
|
308
314
|
validate_vendored_dynamic_frameworks
|
309
315
|
build_pod
|
316
|
+
test_pod unless skip_tests
|
310
317
|
ensure
|
311
318
|
tear_down_validation_environment
|
312
319
|
end
|
@@ -324,7 +331,7 @@ module Pod
|
|
324
331
|
# Recursively perform the extensive analysis on all subspecs
|
325
332
|
#
|
326
333
|
def perform_extensive_subspec_analysis(spec)
|
327
|
-
spec.subspecs.send(fail_fast ? :all? : :each) do |subspec|
|
334
|
+
spec.subspecs.reject(&:test_specification?).send(fail_fast ? :all? : :each) do |subspec|
|
328
335
|
@subspec_name = subspec.name
|
329
336
|
perform_extensive_analysis(subspec)
|
330
337
|
end
|
@@ -378,6 +385,17 @@ module Pod
|
|
378
385
|
validate_url(spec.documentation_url) if spec.documentation_url
|
379
386
|
end
|
380
387
|
|
388
|
+
def validate_dot_swift_version
|
389
|
+
if !used_swift_version.nil? && dot_swift_version.nil?
|
390
|
+
warning(:swift_version,
|
391
|
+
'The validator for Swift projects uses ' \
|
392
|
+
'Swift 3.0 by default, if you are using a different version of ' \
|
393
|
+
'swift you can use a `.swift-version` file to set the version for ' \
|
394
|
+
"your Pod. For example to use Swift 2.3, run: \n" \
|
395
|
+
' `echo "2.3" > .swift-version`')
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
381
399
|
def setup_validation_environment
|
382
400
|
validation_dir.rmtree if validation_dir.exist?
|
383
401
|
validation_dir.mkpath
|
@@ -401,10 +419,11 @@ module Pod
|
|
401
419
|
end
|
402
420
|
|
403
421
|
def download_pod
|
404
|
-
podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks)
|
422
|
+
podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks, consumer.spec.test_specs.map(&:name))
|
405
423
|
sandbox = Sandbox.new(config.sandbox_root)
|
406
424
|
@installer = Installer.new(sandbox, podfile)
|
407
425
|
@installer.use_default_plugins = false
|
426
|
+
@installer.has_dependencies = !spec.dependencies.empty?
|
408
427
|
%i(prepare resolve_dependencies download_dependencies).each { |m| @installer.send(m) }
|
409
428
|
@file_accessor = @installer.pod_targets.flat_map(&:file_accessors).find { |fa| fa.spec.name == consumer.spec.name }
|
410
429
|
end
|
@@ -480,15 +499,13 @@ module Pod
|
|
480
499
|
# for all available platforms with xcodebuild.
|
481
500
|
#
|
482
501
|
def install_pod
|
483
|
-
%i(
|
484
|
-
verify_no_static_framework_transitive_dependencies
|
485
|
-
verify_framework_usage generate_pods_project integrate_user_project
|
502
|
+
%i(validate_targets generate_pods_project integrate_user_project
|
486
503
|
perform_post_install_actions).each { |m| @installer.send(m) }
|
487
504
|
|
488
505
|
deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
|
489
506
|
@installer.aggregate_targets.each do |target|
|
490
507
|
target.pod_targets.each do |pod_target|
|
491
|
-
next unless native_target = pod_target.native_target
|
508
|
+
next unless (native_target = pod_target.native_target)
|
492
509
|
native_target.build_configuration_list.build_configurations.each do |build_configuration|
|
493
510
|
(build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
|
494
511
|
build_configuration.build_settings['SWIFT_VERSION'] = swift_version if pod_target.uses_swift?
|
@@ -529,28 +546,38 @@ module Pod
|
|
529
546
|
UI.warn "Skipping compilation with `xcodebuild' because it can't be found.\n".yellow
|
530
547
|
else
|
531
548
|
UI.message "\nBuilding with xcodebuild.\n".yellow do
|
532
|
-
|
549
|
+
scheme = if skip_import_validation?
|
550
|
+
@installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }.label
|
551
|
+
else
|
552
|
+
'App'
|
553
|
+
end
|
554
|
+
output = xcodebuild('build', scheme, 'Release')
|
533
555
|
UI.puts output
|
534
556
|
parsed_output = parse_xcodebuild_output(output)
|
535
|
-
parsed_output
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
# it's safe for us to do the same.
|
540
|
-
#
|
541
|
-
# For more details see https://github.com/CocoaPods/CocoaPods/issues/2394#issuecomment-56658587
|
542
|
-
#
|
543
|
-
if message.include?("'InputFile' should have")
|
544
|
-
next
|
545
|
-
end
|
557
|
+
translate_output_to_linter_messages(parsed_output)
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
546
561
|
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
562
|
+
# Builds and runs all test sources associated with the current specification being validated.
|
563
|
+
#
|
564
|
+
# @note Xcode warnings are treaded as notes because the spec maintainer
|
565
|
+
# might not be the author of the library
|
566
|
+
#
|
567
|
+
# @return [void]
|
568
|
+
#
|
569
|
+
def test_pod
|
570
|
+
if !xcodebuild_available?
|
571
|
+
UI.warn "Skipping test validation with `xcodebuild' because it can't be found.\n".yellow
|
572
|
+
else
|
573
|
+
UI.message "\nTesting with xcodebuild.\n".yellow do
|
574
|
+
pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }
|
575
|
+
consumer.spec.test_specs.each do |test_spec|
|
576
|
+
scheme = pod_target.native_target_for_spec(test_spec)
|
577
|
+
output = xcodebuild('test', scheme, 'Debug')
|
578
|
+
UI.puts output
|
579
|
+
parsed_output = parse_xcodebuild_output(output)
|
580
|
+
translate_output_to_linter_messages(parsed_output)
|
554
581
|
end
|
555
582
|
end
|
556
583
|
end
|
@@ -670,6 +697,29 @@ module Pod
|
|
670
697
|
add_result(:note, *args)
|
671
698
|
end
|
672
699
|
|
700
|
+
def translate_output_to_linter_messages(parsed_output)
|
701
|
+
parsed_output.each do |message|
|
702
|
+
# Checking the error for `InputFile` is to work around an Xcode
|
703
|
+
# issue where linting would fail even though `xcodebuild` actually
|
704
|
+
# succeeds. Xcode.app also doesn't fail when this issue occurs, so
|
705
|
+
# it's safe for us to do the same.
|
706
|
+
#
|
707
|
+
# For more details see https://github.com/CocoaPods/CocoaPods/issues/2394#issuecomment-56658587
|
708
|
+
#
|
709
|
+
if message.include?("'InputFile' should have")
|
710
|
+
next
|
711
|
+
end
|
712
|
+
|
713
|
+
if message =~ /\S+:\d+:\d+: error:/
|
714
|
+
error('xcodebuild', message)
|
715
|
+
elsif message =~ /\S+:\d+:\d+: warning:/
|
716
|
+
warning('xcodebuild', message)
|
717
|
+
else
|
718
|
+
note('xcodebuild', message)
|
719
|
+
end
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
673
723
|
def shares_pod_target_xcscheme?(pod_target)
|
674
724
|
Pathname.new(@installer.pods_project.path + pod_target.label).exist?
|
675
725
|
end
|
@@ -719,13 +769,16 @@ module Pod
|
|
719
769
|
# @param [Bool] use_frameworks
|
720
770
|
# whether frameworks should be used for the installation
|
721
771
|
#
|
772
|
+
# @param [Array<String>] test_spec_names
|
773
|
+
# the test spec names to include in the podfile.
|
774
|
+
#
|
722
775
|
# @return [Podfile] a podfile that requires the specification on the
|
723
776
|
# current platform.
|
724
777
|
#
|
725
778
|
# @note The generated podfile takes into account whether the linter is
|
726
779
|
# in local mode.
|
727
780
|
#
|
728
|
-
def podfile_from_spec(platform_name, deployment_target, use_frameworks = true)
|
781
|
+
def podfile_from_spec(platform_name, deployment_target, use_frameworks = true, test_spec_names = [])
|
729
782
|
name = subspec_name || spec.name
|
730
783
|
podspec = file.realpath
|
731
784
|
local = local?
|
@@ -741,6 +794,13 @@ module Pod
|
|
741
794
|
else
|
742
795
|
pod name, :podspec => podspec.to_s
|
743
796
|
end
|
797
|
+
test_spec_names.each do |test_spec_name|
|
798
|
+
if local
|
799
|
+
pod test_spec_name, :path => podspec.dirname.to_s
|
800
|
+
else
|
801
|
+
pod test_spec_name, :podspec => podspec.to_s
|
802
|
+
end
|
803
|
+
end
|
744
804
|
end
|
745
805
|
end
|
746
806
|
end
|
@@ -771,14 +831,9 @@ module Pod
|
|
771
831
|
# @return [String] Executes xcodebuild in the current working directory and
|
772
832
|
# returns its output (both STDOUT and STDERR).
|
773
833
|
#
|
774
|
-
def xcodebuild
|
834
|
+
def xcodebuild(action, scheme, configuration)
|
775
835
|
require 'fourflusher'
|
776
|
-
|
777
|
-
@installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }.label
|
778
|
-
else
|
779
|
-
'App'
|
780
|
-
end
|
781
|
-
command = %W(clean build -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration Release)
|
836
|
+
command = %W(clean #{action} -workspace #{File.join(validation_dir, 'App.xcworkspace')} -scheme #{scheme} -configuration #{configuration})
|
782
837
|
case consumer.platform_name
|
783
838
|
when :osx, :macos
|
784
839
|
command += %w(CODE_SIGN_IDENTITY=)
|