Skip to content

Commit

Permalink
Validation of subspecs
Browse files Browse the repository at this point in the history
The validation done by `pod spec lint` and `pod lib lint` commands
now checks that all subspecs build independently.

This new behavior can be disabled with `--no-subspecs`.

The validation of a single subspec can be done checked with `--subspec=NAME`.
  • Loading branch information
marcc-orange committed Dec 5, 2013
1 parent 18f71e5 commit fc7a717
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 15 deletions.
12 changes: 9 additions & 3 deletions lib/cocoapods/command/lib.rb
Expand Up @@ -90,13 +90,17 @@ class Lint < Lib
def self.options
[ ["--quick", "Lint skips checks that would require to download and build the spec"],
["--only-errors", "Lint validates even if warnings are present"],
["--subspec=NAME","Lint validates only the given subspec"],
["--no-subspecs", "Lint skips validation of subspecs"],
["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
end

def initialize(argv)
@quick = argv.flag?('quick')
@only_errors = argv.flag?('only-errors')
@clean = argv.flag?('clean', true)
@quick = argv.flag?('quick')
@only_errors = argv.flag?('only-errors')
@clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec')
super
end

Expand All @@ -111,6 +115,8 @@ def run
validator.quick = @quick
validator.no_clean = !@clean
validator.only_errors = @only_errors
validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec
validator.validate

if validator.validated?
Expand Down
12 changes: 9 additions & 3 deletions lib/cocoapods/command/spec.rb
Expand Up @@ -61,13 +61,17 @@ class Lint < Spec
def self.options
[ ["--quick", "Lint skips checks that would require to download and build the spec"],
["--only-errors", "Lint validates even if warnings are present"],
["--subspec=NAME","Lint validates only the given subspec"],
["--no-subspecs", "Lint skips validation of subspecs"],
["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
end

def initialize(argv)
@quick = argv.flag?('quick')
@only_errors = argv.flag?('only-errors')
@clean = argv.flag?('clean', true)
@quick = argv.flag?('quick')
@only_errors = argv.flag?('only-errors')
@clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec')
@podspecs_paths = argv.arguments!
super
end
Expand All @@ -80,6 +84,8 @@ def run
validator.quick = @quick
validator.no_clean = !@clean
validator.only_errors = @only_errors
validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec
validator.validate
invalid_count += 1 unless validator.validated?

Expand Down
69 changes: 60 additions & 9 deletions lib/cocoapods/validator.rb
Expand Up @@ -46,7 +46,7 @@ def file

#-------------------------------------------------------------------------#

# Lints the specification adding a {Specification::Linter::Result} for any
# Lints the specification adding a {Result} for any
# failed check to the {#results} list.
#
# @note This method shows immediately which pod is being processed and
Expand All @@ -56,13 +56,21 @@ def file
#
def validate
@results = []
UI.print " -> #{spec ? spec.name : file.basename}\r" unless config.silent?

# Replace default spec with a subspec if asked for
a_spec = spec
if spec && @only_subspec
a_spec = spec.subspec_by_name(@only_subspec)
@subspec_name = a_spec.name
end

UI.print " -> #{a_spec ? a_spec.name : file.basename}\r" unless config.silent?
$stdout.flush

perform_linting
perform_extensive_analysis if spec && !quick
perform_extensive_analysis(a_spec) if a_spec && !quick

UI.puts " -> ".send(result_color) << (spec ? spec.to_s : file.basename.to_s)
UI.puts " -> ".send(result_color) << (a_spec ? a_spec.to_s : file.basename.to_s)
print_results
validated?
end
Expand All @@ -79,12 +87,22 @@ def print_results
platform_message = "[OSX] "
end

subspecs_message = ""
if result.is_a?(Result)
subspecs = result.subspecs.uniq
if subspecs.count > 2
subspecs_message = "[" + subspecs[0..2].join(', ') + ", and more...] "
elsif subspecs.count > 0
subspecs_message = "[" + subspecs.join(',') + "] "
end
end

case result.type
when :error then type = "ERROR"
when :warning then type = "WARN"
when :note then type = "NOTE"
else raise "#{result.type}" end
UI.puts " - #{type.ljust(5)} | #{platform_message}#{result.message}"
UI.puts " - #{type.ljust(5)} | #{platform_message}#{subspecs_message}#{result.message}"
end
UI.puts
end
Expand Down Expand Up @@ -116,6 +134,14 @@ def local?; @local; end
#
attr_accessor :only_errors

# @return [String] name of the subspec to check, if nil all subspecs are checked.
#
attr_accessor :only_subspec

# @return [Bool] Whether the validator should validate all subspecs
#
attr_accessor :no_subspecs

#-------------------------------------------------------------------------#

# !@group Lint results
Expand Down Expand Up @@ -167,9 +193,9 @@ def perform_linting
@results.concat(linter.results)
end

# Perform analysis for a given spec (or subspec)
#
#
def perform_extensive_analysis
def perform_extensive_analysis(spec)
spec.available_platforms.each do |platform|
UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
@consumer = spec.consumer(platform)
Expand All @@ -179,9 +205,20 @@ def perform_extensive_analysis
check_file_patterns
tear_down_validation_environment
end
perform_extensive_subspec_analysis(spec) unless @no_subspecs
end

# Recurively perform the extensive analysis on all subspecs
#
def perform_extensive_subspec_analysis(spec)
spec.subspecs.each do |subspec|
@subspec_name = subspec.name
perform_extensive_analysis(subspec)
end
end

attr_accessor :consumer
attr_accessor :subspec_name

def setup_validation_environment
validation_dir.rmtree if validation_dir.exist?
Expand Down Expand Up @@ -283,10 +320,24 @@ def note(message)
def add_result(type, message)
result = results.find { |r| r.type == type && r.message == message }
unless result
result = Specification::Linter::Result.new(type, message)
result = Result.new(type, message)
results << result
end
result.platforms << consumer.platform_name if consumer
result.subspecs << subspec_name if subspec_name && !result.subspecs.include?(subspec_name)
end

# Specialized Result to support subspecs aggregation
#
class Result < Specification::Linter::Result

def initialize(type, message)
super(type, message)
@subspecs = []
end

attr_reader :subspecs

end

#-------------------------------------------------------------------------#
Expand All @@ -302,7 +353,7 @@ def add_result(type, message)
# in local mode.
#
def podfile_from_spec(platform_name, deployment_target)
name = spec.name
name = subspec_name ? subspec_name : spec.name
podspec = file.realpath
local = local?
podfile = Pod::Podfile.new do
Expand Down

0 comments on commit fc7a717

Please sign in to comment.