Commit ae244a6f authored by Boris Bügling's avatar Boris Bügling

Merge branch 'master' into feature-allow-homepage-redirects

Conflicts:
	lib/cocoapods/validator.rb
parents 7691aedd d3b515b3
......@@ -20,6 +20,19 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
[Piet Brauer](https://github.com/pietbrauer)
[Orta Therox](https://github.com/orta)
* Validate the reachability of screenshot URLs in podspecs while linting a
specification.
[Kyle Fuller](https://github.com/kylef)
[#2010](https://github.com/CocoaPods/CocoaPods/issues/2010)
* Prevent the user from using `pod` commands as root
[Kyle Fuller](https://github.com/kylef)
[#1815](https://github.com/CocoaPods/CocoaPods/issues/1815)
* Fix to keep absolute paths specified for local pods as is.
[Samuel Ford](https://github.com/samuelwford)
[#1042](https://github.com/CocoaPods/CocoaPods/issues/1042)
## 0.31.1
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.31.1...0.31.0)
[CocoaPods-Core](https://github.com/CocoaPods/Core/compare/0.31.1...0.31.0)
......@@ -55,6 +68,11 @@ To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides
[Robert Zuber](https://github.com/z00b)
[#1617](https://github.com/CocoaPods/CocoaPods/issues/1617)
* Generated prefix header file will now have unique prefix_header_contents for
Pods with subspecs.
[Luis de la Rosa](https://github.com/luisdelarosa)
[#1449](https://github.com/CocoaPods/CocoaPods/issues/1449)
* The linter will now check the reachability of the homepage of Podspecs during
a full lint.
[Richard Lee](https://github.com/dlackty)
......
......@@ -7,7 +7,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Core.git
revision: 5736f3cfbebe805c04e67a53729b9fa098ea8f9d
revision: a6d129d9a72bd7324414001daacbe8bfd96b2311
branch: master
specs:
cocoapods-core (0.31.1)
......@@ -59,10 +59,10 @@ GIT
GIT
remote: https://github.com/irrationalfab/PrettyBacon.git
revision: eaf7e6c786fd5ccc6fb88e943bf7c5e6c27569a3
revision: 1eeb06f7d381acd65414b86b42fdf3538faae01c
branch: master
specs:
prettybacon (0.0.1)
prettybacon (0.0.2)
bacon (~> 1.2)
GIT
......@@ -148,7 +148,7 @@ GEM
redcarpet (2.3.0)
rest-client (1.6.7)
mime-types (>= 1.16)
safe_yaml (1.0.1)
safe_yaml (1.0.2)
simplecov (0.8.2)
docile (~> 1.1.0)
multi_json
......@@ -158,7 +158,7 @@ GEM
term-ansicolor (1.3.0)
tins (~> 1.0)
thor (0.19.1)
tins (1.0.1)
tins (1.1.0)
webmock (1.15.2)
addressable (>= 2.2.7)
crack (>= 0.3.2)
......
......@@ -72,24 +72,3 @@ if ENV['COCOA_PODS_ENV'] == 'development'
# require 'awesome_print'
# require 'pry'
end
# TODO remove for CocoaPods 0.31
#
module Pod
class Specification
def pre_install(&block)
UI.warn "[#{self}] The pre install hook of the specification " \
"DSL has been deprecated, use the `resource_bundles` or the " \
"`prepare_command` attributes."
UI.puts "[#{self}] The pre_install hook will be removed in the next release".red
@pre_install_callback = block
end
def post_install(&block)
UI.warn "[#{self}] The post install hook of the specification " \
"DSL has been deprecated, use the `resource_bundles` or the " \
"`prepare_command` attributes."
UI.puts "[#{self}] The post_install hook will be removed in the next release".red
@post_install_callback = block
end
end
end
......@@ -43,11 +43,14 @@ module Pod
end
def self.run(argv)
help! "You cannot run CocoaPods as root." if Process.uid == 0
argv = CLAide::ARGV.new(argv)
if argv.flag?('version')
UI.puts VERSION
exit 0
end
super(argv)
UI.print_warnings
end
......
......@@ -480,7 +480,7 @@ Pod::Spec.new do |s|
DESC
s.homepage = "#{data[:homepage]}"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
......
......@@ -352,7 +352,8 @@ module Pod
UI.titled_section("Fetching podspec for `#{name}` #{description}", { :verbose_prefix => "-> " }) do
podspec = podspec_path
store_podspec(sandbox, podspec)
sandbox.store_local_path(name, podspec.dirname)
path_is_absolute_or_rooted_to_home = declared_path.absolute? || declared_path.to_s.start_with?('~')
sandbox.store_local_path(name, podspec.dirname, path_is_absolute_or_rooted_to_home)
end
end
......@@ -368,10 +369,15 @@ module Pod
# @!group Helpers
# @return [Pathname] the path as declared in the podspec
#
def declared_path
Pathname.new params[:path] || params[:local]
end
# @return [Pathname] the path of the podspec.
#
def podspec_path
declared_path = (params[:path] || params[:local]).to_s
path_with_ext = File.extname(declared_path) == '.podspec' ? declared_path : "#{declared_path}/#{name}.podspec"
podfile_dir = File.dirname(podfile_path || '')
absolute_path = File.expand_path(path_with_ext, podfile_dir)
......
......@@ -40,9 +40,12 @@ module Pod
# added to the top of the prefix header. For OS X `Cocoa/Cocoa.h`
# is imported.
#
# @note Only unique prefix_header_contents are added to the prefix header.
#
# @return [String]
#
# @todo Subspecs can specify prefix header information too.
# @todo Check to see if we have a similar duplication issue with file_accessor.prefix_header.
#
def generate
result = "#ifdef __OBJC__\n"
......@@ -53,12 +56,18 @@ module Pod
result << %|\n#import "#{import}"|
end
file_accessors.each do |file_accessor|
unique_prefix_header_contents = file_accessors.collect do |file_accessor|
file_accessor.spec_consumer.prefix_header_contents
end.compact.uniq
result << "\n"
if prefix_header_contents = file_accessor.spec_consumer.prefix_header_contents
unique_prefix_header_contents.each do |prefix_header_contents|
result << prefix_header_contents
result << "\n"
end
file_accessors.each do |file_accessor|
if prefix_header = file_accessor.prefix_header
result << Pathname(prefix_header).read
end
......
......@@ -296,9 +296,10 @@ module Pod
pod_names = pod_targets.map(&:pod_name).uniq
pod_names.each do |pod_name|
path = sandbox.pod_dir(pod_name)
local = sandbox.local?(pod_name)
@pods_project.add_pod_group(pod_name, path, local)
path = sandbox.pod_dir(pod_name)
was_absolute = sandbox.local_path_was_absolute?(pod_name)
@pods_project.add_pod_group(pod_name, path, local, was_absolute)
end
if config.podfile_path
......
......@@ -69,6 +69,7 @@ module Pod
@head_pods = []
@checkout_sources = {}
@development_pods = {}
@pods_with_absolute_path = []
end
# @return [Lockfile] the manifest which contains the information about the
......@@ -159,6 +160,16 @@ module Pod
end
end
# Returns true if the path as originally specified was absolute.
#
# @param [String] name
#
# @return [Bool] true if originally absolute
#
def local_path_was_absolute?(name)
@pods_with_absolute_path.include? name
end
# @return [Pathname] the directory where to store the documentation.
#
def documentation_dir
......@@ -338,11 +349,15 @@ module Pod
# @param [#to_s] path
# The local path where the Pod is stored.
#
# @param [Bool] was_absolute
# True if the specified local path was absolute.
#
# @return [void]
#
def store_local_path(name, path)
def store_local_path(name, path, was_absolute = false)
root_name = Specification.root_name(name)
development_pods[root_name] = path.to_s
@pods_with_absolute_path << root_name if was_absolute
end
# @return [Hash{String=>String}] The path of the Pods with a local source
......
......@@ -197,6 +197,7 @@ module Pod
#
def perform_extensive_analysis(spec)
validate_homepage(spec)
validate_screenshots(spec)
spec.available_platforms.each do |platform|
UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
......@@ -224,25 +225,23 @@ module Pod
MAX_HTTP_REDIRECTS = 3
# Performs validations related to the `homepage` attribute.
# Performs validation of a URL
#
def validate_homepage(spec)
def validate_url(url)
require 'rest'
homepage = spec.homepage
return unless homepage
begin
redirects = 0
resp = nil
loop do
resp = ::REST.head(homepage)
resp = ::REST.head(url)
if resp.status_code == 405
resp = ::REST.get(homepage)
resp = ::REST.get(url)
end
if [301, 302, 303, 307, 308].include? resp.status_code
homepage = resp.headers['location'].first
url = resp.headers['location'].first
redirects += 1
else
break
......@@ -251,12 +250,33 @@ module Pod
break unless redirects < MAX_HTTP_REDIRECTS
end
rescue
warning "There was a problem validating the homepage."
warning "There was a problem validating the URL #{url}."
resp = nil
end
if resp && !resp.success?
warning "The homepage is not reachable."
warning "The URL (#{url}) is not reachable."
end
resp
end
# Performs validations related to the `homepage` attribute.
#
def validate_homepage(spec)
if spec.homepage
validate_url(spec.homepage)
end
end
# Performs validation related to the `screenshots` attribute.
#
def validate_screenshots(spec)
spec.screenshots.each do |screenshot|
request = validate_url(screenshot)
if request && !(request.headers['content-type'] && request.headers['content-type'].first =~ /image\/.*/i)
warning "The screenshot #{screenshot} is not a valid image."
end
end
end
......
Subproject commit d0378da111a5368a28c019e57e4a9f3d3d8e9d94
Subproject commit eced44cc9e4bf19ce9c3b6d68dc4806af25252fa
......@@ -14,5 +14,9 @@ module Pod
UI.output.should.include 'spec/fixtures/spec-repos/master/AFNetworking'
end
it "doesn't let you run as root" do
Process.stubs(:uid).returns(0)
lambda { Pod::Command.run(['--version']) }.should.raise CLAide::Help
end
end
end
......@@ -331,6 +331,10 @@ describe "Integration" do
check "install --no-repo-update", "install_subspecs"
end
describe "Installs a Pod with subspecs and does not duplicate the prefix header" do
check "install --no-repo-update", "install_subspecs_no_duplicate_prefix"
end
describe "Installs a Pod with a local source" do
check "install --no-repo-update", "install_local_source"
end
......
......@@ -21,6 +21,43 @@ module Pod
EOS
end
# @note Declaring a subspec was found in issue #1449 to generate duplicates of the prefix_header_contents
it "does not duplicate the contents of the specification's prefix header when a subspec is declared" do
@spec.prefix_header_contents = '#import "BlocksKit.h"'
@spec.prefix_header_file = nil
@spec.subspec 'UI' do |subspec|
subspec.source_files = 'Source/UI/*.{h,m}'
end
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
# @note Declaring a subspec was found in issue #1449 to generate duplicates of the prefix_header_contents
it "does not duplicate the contents of the specification's prefix header when a subspec is declared multiple times" do
@spec.prefix_header_contents = '#import "BlocksKit.h"'
@spec.prefix_header_file = nil
@spec.subspec 'UI' do |su|
su.source_files = 'Source/UI/*.{h,m}'
end
@spec.subspec 'Helpers' do |sh|
sh.source_files = 'Source/Helpers/*.{h,m}'
end
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
it "includes the contents of the specification's prefix header file" do
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
......
......@@ -21,6 +21,16 @@ def generate_podfile(pods = ['JSONKit'])
end
end
# @return [Podfile]
#
def generate_local_podfile
podfile = Pod::Podfile.new do
platform :ios
xcodeproj SpecHelper.fixture('SampleProject/SampleProject'), 'Test' => :debug, 'App Store' => :release
pod 'SSToolkit', :path => SpecHelper.fixture('integration/sstoolkit')
end
end
#-----------------------------------------------------------------------------#
module Pod
......@@ -247,6 +257,15 @@ module Pod
@installer.pods_project.class.should == Pod::Project
end
it "preserves Pod paths specified as absolute or rooted to home" do
local_podfile = generate_local_podfile
local_installer = Installer.new(config.sandbox, local_podfile)
local_installer.send(:analyze)
local_installer.send(:prepare_pods_project)
group = local_installer.pods_project.group_for_spec('SSToolkit')
Pathname.new(group.path).should.be.absolute
end
it "adds the Podfile to the Pods project" do
config.stubs(:podfile_path).returns(Pathname.new('/Podfile'))
@installer.send(:prepare_pods_project)
......
......@@ -75,6 +75,7 @@ module Pod
validator = Validator.new(file)
validator.quick = true
validator.stubs(:validate_homepage)
validator.stubs(:validate_screenshots)
validator.validate
validator.validation_dir.should.be == Pathname.new("/private/tmp/CocoaPods/Lint")
end
......@@ -99,14 +100,14 @@ module Pod
WebMock::API.stub_request(:head, /not-found/).to_return(:status => 404)
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/not-found/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /The homepage is not reachable/
@sut.results.map(&:to_s).first.should.match /The URL (.*) is not reachable/
end
it "indicates if it was not able to validate the homepage" do
WebMock::API.stub_request(:head, 'banana-corp.local').to_raise(SocketError)
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /There was a problem validating the homepage/
@sut.results.map(&:to_s).first.should.match /There was a problem validating the URL/
end
it "does not fail if the homepage redirects" do
......@@ -131,7 +132,34 @@ module Pod
:status => 301, :headers => { 'Location' => 'http://banana-corp.local/redirect/' } )
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/redirect/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /The homepage is not reachable/
@sut.results.map(&:to_s).first.should.match /The URL \(.*\) is not reachable/
end
end
describe "Screenshot validation" do
require 'webmock'
before do
@sut = Validator.new(podspec_path)
@sut.stubs(:install_pod)
@sut.stubs(:build_pod)
@sut.stubs(:check_file_patterns)
@sut.stubs(:tear_down_validation_environment)
@sut.stubs(:validate_homepage)
WebMock::API.stub_request(:head, 'banana-corp.local/valid-image.png').to_return(:status => 200, :headers => { 'Content-Type' => 'image/png' })
end
it "checks if the screenshots are valid" do
Specification.any_instance.stubs(:screenshots).returns(['http://banana-corp.local/valid-image.png'])
@sut.validate
@sut.results.should.be.empty?
end
it "should fail if any of the screenshots URLS do not return an image" do
WebMock::API.stub_request(:head, 'banana-corp.local/').to_return(:status => 200)
Specification.any_instance.stubs(:screenshots).returns(['http://banana-corp.local/valid-image.png', 'http://banana-corp.local/'])
@sut.validate
@sut.results.map(&:to_s).first.should.match /The screenshot .* is not a valid image/
end
end
......@@ -139,6 +167,7 @@ module Pod
file = write_podspec(stub_podspec)
sut = Validator.new(file)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.no_clean = true
sut.validate
sut.validation_dir.should.exist
......@@ -148,6 +177,7 @@ module Pod
file = write_podspec(stub_podspec)
sut = Validator.new(file)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.expects(:install_pod).twice
sut.expects(:build_pod).twice
sut.expects(:check_file_patterns).twice
......@@ -157,6 +187,7 @@ module Pod
it "uses the deployment target of the specification" do
sut = Validator.new(podspec_path)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
podfile = sut.send(:podfile_from_spec, :ios, '5.0')
dependency = podfile.target_definitions['Pods'].dependencies.first
dependency.external_source.has_key?(:podspec).should.be.true
......@@ -165,6 +196,7 @@ module Pod
it "respects the local option" do
sut = Validator.new(podspec_path)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
podfile = sut.send(:podfile_from_spec, :ios, '5.0')
deployment_target = podfile.target_definitions['Pods'].platform.deployment_target
deployment_target.to_s.should == "5.0"
......@@ -175,6 +207,7 @@ module Pod
sut.stubs(:check_file_patterns)
sut.stubs(:xcodebuild).returns("file.m:1:1: warning: direct access to objective-c's isa is deprecated")
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.validate
first = sut.results.map(&:to_s).first
first.should.include "[xcodebuild]"
......@@ -186,6 +219,7 @@ module Pod
sut = Validator.new(file)
sut.stubs(:build_pod)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.validate
sut.results.map(&:to_s).first.should.match /source_files.*did not match/
sut.result_type.should == :error
......@@ -200,6 +234,7 @@ module Pod
spec = Specification.from_file(file)
sut = Validator.new(spec)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.stubs(:build_pod)
sut.validate
sut.validated?.should.be.true
......
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