xcocoapods 1.5.3

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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6303 -0
  3. data/LICENSE +28 -0
  4. data/README.md +80 -0
  5. data/bin/pod +56 -0
  6. data/bin/sandbox-pod +168 -0
  7. data/lib/cocoapods.rb +73 -0
  8. data/lib/cocoapods/command.rb +175 -0
  9. data/lib/cocoapods/command/cache.rb +28 -0
  10. data/lib/cocoapods/command/cache/clean.rb +90 -0
  11. data/lib/cocoapods/command/cache/list.rb +69 -0
  12. data/lib/cocoapods/command/env.rb +66 -0
  13. data/lib/cocoapods/command/init.rb +128 -0
  14. data/lib/cocoapods/command/install.rb +45 -0
  15. data/lib/cocoapods/command/ipc.rb +19 -0
  16. data/lib/cocoapods/command/ipc/list.rb +40 -0
  17. data/lib/cocoapods/command/ipc/podfile.rb +31 -0
  18. data/lib/cocoapods/command/ipc/podfile_json.rb +30 -0
  19. data/lib/cocoapods/command/ipc/repl.rb +51 -0
  20. data/lib/cocoapods/command/ipc/spec.rb +29 -0
  21. data/lib/cocoapods/command/ipc/update_search_index.rb +24 -0
  22. data/lib/cocoapods/command/lib.rb +11 -0
  23. data/lib/cocoapods/command/lib/create.rb +105 -0
  24. data/lib/cocoapods/command/lib/lint.rb +121 -0
  25. data/lib/cocoapods/command/list.rb +39 -0
  26. data/lib/cocoapods/command/options/project_directory.rb +36 -0
  27. data/lib/cocoapods/command/options/repo_update.rb +34 -0
  28. data/lib/cocoapods/command/outdated.rb +140 -0
  29. data/lib/cocoapods/command/repo.rb +29 -0
  30. data/lib/cocoapods/command/repo/add.rb +103 -0
  31. data/lib/cocoapods/command/repo/lint.rb +82 -0
  32. data/lib/cocoapods/command/repo/list.rb +93 -0
  33. data/lib/cocoapods/command/repo/push.rb +281 -0
  34. data/lib/cocoapods/command/repo/remove.rb +36 -0
  35. data/lib/cocoapods/command/repo/update.rb +28 -0
  36. data/lib/cocoapods/command/setup.rb +103 -0
  37. data/lib/cocoapods/command/spec.rb +112 -0
  38. data/lib/cocoapods/command/spec/cat.rb +51 -0
  39. data/lib/cocoapods/command/spec/create.rb +283 -0
  40. data/lib/cocoapods/command/spec/edit.rb +87 -0
  41. data/lib/cocoapods/command/spec/env_spec.rb +53 -0
  42. data/lib/cocoapods/command/spec/lint.rb +137 -0
  43. data/lib/cocoapods/command/spec/which.rb +43 -0
  44. data/lib/cocoapods/command/update.rb +101 -0
  45. data/lib/cocoapods/config.rb +347 -0
  46. data/lib/cocoapods/core_overrides.rb +1 -0
  47. data/lib/cocoapods/downloader.rb +190 -0
  48. data/lib/cocoapods/downloader/cache.rb +233 -0
  49. data/lib/cocoapods/downloader/request.rb +86 -0
  50. data/lib/cocoapods/downloader/response.rb +16 -0
  51. data/lib/cocoapods/executable.rb +222 -0
  52. data/lib/cocoapods/external_sources.rb +57 -0
  53. data/lib/cocoapods/external_sources/abstract_external_source.rb +205 -0
  54. data/lib/cocoapods/external_sources/downloader_source.rb +30 -0
  55. data/lib/cocoapods/external_sources/path_source.rb +55 -0
  56. data/lib/cocoapods/external_sources/podspec_source.rb +54 -0
  57. data/lib/cocoapods/gem_version.rb +5 -0
  58. data/lib/cocoapods/generator/acknowledgements.rb +107 -0
  59. data/lib/cocoapods/generator/acknowledgements/markdown.rb +44 -0
  60. data/lib/cocoapods/generator/acknowledgements/plist.rb +94 -0
  61. data/lib/cocoapods/generator/app_target_helper.rb +244 -0
  62. data/lib/cocoapods/generator/bridge_support.rb +22 -0
  63. data/lib/cocoapods/generator/constant.rb +19 -0
  64. data/lib/cocoapods/generator/copy_resources_script.rb +230 -0
  65. data/lib/cocoapods/generator/dummy_source.rb +31 -0
  66. data/lib/cocoapods/generator/embed_frameworks_script.rb +215 -0
  67. data/lib/cocoapods/generator/header.rb +103 -0
  68. data/lib/cocoapods/generator/info_plist_file.rb +116 -0
  69. data/lib/cocoapods/generator/module_map.rb +99 -0
  70. data/lib/cocoapods/generator/prefix_header.rb +60 -0
  71. data/lib/cocoapods/generator/umbrella_header.rb +46 -0
  72. data/lib/cocoapods/hooks_manager.rb +132 -0
  73. data/lib/cocoapods/installer.rb +703 -0
  74. data/lib/cocoapods/installer/analyzer.rb +972 -0
  75. data/lib/cocoapods/installer/analyzer/analysis_result.rb +87 -0
  76. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +98 -0
  77. data/lib/cocoapods/installer/analyzer/pod_variant.rb +67 -0
  78. data/lib/cocoapods/installer/analyzer/pod_variant_set.rb +157 -0
  79. data/lib/cocoapods/installer/analyzer/podfile_dependency_cache.rb +54 -0
  80. data/lib/cocoapods/installer/analyzer/sandbox_analyzer.rb +240 -0
  81. data/lib/cocoapods/installer/analyzer/specs_state.rb +84 -0
  82. data/lib/cocoapods/installer/analyzer/target_inspection_result.rb +53 -0
  83. data/lib/cocoapods/installer/analyzer/target_inspector.rb +260 -0
  84. data/lib/cocoapods/installer/installation_options.rb +158 -0
  85. data/lib/cocoapods/installer/pod_source_installer.rb +202 -0
  86. data/lib/cocoapods/installer/pod_source_preparer.rb +77 -0
  87. data/lib/cocoapods/installer/podfile_validator.rb +139 -0
  88. data/lib/cocoapods/installer/post_install_hooks_context.rb +132 -0
  89. data/lib/cocoapods/installer/pre_install_hooks_context.rb +51 -0
  90. data/lib/cocoapods/installer/source_provider_hooks_context.rb +34 -0
  91. data/lib/cocoapods/installer/user_project_integrator.rb +250 -0
  92. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +463 -0
  93. data/lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +146 -0
  94. data/lib/cocoapods/installer/xcode.rb +8 -0
  95. data/lib/cocoapods/installer/xcode/pods_project_generator.rb +416 -0
  96. data/lib/cocoapods/installer/xcode/pods_project_generator/aggregate_target_installer.rb +181 -0
  97. data/lib/cocoapods/installer/xcode/pods_project_generator/app_host_installer.rb +84 -0
  98. data/lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb +334 -0
  99. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +777 -0
  100. data/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_integrator.rb +116 -0
  101. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installation_result.rb +86 -0
  102. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb +256 -0
  103. data/lib/cocoapods/installer/xcode/pods_project_generator/target_installer_helper.rb +68 -0
  104. data/lib/cocoapods/installer/xcode/target_validator.rb +147 -0
  105. data/lib/cocoapods/open-uri.rb +33 -0
  106. data/lib/cocoapods/project.rb +414 -0
  107. data/lib/cocoapods/resolver.rb +585 -0
  108. data/lib/cocoapods/resolver/lazy_specification.rb +79 -0
  109. data/lib/cocoapods/sandbox.rb +404 -0
  110. data/lib/cocoapods/sandbox/file_accessor.rb +444 -0
  111. data/lib/cocoapods/sandbox/headers_store.rb +146 -0
  112. data/lib/cocoapods/sandbox/path_list.rb +220 -0
  113. data/lib/cocoapods/sandbox/pod_dir_cleaner.rb +85 -0
  114. data/lib/cocoapods/sandbox/podspec_finder.rb +23 -0
  115. data/lib/cocoapods/sources_manager.rb +157 -0
  116. data/lib/cocoapods/target.rb +261 -0
  117. data/lib/cocoapods/target/aggregate_target.rb +338 -0
  118. data/lib/cocoapods/target/build_settings.rb +1075 -0
  119. data/lib/cocoapods/target/pod_target.rb +559 -0
  120. data/lib/cocoapods/user_interface.rb +459 -0
  121. data/lib/cocoapods/user_interface/error_report.rb +187 -0
  122. data/lib/cocoapods/user_interface/inspector_reporter.rb +109 -0
  123. data/lib/cocoapods/validator.rb +981 -0
  124. metadata +533 -0
@@ -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
@@ -0,0 +1,222 @@
1
+ module Pod
2
+ # Module which provides support for running executables.
3
+ #
4
+ # In a class it can be used as:
5
+ #
6
+ # extend Executable
7
+ # executable :git
8
+ #
9
+ # This will create two methods `git` and `git!` both accept a command but
10
+ # the later will raise on non successful executions. The methods return the
11
+ # output of the command.
12
+ #
13
+ module Executable
14
+ # Creates the methods for the executable with the given name.
15
+ #
16
+ # @param [Symbol] name
17
+ # the name of the executable.
18
+ #
19
+ # @return [void]
20
+ #
21
+ def executable(name)
22
+ define_method(name) do |*command|
23
+ Executable.execute_command(name, Array(command).flatten, false)
24
+ end
25
+
26
+ define_method(name.to_s + '!') do |*command|
27
+ Executable.execute_command(name, Array(command).flatten, true)
28
+ end
29
+ end
30
+
31
+ # Executes the given command displaying it if in verbose mode.
32
+ #
33
+ # @param [String] executable
34
+ # The binary to use.
35
+ #
36
+ # @param [Array<#to_s>] command
37
+ # The command to send to the binary.
38
+ #
39
+ # @param [Bool] raise_on_failure
40
+ # Whether it should raise if the command fails.
41
+ #
42
+ # @raise If the executable could not be located.
43
+ #
44
+ # @raise If the command fails and the `raise_on_failure` is set to true.
45
+ #
46
+ # @return [String] the output of the command (STDOUT and STDERR).
47
+ #
48
+ def self.execute_command(executable, command, raise_on_failure = true)
49
+ bin = which!(executable)
50
+
51
+ command = command.map(&:to_s)
52
+ full_command = "#{bin} #{command.join(' ')}"
53
+
54
+ if Config.instance.verbose?
55
+ UI.message("$ #{full_command}")
56
+ stdout = Indenter.new(STDOUT)
57
+ stderr = Indenter.new(STDERR)
58
+ else
59
+ stdout = Indenter.new
60
+ stderr = Indenter.new
61
+ end
62
+
63
+ status = popen3(bin, command, stdout, stderr)
64
+ stdout = stdout.join
65
+ stderr = stderr.join
66
+ output = stdout + stderr
67
+ unless status.success?
68
+ if raise_on_failure
69
+ raise Informative, "#{full_command}\n\n#{output}"
70
+ else
71
+ UI.message("[!] Failed: #{full_command}".red)
72
+ end
73
+ end
74
+
75
+ output
76
+ end
77
+
78
+ # Returns the absolute path to the binary with the given name on the current
79
+ # `PATH`, or `nil` if none is found.
80
+ #
81
+ # @param [String] program
82
+ # The name of the program being searched for.
83
+ #
84
+ # @return [String,Nil] The absolute path to the given program, or `nil` if
85
+ # it wasn't found in the current `PATH`.
86
+ #
87
+ def self.which(program)
88
+ program = program.to_s
89
+ paths = ENV.fetch('PATH') { '' }.split(File::PATH_SEPARATOR)
90
+ paths.unshift('./')
91
+ paths.uniq!
92
+ paths.each do |path|
93
+ bin = File.expand_path(program, path)
94
+ if File.file?(bin) && File.executable?(bin)
95
+ return bin
96
+ end
97
+ end
98
+ nil
99
+ end
100
+
101
+ # Returns the absolute path to the binary with the given name on the current
102
+ # `PATH`, or raises if none is found.
103
+ #
104
+ # @param [String] program
105
+ # The name of the program being searched for.
106
+ #
107
+ # @return [String] The absolute path to the given program.
108
+ #
109
+ def self.which!(program)
110
+ which(program).tap do |bin|
111
+ raise Informative, "Unable to locate the executable `#{program}`" unless bin
112
+ end
113
+ end
114
+
115
+ # Runs the given command, capturing the desired output.
116
+ #
117
+ # @param [String] bin
118
+ # The binary to use.
119
+ #
120
+ # @param [Array<#to_s>] command
121
+ # The command to send to the binary.
122
+ #
123
+ # @param [Symbol] capture
124
+ # Whether it should raise if the command fails.
125
+ #
126
+ # @raise If the executable could not be located.
127
+ #
128
+ # @return [(String, Process::Status)]
129
+ # The desired captured output from the command, and the status from
130
+ # running the command.
131
+ #
132
+ def self.capture_command(executable, command, capture: :merge)
133
+ bin = which!(executable)
134
+
135
+ require 'open3'
136
+ command = command.map(&:to_s)
137
+ case capture
138
+ when :merge then Open3.capture2e(bin, *command)
139
+ when :both then Open3.capture3(bin, *command)
140
+ when :out then Open3.capture3(bin, *command).values_at(0, -1)
141
+ when :err then Open3.capture3(bin, *command).drop(1)
142
+ when :none then Open3.capture3(bin, *command).last
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ def self.popen3(bin, command, stdout, stderr)
149
+ require 'open3'
150
+ Open3.popen3(bin, *command) do |i, o, e, t|
151
+ reader(o, stdout)
152
+ reader(e, stderr)
153
+ i.close
154
+
155
+ status = t.value
156
+
157
+ o.flush
158
+ e.flush
159
+ sleep(0.01)
160
+
161
+ status
162
+ end
163
+ end
164
+
165
+ def self.reader(input, output)
166
+ Thread.new do
167
+ buf = ''
168
+ begin
169
+ loop do
170
+ buf << input.readpartial(4096)
171
+ loop do
172
+ string, separator, buf = buf.partition(/[\r\n]/)
173
+ if separator.empty?
174
+ buf = string
175
+ break
176
+ end
177
+ output << (string << separator)
178
+ end
179
+ end
180
+ rescue EOFError
181
+ output << (buf << $/) unless buf.empty?
182
+ end
183
+ end
184
+ end
185
+
186
+ #-------------------------------------------------------------------------#
187
+
188
+ # Helper class that allows to write to an {IO} instance taking into account
189
+ # the UI indentation level.
190
+ #
191
+ class Indenter < ::Array
192
+ # @return [Fixnum] The indentation level of the UI.
193
+ #
194
+ attr_reader :indent
195
+
196
+ # @return [IO] the {IO} to which the output should be printed.
197
+ #
198
+ attr_reader :io
199
+
200
+ # Init a new Indenter
201
+ #
202
+ # @param [IO] io @see io
203
+ #
204
+ def initialize(io = nil)
205
+ @io = io
206
+ @indent = ' ' * UI.indentation_level
207
+ end
208
+
209
+ # Stores a portion of the output and prints it to the {IO} instance.
210
+ #
211
+ # @param [String] value
212
+ # the output to print.
213
+ #
214
+ # @return [void]
215
+ #
216
+ def <<(value)
217
+ super
218
+ io << "#{indent}#{value}" if io
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,57 @@
1
+ require 'cocoapods/external_sources/abstract_external_source'
2
+ require 'cocoapods/external_sources/downloader_source'
3
+ require 'cocoapods/external_sources/path_source'
4
+ require 'cocoapods/external_sources/podspec_source'
5
+
6
+ module Pod
7
+ # Provides support for initializing the correct concrete class of an external
8
+ # source.
9
+ #
10
+ module ExternalSources
11
+ # Instantiate a matching {AbstractExternalSource} for a given dependency.
12
+ #
13
+ # @param [Dependency] dependency
14
+ # the dependency
15
+ #
16
+ # @param [String] podfile_path
17
+ # @see AbstractExternalSource#podfile_path
18
+ #
19
+ # @param [Boolean] can_cache
20
+ # @see AbstractExternalSource#can_cache
21
+ #
22
+ # @return [AbstractExternalSource] an initialized instance of the concrete
23
+ # external source class associated with the option specified in the
24
+ # hash.
25
+ #
26
+ def self.from_dependency(dependency, podfile_path, can_cache)
27
+ from_params(dependency.external_source, dependency, podfile_path, can_cache)
28
+ end
29
+
30
+ def self.from_params(params, dependency, podfile_path, can_cache)
31
+ name = dependency.root_name
32
+ if klass = concrete_class_from_params(params)
33
+ klass.new(name, params, podfile_path, can_cache)
34
+ else
35
+ msg = "Unknown external source parameters for `#{name}`: `#{params}`"
36
+ raise Informative, msg
37
+ end
38
+ end
39
+
40
+ # Get the class to represent the defined source type of a dependency
41
+ #
42
+ # @param [Array<Symbol>] params
43
+ # the source params of the dependency
44
+ #
45
+ # @return [Class]
46
+ #
47
+ def self.concrete_class_from_params(params)
48
+ if params.key?(:podspec)
49
+ PodspecSource
50
+ elsif params.key?(:path)
51
+ PathSource
52
+ elsif Downloader.strategy_from_options(params)
53
+ DownloaderSource
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,205 @@
1
+ module Pod
2
+ module ExternalSources
3
+ # Abstract class that defines the common behaviour of external sources.
4
+ #
5
+ class AbstractExternalSource
6
+ # @return [String] the name of the Pod described by this external source.
7
+ #
8
+ attr_reader :name
9
+
10
+ # @return [Hash{Symbol => String}] the hash representation of the
11
+ # external source.
12
+ #
13
+ attr_reader :params
14
+
15
+ # @return [String] the path where the podfile is defined to resolve
16
+ # relative paths.
17
+ #
18
+ attr_reader :podfile_path
19
+
20
+ # @return [Boolean] Whether the source is allowed to touch the cache.
21
+ #
22
+ attr_reader :can_cache
23
+ alias_method :can_cache?, :can_cache
24
+
25
+ # Initialize a new instance
26
+ #
27
+ # @param [String] name @see #name
28
+ # @param [Hash] params @see #params
29
+ # @param [String] podfile_path @see #podfile_path
30
+ # @param [Boolean] can_cache @see #can_cache
31
+ #
32
+ def initialize(name, params, podfile_path, can_cache = true)
33
+ @name = name
34
+ @params = params
35
+ @podfile_path = podfile_path
36
+ @can_cache = can_cache
37
+ end
38
+
39
+ # @return [Bool] whether an external source source is equal to another
40
+ # according to the {#name} and to the {#params}.
41
+ #
42
+ def ==(other)
43
+ return false if other.nil?
44
+ name == other.name && params == other.params
45
+ end
46
+
47
+ public
48
+
49
+ # @!group Subclasses hooks
50
+
51
+ # Fetches the external source from the remote according to the params.
52
+ #
53
+ # @param [Sandbox] _sandbox
54
+ # the sandbox where the specification should be stored.
55
+ #
56
+ # @return [void]
57
+ #
58
+ def fetch(_sandbox)
59
+ raise 'Abstract method'
60
+ end
61
+
62
+ # @return [String] a string representation of the source suitable for UI.
63
+ #
64
+ def description
65
+ raise 'Abstract method'
66
+ end
67
+
68
+ protected
69
+
70
+ # Return the normalized path for a podspec for a relative declared path.
71
+ #
72
+ # @param [String] declared_path
73
+ # The path declared in the podfile.
74
+ #
75
+ # @return [String] The uri of the podspec appending the name of the file
76
+ # and expanding it if necessary.
77
+ #
78
+ # @note If the declared path is expanded only if the represents a path
79
+ # relative to the file system.
80
+ #
81
+ def normalized_podspec_path(declared_path)
82
+ extension = File.extname(declared_path)
83
+ if extension == '.podspec' || extension == '.json'
84
+ path_with_ext = declared_path
85
+ else
86
+ path_with_ext = "#{declared_path}/#{name}.podspec"
87
+ end
88
+ podfile_dir = File.dirname(podfile_path || '')
89
+ File.expand_path(path_with_ext, podfile_dir)
90
+ end
91
+
92
+ private
93
+
94
+ # @! Subclasses helpers
95
+
96
+ # Pre-downloads a Pod passing the options to the downloader and informing
97
+ # the sandbox.
98
+ #
99
+ # @param [Sandbox] sandbox
100
+ # The sandbox where the Pod should be downloaded.
101
+ #
102
+ # @note To prevent a double download of the repository the pod is
103
+ # marked as pre-downloaded indicating to the installer that only
104
+ # clean operations are needed.
105
+ #
106
+ # @todo The downloader configuration is the same of the
107
+ # #{PodSourceInstaller} and it needs to be kept in sync.
108
+ #
109
+ # @return [void]
110
+ #
111
+ def pre_download(sandbox)
112
+ title = "Pre-downloading: `#{name}` #{description}"
113
+ UI.titled_section(title, :verbose_prefix => '-> ') do
114
+ target = sandbox.pod_dir(name)
115
+ begin
116
+ download_result = Downloader.download(download_request, target, :can_cache => can_cache)
117
+ rescue Pod::DSLError => e
118
+ raise Informative, "Failed to load '#{name}' podspec: #{e.message}"
119
+ rescue => e
120
+ raise Informative, "Failed to download '#{name}': #{e.message}"
121
+ end
122
+
123
+ spec = download_result.spec
124
+ raise Informative, "Unable to find a specification for '#{name}'." unless spec
125
+
126
+ # since the podspec might be cleaned, we want the checksum to refer
127
+ # to the json in the sandbox
128
+ spec.defined_in_file = nil
129
+
130
+ store_podspec(sandbox, spec)
131
+ sandbox.store_pre_downloaded_pod(name)
132
+ sandbox.store_checkout_source(name, download_result.checkout_options)
133
+ end
134
+ end
135
+
136
+ def download_request
137
+ Downloader::Request.new(
138
+ :name => name,
139
+ :params => params,
140
+ )
141
+ end
142
+
143
+ # Stores the podspec in the sandbox and marks it as from an external
144
+ # source.
145
+ #
146
+ # @param [Sandbox] sandbox
147
+ # The sandbox where the specification should be stored.
148
+ #
149
+ # @param [Pathname, String, Specification] spec
150
+ # The path of the specification or its contents.
151
+ #
152
+ # @note All the concrete implementations of #{fetch} should invoke this
153
+ # method.
154
+ #
155
+ # @note The sandbox ensures that the podspec exists and that the names
156
+ # match.
157
+ #
158
+ # @return [void]
159
+ #
160
+ def store_podspec(sandbox, spec, json = false)
161
+ begin
162
+ spec = case spec
163
+ when Pathname
164
+ Specification.from_file(spec)
165
+ when String
166
+ path = "#{name}.podspec"
167
+ path << '.json' if json
168
+ Specification.from_string(spec, path).tap { |s| s.defined_in_file = nil }
169
+ when Specification
170
+ spec.dup
171
+ else
172
+ raise "Unknown spec type: #{spec}"
173
+ end
174
+ rescue Pod::DSLError => e
175
+ raise Informative, "Failed to load '#{name}' podspec: #{e.message}"
176
+ end
177
+
178
+ validate_podspec(spec)
179
+ sandbox.store_podspec(name, spec, true, true)
180
+ end
181
+
182
+ def validate_podspec(podspec)
183
+ defined_in_file = podspec.defined_in_file
184
+ podspec.defined_in_file = nil
185
+
186
+ validator = validator_for_podspec(podspec)
187
+ validator.quick = true
188
+ validator.allow_warnings = true
189
+ validator.ignore_public_only_results = true
190
+ Config.instance.with_changes(:silent => true) do
191
+ validator.validate
192
+ end
193
+ unless validator.validated?
194
+ raise Informative, "The `#{name}` pod failed to validate due to #{validator.failure_reason}:\n#{validator.results_message}"
195
+ end
196
+ ensure
197
+ podspec.defined_in_file = defined_in_file
198
+ end
199
+
200
+ def validator_for_podspec(podspec)
201
+ Validator.new(podspec, [], [])
202
+ end
203
+ end
204
+ end
205
+ end