cocoapods 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +18 -1
- data/lib/cocoapods.rb +1 -1
- data/lib/cocoapods/command.rb +5 -1
- data/lib/cocoapods/command/error_report.rb +6 -6
- data/lib/cocoapods/command/linter.rb +292 -0
- data/lib/cocoapods/command/push.rb +4 -3
- data/lib/cocoapods/command/repo.rb +69 -2
- data/lib/cocoapods/command/spec.rb +70 -335
- data/lib/cocoapods/config.rb +0 -10
- data/lib/cocoapods/dependency.rb +3 -2
- data/lib/cocoapods/downloader/subversion.rb +8 -2
- data/lib/cocoapods/file_list.rb +1 -1
- data/lib/cocoapods/installer/target_installer.rb +10 -6
- data/lib/cocoapods/installer/user_project_integrator.rb +4 -1
- data/lib/cocoapods/local_pod.rb +42 -2
- data/lib/cocoapods/sandbox.rb +51 -35
- data/lib/cocoapods/specification.rb +3 -0
- metadata +7 -3
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,21 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.11.0
|
2
|
+
|
3
|
+
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.10.0...master)
|
4
|
+
|
5
|
+
###### Enhancements
|
6
|
+
|
7
|
+
- Added support for public headers. [#440]
|
8
|
+
- Added `pod repo lint`. [#423]
|
9
|
+
- Improved support for `:head` option and svn repositories.
|
10
|
+
- When integrating Pods with a project without "Frameworks" group in root of the project, raise an informative message. [#431](https://github.com/CocoaPods/CocoaPods/pull/431)
|
11
|
+
- Dropped support for legacy `config.ios?` and `config.osx?`
|
12
|
+
|
13
|
+
###### Bug fixes
|
14
|
+
|
15
|
+
- Version message now correctly terminates with a 0 exit status.
|
16
|
+
- Resolved an issue that lead to git error messages in the error report.
|
17
|
+
|
18
|
+
## 0.10.0
|
2
19
|
|
3
20
|
[CocoaPods](http://git.io/4i75YA)
|
4
21
|
|
data/lib/cocoapods.rb
CHANGED
data/lib/cocoapods/command.rb
CHANGED
@@ -5,6 +5,7 @@ module Pod
|
|
5
5
|
autoload :ErrorReport, 'cocoapods/command/error_report'
|
6
6
|
autoload :Install, 'cocoapods/command/install'
|
7
7
|
autoload :List, 'cocoapods/command/list'
|
8
|
+
autoload :Linter, 'cocoapods/command/linter'
|
8
9
|
autoload :Presenter, 'cocoapods/command/presenter'
|
9
10
|
autoload :Push, 'cocoapods/command/push'
|
10
11
|
autoload :Repo, 'cocoapods/command/repo'
|
@@ -86,7 +87,10 @@ module Pod
|
|
86
87
|
|
87
88
|
def self.parse(*argv)
|
88
89
|
argv = ARGV.new(argv)
|
89
|
-
|
90
|
+
if argv.option('--version')
|
91
|
+
puts VERSION
|
92
|
+
exit!(0)
|
93
|
+
end
|
90
94
|
|
91
95
|
show_help = argv.option('--help')
|
92
96
|
Config.instance.silent = argv.option('--silent')
|
@@ -10,7 +10,7 @@ module Pod
|
|
10
10
|
def report(error)
|
11
11
|
return <<-EOS
|
12
12
|
|
13
|
-
#{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
|
13
|
+
#{'――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――'.reversed}
|
14
14
|
|
15
15
|
### Report
|
16
16
|
|
@@ -59,14 +59,14 @@ EOS
|
|
59
59
|
|
60
60
|
def markdown_podfile
|
61
61
|
return '' unless Config.instance.project_podfile && Config.instance.project_podfile.exist?
|
62
|
-
<<-EOS
|
62
|
+
<<-EOS
|
63
63
|
|
64
64
|
### Podfile
|
65
65
|
|
66
66
|
```ruby
|
67
|
-
#{Config.instance.project_podfile.read.strip}
|
67
|
+
#{Config.instance.project_podfile.read.strip}
|
68
68
|
```
|
69
|
-
EOS
|
69
|
+
EOS
|
70
70
|
end
|
71
71
|
|
72
72
|
def error_from_podfile(error)
|
@@ -89,8 +89,8 @@ EOS
|
|
89
89
|
Pod::Source.all.map do |source|
|
90
90
|
repo = source.repo
|
91
91
|
Dir.chdir(repo) do
|
92
|
-
url = `git config --get remote.origin.url`.strip
|
93
|
-
sha = `git rev-parse HEAD`.strip
|
92
|
+
url = `git config --get remote.origin.url 2>&1`.strip
|
93
|
+
sha = `git rev-parse HEAD 2>&1`.strip
|
94
94
|
"#{repo.basename} - #{url} @ #{sha}"
|
95
95
|
end
|
96
96
|
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Linter
|
4
|
+
include Config::Mixin
|
5
|
+
|
6
|
+
# TODO: Add check to ensure that attributes inherited by subspecs are not duplicated ?
|
7
|
+
|
8
|
+
attr_accessor :quick, :no_clean, :repo_path
|
9
|
+
attr_reader :spec, :file
|
10
|
+
attr_reader :errors, :warnings, :notes
|
11
|
+
|
12
|
+
def initialize(podspec)
|
13
|
+
@file = podspec
|
14
|
+
end
|
15
|
+
|
16
|
+
def spec_name
|
17
|
+
name = file.basename('.*').to_s
|
18
|
+
if @spec
|
19
|
+
name << " (#{spec.version})"
|
20
|
+
elsif @repo_path
|
21
|
+
name << " (#{file.dirname.basename})"
|
22
|
+
end
|
23
|
+
name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Takes an array of podspec files and lints them all
|
27
|
+
#
|
28
|
+
# It returns true if the spec passed validation
|
29
|
+
#
|
30
|
+
def lint
|
31
|
+
@errors, @warnings, @notes = [], [], []
|
32
|
+
@platform_errors, @platform_warnings, @platform_notes = {}, {}, {}
|
33
|
+
|
34
|
+
if !deprecation_errors.empty?
|
35
|
+
@errors = deprecation_errors
|
36
|
+
@errors << "#{spec_name} [!] Fatal errors found skipping the rest of the validation"
|
37
|
+
else
|
38
|
+
@spec = Specification.from_file(file)
|
39
|
+
platforms = spec.available_platforms
|
40
|
+
|
41
|
+
if @repo_path
|
42
|
+
expected_path = "#{@spec.name}/#{@spec.version}/#{@spec.name}.podspec"
|
43
|
+
path = file.relative_path_from(@repo_path).to_s
|
44
|
+
@errors << "Incorrect path, the path is `#{file}` and should be `#{expected_path}`" unless path.end_with?(expected_path)
|
45
|
+
end
|
46
|
+
|
47
|
+
platforms.each do |platform|
|
48
|
+
@platform_errors[platform], @platform_warnings[platform], @platform_notes[platform] = [], [], []
|
49
|
+
|
50
|
+
spec.activate_platform(platform)
|
51
|
+
@platform = platform
|
52
|
+
puts "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed if config.verbose? && !@quick
|
53
|
+
|
54
|
+
# Skip validation if there are errors in the podspec as it would result in a crash
|
55
|
+
if !podspec_errors.empty?
|
56
|
+
@platform_errors[platform] += podspec_errors
|
57
|
+
@platform_notes[platform] << "#{platform.name} [!] Fatal errors found skipping the rest of the validation"
|
58
|
+
else
|
59
|
+
@platform_warnings[platform] += podspec_warnings
|
60
|
+
peform_extensive_analysis unless quick
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get common messages
|
65
|
+
@errors += @platform_errors.values.reduce(:&)
|
66
|
+
@warnings += @platform_warnings.values.reduce(:&)
|
67
|
+
@notes += @platform_notes.values.reduce(:&)
|
68
|
+
|
69
|
+
platforms.each do |platform|
|
70
|
+
# Mark platform specific messages
|
71
|
+
@errors += (@platform_errors[platform] - @errors).map {|m| "[#{platform}] #{m}"}
|
72
|
+
@warnings += (@platform_warnings[platform] - @warnings).map {|m| "[#{platform}] #{m}"}
|
73
|
+
@notes += (@platform_notes[platform] - @notes).map {|m| "[#{platform}] #{m}"}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def result_type
|
79
|
+
return :error unless errors.empty?
|
80
|
+
return :warning unless warnings.empty?
|
81
|
+
return :note unless notes.empty?
|
82
|
+
:success
|
83
|
+
end
|
84
|
+
|
85
|
+
# Performs platform specific analysis.
|
86
|
+
# It requires to download the source at each iteration
|
87
|
+
#
|
88
|
+
def peform_extensive_analysis
|
89
|
+
set_up_lint_environment
|
90
|
+
install_pod
|
91
|
+
if `which xcodebuild`.strip.empty?
|
92
|
+
puts "Skipping compilation with `xcodebuild' because it can't be found.\n".yellow if config.verbose?
|
93
|
+
else
|
94
|
+
puts "Building with xcodebuild.\n".yellow if config.verbose?
|
95
|
+
# treat xcodebuild warnings as notes because the spec maintainer might not be the author of the library
|
96
|
+
xcodebuild_output.each { |msg| ( msg.include?('error: ') ? @platform_errors[@platform] : @platform_notes[@platform] ) << msg }
|
97
|
+
end
|
98
|
+
@platform_errors[@platform] += file_patterns_errors
|
99
|
+
@platform_warnings[@platform] += file_patterns_warnings
|
100
|
+
tear_down_lint_environment
|
101
|
+
end
|
102
|
+
|
103
|
+
def install_pod
|
104
|
+
podfile = podfile_from_spec
|
105
|
+
config.verbose
|
106
|
+
installer = Installer.new(podfile)
|
107
|
+
installer.install!
|
108
|
+
@pod = installer.pods.find { |pod| pod.top_specification == spec }
|
109
|
+
config.silent
|
110
|
+
end
|
111
|
+
|
112
|
+
def podfile_from_spec
|
113
|
+
name = spec.name
|
114
|
+
podspec = file.realpath.to_s
|
115
|
+
platform = @platform
|
116
|
+
podfile = Pod::Podfile.new do
|
117
|
+
platform(platform.to_sym, platform.deployment_target)
|
118
|
+
pod name, :podspec => podspec
|
119
|
+
end
|
120
|
+
podfile
|
121
|
+
end
|
122
|
+
|
123
|
+
def set_up_lint_environment
|
124
|
+
tmp_dir.rmtree if tmp_dir.exist?
|
125
|
+
tmp_dir.mkpath
|
126
|
+
@original_config = Config.instance.clone
|
127
|
+
config.project_root = tmp_dir
|
128
|
+
config.project_pods_root = tmp_dir + 'Pods'
|
129
|
+
config.silent = !config.verbose
|
130
|
+
config.integrate_targets = false
|
131
|
+
config.generate_docs = false
|
132
|
+
end
|
133
|
+
|
134
|
+
def tear_down_lint_environment
|
135
|
+
tmp_dir.rmtree unless no_clean
|
136
|
+
Config.instance = @original_config
|
137
|
+
end
|
138
|
+
|
139
|
+
def tmp_dir
|
140
|
+
Pathname.new('/tmp/CocoaPods/Lint')
|
141
|
+
end
|
142
|
+
|
143
|
+
def pod_dir
|
144
|
+
tmp_dir + 'Pods' + spec.name
|
145
|
+
end
|
146
|
+
|
147
|
+
# It reads a podspec file and checks for strings corresponding
|
148
|
+
# to features that are or will be deprecated
|
149
|
+
#
|
150
|
+
# @return [Array<String>]
|
151
|
+
#
|
152
|
+
def deprecation_errors
|
153
|
+
text = @file.read
|
154
|
+
deprecations = []
|
155
|
+
deprecations << "`config.ios?' and `config.osx?' are deprecated" if text. =~ /config\..?os.?/
|
156
|
+
deprecations << "clean_paths are deprecated and ignored (use preserve_paths)" if text. =~ /clean_paths/
|
157
|
+
deprecations
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [Array<String>] List of the fatal defects detected in a podspec
|
161
|
+
def podspec_errors
|
162
|
+
messages = []
|
163
|
+
messages << "The name of the spec should match the name of the file" unless names_match?
|
164
|
+
messages << "Unrecognized platfrom" unless platform_valid?
|
165
|
+
messages << "Missing name" unless spec.name
|
166
|
+
messages << "Missing version" unless spec.version
|
167
|
+
messages << "Missing summary" unless spec.summary
|
168
|
+
messages << "Missing homepage" unless spec.homepage
|
169
|
+
messages << "Missing author(s)" unless spec.authors
|
170
|
+
messages << "Missing or invalid source: #{spec.source}" unless source_valid?
|
171
|
+
|
172
|
+
# attributes with multiplatform values
|
173
|
+
return messages unless platform_valid?
|
174
|
+
messages << "The spec appears to be empty (no source files, resources, or preserve paths)" if spec.source_files.empty? && spec.subspecs.empty? && spec.resources.empty? && spec.preserve_paths.empty?
|
175
|
+
messages += paths_starting_with_a_slash_errors
|
176
|
+
messages += deprecation_errors
|
177
|
+
messages
|
178
|
+
end
|
179
|
+
|
180
|
+
def names_match?
|
181
|
+
return true unless spec.name
|
182
|
+
root_name = spec.name.match(/[^\/]*/)[0]
|
183
|
+
file.basename.to_s == root_name + '.podspec'
|
184
|
+
end
|
185
|
+
|
186
|
+
def platform_valid?
|
187
|
+
!spec.platform || [:ios, :osx].include?(spec.platform.name)
|
188
|
+
end
|
189
|
+
|
190
|
+
def source_valid?
|
191
|
+
spec.source && !(spec.source =~ /http:\/\/EXAMPLE/)
|
192
|
+
end
|
193
|
+
|
194
|
+
def paths_starting_with_a_slash_errors
|
195
|
+
messages = []
|
196
|
+
%w[source_files public_header_files resources clean_paths].each do |accessor|
|
197
|
+
patterns = spec.send(accessor.to_sym)
|
198
|
+
# Some values are multiplaform
|
199
|
+
patterns = patterns.is_a?(Hash) ? patterns.values.flatten(1) : patterns
|
200
|
+
patterns = patterns.compact # some patterns may be nil (public_header_files, for instance)
|
201
|
+
patterns.each do |pattern|
|
202
|
+
# Skip FileList that would otherwise be resolved from the working directory resulting
|
203
|
+
# in a potentially very expensi operation
|
204
|
+
next if pattern.is_a?(FileList)
|
205
|
+
invalid = pattern.is_a?(Array) ? pattern.any? { |path| path.start_with?('/') } : pattern.start_with?('/')
|
206
|
+
if invalid
|
207
|
+
messages << "Paths cannot start with a slash (#{accessor})"
|
208
|
+
break
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
messages
|
213
|
+
end
|
214
|
+
|
215
|
+
# @return [Array<String>] List of the **non** fatal defects detected in a podspec
|
216
|
+
def podspec_warnings
|
217
|
+
license = spec.license || {}
|
218
|
+
source = spec.source || {}
|
219
|
+
text = @file.read
|
220
|
+
messages = []
|
221
|
+
messages << "Missing license type" unless license[:type]
|
222
|
+
messages << "Sample license type" if license[:type] && license[:type] =~ /\(example\)/
|
223
|
+
messages << "Invalid license type" if license[:type] && license[:type] =~ /\n/
|
224
|
+
messages << "The summary is not meaningful" if spec.summary =~ /A short description of/
|
225
|
+
messages << "The description is not meaningful" if spec.description && spec.description =~ /An optional longer description of/
|
226
|
+
messages << "The summary should end with a dot" if spec.summary !~ /.*\./
|
227
|
+
messages << "The description should end with a dot" if spec.description !~ /.*\./ && spec.description != spec.summary
|
228
|
+
messages << "Git sources should specify either a tag or a commit" if source[:git] && !source[:commit] && !source[:tag]
|
229
|
+
messages << "Github repositories should end in `.git'" if github_source? && source[:git] !~ /.*\.git/
|
230
|
+
messages << "Github repositories should use `https' link" if github_source? && source[:git] !~ /https:\/\/github.com/
|
231
|
+
messages << "Comments must be deleted" if text.scan(/^\s*#/).length > 24
|
232
|
+
messages
|
233
|
+
end
|
234
|
+
|
235
|
+
def github_source?
|
236
|
+
spec.source && spec.source[:git] =~ /github.com/
|
237
|
+
end
|
238
|
+
|
239
|
+
# It creates a podfile in memory and builds a library containing
|
240
|
+
# the pod for all available platfroms with xcodebuild.
|
241
|
+
#
|
242
|
+
# @return [Array<String>]
|
243
|
+
#
|
244
|
+
def xcodebuild_output
|
245
|
+
return [] if `which xcodebuild`.strip.empty?
|
246
|
+
messages = []
|
247
|
+
output = Dir.chdir(config.project_pods_root) { `xcodebuild clean build 2>&1` }
|
248
|
+
clean_output = process_xcode_build_output(output)
|
249
|
+
messages += clean_output
|
250
|
+
puts(output) if config.verbose?
|
251
|
+
messages
|
252
|
+
end
|
253
|
+
|
254
|
+
def process_xcode_build_output(output)
|
255
|
+
output_by_line = output.split("\n")
|
256
|
+
selected_lines = output_by_line.select do |l|
|
257
|
+
l.include?('error: ') && (l !~ /errors? generated\./) && (l !~ /error: \(null\)/)\
|
258
|
+
|| l.include?('warning: ') && (l !~ /warnings? generated\./)\
|
259
|
+
|| l.include?('note: ') && (l !~ /expanded from macro/)
|
260
|
+
end
|
261
|
+
selected_lines.map do |l|
|
262
|
+
new = l.gsub(/\/tmp\/CocoaPods\/Lint\/Pods\//,'') # Remove the unnecessary tmp path
|
263
|
+
new.gsub!(/^ */,' ') # Remove indentation
|
264
|
+
"XCODEBUILD > " << new # Mark
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# It checks that every file pattern specified in a spec yields
|
269
|
+
# at least one file. It requires the pods to be alredy present
|
270
|
+
# in the current working directory under Pods/spec.name.
|
271
|
+
#
|
272
|
+
# @return [Array<String>]
|
273
|
+
#
|
274
|
+
def file_patterns_errors
|
275
|
+
messages = []
|
276
|
+
messages << "The sources did not match any file" if !spec.source_files.empty? && @pod.source_files.empty?
|
277
|
+
messages << "The resources did not match any file" if !spec.resources.empty? && @pod.resource_files.empty?
|
278
|
+
messages << "The preserve_paths did not match any file" if !spec.preserve_paths.empty? && @pod.preserve_files.empty?
|
279
|
+
messages << "The exclude_header_search_paths did not match any file" if !spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty?
|
280
|
+
messages
|
281
|
+
end
|
282
|
+
|
283
|
+
def file_patterns_warnings
|
284
|
+
messages = []
|
285
|
+
unless @pod.license_file || spec.license && ( spec.license[:type] == 'Public Domain' || spec.license[:text] )
|
286
|
+
messages << "Unable to find a license file"
|
287
|
+
end
|
288
|
+
messages
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
@@ -8,9 +8,10 @@ module Pod
|
|
8
8
|
|
9
9
|
$ pod push REPO [NAME.podspec]
|
10
10
|
|
11
|
-
Validates NAME.podspec or `*.podspec' in the current working dir,
|
12
|
-
|
13
|
-
|
11
|
+
Validates NAME.podspec or `*.podspec' in the current working dir, creates
|
12
|
+
a directory and version folder for the pod in the local copy of
|
13
|
+
REPO (~/.cocoapods/[REPO]), copies the podspec file into the version directory,
|
14
|
+
and finally it pushes REPO to its remote.}
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.options
|
@@ -11,10 +11,20 @@ module Pod
|
|
11
11
|
Clones `URL' in the local spec-repos directory at `~/.cocoapods'. The
|
12
12
|
remote can later be referred to by `NAME'.
|
13
13
|
|
14
|
-
$ pod repo update NAME
|
14
|
+
$ pod repo update [NAME]
|
15
15
|
|
16
16
|
Updates the local clone of the spec-repo `NAME'. If `NAME' is omitted
|
17
|
-
this will update all spec-repos in `~/.cocoapods'.
|
17
|
+
this will update all spec-repos in `~/.cocoapods'.
|
18
|
+
|
19
|
+
$ pod repo update [NAME | DIRECTORY]
|
20
|
+
|
21
|
+
Lints the spec-repo `NAME'. If a directory is provided it is assumed
|
22
|
+
to be the root of a repo. Finally, if NAME is not provided this will
|
23
|
+
lint all the spec-repos known to CocoaPods.}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.options
|
27
|
+
[["--only-errors", "Lint presents only the errors"]].concat(super)
|
18
28
|
end
|
19
29
|
|
20
30
|
extend Executable
|
@@ -29,6 +39,9 @@ module Pod
|
|
29
39
|
@branch = argv.arguments[3]
|
30
40
|
when 'update'
|
31
41
|
@name = argv.arguments[1]
|
42
|
+
when 'lint'
|
43
|
+
@name = argv.arguments[1]
|
44
|
+
@only_errors = argv.option('--only-errors')
|
32
45
|
else
|
33
46
|
super
|
34
47
|
end
|
@@ -66,6 +79,60 @@ module Pod
|
|
66
79
|
end
|
67
80
|
end
|
68
81
|
|
82
|
+
def lint
|
83
|
+
if @name
|
84
|
+
dirs = File.exists?(@name) ? [ Pathname.new(@name) ] : [ dir ]
|
85
|
+
else
|
86
|
+
dirs = config.repos_dir.children.select {|c| c.directory?}
|
87
|
+
end
|
88
|
+
dirs.each do |dir|
|
89
|
+
check_versions(dir)
|
90
|
+
puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow
|
91
|
+
podspecs = dir.glob('**/*.podspec')
|
92
|
+
invalid_count = 0
|
93
|
+
|
94
|
+
podspecs.each do |podspec|
|
95
|
+
linter = Linter.new(podspec)
|
96
|
+
linter.quick = true
|
97
|
+
linter.repo_path = dir
|
98
|
+
|
99
|
+
linter.lint
|
100
|
+
|
101
|
+
case linter.result_type
|
102
|
+
when :error
|
103
|
+
invalid_count += 1
|
104
|
+
color = :red
|
105
|
+
should_display = true
|
106
|
+
when :warning
|
107
|
+
color = :yellow
|
108
|
+
should_display = !@only_errors
|
109
|
+
end
|
110
|
+
|
111
|
+
if should_display
|
112
|
+
puts " -> ".send(color) << linter.spec_name
|
113
|
+
print_messages('ERROR', linter.errors)
|
114
|
+
unless @only_errors
|
115
|
+
print_messages('WARN', linter.warnings)
|
116
|
+
print_messages('NOTE', linter.notes)
|
117
|
+
end
|
118
|
+
puts unless config.silent?
|
119
|
+
end
|
120
|
+
end
|
121
|
+
puts "Analyzed #{podspecs.count} podspecs files.\n\n" unless config.silent?
|
122
|
+
|
123
|
+
if invalid_count == 0
|
124
|
+
puts "All the specs passed validation.".green << "\n\n" unless config.silent?
|
125
|
+
else
|
126
|
+
raise Informative, "#{invalid_count} podspecs failed validation."
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def print_messages(type, messages)
|
132
|
+
return if config.silent?
|
133
|
+
messages.each {|msg| puts " - #{type.ljust(5)} | #{msg}"}
|
134
|
+
end
|
135
|
+
|
69
136
|
def check_versions(dir)
|
70
137
|
versions = versions(dir)
|
71
138
|
unless is_compatilbe(versions)
|