Commit ce8650bb authored by Luke Redpath's avatar Luke Redpath

Refactor the handling of different external sources within a dependency, and if the specification

for an external source can be loaded from the sandbox, because it's already been downloaded, then
just use it rather than trying to pre-download it again.
parent f6e3c90c
Subproject commit 07cf34ba82c250093fd1bba5dd37d6298bcdfeeb Subproject commit dd73ed13de67165c2e7e6271482b5a4a20e07f69
module Gem module Gem
end end
require 'rubygems/dependency' require 'rubygems/dependency'
require 'open-uri'
module Pod module Pod
class Dependency < Gem::Dependency class Dependency < Gem::Dependency
attr_accessor :only_part_of_other_pod attr_accessor :only_part_of_other_pod
alias_method :only_part_of_other_pod?, :only_part_of_other_pod alias_method :only_part_of_other_pod?, :only_part_of_other_pod
attr_accessor :external_spec_source attr_reader :external_source
attr_accessor :specification attr_accessor :specification
def initialize(*name_and_version_requirements, &block) def initialize(*name_and_version_requirements, &block)
...@@ -19,7 +19,7 @@ module Pod ...@@ -19,7 +19,7 @@ module Pod
elsif !name_and_version_requirements.empty? && block.nil? elsif !name_and_version_requirements.empty? && block.nil?
if name_and_version_requirements.last.is_a?(Hash) if name_and_version_requirements.last.is_a?(Hash)
@external_spec_source = name_and_version_requirements.pop @external_source = ExternalSources.from_params(name_and_version_requirements[0], name_and_version_requirements.pop)
end end
super(*name_and_version_requirements) super(*name_and_version_requirements)
...@@ -33,12 +33,20 @@ module Pod ...@@ -33,12 +33,20 @@ module Pod
def ==(other) def ==(other)
super && super &&
@only_part_of_other_pod == other.only_part_of_other_pod && @only_part_of_other_pod == other.only_part_of_other_pod &&
(@specification ? @specification == other.specification : @external_spec_source == other.external_spec_source) (@specification ? @specification == other.specification : @external_source == other.external_source)
end end
def subspec_dependency? def subspec_dependency?
@name.include?('/') @name.include?('/')
end end
def inline?
@inline_podspec
end
def external?
!@external_source.nil?
end
# In case this is a dependency for a subspec, e.g. 'RestKit/Networking', # In case this is a dependency for a subspec, e.g. 'RestKit/Networking',
# this returns 'RestKit', which is what the Pod::Source needs to know to # this returns 'RestKit', which is what the Pod::Source needs to know to
...@@ -58,48 +66,18 @@ module Pod ...@@ -58,48 +66,18 @@ module Pod
def to_s def to_s
version = '' version = ''
if source = @external_spec_source if external?
version << "from `#{source[:git] || source[:podspec]}'" version << @external_source.description
version << ", commit `#{source[:commit]}'" if source[:commit] elsif inline?
version << ", tag `#{source[:tag]}'" if source[:tag]
elsif @inline_podspec
version << "defined in Podfile" version << "defined in Podfile"
elsif @version_requirements != Gem::Requirement.default elsif @version_requirements != Gem::Requirement.default
version << @version_requirements.to_s version << @version_requirements.to_s
end end
version.empty? ? @name : "#{@name} (#{version})" version.empty? ? @name : "#{@name} (#{version})"
end end
# In case this dependency was defined with either a repo url, :podspec, or block,
# this method will return the Specification instance.
def specification
@specification ||= begin
if @external_spec_source
config = Config.instance
pod_root = config.project_pods_root + @name
spec = nil
if @external_spec_source[:podspec]
config.project_pods_root.mkpath
spec = config.project_pods_root + "#{@name}.podspec"
source = @external_spec_source[:podspec]
# can be http, file, etc
require 'open-uri'
puts " * Fetching podspec for `#{@name}' from: #{source}" unless config.silent?
open(source) do |io|
spec.open('w') { |f| f << io.read }
end
else
puts " * Pre-downloading: `#{@name}'" unless config.silent?
Downloader.for_dependency(self).download
spec = pod_root + "#{@name}.podspec"
end
Specification.from_file(spec)
end
end
end
def pod_root def specification_from_sandbox(sandbox)
Config.instance.project_pods_root + @name @external_source.specification_from_sandbox(sandbox)
end end
# Taken from RubyGems 1.3.7 # Taken from RubyGems 1.3.7
...@@ -138,5 +116,68 @@ module Pod ...@@ -138,5 +116,68 @@ module Pod
end end
end end
module ExternalSources
def self.from_params(name, params)
if params.key?(:git)
GitSource.new(name, params)
elsif params.key?(:podspec)
PodspecSource.new(name, params)
else
raise Informative, "Unknown external source parameters for #{name}: #{params}"
end
end
class AbstractExternalSource
attr_reader :name, :params
def initialize(name, params)
@name, @params = name, params
end
def specification_from_sandbox(sandbox)
if local_pod = sandbox.installed_pod_named(name)
local_pod.specification
else
copy_external_source_into_sandbox(sandbox)
sandbox.installed_pod_named(name).specification
end
end
def ==(other_source)
return if other_source.nil?
name == other_source.name &&
params == other_source.params
end
end
class GitSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox)
puts " * Pre-downloading: '#{name}'" unless Config.instance.silent?
Downloader.for_target(sandbox.root + name, @params).download
end
def description
"from '#{@params[:git]}'".tap do |description|
description << ", commit `#{@params[:commit]}'" if @params[:commit]
description << ", tag `#{@params[:tag]}'" if @params[:tag]
end
end
end
class PodspecSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox)
output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
podspec_url = @params[:podspec] # can be http, file, etc
puts " * Fetching podspec for `#{name}' from: #{podspec_url}" unless Config.instance.silent?
open(source) do |io|
output_path.open('w') { |f| f << io.read }
end
end
def description
version << "from '#{source[:podspec]}'"
end
end
end
end end
end end
...@@ -11,10 +11,6 @@ module Pod ...@@ -11,10 +11,6 @@ module Pod
spec = spec.part_of_specification if spec.part_of_other_pod? spec = spec.part_of_specification if spec.part_of_other_pod?
for_target(pod.root, spec.source.dup) for_target(pod.root, spec.source.dup)
end end
def self.for_dependency(dependency)
for_target(dependency.pod_root, dependency.external_spec_source)
end
attr_reader :target_path, :url, :options attr_reader :target_path, :url, :options
......
...@@ -22,6 +22,10 @@ module Pod ...@@ -22,6 +22,10 @@ module Pod
end end
end end
def name
specification.name
end
def create def create
root.mkpath unless exists? root.mkpath unless exists?
end end
......
module Pod module Pod
class Resolver class Resolver
def initialize(podfile) def initialize(podfile, sandbox)
@podfile = podfile @podfile = podfile
@sandbox = sandbox
end end
def resolve def resolve
...@@ -37,8 +38,11 @@ module Pod ...@@ -37,8 +38,11 @@ module Pod
end end
def find_dependency_set(dependency) def find_dependency_set(dependency)
if external_spec = dependency.specification if dependency.specification
Specification::Set::External.new(external_spec) Specification::Set::External.new(dependency.specification)
elsif external_source = dependency.external_source
specification = external_source.specification_from_sandbox(@sandbox)
Specification::Set::External.new(specification)
else else
Source.search(dependency) Source.search(dependency)
end end
......
...@@ -49,5 +49,9 @@ module Pod ...@@ -49,5 +49,9 @@ module Pod
LocalPod.from_podspec(Pathname.new(podspec), self) LocalPod.from_podspec(Pathname.new(podspec), self)
end end
end end
def installed_pod_named(name)
installed_pods.find { |pod| pod.name == name }
end
end end
end end
...@@ -30,12 +30,12 @@ describe "Pod::Dependency" do ...@@ -30,12 +30,12 @@ describe "Pod::Dependency" do
dep.to_top_level_spec_dependency.should == Pod::Dependency.new('RestKit', '>= 1.2.3') dep.to_top_level_spec_dependency.should == Pod::Dependency.new('RestKit', '>= 1.2.3')
end end
it "is equal to another dependency if `external_spec_source' is the same" do it "is equal to another dependency if `external_source' is the same" do
dep1 = Pod::Dependency.new('bananas', :git => 'GIT-URL') dep1 = Pod::Dependency.new('bananas', :git => 'GIT-URL')
dep2 = Pod::Dependency.new('bananas') dep2 = Pod::Dependency.new('bananas')
dep1.should.not == dep2 dep1.should.not == dep2
dep2.external_spec_source = { :git => 'GIT-URL' } dep3 = Pod::Dependency.new('bananas', :git => 'GIT-URL')
dep1.should == dep2 dep1.should == dep3
end end
it "is equal to another dependency if `specification' is equal" do it "is equal to another dependency if `specification' is equal" do
...@@ -45,4 +45,35 @@ describe "Pod::Dependency" do ...@@ -45,4 +45,35 @@ describe "Pod::Dependency" do
dep2 = Pod::Dependency.new { |s| s.name = 'bananas'; s.version = '1' } dep2 = Pod::Dependency.new { |s| s.name = 'bananas'; s.version = '1' }
dep1.should == dep2 dep1.should == dep2
end end
it 'raises if created without either valid name/version/external requirements or a block' do
lambda { Pod::Dependency.new }.should.raise Pod::Informative
end
end
describe "Pod::Dependency", "defined with a block" do
before do
@dependency = Pod::Dependency.new do |spec|
spec.name = "my-custom-spec"
spec.version = "1.0.3"
end
end
it 'it identifies itself as an inline dependency' do
@dependency.should.be.inline
end
it 'attaches a custom spec to the dependency, configured by the block' do
@dependency.specification.name.should == "my-custom-spec"
end
end
describe "Pod::Dependency", "with a hash of external source settings" do
before do
@dependency = Pod::Dependency.new("cocoapods", :git => "git://github.com/cocoapods/cocoapods")
end
it 'it identifies itself as an external dependency' do
@dependency.should.be.external
end
end end
...@@ -23,7 +23,7 @@ describe "Pod::Podfile" do ...@@ -23,7 +23,7 @@ describe "Pod::Podfile" do
dependency 'SomeExternalPod', :git => 'GIT-URL', :commit => '1234' dependency 'SomeExternalPod', :git => 'GIT-URL', :commit => '1234'
end end
dep = podfile.dependency_by_top_level_spec_name('SomeExternalPod') dep = podfile.dependency_by_top_level_spec_name('SomeExternalPod')
dep.external_spec_source.should == { :git => 'GIT-URL', :commit => '1234' } dep.external_source.params.should == { :git => 'GIT-URL', :commit => '1234' }
end end
it "adds a dependency on a library outside of a spec repo (the repo does not need to contain a podspec)" do it "adds a dependency on a library outside of a spec repo (the repo does not need to contain a podspec)" do
...@@ -31,7 +31,7 @@ describe "Pod::Podfile" do ...@@ -31,7 +31,7 @@ describe "Pod::Podfile" do
dependency 'SomeExternalPod', :podspec => 'http://gist/SomeExternalPod.podspec' dependency 'SomeExternalPod', :podspec => 'http://gist/SomeExternalPod.podspec'
end end
dep = podfile.dependency_by_top_level_spec_name('SomeExternalPod') dep = podfile.dependency_by_top_level_spec_name('SomeExternalPod')
dep.external_spec_source.should == { :podspec => 'http://gist/SomeExternalPod.podspec' } dep.external_source.params.should == { :podspec => 'http://gist/SomeExternalPod.podspec' }
end end
it "adds a dependency on a library by specifying the podspec inline" do it "adds a dependency on a library by specifying the podspec inline" do
......
...@@ -39,13 +39,13 @@ describe "Pod::Resolver" do ...@@ -39,13 +39,13 @@ describe "Pod::Resolver" do
end end
it "returns all specs needed for the dependency" do it "returns all specs needed for the dependency" do
specs = Pod::Resolver.new(@podfile).resolve specs = Pod::Resolver.new(@podfile, stub('sandbox')).resolve
specs.map(&:class).uniq.should == [Pod::Specification] specs.map(&:class).uniq.should == [Pod::Specification]
specs.map(&:name).sort.should == %w{ ASIHTTPRequest ASIWebPageRequest Reachability } specs.map(&:name).sort.should == %w{ ASIHTTPRequest ASIWebPageRequest Reachability }
end end
it "does not raise if all dependencies match the platform of the root spec (Podfile)" do it "does not raise if all dependencies match the platform of the root spec (Podfile)" do
resolver = Pod::Resolver.new(@podfile) resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
@podfile.platform :ios @podfile.platform :ios
lambda { resolver.resolve }.should.not.raise lambda { resolver.resolve }.should.not.raise
...@@ -54,7 +54,7 @@ describe "Pod::Resolver" do ...@@ -54,7 +54,7 @@ describe "Pod::Resolver" do
end end
it "raises once any of the dependencies does not match the platform of the root spec (Podfile)" do it "raises once any of the dependencies does not match the platform of the root spec (Podfile)" do
resolver = StubbedResolver.new(config.rootspec) resolver = StubbedResolver.new(config.rootspec, stub('sandbox'))
@podfile.platform :ios @podfile.platform :ios
resolver.stub_platform = :ios resolver.stub_platform = :ios
...@@ -76,7 +76,7 @@ describe "Pod::Resolver" do ...@@ -76,7 +76,7 @@ describe "Pod::Resolver" do
dependency 'RestKit/ObjectMapping' dependency 'RestKit/ObjectMapping'
end end
config.rootspec = @podfile config.rootspec = @podfile
resolver = Pod::Resolver.new(@podfile) resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.map(&:name).sort.should == %w{ LibComponentLogging-Core LibComponentLogging-NSLog RestKit RestKit/Network RestKit/ObjectMapping } resolver.resolve.map(&:name).sort.should == %w{ LibComponentLogging-Core LibComponentLogging-NSLog RestKit RestKit/Network RestKit/ObjectMapping }
end end
end end
......
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