cocoapods 1.2.1 → 1.3.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.
@@ -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
@@ -254,6 +254,11 @@ module Pod
254
254
  end
255
255
  end
256
256
  settings['GCC_PREPROCESSOR_DEFINITIONS'] = definitions
257
+
258
+ if type == :debug
259
+ settings['SWIFT_ACTIVE_COMPILATION_CONDITIONS'] = 'DEBUG'
260
+ end
261
+
257
262
  build_configuration
258
263
  end
259
264
 
@@ -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
 
@@ -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<PBXTarget>] the resource bundle targets belonging
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
- return true
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
- return false
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
- return podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
338
+ podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
272
339
  end
273
340
  end
274
341
 
@@ -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
- if dot_swift_version.nil?
146
- reasons.to_sentence + ".\n[!] The validator for Swift projects uses " \
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.tmpdir) + 'CocoaPods/Lint'
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(verify_no_duplicate_framework_and_library_names
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
- output = xcodebuild
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.each do |message|
536
- # Checking the error for `InputFile` is to work around an Xcode
537
- # issue where linting would fail even though `xcodebuild` actually
538
- # succeeds. Xcode.app also doesn't fail when this issue occurs, so
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
- if message =~ /\S+:\d+:\d+: error:/
548
- error('xcodebuild', message)
549
- elsif message =~ /\S+:\d+:\d+: warning:/
550
- warning('xcodebuild', message)
551
- else
552
- note('xcodebuild', message)
553
- end
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
- scheme = if skip_import_validation?
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=)