Commit 50405dc5 authored by Fabio Pelosin's avatar Fabio Pelosin

Merge branch 'master' into deployment-target-check

* master:
  [Installer] Don't generate documenation if already installed
  [Command::Spec::Linter] Fix - Skip documentation generation
  [Config#doc] Renamed to generate_docs
  [Command::Spec::Linter] Bug fix.
  [# 242 Command::Spec::Linter] Refactoring
  [#246 | Resolver] Validate plaforms against each target.
  [Resolver] Check target plafroms instead of podfile.

Conflicts:
	lib/cocoapods/resolver.rb
parents 86be3d31 fcc94b68
...@@ -35,7 +35,7 @@ module Pod ...@@ -35,7 +35,7 @@ module Pod
def initialize(argv) def initialize(argv)
config.clean = !argv.option('--no-clean') config.clean = !argv.option('--no-clean')
config.doc = !argv.option('--no-doc') config.generate_docs = !argv.option('--no-doc')
config.force_doc = argv.option('--force-doc') config.force_doc = argv.option('--force-doc')
config.integrate_targets = !argv.option('--no-integrate') config.integrate_targets = !argv.option('--no-integrate')
@update_repo = !argv.option('--no-update') @update_repo = !argv.option('--no-update')
......
...@@ -61,18 +61,18 @@ module Pod ...@@ -61,18 +61,18 @@ module Pod
def lint def lint
puts puts
all_valid = lint_podspecs invalid_count = lint_podspecs
if all_valid if invalid_count == 0
puts lint_passed_message unless config.silent? puts lint_passed_message unless config.silent?
else else
raise Informative, lint_failed_message raise Informative, lint_failed_message(invalid_count)
end end
end end
private private
def lint_podspecs def lint_podspecs
all_valid = true specs_count, invalid_count = 0, 0
podspecs_to_lint.each do |podspec_file| podspecs_to_lint.each do |podspec_file|
root_spec = Specification.from_file(podspec_file) root_spec = Specification.from_file(podspec_file)
specs = root_spec.recursive_subspecs.any? ? root_spec.recursive_subspecs : [root_spec] specs = root_spec.recursive_subspecs.any? ? root_spec.recursive_subspecs : [root_spec]
...@@ -81,19 +81,23 @@ module Pod ...@@ -81,19 +81,23 @@ module Pod
print " -> #{spec}\r" unless config.silent? || is_repo? print " -> #{spec}\r" unless config.silent? || is_repo?
$stdout.flush $stdout.flush
linter = Linter.new(spec, podspec_file, is_repo?, @quick, @only_errors) linter = Linter.new(spec, podspec_file)
all_valid = linter.lint && all_valid linter.lenient = @only_errors
linter.quick = @quick || is_repo?
invalid_count += 1 unless linter.lint
# This overwrites the previously printed text # This overwrites the previously printed text
puts " -> ".send(lint_result_color(linter)) << spec.to_s unless config.silent? || should_skip?(linter) puts " -> ".send(lint_result_color(linter)) << spec.to_s unless config.silent? || should_skip?(linter)
print_messages(spec, 'ERROR', linter.errors) print_messages(spec, 'ERROR', linter.errors)
print_messages(spec, 'WARN', linter.warnings) print_messages(spec, 'WARN', linter.warnings)
print_messages(spec, 'NOTE', linter.notes) print_messages(spec, 'NOTE', linter.notes)
puts unless config.silent? || should_skip?(linter) puts unless config.silent? || should_skip?(linter)
GC.start
end end
specs_count += specs.count
end end
all_valid puts "Analyzed #{specs_count} specs in #{podspecs_to_lint.count} podspecs files.\n\n" if is_repo? && !config.silent?
invalid_count
end end
def lint_result_color(linter) def lint_result_color(linter)
...@@ -159,8 +163,8 @@ module Pod ...@@ -159,8 +163,8 @@ module Pod
( podspecs_to_lint.count == 1 ? "#{podspecs_to_lint.first.basename} passed validation" : "All the specs passed validation" ).green << "\n\n" ( podspecs_to_lint.count == 1 ? "#{podspecs_to_lint.first.basename} passed validation" : "All the specs passed validation" ).green << "\n\n"
end end
def lint_failed_message def lint_failed_message(count)
( podspecs_to_lint.count == 1 ? "[!] The spec did not pass validation" : "[!] Not all specs passed validation" ).red << "\n\n" ( podspecs_to_lint.count == 1 ? "[!] The spec did not pass validation" : "[!] #{count} specs failed validation" ).red << "\n\n"
end end
# Linter class # Linter class
...@@ -168,14 +172,12 @@ module Pod ...@@ -168,14 +172,12 @@ module Pod
class Linter class Linter
include Config::Mixin include Config::Mixin
attr_reader :spec, :file, :is_repo, :quick, :only_errors attr_accessor :quick, :lenient
attr_reader :spec, :file
def initialize(spec, podspec_file, is_repo, quick, only_errors) def initialize(spec, podspec_file)
@spec = spec @spec = spec
@file = podspec_file.realpath @file = podspec_file.realpath
@is_repo = is_repo
@quick = quick
@only_errors = only_errors
end end
# Takes an array of podspec files and lints them all # Takes an array of podspec files and lints them all
...@@ -186,17 +188,22 @@ module Pod ...@@ -186,17 +188,22 @@ module Pod
# If the spec doesn't validate it raises and informative # If the spec doesn't validate it raises and informative
# TODO: consider raising the informative in the clients of Pod::Specification#validate! # TODO: consider raising the informative in the clients of Pod::Specification#validate!
# and just report the errors here # and just report the errors here
spec.validate! peform_multiplatform_analysis unless quick
peform_multiplatform_analysis unless is_repo || quick
# Skip validation if there are errors in the podspec as it would result in a crash
unless podspec_errors.empty?
@errors, @warnings, @notes = podspec_errors, [], ['[!] Fatal errors found skipping the rest of the validation']
return false
end
valid? valid?
end end
def valid? def valid?
only_errors ? errors.empty? : errors.empty? && warnings.empty? lenient ? errors.empty? : errors.empty? && warnings.empty?
end end
def errors def errors
@errors ||= podspec_errors + file_patterns_errors + build_errors @errors ||= file_patterns_errors + build_errors
end end
def warnings def warnings
...@@ -213,6 +220,7 @@ module Pod ...@@ -213,6 +220,7 @@ module Pod
def peform_multiplatform_analysis def peform_multiplatform_analysis
platform_names.each do |platform_name| platform_names.each do |platform_name|
set_up_lint_environment set_up_lint_environment
install_pod(platform_name)
xcodebuild_output.concat(xcodebuild_output_for_platfrom(platform_name)) xcodebuild_output.concat(xcodebuild_output_for_platfrom(platform_name))
file_patterns_errors.concat(file_patterns_errors_for_platfrom(platform_name)) file_patterns_errors.concat(file_patterns_errors_for_platfrom(platform_name))
tear_down_lint_environment tear_down_lint_environment
...@@ -223,6 +231,14 @@ module Pod ...@@ -223,6 +231,14 @@ module Pod
spec.platform.name ? [spec.platform.name] : [:ios, :osx] spec.platform.name ? [spec.platform.name] : [:ios, :osx]
end end
def install_pod(platform_name)
puts "\n\n#{spec} - generating build errors for #{platform_name} platform".yellow.reversed if config.verbose?
podfile = podfile_from_spec(platform_name)
config.verbose
Installer.new(podfile).install!
config.silent
end
def set_up_lint_environment def set_up_lint_environment
tmp_dir.rmtree if tmp_dir.exist? tmp_dir.rmtree if tmp_dir.exist?
tmp_dir.mkpath tmp_dir.mkpath
...@@ -231,11 +247,11 @@ module Pod ...@@ -231,11 +247,11 @@ module Pod
config.project_pods_root = tmp_dir + 'Pods' config.project_pods_root = tmp_dir + 'Pods'
config.silent = !config.verbose config.silent = !config.verbose
config.integrate_targets = false config.integrate_targets = false
config.doc_install = false config.generate_docs = false
end end
def tear_down_lint_environment def tear_down_lint_environment
# tmp_dir.rmtree tmp_dir.rmtree
Config.instance = @original_config Config.instance = @original_config
end end
...@@ -250,7 +266,43 @@ module Pod ...@@ -250,7 +266,43 @@ module Pod
# @return [Array<String>] List of the fatal defects detected in a podspec # @return [Array<String>] List of the fatal defects detected in a podspec
def podspec_errors def podspec_errors
messages = [] messages = []
messages << "Missing name" unless spec.name
messages << "Missing version" unless spec.version
messages << "Missing summary" unless spec.summary
messages << "Missing homepage" unless spec.homepage
messages << "Missing author(s)" unless spec.authors
messages << "Missing source or part_of" unless spec.source || spec.part_of
messages << "Missing source_files" if spec.source_files.empty? && spec.subspecs.empty?
messages << "The name of the spec should match the name of the file" unless names_match? messages << "The name of the spec should match the name of the file" unless names_match?
messages << "Unrecognized platfrom (no value, :ios, :osx)" unless [nil, :ios, :osx].include?(spec.platform.name)
messages += paths_starting_with_a_slash_errors
messages
end
def names_match?
return true unless spec.name
root_name = spec.name.match(/[^\/]*/)[0]
file.basename.to_s == root_name + '.podspec'
end
def paths_starting_with_a_slash_errors
messages = []
%w[source_files resources clean_paths].each do |accessor|
patterns = spec.send(accessor.to_sym)
# Some values are multiplaform
patterns = patterns.is_a?(Hash) ? patterns.values.flatten(1) : patterns
patterns.each do |pattern|
# Skip Filelist that would otherwise be resolved from the working directory resulting
# in a potentially very expensi operation
next if pattern.is_a?(FileList)
invalid = pattern.is_a?(Array) ? pattern.any? { |path| path.start_with?('/') } : pattern.start_with?('/')
if invalid
messages << "Paths cannot start with a slash (#{accessor})"
break
end
end
end
messages messages
end end
...@@ -271,20 +323,14 @@ module Pod ...@@ -271,20 +323,14 @@ module Pod
messages messages
end end
def names_match?
root_name = @spec.name.match(/[^\/]*/)[0]
@file.basename.to_s == root_name + '.podspec'
end
def github_source? def github_source?
@spec.source && @spec.source[:git] =~ /github.com/ @spec.source && @spec.source[:git] =~ /github.com/
end end
# It reads a podspec file and checks for strings corresponding # It reads a podspec file and checks for strings corresponding
# to a feature that are or will be deprecated # to features that are or will be deprecated
#
# It returns a array of strings
# #
# @return [Array<String>]
def deprecation_warnings def deprecation_warnings
text = @file.read text = @file.read
deprecations = [] deprecations = []
...@@ -293,7 +339,6 @@ module Pod ...@@ -293,7 +339,6 @@ module Pod
deprecations deprecations
end end
def build_errors def build_errors
@build_errors ||= xcodebuild_output.select {|msg| msg.include?('error')} @build_errors ||= xcodebuild_output.select {|msg| msg.include?('error')}
end end
...@@ -312,12 +357,8 @@ module Pod ...@@ -312,12 +357,8 @@ module Pod
# It returns a array of strings # It returns a array of strings
# #
def xcodebuild_output_for_platfrom(platform_name) def xcodebuild_output_for_platfrom(platform_name)
return [] if `which xcodebuild`.strip.empty?
messages = [] messages = []
puts "\n\n#{spec} - generating build errors for #{platform_name} platform".yellow.reversed if config.verbose?
podfile = podfile_from_spec(platform_name)
Installer.new(podfile).install!
return messages if `which xcodebuild`.strip.empty?
output = Dir.chdir(config.project_pods_root) { `xcodebuild 2>&1` } output = Dir.chdir(config.project_pods_root) { `xcodebuild 2>&1` }
clean_output = process_xcode_build_output(output).map {|l| "#{platform_name}: #{l}"} clean_output = process_xcode_build_output(output).map {|l| "#{platform_name}: #{l}"}
messages += clean_output messages += clean_output
...@@ -341,8 +382,11 @@ module Pod ...@@ -341,8 +382,11 @@ module Pod
|| l.include?('warning') && (l !~ /warnings? generated\./)\ || l.include?('warning') && (l !~ /warnings? generated\./)\
|| l.include?('note') || l.include?('note')
end end
# Remove the unnecessary tmp path selected_lines.map do |l|
selected_lines.map {|l| l.gsub(/\/tmp\/CocoaPods\/Lint\/Pods\//,'')} new = l.gsub(/\/tmp\/CocoaPods\/Lint\/Pods\//,'') # Remove the unnecessary tmp path
new.gsub!(/^ */,' ') # Remove indentation
"XCODEBUILD > " << new # Mark
end
end end
def file_patterns_errors def file_patterns_errors
...@@ -365,12 +409,10 @@ module Pod ...@@ -365,12 +409,10 @@ module Pod
end end
end end
# TODO: FileList doesn't work and always adds the error message
# pod spec lint ~/.cocoapods/master/MKNetworkKit/0.83/MKNetworkKit.podspec
def check_spec_files_exists(accessor, platform_name, options = {}) def check_spec_files_exists(accessor, platform_name, options = {})
result = [] result = []
patterns = spec.send(accessor)[platform_name] patterns = spec.send(accessor)[platform_name]
patterns.map do |original_pattern| patterns.each do |original_pattern|
pattern = pod_dir + original_pattern pattern = pod_dir + original_pattern
if pattern.directory? && options[:glob] if pattern.directory? && options[:glob]
pattern += options[:glob] pattern += options[:glob]
...@@ -379,7 +421,6 @@ module Pod ...@@ -379,7 +421,6 @@ module Pod
end end
result result
end end
end end
# Templates and github information retrival for spec create # Templates and github information retrival for spec create
......
...@@ -12,13 +12,13 @@ module Pod ...@@ -12,13 +12,13 @@ module Pod
attr_accessor :repos_dir, :project_root, :project_pods_root attr_accessor :repos_dir, :project_root, :project_pods_root
attr_accessor :clean, :verbose, :silent attr_accessor :clean, :verbose, :silent
attr_accessor :doc, :doc_install, :force_doc attr_accessor :generate_docs, :doc_install, :force_doc
attr_accessor :integrate_targets attr_accessor :integrate_targets
alias_method :clean?, :clean alias_method :clean?, :clean
alias_method :verbose?, :verbose alias_method :verbose?, :verbose
alias_method :silent?, :silent alias_method :silent?, :silent
alias_method :doc?, :doc # TODO rename to generate_docs? alias_method :generate_docs?, :generate_docs
alias_method :doc_install?, :doc_install alias_method :doc_install?, :doc_install
alias_method :force_doc?, :force_doc alias_method :force_doc?, :force_doc
alias_method :integrate_targets?, :integrate_targets alias_method :integrate_targets?, :integrate_targets
...@@ -26,7 +26,7 @@ module Pod ...@@ -26,7 +26,7 @@ module Pod
def initialize def initialize
@repos_dir = Pathname.new(File.expand_path("~/.cocoapods")) @repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
@verbose = @silent = @force_doc = false @verbose = @silent = @force_doc = false
@clean = @doc = @doc_install = @integrate_targets = true @clean = @generate_docs = @doc_install = @integrate_targets = true
end end
def project_root def project_root
......
...@@ -74,6 +74,10 @@ module Pod ...@@ -74,6 +74,10 @@ module Pod
options += spec_appledoc_options options += spec_appledoc_options
end end
def already_installed?
Pathname.new(File.expand_path("~/Library/Developer/Shared/Documentation/DocSets/org.cocoapods.#{name.gsub(/ /,'-')}.docset")).exist?
end
def generate(install = false) def generate(install = false)
options = appledoc_options options = appledoc_options
options += ['--output', @target_path.to_s] options += ['--output', @target_path.to_s]
......
...@@ -59,9 +59,14 @@ module Pod ...@@ -59,9 +59,14 @@ module Pod
end end
end end
if (should_install && config.doc?) || config.force_doc? if (should_install && config.generate_docs?) || config.force_doc?
doc_generator = Generator::Documentation.new(pod)
if doc_generator.already_installed?
puts "Using Existing Documentation for #{pod.specification}".green if config.verbose?
else
puts "Installing Documentation for #{pod.specification}".green if config.verbose? puts "Installing Documentation for #{pod.specification}".green if config.verbose?
Generator::Documentation.new(pod).generate(config.doc_install?) doc_generator.generate(config.doc_install?)
end
end end
end end
end end
......
...@@ -20,10 +20,10 @@ module Pod ...@@ -20,10 +20,10 @@ module Pod
targets_and_specs = {} targets_and_specs = {}
@podfile.target_definitions.values.each do |target_definition| @podfile.target_definitions.values.each do |target_definition|
puts "\nResolving dependencies for target `#{target_definition.name}'".green if config.verbose? puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform})".green if config.verbose?
@loaded_specs = [] @loaded_specs = []
# TODO @podfile.platform will change to target_definition.platform # TODO @podfile.platform will change to target_definition.platform
find_dependency_sets(@podfile, target_definition.dependencies, target_definition.platform) find_dependency_sets(@podfile, target_definition.dependencies, target_definition)
targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name) targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
end end
...@@ -56,11 +56,11 @@ module Pod ...@@ -56,11 +56,11 @@ module Pod
end end
end end
def find_dependency_sets(dependent_specification, dependencies, platform) def find_dependency_sets(dependent_specification, dependencies, target_definition)
@log_indent += 1 @log_indent += 1
dependencies.each do |dependency| dependencies.each do |dependency|
puts ' ' * @log_indent + "- #{dependency}" if config.verbose? puts ' ' * @log_indent + "- #{dependency}" if config.verbose?
set = find_cached_set(dependency, platform) set = find_cached_set(dependency, target_definition.platform)
set.required_by(dependent_specification) set.required_by(dependent_specification)
# Ensure we don't resolve the same spec twice for one target # Ensure we don't resolve the same spec twice for one target
unless @loaded_specs.include?(dependency.name) unless @loaded_specs.include?(dependency.name)
...@@ -71,27 +71,24 @@ module Pod ...@@ -71,27 +71,24 @@ module Pod
if dependency.subspec_dependency? if dependency.subspec_dependency?
spec = spec.subspec_by_name(dependency.name) spec = spec.subspec_by_name(dependency.name)
end end
validate_platform!(spec)
@loaded_specs << spec.name @loaded_specs << spec.name
@specs[spec.name] = spec @specs[spec.name] = spec
# And recursively load the dependencies of the spec. # And recursively load the dependencies of the spec.
# TODO fix the need to return an empty arrayf if there are no deps for the given platform # TODO fix the need to return an empty arrayf if there are no deps for the given platform
find_dependency_sets(spec, (spec.dependencies[platform.to_sym] || []), platform) find_dependency_sets(spec, (spec.dependencies[target_definition.platform.to_sym] || []), target_definition)
end end
validate_platform!(spec || @specs[dependency.name], target_definition)
end end
@log_indent -= 1 @log_indent -= 1
end end
def validate_platform!(spec) def validate_platform!(spec, target)
platform = @podfile.target_definitions[:default].platform unless target.platform.support?(spec.platform)
unless platform.support?(spec.platform) raise Informative, "[!] The platform required by the target `#{target.name}' `#{target.platform}' does not match that of #{spec} `#{spec.platform}'".red
raise Informative, "The platform required by the Podfile `#{platform}' does not match that of #{spec} `#{spec.platform}'"
end end
unless !platform.deployment_target || !spec.deployment_target[platform.name] || spec.deployment_target[platform.name].satisfied_by?(platform.deployment_target) unless !target.platform.deployment_target || !spec.deployment_target[platform.name] || spec.deployment_target[platform.name].satisfied_by?(target.platform.deployment_target)
raise Informative, "The platform required by the Podfile `#{platform}' does not match that of #{spec} `#{spec.platform} #{spec.deployment_target[platform.name]}'".magenta raise Informative, "[!] The platform required by the target `#{target.name}' `#{target.platform}' does not match that of `#{spec}' `#{spec.platform} #{spec.deployment_target[platform.name]}'".magenta
end end
end end
end end
......
...@@ -347,49 +347,6 @@ module Pod ...@@ -347,49 +347,6 @@ module Pod
"#<#{self.class.name} for #{to_s}>" "#<#{self.class.name} for #{to_s}>"
end end
def validate!
missing = []
missing << "name" unless name
missing << "version" unless version
missing << "summary" unless summary
missing << "homepage" unless homepage
missing << "author(s)" unless authors
missing << "source or part_of" unless source || part_of
missing << "source_files" if source_files.empty? && subspecs.empty?
# TODO
# * validate subspecs
incorrect = []
allowed = [nil, :ios, :osx]
incorrect << "platform - accepted values are (no value, :ios, :osx)" unless allowed.include?(platform.name)
{
:source_files => source_files.values,
:resources => resources.values,
:clean_paths => clean_paths
}.each do |name, paths|
if paths.flatten.any? { |path| path.start_with?("/") }
incorrect << "#{name} - paths cannot start with a slash"
end
end
if source && source[:local] && source[:local].start_with?("/")
incorrect << "source[:local] - paths cannot start with a slash"
end
no_errors_found = missing.empty? && incorrect.empty?
unless no_errors_found
message = "\n[!] The #{name || 'nameless'} specification is incorrect\n".red
missing.each {|s| message << " - Missing #{s}\n"}
incorrect.each {|s| message << " - Incorrect #{s}\n"}
message << "\n"
raise Informative, message
end
no_errors_found
end
# This is a convenience method which gets called after all pods have been # This is a convenience method which gets called after all pods have been
# downloaded, installed, and the Xcode project and related files have been # downloaded, installed, and the Xcode project and related files have been
# generated. (It receives the Pod::Installer::Target instance for the current # generated. (It receives the Pod::Installer::Target instance for the current
......
...@@ -14,7 +14,7 @@ describe Pod::Command::Spec do ...@@ -14,7 +14,7 @@ describe Pod::Command::Spec do
end end
end end
describe "Pod::Command::Spec create" do describe "Pod::Command::Spec#create" do
extend SpecHelper::Command extend SpecHelper::Command
extend SpecHelper::Github extend SpecHelper::Github
extend SpecHelper::TemporaryDirectory extend SpecHelper::TemporaryDirectory
...@@ -51,7 +51,7 @@ describe "Pod::Command::Spec create" do ...@@ -51,7 +51,7 @@ describe "Pod::Command::Spec create" do
spec.source.should == { :git => 'https://github.com/lukeredpath/libPusher.git', :tag => 'v1.3' } spec.source.should == { :git => 'https://github.com/lukeredpath/libPusher.git', :tag => 'v1.3' }
end end
it "accepts the a name when creating a podspec form github" do it "accepts a name when creating a podspec form github" do
expect_github_repo_request expect_github_repo_request
expect_github_user_request expect_github_user_request
expect_github_tags_request expect_github_tags_request
...@@ -90,7 +90,7 @@ describe "Pod::Command::Spec create" do ...@@ -90,7 +90,7 @@ describe "Pod::Command::Spec create" do
end end
end end
describe "Pod::Command::Spec lint" do describe "Pod::Command::Spec#lint" do
extend SpecHelper::Command extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory extend SpecHelper::TemporaryDirectory
extend SpecHelper::Git extend SpecHelper::Git
...@@ -104,13 +104,8 @@ describe "Pod::Command::Spec lint" do ...@@ -104,13 +104,8 @@ describe "Pod::Command::Spec lint" do
end end
it "lints a repo" do it "lints a repo" do
# the fixture master repo has warnings and does not validates # The fixture has an error due to a name mismatch
lambda { run_command('spec', 'lint', 'master') }.should.raise Pod::Informative cmd = command('spec', 'lint', 'master')
end
it "lints a repo with --only-errors option and show the warnings" do
# The fixture has an error due to name mismatch
cmd = command('spec', 'lint', 'master', '--only-errors')
lambda { cmd.run }.should.raise Pod::Informative lambda { cmd.run }.should.raise Pod::Informative
cmd.output.should.include "InAppSettingKit (0.0.1)\n - ERROR | The name of the spec should match the name of the file" cmd.output.should.include "InAppSettingKit (0.0.1)\n - ERROR | The name of the spec should match the name of the file"
cmd.output.should.include "WARN" cmd.output.should.include "WARN"
...@@ -136,51 +131,10 @@ describe "Pod::Command::Spec lint" do ...@@ -136,51 +131,10 @@ describe "Pod::Command::Spec lint" do
cmd.output.should.include "Missing license[:file] or [:text]" cmd.output.should.include "Missing license[:file] or [:text]"
end end
before do it "respects the -only--errors option" do
spec = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read spec_file = fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec'
spec.gsub!(/https:\/\/github\.com\/johnezang\/JSONKit\.git/, fixture('integration/JSONKit').to_s) cmd = command('spec', 'lint', '--quick', '--only-errors', spec_file.to_s)
spec.gsub!(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\ns.resources = 'WRONG_FOLDER'") lambda { cmd.run }.should.not.raise
File.open(temporary_directory + 'JSONKit.podspec', 'w') {|f| f.write(spec) } cmd.output.should.include "Missing license[:file] or [:text]"
end
it "fails if there are warnings" do
cmd = command('spec', 'lint', '--quick')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.include "- WARN | Missing license[:file] or [:text]"
end
it "respects the --only-errors option" do
cmd = command('spec', 'lint', '--quick', '--only-errors')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.not.raise Pod::Informative }
cmd.output.should.include "- WARN | Missing license[:file] or [:text]"
cmd.output.should.include "passed validation"
end
it "respects the --quick option" do
cmd = command('spec', '--quick', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.not.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses"
end
it "uses xcodebuild to generate warnings and checks for file patterns" do
# those two checks are merged because pod install is computationally expensive
cmd = command('spec', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
unless `which xcodebuild`.strip.empty?
cmd.output.should.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses"
end
cmd.output.should.include "- ERROR | [resources = 'WRONG_FOLDER'] -> did not match any file"
end
before do
spec = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
spec.gsub!(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\n if config.ios?\nend")
File.open(temporary_directory + 'JSONKit.podspec', 'w') {|f| f.write(spec) }
end
it "produces deprecation notices" do
cmd = command('spec', '--quick', 'lint')
Dir.chdir(temporary_directory) { lambda { cmd.run }.should.raise Pod::Informative }
cmd.output.should.include "- WARN | `config.ios?' and `config.osx' will be removed in version 0.7"
end end
end end
...@@ -45,7 +45,7 @@ else ...@@ -45,7 +45,7 @@ else
@config_before = config @config_before = config
create_config! create_config!
config.doc = false config.generate_docs = false
end end
after do after do
...@@ -208,6 +208,8 @@ else ...@@ -208,6 +208,8 @@ else
dependency 'SSToolkit' dependency 'SSToolkit'
end end
Pod::Generator::Documentation.any_instance.stubs(:already_installed?).returns(false)
installer = SpecHelper::Installer.new(podfile) installer = SpecHelper::Installer.new(podfile)
installer.install! installer.install!
......
require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Spec::Linter" do
extend SpecHelper::TemporaryDirectory
def write_podspec(text, name = 'JSONKit.podspec')
file = temporary_directory + 'JSONKit.podspec'
File.open(file, 'w') {|f| f.write(text) }
spec = Pod::Specification.from_file(file)
[spec, file]
end
def stub_podspec(pattern = nil, replacement = nil)
spec = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
spec.gsub!(/https:\/\/github\.com\/johnezang\/JSONKit\.git/, fixture('integration/JSONKit').to_s)
spec.gsub!(pattern, replacement) if pattern && replacement
spec
end
it "fails a specifications that does not contain the minimum required attributes" do
spec, file = write_podspec('Pod::Spec.new do |s| end')
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.join(' | ') =~ /name.*version.*summary.*homepage.*authors.*(source.*part_of).*source_files/
end
it "fails specifications if the name does not match the name of the file" do
spec, file = write_podspec(stub_podspec(/s.name *= 'JSONKit'/, "s.name = 'JSONKitAAA'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
linter.errors[0].should =~ /The name of the spec should match the name of the file/
end
it "fails a specification if a path starts with a slash" do
spec, file = write_podspec(stub_podspec(/s.source_files = 'JSONKit\.\*'/, "s.source_files = '/JSONKit.*'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
linter.errors[0].should =~ /Paths cannot start with a slash/
end
it "fails a specification if the plafrom is unrecognized" do
spec, file = write_podspec(stub_podspec(/s.name *= 'JSONKit'/, "s.name = 'JSONKit'\ns.platform = :iososx\n"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
linter.errors[0].should =~ /Unrecognized platfrom/
end
it "fails validation if the specification contains warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = false, true
linter.lint.should == false
linter.errors.should.be.empty
linter.warnings.should.not.be.empty
end
it "validates in lenient mode if there are no erros but there are warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = true, true
linter.lint.should == true
linter.errors.should.be.empty
linter.warnings.should.not.be.empty
end
it "respects quick mode" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.expects(:peform_multiplatform_analysis).never
linter.expects(:install_pod).never
linter.expects(:xcodebuild_output_for_platfrom).never
linter.expects(:file_patterns_errors_for_platfrom).never
linter.lenient, linter.quick = false, true
linter.lint
end
it "produces deprecation notices" do
spec, file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\n if config.ios?\nend"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = false, true
linter.lint.should == false
linter.errors.should.be.empty
linter.warnings.join(' | ').should =~ /`config.ios\?' and `config.osx' will be removed in version 0.7/
end
it "uses xcodebuild to generate notes and warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.lenient, linter.quick = false, false
linter.lint.should == false
linter.notes.join(' | ').should.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses" unless `which xcodebuild`.strip.empty?
end
it "checks for file patterns" do
spec, file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\ns.resources = 'WRONG_FOLDER'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.stubs(:xcodebuild_output_for_platfrom).returns([])
linter.lenient, linter.quick = false, false
linter.lint.should == false
linter.errors.join(' | ').should.include "[resources = 'WRONG_FOLDER'] -> did not match any file"
end
end
...@@ -149,25 +149,6 @@ describe "A Pod::Specification, in general," do ...@@ -149,25 +149,6 @@ describe "A Pod::Specification, in general," do
@spec = Pod::Spec.new @spec = Pod::Spec.new
end end
def validate(&block)
Proc.new(&block).should.raise(Pod::Informative)
end
it "raises if the specification does not contain the minimum required attributes" do
exception = validate { @spec.validate! }
exception.message =~ /name.*version.*summary.*homepage.*authors.*(source.*part_of).*source_files/
end
it "raises if the platform is unrecognized" do
validate { @spec.validate! }.message.should.not.include 'platform'
@spec.platform = :ios
validate { @spec.validate! }.message.should.not.include 'platform'
@spec.platform = :osx
validate { @spec.validate! }.message.should.not.include 'platform'
@spec.platform = :windows
validate { @spec.validate! }.message.should.include 'platform'
end
it "returns the platform that the static library should be build for" do it "returns the platform that the static library should be build for" do
@spec.platform = :ios @spec.platform = :ios
@spec.platform.should == :ios @spec.platform.should == :ios
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment