Commit 0d387594 authored by Fabio Pelosin's avatar Fabio Pelosin

[ExternalSources] Clean-up and docs.

parent 48fdc200
module Pod module Pod
# Provides support for initializing the correct concrete class of an external
# source.
#
module ExternalSources module ExternalSources
# @return [AbstractExternalSource] an initialized instance of the concrete
# external source class associated with the option specified in the
# hash.
#
def self.from_dependency(dependency) def self.from_dependency(dependency)
name = dependency.root_name name = dependency.root_name
params = dependency.external_source params = dependency.external_source
if params.key?(:git)
GitSource.new(name, params) klass = if params.key?(:git) then GitSource
elsif params.key?(:podspec) elsif params.key?(:podspec) then PodspecSource
PodspecSource.new(name, params) elsif params.key?(:local) then LocalSource
elsif params.key?(:local) end
LocalSource.new(name, params)
if klass
klass.new(name, params)
else else
raise Informative, "Unknown external source parameters for #{name}: #{params}" msg = "Unknown external source parameters for `#{name}`: `#{params}`"
raise Informative, msg
end end
end end
#-------------------------------------------------------------------------#
# Abstract class that defines the common behaviour of external sources.
#
class AbstractExternalSource class AbstractExternalSource
include Config::Mixin # @return [String] the name of the Pod described by this external source.
#
attr_reader :name
attr_reader :name, :params # @return [Hash{Symbol => String}] the hash representation of the
# external source.
#
attr_reader :params
# @param [String] name @see name
# @param [Hash] params @see params
#
def initialize(name, params) def initialize(name, params)
@name, @params = name, params @name, @params = name, params
end end
# @return [Bool] whether an external source source is equal to another
# according to the {#name} and to the {#params}.
#
def ==(other)
return false if other.nil?
name == other.name && params == other.params
end
#--------------------------------------#
# @!group Specifications
public
# @return [Specification] returns the specification, either from the
# sandbox or by fetching the remote source, associated with the
# external source.
#
# TODO: rename to specification.
#
def specification_from_sandbox(sandbox, platform) def specification_from_sandbox(sandbox, platform)
specification_from_local(sandbox, platform) || specification_from_external(sandbox, platform) specification_from_local(sandbox, platform) ||
specification_from_external(sandbox, platform)
end end
# @return [Specification] returns the specification associated with the
# external source if available in the sandbox.
#
def specification_from_local(sandbox, platform) def specification_from_local(sandbox, platform)
if local_pod = sandbox.installed_pod_named(name, platform) if local_pod = sandbox.installed_pod_named(name, platform)
local_pod.top_specification local_pod.top_specification
end end
end end
# @return [Specification] returns the specification associated with the
# external source after fetching it from the remote source, even
# if is already present in the sandbox.
#
# @raise If not specification could be found.
#
def specification_from_external(sandbox, platform) def specification_from_external(sandbox, platform)
podspec = copy_external_source_into_sandbox(sandbox, platform) copy_external_source_into_sandbox(sandbox, platform)
spec = specification_from_local(sandbox, platform) spec = specification_from_local(sandbox, platform)
raise Informative, "No podspec found for `#{name}' in #{description}" unless spec unless spec
raise Informative, "No podspec found for `#{name}' in #{description}"
end
spec spec
end end
# Can store from a pathname or a string #--------------------------------------#
# @!group Subclasses hooks
# Fetches the external source from the remote according to the params.
#
# @param [Sandbox] sandbox
# the sandbox where the specification should be stored.
#
# @param [Platform] platform
# TODO this is not needed.
#
# @return [void]
#
def copy_external_source_into_sandbox(sandbox, platform)
raise "Abstract method"
end
# @return [String] a string representation of the source suitable for UI.
#
def description
raise "Abstract method"
end
private
# Stores a specification in the `Local Podspecs` folder.
#
# @param [Sandbox] sandbox
# the sandbox where the podspec should be stored.
#
# @param [String, Pathname] podspec
# The contents of the specification (String) or the path to a
# podspec file (Pathname).
#
# TODO This could be done by the sandbox.
# TODO The check for the podspec string is a bit primitive.
# #
def store_podspec(sandbox, podspec) def store_podspec(sandbox, podspec)
output_path = sandbox.root + "Local Podspecs/#{name}.podspec" output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
output_path.dirname.mkpath output_path.dirname.mkpath
if podspec.is_a?(String) if podspec.is_a?(String)
raise Informative, "No podspec found for `#{name}' in #{description}" unless podspec.include?('Spec.new') unless podspec.include?('Spec.new')
raise Informative, "No podspec found for `#{name}` in #{description}"
end
output_path.open('w') { |f| f.puts(podspec) } output_path.open('w') { |f| f.puts(podspec) }
else else
raise Informative, "No podspec found for `#{name}' in #{description}" unless podspec.exist? unless podspec.exist?
raise Informative, "No podspec found for `#{name}` in #{description}"
end
FileUtils.copy(podspec, output_path) FileUtils.copy(podspec, output_path)
end end
end end
def ==(other)
return if other.nil?
name == other.name && params == other.params
end
end end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a Git remote.
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class GitSource < AbstractExternalSource class GitSource < AbstractExternalSource
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
# @note To prevent a double download of the repository the pod is marked
# as pre-downloaded indicating to the installer that only clean
# operations are needed.
#
def copy_external_source_into_sandbox(sandbox, platform) def copy_external_source_into_sandbox(sandbox, platform)
UI.info("->".green + " Pre-downloading: '#{name}'") do UI.info("->".green + " Pre-downloading: '#{name}'") do
target = sandbox.root + name target = sandbox.root + name
...@@ -75,17 +183,26 @@ module Pod ...@@ -75,17 +183,26 @@ module Pod
end end
end end
# @see AbstractExternalSource#description
#
def description def description
"from `#{@params[:git]}'".tap do |description| "from `#{@params[:git]}'".tap do |description|
description << ", commit `#{@params[:commit]}'" if @params[:commit] description << ", commit `#{@params[:commit]}`" if @params[:commit]
description << ", branch `#{@params[:branch]}'" if @params[:branch] description << ", branch `#{@params[:branch]}`" if @params[:branch]
description << ", tag `#{@params[:tag]}'" if @params[:tag] description << ", tag `#{@params[:tag]}`" if @params[:tag]
end end
end end
end end
# can be http, file, etc #-------------------------------------------------------------------------#
# Provides support for fetching a specification file from an URL. Can be
# http, file, etc.
#
class PodspecSource < AbstractExternalSource class PodspecSource < AbstractExternalSource
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
def copy_external_source_into_sandbox(sandbox, _) def copy_external_source_into_sandbox(sandbox, _)
UI.info("->".green + " Fetching podspec for `#{name}' from: #{@params[:podspec]}") do UI.info("->".green + " Fetching podspec for `#{name}' from: #{@params[:podspec]}") do
path = @params[:podspec] path = @params[:podspec]
...@@ -94,27 +211,50 @@ module Pod ...@@ -94,27 +211,50 @@ module Pod
end end
end end
# @see AbstractExternalSource#description
#
def description def description
"from `#{@params[:podspec]}'" "from `#{@params[:podspec]}`"
end end
end end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a path local to
# the machine running the installation.
#
# Works with the {LocalPod::LocalSourcedPod} class.
#
class LocalSource < AbstractExternalSource class LocalSource < AbstractExternalSource
def pod_spec_path
path = Pathname.new(@params[:local]).expand_path
path += "#{name}.podspec"# unless path.to_s.include?("#{name}.podspec")
raise Informative, "No podspec found for `#{name}' in `#{@params[:local]}'" unless path.exist?
path
end
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
def copy_external_source_into_sandbox(sandbox, _) def copy_external_source_into_sandbox(sandbox, _)
store_podspec(sandbox, pod_spec_path) store_podspec(sandbox, pod_spec_path)
end end
# @see AbstractExternalSource#description
#
def description
"from `#{@params[:local]}`"
end
# @see AbstractExternalSource#specification_from_local
#
# @note The LocalSource class always fetches podspecs from the external
# source to provide always the freshest specification. Otherwise,
# once installed, the podspec would be updated only by `pod
# update`.
#
def specification_from_local(sandbox, platform) def specification_from_local(sandbox, platform)
specification_from_external(sandbox, platform) specification_from_external(sandbox, platform)
end end
# @see AbstractExternalSource#specification_from_local
#
# @note The LocalSource overrides the source of the specification to
# point to the local path.
#
def specification_from_external(sandbox, platform) def specification_from_external(sandbox, platform)
copy_external_source_into_sandbox(sandbox, platform) copy_external_source_into_sandbox(sandbox, platform)
spec = Specification.from_file(pod_spec_path) spec = Specification.from_file(pod_spec_path)
...@@ -122,8 +262,21 @@ module Pod ...@@ -122,8 +262,21 @@ module Pod
spec spec
end end
def description #--------------------------------------#
"from `#{@params[:local]}'"
# @!group Helpers
private
# @return [Pathname] the path of the podspec.
#
def pod_spec_path
path = Pathname.new(@params[:local]).expand_path
path += "#{name}.podspec"# unless path.to_s.include?("#{name}.podspec")
unless path.exist?
raise Informative, "No podspec found for `#{name}` in `#{@params[:local]}`"
end
path
end end
end end
end end
......
...@@ -2,39 +2,66 @@ require File.expand_path('../../spec_helper', __FILE__) ...@@ -2,39 +2,66 @@ require File.expand_path('../../spec_helper', __FILE__)
module Pod module Pod
describe ExternalSources do describe ExternalSources do
before do it "returns the instance of appropriate concrete class according to the parameters" do
@sandbox = temporary_sandbox git = Dependency.new("Reachability", :git => nil)
podspec = Dependency.new("Reachability", :podspec => nil)
local = Dependency.new("Reachability", :local => nil)
ExternalSources.from_dependency(git).class.should == ExternalSources::GitSource
ExternalSources.from_dependency(podspec).class.should == ExternalSources::PodspecSource
ExternalSources.from_dependency(local).class.should == ExternalSources::LocalSource
end end
end
describe ExternalSources::AbstractExternalSource do
xit "returns the name" do end
xit "returns the params" do end
xit "returns the compares to another" do end
xit "returns the specification" do end
xit "returns the specification from the sandbox if available" do end
xit "returns the specification fetching it from the external source" do end
end
it "marks a LocalPod as downloaded if it's from GitSource" do describe ExternalSources::GitSource do
it "creates a copy of the podspec" do
dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability')) dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability'))
external_source = ExternalSources.from_dependency(dependency) external_source = ExternalSources.from_dependency(dependency)
external_source.copy_external_source_into_sandbox(@sandbox, Platform.ios) external_source.copy_external_source_into_sandbox(config.sandbox, Platform.ios)
@sandbox.installed_pod_named('Reachability', Platform.ios).downloaded.should.be.true path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end end
it "creates a copy of the podspec (GitSource)" do it "marks a LocalPod as downloaded" do
dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability')) dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability'))
external_source = ExternalSources.from_dependency(dependency) external_source = ExternalSources.from_dependency(dependency)
external_source.copy_external_source_into_sandbox(@sandbox, Platform.ios) external_source.copy_external_source_into_sandbox(config.sandbox, Platform.ios)
path = @sandbox.root + 'Local Podspecs/Reachability.podspec' config.sandbox.installed_pod_named('Reachability', Platform.ios).downloaded.should.be.true
path.should.exist?
end end
it "creates a copy of the podspec (PodspecSource)" do xit "returns the description" do end
end
describe ExternalSources::PodspecSource do
it "creates a copy of the podspec" do
dependency = Dependency.new("Reachability", :podspec => fixture('integration/Reachability/Reachability.podspec').to_s) dependency = Dependency.new("Reachability", :podspec => fixture('integration/Reachability/Reachability.podspec').to_s)
external_source = ExternalSources.from_dependency(dependency) external_source = ExternalSources.from_dependency(dependency)
external_source.copy_external_source_into_sandbox(@sandbox, Platform.ios) external_source.copy_external_source_into_sandbox(config.sandbox, Platform.ios)
path = @sandbox.root + 'Local Podspecs/Reachability.podspec' path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist? path.should.exist?
end end
it "creates a copy of the podspec (LocalSource)" do xit "returns the description" do end
end
describe ExternalSources::LocalSource do
it "creates a copy of the podspec" do
dependency = Dependency.new("Reachability", :local => fixture('integration/Reachability')) dependency = Dependency.new("Reachability", :local => fixture('integration/Reachability'))
external_source = ExternalSources.from_dependency(dependency) external_source = ExternalSources.from_dependency(dependency)
external_source.copy_external_source_into_sandbox(@sandbox, Platform.ios) external_source.copy_external_source_into_sandbox(config.sandbox, Platform.ios)
path = @sandbox.root + 'Local Podspecs/Reachability.podspec' path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist? path.should.exist?
end end
xit "returns the description" do end
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