Commit 943ea72d authored by Fabio Pelosin's avatar Fabio Pelosin

[Installer] Clean up & specs

parent d9f450c7
...@@ -81,17 +81,35 @@ module Pod ...@@ -81,17 +81,35 @@ module Pod
# @return [void] # @return [void]
# #
def install! def install!
resolve_dependencies
download_dependencies
generate_pods_project
if config.integrate_targets?
UI.section "Integrating client projects" do
integrate_user_project
end
end
end
def resolve_dependencies
UI.section "Resolving dependencies" do
analyze analyze
detect_pods_to_install detect_pods_to_install
prepare_for_legacy_compatibility prepare_for_legacy_compatibility
prepare_sandbox prepare_sandbox
end
end
def download_dependencies
UI.section "Downloading dependencies" do UI.section "Downloading dependencies" do
create_file_accessors create_file_accessors
install_pod_sources install_pod_sources
end end
end
UI.section "Generating Pods Project" do def generate_pods_project
UI.section "Generating pods project" do
prepare_pods_project prepare_pods_project
run_pre_install_hooks run_pre_install_hooks
install_file_references install_file_references
...@@ -100,12 +118,6 @@ module Pod ...@@ -100,12 +118,6 @@ module Pod
write_pod_project write_pod_project
write_lockfiles write_lockfiles
end end
if config.integrate_targets?
UI.section "Integrating client projects" do
integrate_user_project
end
end
end end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
...@@ -117,7 +129,7 @@ module Pod ...@@ -117,7 +129,7 @@ module Pod
# @return [Analyzer] the analyzer which provides the information about what # @return [Analyzer] the analyzer which provides the information about what
# needs to be installed. # needs to be installed.
# #
attr_reader :analyzer attr_reader :analysis_result
# @return [Pod::Project] the `Pods/Pods.xcodeproj` project. # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
# #
...@@ -140,18 +152,15 @@ module Pod ...@@ -140,18 +152,15 @@ module Pod
private private
# TODO: This is recreating the file accessors
# TODO: the file accessor should be initializable without a path list
# @!group Installation steps # @!group Installation steps
# @return [void] # @return [void]
# #
def analyze def analyze
@analyzer = Analyzer.new(sandbox, podfile, lockfile) analyzer = Analyzer.new(sandbox, podfile, lockfile)
@analyzer.update_mode = update_mode analyzer.update_mode = update_mode
@analyzer.analyze @analysis_result = analyzer.analyze
@libraries = analyzer.libraries @libraries = analyzer.result.libraries
end end
# Computes the list of the Pods that should be installed or reinstalled in # Computes the list of the Pods that should be installed or reinstalled in
...@@ -173,11 +182,11 @@ module Pod ...@@ -173,11 +182,11 @@ module Pod
def detect_pods_to_install def detect_pods_to_install
names = [] names = []
analyzer.specifications.each do |spec| analysis_result.specifications.each do |spec|
root_name = spec.root.name root_name = spec.root.name
if update_mode if update_mode
if spec.version.head? #|| TODO resolver.pods_from_external_sources.include?(root_name) if spec.version.head? # || resolver.pods_from_external_sources.include?(root_name) TODO
names << root_name names << root_name
end end
end end
...@@ -187,7 +196,7 @@ module Pod ...@@ -187,7 +196,7 @@ module Pod
end end
end end
names += analyzer.sandbox_state.added + analyzer.sandbox_state.changed names += analysis_result.sandbox_state.added + analysis_result.sandbox_state.changed
names = names.map { |name| Specification.root_name(name) } names = names.map { |name| Specification.root_name(name) }
names = names.flatten.uniq names = names.flatten.uniq
@names_of_pods_to_install = names @names_of_pods_to_install = names
...@@ -210,10 +219,6 @@ module Pod ...@@ -210,10 +219,6 @@ module Pod
# #
# @todo [#247] Clean the headers of only the pods to install. # @todo [#247] Clean the headers of only the pods to install.
# #
# @todo [#534] Clean all the Pods folder that are not unchanged
#
# @todo Use the local pod implode.
#
# @todo Clean the podspecs of all the pods that aren't unchanged so the # @todo Clean the podspecs of all the pods that aren't unchanged so the
# resolution process doesn't get confused by them. # resolution process doesn't get confused by them.
# #
...@@ -221,36 +226,19 @@ module Pod ...@@ -221,36 +226,19 @@ module Pod
sandbox.build_headers.implode! sandbox.build_headers.implode!
sandbox.public_headers.implode! sandbox.public_headers.implode!
# TODO local option unless analysis_result.sandbox_state.deleted.empty?
unless analyzer.sandbox_state.deleted.empty?
UI.section "Removing deleted dependencies" do UI.section "Removing deleted dependencies" do
analyzer.sandbox_state.deleted.each do |pod_name| analysis_result.sandbox_state.deleted.each do |pod_name|
UI.section("Removing #{pod_name}", "-> ".red) do UI.section("Removing #{pod_name}", "-> ".red) do
path = sandbox.root + pod_name sandbox.clean_pod(pod_name)
path.rmtree if path.exist?
end end
end end
end end
end end
end end
# Creates the Pods project from scratch if it doesn't exists. # TODO: the file accessor should be initialized by the sandbox as they
# # created by the Pod source installer as well.
# @return [void]
#
# @todo Clean and modify the project if it exists.
#
def prepare_pods_project
UI.message "- Creating Pods project" do
@pods_project = Pod::Project.new(sandbox.project_path)
if config.podfile_path.exist?
@pods_project.add_podfile(config.podfile_path)
end
sandbox.project = @pods_project
end
end
#
# #
def create_file_accessors def create_file_accessors
libraries.each do |library| libraries.each do |library|
...@@ -275,7 +263,6 @@ module Pod ...@@ -275,7 +263,6 @@ module Pod
# #
def install_pod_sources def install_pod_sources
@installed_specs = [] @installed_specs = []
root_specs = analyzer.specifications.map { |spec| spec.root }.uniq
root_specs.each do |spec| root_specs.each do |spec|
if names_of_pods_to_install.include?(spec.name) if names_of_pods_to_install.include?(spec.name)
UI.section("Installing #{spec}".green, "-> ".green) do UI.section("Installing #{spec}".green, "-> ".green) do
...@@ -313,6 +300,22 @@ module Pod ...@@ -313,6 +300,22 @@ module Pod
@installed_specs.concat(specs_by_platform.values.flatten) @installed_specs.concat(specs_by_platform.values.flatten)
end end
# Creates the Pods project from scratch if it doesn't exists.
#
# @return [void]
#
# @todo Clean and modify the project if it exists.
#
def prepare_pods_project
UI.message "- Creating Pods project" do
@pods_project = Pod::Project.new(sandbox.project_path)
if config.podfile_path.exist?
@pods_project.add_podfile(config.podfile_path)
end
sandbox.project = @pods_project
end
end
# Installs the file references in the Pods project. This is done once per # Installs the file references in the Pods project. This is done once per
# Pod as the same file reference might be shared by multiple targets. # Pod as the same file reference might be shared by multiple targets.
...@@ -353,12 +356,13 @@ module Pod ...@@ -353,12 +356,13 @@ module Pod
# Writes the Podfile and the lock files. # Writes the Podfile and the lock files.
# #
# @todo Pass the checkout options to the Lockfile.
#
# @return [void] # @return [void]
# #
def write_lockfiles def write_lockfiles
# checkout_options = sandbox.checkout_options # checkout_options = sandbox.checkout_options
# TODO pass the options to the Lockfile @lockfile = Lockfile.generate(podfile, analysis_result.specifications)
@lockfile = Lockfile.generate(podfile, analyzer.specifications)
UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
@lockfile.write_to_disk(config.lockfile_path) @lockfile.write_to_disk(config.lockfile_path)
...@@ -383,13 +387,13 @@ module Pod ...@@ -383,13 +387,13 @@ module Pod
# #
def integrate_user_project def integrate_user_project
installation_root = config.installation_root installation_root = config.installation_root
libraries = analyzer.libraries integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, libraries)
UserProjectIntegrator.new(podfile, sandbox, installation_root, libraries).integrate! integrator.integrate!
end end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
public private
# @!group Hooks # @!group Hooks
...@@ -400,7 +404,7 @@ module Pod ...@@ -400,7 +404,7 @@ module Pod
def run_pre_install_hooks def run_pre_install_hooks
UI.message "- Running pre install hooks" do UI.message "- Running pre install hooks" do
installed_specs.each do |spec| installed_specs.each do |spec|
executed = spec.pre_install!(pod_data(spec), library_data(libraries.first)) #todo executed = spec.pre_install!(pod_data(spec), library_data(libraries.first)) #TODO
UI.message "- #{spec.name}" if executed UI.message "- #{spec.name}" if executed
end end
...@@ -429,6 +433,8 @@ module Pod ...@@ -429,6 +433,8 @@ module Pod
end end
end end
#-------------------------------------------------------------------------#
public public
# @!group Hooks Data # @!group Hooks Data
...@@ -447,8 +453,6 @@ module Pod ...@@ -447,8 +453,6 @@ module Pod
end end
def pods_data def pods_data
specs = libraries.map(&:specs).flatten
root_specs = specs.map { |spec| spec.root }.uniq
root_specs.map do |spec| root_specs.map do |spec|
pod_data(spec) pod_data(spec)
end end
...@@ -466,5 +470,18 @@ module Pod ...@@ -466,5 +470,18 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
private
# @!group Private helpers
# @return [Array<Specification>] All the root specifications of the
# installation.
#
def root_specs
analysis_result.specifications.map { |spec| spec.root }.uniq
end
#-------------------------------------------------------------------------#
end end
end end
...@@ -12,8 +12,8 @@ module Pod ...@@ -12,8 +12,8 @@ module Pod
# #
attr_reader :sandbox attr_reader :sandbox
# @return [Podfile] The Podfile specification that contains the information # @return [Podfile] The Podfile specification that contains the
# of the Pods that should be installed. # information of the Pods that should be installed.
# #
attr_reader :podfile attr_reader :podfile
...@@ -37,23 +37,27 @@ module Pod ...@@ -37,23 +37,27 @@ module Pod
# Performs the analysis. # Performs the analysis.
# #
# The Podfile and the Lockfile provide the information necessary to compute # The Podfile and the Lockfile provide the information necessary to
# which specification should be installed. The manifest of the sandbox # compute which specification should be installed. The manifest of the
# returns which specifications are installed. # sandbox returns which specifications are installed.
# #
# @return [void] # @return [AnalysisResult]
# #
def analyze def analyze
@podfile_state = generate_podfile_state
update_repositories_if_needed update_repositories_if_needed
@result = AnalysisResult.new
@result.podfile_state = generate_podfile_state
@libraries = generated_libraries @result.libraries = generated_libraries
@locked_dependencies = generate_version_locking_dependencies @locked_dependencies = generate_version_locking_dependencies
@specs_by_target = resolve_dependencies @result.specs_by_target = resolve_dependencies
@specifications = generate_specifications @result.specifications = generate_specifications
@sandbox_state = generate_sandbox_state @result.sandbox_state = generate_sandbox_state
@result
end end
attr_accessor :result
# @return [Bool] Whether an installation should be performed or this # @return [Bool] Whether an installation should be performed or this
# CocoaPods project is already up to date. # CocoaPods project is already up to date.
# #
...@@ -75,7 +79,7 @@ module Pod ...@@ -75,7 +79,7 @@ module Pod
lockfile != sandbox.manifest lockfile != sandbox.manifest
end end
#-------------------------------------------------------------------------# #-----------------------------------------------------------------------#
# @!group Configuration # @!group Configuration
...@@ -96,42 +100,12 @@ module Pod ...@@ -96,42 +100,12 @@ module Pod
attr_accessor :allow_pre_downloads attr_accessor :allow_pre_downloads
alias_method :allow_pre_downloads?, :allow_pre_downloads alias_method :allow_pre_downloads?, :allow_pre_downloads
#-------------------------------------------------------------------------# #-----------------------------------------------------------------------#
# @!group Analysis products
public
# @return [SpecsState] the states of the Podfile specs.
#
attr_reader :podfile_state
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
# grouped by target.
#
attr_reader :specs_by_target
# @return [Array<Specification>] the specifications of the resolved version private
# of Pods that should be installed.
#
attr_reader :specifications
# @return [SpecsState] the states of the {Sandbox} respect the resolved
# specifications.
#
attr_reader :sandbox_state
# @return [Array<Library>] the libraries generated by the target
# definitions.
#
attr_reader :libraries
#-------------------------------------------------------------------------#
# @!group Analysis steps # @!group Analysis steps
private
# Compares the {Podfile} with the {Lockfile} in order to detect which # Compares the {Podfile} with the {Lockfile} in order to detect which
# dependencies should be locked. # dependencies should be locked.
# #
...@@ -176,9 +150,10 @@ module Pod ...@@ -176,9 +150,10 @@ module Pod
# Creates the models that represent the libraries generated by CocoaPods. # Creates the models that represent the libraries generated by CocoaPods.
# #
# @note The libraries are generated before the resolution process because # @note The libraries are generated before the resolution process
# it might be necessary to infer the platform from the user # because it might be necessary to infer the platform from the
# targets, which in turns requires to identify the user project. # user targets, which in turns requires to identify the user
# project.
# #
# @note The specification of the libraries are added in the # @note The specification of the libraries are added in the
# {#resolve_dependencies} step. # {#resolve_dependencies} step.
...@@ -214,11 +189,11 @@ module Pod ...@@ -214,11 +189,11 @@ module Pod
libraries libraries
end end
# Generates dependencies that require the specific version of the Pods that # Generates dependencies that require the specific version of the Pods
# haven't changed in the {Lockfile}. # that haven't changed in the {Lockfile}.
# #
# These dependencies are passed to the {Resolver}, unless the installer is # These dependencies are passed to the {Resolver}, unless the installer
# in update mode, to prevent it from upgrading the Pods that weren't # is in update mode, to prevent it from upgrading the Pods that weren't
# changed in the {Podfile}. # changed in the {Podfile}.
# #
# @return [Array<Dependency>] the dependencies generate by the lockfile # @return [Array<Dependency>] the dependencies generate by the lockfile
...@@ -226,7 +201,7 @@ module Pod ...@@ -226,7 +201,7 @@ module Pod
# #
def generate_version_locking_dependencies def generate_version_locking_dependencies
return [] if update_mode? return [] if update_mode?
podfile_state.unchanged.map do |pod| result.podfile_state.unchanged.map do |pod|
lockfile.dependency_to_lock_pod_named(pod) lockfile.dependency_to_lock_pod_named(pod)
end end
end end
...@@ -235,16 +210,16 @@ module Pod ...@@ -235,16 +210,16 @@ module Pod
# #
# @note In this step the specs are added to the libraries. # @note In this step the specs are added to the libraries.
# #
# @note As some dependencies might have external sources the resolver is # @note As some dependencies might have external sources the resolver
# aware of the {Sandbox} and interacts with it to download the # is aware of the {Sandbox} and interacts with it to download the
# podspecs of the external sources. This is necessary because the # podspecs of the external sources. This is necessary because the
# resolver needs their specifications to analyze their # resolver needs their specifications to analyze their
# dependencies. # dependencies.
# #
# @note The specifications of the external sources which are added, # @note The specifications of the external sources which are added,
# modified or removed need to deleted from the sandbox before the # modified or removed need to deleted from the sandbox before the
# resolution process. Otherwise the resolver might use an incorrect # resolution process. Otherwise the resolver might use an
# specification instead of pre-downloading it. # incorrect specification instead of pre-downloading it.
# #
# @note In update mode the resolver is set to always update the specs # @note In update mode the resolver is set to always update the specs
# from external sources. # from external sources.
...@@ -255,6 +230,7 @@ module Pod ...@@ -255,6 +230,7 @@ module Pod
def resolve_dependencies def resolve_dependencies
specs_by_target = nil specs_by_target = nil
podfile_state = result.podfile_state
if allow_pre_downloads? if allow_pre_downloads?
changed_pods = podfile_state.added + podfile_state.changed + podfile_state.deleted changed_pods = podfile_state.added + podfile_state.changed + podfile_state.deleted
changed_pods.each do |pod_name| changed_pods.each do |pod_name|
...@@ -271,7 +247,7 @@ module Pod ...@@ -271,7 +247,7 @@ module Pod
end end
specs_by_target.each do |target_definition, specs| specs_by_target.each do |target_definition, specs|
lib = libraries.find { |l| l.target_definition == target_definition} lib = result.libraries.find { |l| l.target_definition == target_definition}
lib.specs = specs lib.specs = specs
end end
...@@ -283,10 +259,11 @@ module Pod ...@@ -283,10 +259,11 @@ module Pod
# @return [Array<Specification>] the list of the specifications. # @return [Array<Specification>] the list of the specifications.
# #
def generate_specifications def generate_specifications
specs_by_target.values.flatten.uniq result.specs_by_target.values.flatten.uniq
end end
# Computes the state of the sandbox respect to the resolved specifications. # Computes the state of the sandbox respect to the resolved
# specifications.
# #
# The logic is the following: # The logic is the following:
# #
...@@ -305,8 +282,8 @@ module Pod ...@@ -305,8 +282,8 @@ module Pod
# Unchanged # Unchanged
# - If none of the above conditions match. # - If none of the above conditions match.
# #
# @todo [CocoaPods > 0.18] Version 0.17 falls back to the lockfile of the # @todo [CocoaPods > 0.18] Version 0.17 falls back to the lockfile of
# Podfile for the sandbox manifest to prevent the full # the Podfile for the sandbox manifest to prevent the full
# re-installation for upgrading users (this was the old behaviour # re-installation for upgrading users (this was the old behaviour
# pre sandbox manifest) of all the pods. Drop in 0.18. # pre sandbox manifest) of all the pods. Drop in 0.18.
# #
...@@ -318,14 +295,14 @@ module Pod ...@@ -318,14 +295,14 @@ module Pod
sandbox_state = SpecsState.new sandbox_state = SpecsState.new
UI.section "Comparing resolved specification to the sandbox manifest:" do UI.section "Comparing resolved specification to the sandbox manifest:" do
resolved_subspecs_names = specifications.group_by { |s| s.root.name } resolved_subspecs_names = result.specifications.group_by { |s| s.root.name }
resolved_names = resolved_subspecs_names.keys resolved_names = resolved_subspecs_names.keys
if sandbox_lockfile if sandbox_lockfile
sandbox_subspecs_names = sandbox_lockfile.pod_names.group_by { |name| Specification.root_name(name) } sandbox_subspecs_names = sandbox_lockfile.pod_names.group_by { |name| Specification.root_name(name) }
sandbox_names = sandbox_subspecs_names.keys sandbox_names = sandbox_subspecs_names.keys
all_names = (resolved_names + sandbox_names).uniq all_names = (resolved_names + sandbox_names).uniq
root_specs = specifications.map(&:root).uniq root_specs = result.specifications.map(&:root).uniq
is_changed = lambda do |name| is_changed = lambda do |name|
spec = root_specs.find { |r_spec| r_spec.name == name } spec = root_specs.find { |r_spec| r_spec.name == name }
...@@ -352,7 +329,7 @@ module Pod ...@@ -352,7 +329,7 @@ module Pod
sandbox_state sandbox_state
end end
#-------------------------------------------------------------------------# #-----------------------------------------------------------------------#
# @!group Analysis internal products # @!group Analysis internal products
...@@ -361,7 +338,7 @@ module Pod ...@@ -361,7 +338,7 @@ module Pod
# #
attr_reader :locked_dependencies attr_reader :locked_dependencies
#-------------------------------------------------------------------------# #-----------------------------------------------------------------------#
private private
...@@ -479,7 +456,37 @@ module Pod ...@@ -479,7 +456,37 @@ module Pod
platform platform
end end
#-------------------------------------------------------------------------# #-----------------------------------------------------------------------#
class AnalysisResult
# @return [SpecsState] the states of the Podfile specs.
#
attr_accessor :podfile_state
# @return [Hash{TargetDefinition => Array<Spec>}] the specifications
# grouped by target.
#
attr_accessor :specs_by_target
# @return [Array<Specification>] the specifications of the resolved
# version of Pods that should be installed.
#
attr_accessor :specifications
# @return [SpecsState] the states of the {Sandbox} respect the resolved
# specifications.
#
attr_accessor :sandbox_state
# @return [Array<Library>] the libraries generated by the target
# definitions.
#
attr_accessor :libraries
end
#-----------------------------------------------------------------------#
# This class represents the state of a collection of Pods. # This class represents the state of a collection of Pods.
# #
...@@ -489,8 +496,8 @@ module Pod ...@@ -489,8 +496,8 @@ module Pod
class SpecsState class SpecsState
# @param [Hash{Symbol=>String}] pods_by_state # @param [Hash{Symbol=>String}] pods_by_state
# The **root** name of the pods grouped by their state (`:added`, # The **root** name of the pods grouped by their state
# `:removed`, `:changed` or `:unchanged`). # (`:added`, `:removed`, `:changed` or `:unchanged`).
# #
def initialize(pods_by_state = nil) def initialize(pods_by_state = nil)
@added = [] @added = []
...@@ -535,10 +542,10 @@ module Pod ...@@ -535,10 +542,10 @@ module Pod
# Adds the name of a Pod to the give state. # Adds the name of a Pod to the give state.
# #
# @parm [String] # @param [String]
# the name of the Pod. # the name of the Pod.
# #
# @parm [Symbol] # @param [Symbol]
# the state of the Pod. # the state of the Pod.
# #
# @raise If there is an attempt to add the name of a subspec. # @raise If there is an attempt to add the name of a subspec.
......
...@@ -86,6 +86,19 @@ module Pod ...@@ -86,6 +86,19 @@ module Pod
root.rmtree root.rmtree
end end
#
#
#
def clean_pod(name)
root_name = Specification.root_name(name)
unless local?(root_name)
path = pod_dir(name)
path.rmtree if path.exist?
end
podspe_path = specification_path(name)
podspe_path.rmtree if podspe_path
end
# @return [String] a string representation suitable for debugging. # @return [String] a string representation suitable for debugging.
# #
def inspect def inspect
......
...@@ -49,8 +49,7 @@ module Pod ...@@ -49,8 +49,7 @@ module Pod
#--------------------------------------# #--------------------------------------#
it "computes the state of the Podfile respect to the Lockfile" do it "computes the state of the Podfile respect to the Lockfile" do
@analyzer.analyze state = @analyzer.analyze.podfile_state
state = @analyzer.podfile_state
state.added.should == ["AFNetworking", "libextobjc"] state.added.should == ["AFNetworking", "libextobjc"]
state.changed.should == ["JSONKit"] state.changed.should == ["JSONKit"]
state.unchanged.should == ["SVPullToRefresh"] state.unchanged.should == ["SVPullToRefresh"]
...@@ -74,8 +73,7 @@ module Pod ...@@ -74,8 +73,7 @@ module Pod
#--------------------------------------# #--------------------------------------#
it "generates the libraries which represent the target definitions" do it "generates the libraries which represent the target definitions" do
@analyzer.analyze libs = @analyzer.analyze.libraries
libs = @analyzer.libraries
libs.map(&:name).should == ['Pods'] libs.map(&:name).should == ['Pods']
lib = libs.first lib = libs.first
lib.support_files_root.should == config.sandbox.root lib.support_files_root.should == config.sandbox.root
...@@ -90,8 +88,7 @@ module Pod ...@@ -90,8 +88,7 @@ module Pod
it "generates configures the library appropriately if the installation will not integrate" do it "generates configures the library appropriately if the installation will not integrate" do
config.integrate_targets = false config.integrate_targets = false
@analyzer.analyze lib = @analyzer.analyze.libraries.first
lib = @analyzer.libraries.first
lib.user_project_path.should == config.installation_root lib.user_project_path.should == config.installation_root
lib.user_target_uuids.should == [] lib.user_target_uuids.should == []
...@@ -115,8 +112,7 @@ module Pod ...@@ -115,8 +112,7 @@ module Pod
#--------------------------------------# #--------------------------------------#
it "resolves the dependencies" do it "resolves the dependencies" do
@analyzer.analyze @analyzer.analyze.specifications.map(&:to_s).should == [
@analyzer.specifications.map(&:to_s).should == [
"AFNetworking (1.0.1)", "AFNetworking (1.0.1)",
"JSONKit (1.5pre)", "JSONKit (1.5pre)",
"SVPullToRefresh (0.4)", "SVPullToRefresh (0.4)",
...@@ -134,8 +130,7 @@ module Pod ...@@ -134,8 +130,7 @@ module Pod
end end
it "adds the specifications to the correspondent libraries in after the resolution" do it "adds the specifications to the correspondent libraries in after the resolution" do
@analyzer.analyze @analyzer.analyze.libraries.first.specs.map(&:to_s).should == [
@analyzer.libraries.first.specs.map(&:to_s).should == [
"AFNetworking (1.0.1)", "AFNetworking (1.0.1)",
"JSONKit (1.5pre)", "JSONKit (1.5pre)",
"SVPullToRefresh (0.4)", "SVPullToRefresh (0.4)",
...@@ -169,8 +164,7 @@ module Pod ...@@ -169,8 +164,7 @@ module Pod
it "computes the state of the Sandbox respect to the resolved dependencies" do it "computes the state of the Sandbox respect to the resolved dependencies" do
@analyzer.stubs(:lockfile).returns(nil) @analyzer.stubs(:lockfile).returns(nil)
@analyzer.analyze state = @analyzer.analyze.sandbox_state
state = @analyzer.sandbox_state
state.added.sort.should == ["AFNetworking", "JSONKit", "SVPullToRefresh", "libextobjc"] state.added.sort.should == ["AFNetworking", "JSONKit", "SVPullToRefresh", "libextobjc"]
end end
......
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
# TODO add tests for multiple targets!
# @return [Lockfile] # @return [Lockfile]
# #
def generate_lockfile def generate_lockfile
...@@ -22,57 +20,410 @@ def generate_podfile(pods = ['JSONKit']) ...@@ -22,57 +20,410 @@ def generate_podfile(pods = ['JSONKit'])
pods.each { |name| pod name } pods.each { |name| pod name }
end end
end end
module Pod
describe Installer do
# before do #-----------------------------------------------------------------------------#
# @sandbox = temporary_sandbox
# config.repos_dir = fixture('spec-repos')
# config.sandbox_root = @sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# end
#
# it 'tells each pod to link its headers' do module Pod
# @pods[0].expects(:link_headers) describe Installer do
# do_install!
# end
describe "Concerning pre-installation computations" do
# @sandbox = temporary_sandbox
# config.sandbox_root = temporary_sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# resolver = Resolver.new(podfile, nil, @sandbox)
# @installer = Installer.new(resolver)
# target_installer = @installer.target_installers.first
# target_installer.install
before do before do
podfile = generate_podfile podfile = generate_podfile
lockfile = generate_lockfile lockfile = generate_lockfile
config.integrate_targets = false
@installer = Installer.new(config.sandbox, podfile, lockfile) @installer = Installer.new(config.sandbox, podfile, lockfile)
SpecHelper.create_sample_app_copy_from_fixture('SampleProject') end
#-------------------------------------------------------------------------#
describe "In general" do
before do
@installer.stubs(:resolve_dependencies)
@installer.stubs(:download_dependencies)
@installer.stubs(:generate_pods_project)
@installer.stubs(:integrate_user_project)
end
it "in runs the pre-install hooks before adding the file references" do
@installer.unstub(:generate_pods_project)
@installer.stubs(:prepare_pods_project)
@installer.stubs(:install_targets)
@installer.stubs(:run_post_install_hooks)
@installer.stubs(:write_pod_project)
@installer.stubs(:write_lockfiles)
def @installer.run_pre_install_hooks
@hook_called = true
end
def @installer.install_file_references
@hook_called.should.be.true
end
@installer.install! @installer.install!
end end
xit "marks all pods as added if there is no lockfile" do it "in runs the post-install hooks before serializing the Pods project" do
true.should.be.true @installer.stubs(:prepare_pods_project)
# @installer.pods_added_from_the_lockfile.should == ['JSONKit'] @installer.stubs(:run_pre_install_hooks)
@installer.stubs(:install_file_references)
@installer.stubs(:install_targets)
@installer.stubs(:write_lockfiles)
@installer.unstub(:generate_pods_project)
def @installer.run_post_install_hooks
@hook_called = true
end
def @installer.write_pod_project
@hook_called.should.be.true
end
@installer.install!
end end
# it "adds the files of the pod to the Pods project only once" do it "integrates the user targets if the corresponding config is set" do
# @installer.install! config.integrate_targets = true
# group = @installer.project.pods.groups.find { |g| g.name == 'Reachability' } @installer.expects(:integrate_user_project)
# group.files.map(&:name).sort.should == ["Reachability.h", "Reachability.m"] @installer.install!
# end end
# it 'clears out its headers root when preparing for install' do it "doesn't integrates the user targets if the corresponding config is not set" do
# @sandbox.prepare_for_install config.integrate_targets = false
# @sandbox.build_headers.root.should.not.exist @installer.expects(:integrate_user_project).never
# end @installer.install!
end
end
#-------------------------------------------------------------------------#
describe "Dependencies Resolution" do
describe "#analyze" do
it "analyzes the Podfile, the Lockfile and the Sandbox" do
@installer.send(:analyze)
@installer.analysis_result.sandbox_state.added.should == ["JSONKit"]
end end
it "stores the libraries created by the analyzer" do
@installer.send(:analyze)
@installer.libraries.map(&:name).should == ['Pods']
end
it "configures the analizer to use update mode if appropriate" do
@installer.update_mode = true
Installer::Analyzer.any_instance.expects(:update_mode=).with(true)
@installer.send(:analyze)
@installer.libraries.map(&:name).should == ['Pods']
end
end
#--------------------------------------#
describe "#detect_pods_to_install" do
before do
@analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.specifications = []
@analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new()
@installer.stubs(:analysis_result).returns(@analysis_result)
Pathname.any_instance.stubs(:exist?).returns(true)
end
it "includes the added Pods" do
@analysis_result.sandbox_state.add_name('Added-Pod', :added)
@installer.send(:detect_pods_to_install)
@installer.names_of_pods_to_install.should == ['Added-Pod']
end
it "includes the changed Pods" do
@analysis_result.sandbox_state.add_name('Changed-Pod', :changed)
@installer.send(:detect_pods_to_install)
@installer.names_of_pods_to_install.should == ['Changed-Pod']
end
it "includes head pods in update mode" do
spec = Spec.new do |s|
s.name = 'Head-Pod'
end
spec.version.head = true
@analysis_result.specifications = [spec]
@installer.update_mode = true
@installer.send(:detect_pods_to_install)
@installer.names_of_pods_to_install.should == ['Head-Pod']
end
it "doesn't includes head pods if not in update mode" do
spec = Spec.new do |s|
s.name = 'Head-Pod'
end
spec.version.head = true
@analysis_result.specifications = [spec]
@installer.update_mode = false
@installer.send(:detect_pods_to_install)
@installer.names_of_pods_to_install.should == []
end
xit "includes pods from external sources in update mode" do
end
xit "doesn't includes pods from external sources if not in update mode" do
end
it "includes pods whose root folder doesn't exists" do
Pathname.any_instance.stubs(:exist?).returns(false)
spec = Spec.new do |s|
s.name = 'Head-Pod'
end
@analysis_result.specifications = [spec]
@installer.update_mode = false
@installer.send(:detect_pods_to_install)
@installer.names_of_pods_to_install.should == ['Head-Pod']
end
xit "includes pods whose root folder is empty" do
end
end
#--------------------------------------#
describe "#prepare_sandbox" do
before do
@analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.specifications = []
@analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new()
@installer.stubs(:analysis_result).returns(@analysis_result)
end
it "cleans the header stores" do
config.sandbox.build_headers.expects(:implode!)
config.sandbox.public_headers.expects(:implode!)
@installer.send(:prepare_sandbox)
end
it "deletes the sources of the removed Pods" do
@analysis_result.sandbox_state.add_name('Deleted-Pod', :deleted)
config.sandbox.expects(:clean_pod).with('Deleted-Pod')
@installer.send(:prepare_sandbox)
end
end
end
#-------------------------------------------------------------------------#
describe "Downloading dependencies" do
describe "#install_pod_sources" do
it "installs all the Pods which are marked as needing installation" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
@installer.stubs(:root_specs).returns([spec])
@installer.stubs(:names_of_pods_to_install).returns(['BananaLib'])
@installer.expects(:install_source_of_pod).with('BananaLib')
@installer.send(:install_pod_sources)
end
it "correctly configures the Pod source installer" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
library = Library.new(nil)
library.specs = [spec]
library.platform = :ios
@installer.stubs(:libraries).returns([library])
@installer.instance_variable_set(:@installed_specs, [])
Installer::PodSourceInstaller.any_instance.expects(:install!)
@installer.send(:install_source_of_pod, 'BananaLib')
end
it "maintains the list of the installed specs" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
library = Library.new(nil)
library.specs = [spec]
@installer.stubs(:libraries).returns([library])
@installer.instance_variable_set(:@installed_specs, [])
Installer::PodSourceInstaller.any_instance.stubs(:install!)
@installer.send(:install_source_of_pod, 'BananaLib')
@installer.installed_specs.should == [spec]
end
end
end
#-------------------------------------------------------------------------#
describe "Generating pods project" do
describe "#prepare_pods_project" do
it "creates the Pods project" do
@installer.send(:prepare_pods_project)
@installer.pods_project.class.should == Pod::Project
end
it "adds the Podfile to the Pods project" do
config.podfile_path.stubs(:exist?).returns(true)
@installer.send(:prepare_pods_project)
f = @installer.pods_project['Podfile']
f.name.should == 'Podfile'
end
end
#--------------------------------------#
describe "#install_file_references" do
it "installs the file references" do
Installer::FileReferencesInstaller.any_instance.expects(:install!)
@installer.send(:install_file_references)
end
end
#--------------------------------------#
describe "#install_targets" do
it "install the targets of the Pod project" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil, nil)
target_definition.target_dependencies << Dependency.new('BananaLib')
library = Library.new(target_definition)
library.specs = [spec]
@installer.stubs(:libraries).returns([library])
Installer::TargetInstaller.any_instance.expects(:install!)
@installer.send(:install_targets)
end
it "skips empty libraries" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil, nil)
library = Library.new(target_definition)
library.specs = [spec]
@installer.stubs(:libraries).returns([library])
Installer::TargetInstaller.any_instance.expects(:install!).never
@installer.send(:install_targets)
end
end
#--------------------------------------#
describe "#write_pod_project" do
it "sorts the main group" do
@installer.send(:prepare_pods_project)
@installer.pods_project.main_group.expects(:sort_by_type!)
@installer.send(:write_pod_project)
end
it "sorts the frameworks group" do
@installer.send(:prepare_pods_project)
@installer.pods_project['Frameworks'].expects(:sort_by_type!)
@installer.send(:write_pod_project)
end
it "saves the project to the given path" do
@installer.send(:prepare_pods_project)
path = temporary_directory + 'Pods/Pods.xcodeproj'
@installer.pods_project.expects(:save_as).with(path)
@installer.send(:write_pod_project)
end
end
#--------------------------------------#
describe "#write_lockfiles" do
before do
@analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.specifications = [fixture_spec('banana-lib/BananaLib.podspec')]
@installer.stubs(:analysis_result).returns(@analysis_result)
end
it "generates the lockfile" do
@installer.send(:write_lockfiles)
@installer.lockfile.pod_names.should == ['BananaLib']
end
it "writes the lockfile" do
@installer.send(:write_lockfiles)
lockfile = Lockfile.from_file(temporary_directory + 'Podfile.lock')
lockfile.pod_names.should == ['BananaLib']
end
it "writes the sandbox manifest" do
@installer.send(:write_lockfiles)
lockfile = Lockfile.from_file(temporary_directory + 'Pods/Manifest.lock')
lockfile.pod_names.should == ['BananaLib']
end
end
end
#-------------------------------------------------------------------------#
describe "Integrating client projects" do
it "integrates the client projects" do
Installer::UserProjectIntegrator.any_instance.expects(:integrate!)
@installer.send(:integrate_user_project)
end
end
#-------------------------------------------------------------------------#
describe "Hooks" do
xit "runs the pre install hooks" do
end
xit "run_post_install_hooks" do
end
xit "creates the installer data hook argument" do
end
xit "creates the target installers data hook argument" do
end
xit "creates the pods data hook argument" do
end
xit "creates the pod data hook argument" do
end
xit "creates the library data hook argument" do
end
end
#-------------------------------------------------------------------------#
# before do
# @sandbox = temporary_sandbox
# config.repos_dir = fixture('spec-repos')
# config.sandbox_root = @sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
# end
#
# describe "by default" do # describe "by default" do
# before do # before do
# podfile = Podfile.new do # podfile = Podfile.new do
......
...@@ -36,6 +36,24 @@ module Pod ...@@ -36,6 +36,24 @@ module Pod
File.directory?(temporary_directory + 'Sandbox').should.be.false File.directory?(temporary_directory + 'Sandbox').should.be.false
end end
it "cleans any trace of the Pod with the given name" do
pod_root = @sandbox.root + 'BananaLib'
pod_root.mkpath
@sandbox.store_podspec('BananaLib', fixture('banana-lib/BananaLib.podspec'))
specification_path = @sandbox.specification_path('BananaLib')
@sandbox.clean_pod('BananaLib')
pod_root.should.not.exist
specification_path.should.not.exist
end
it "doesn't remove the root of local Pods while cleaning" do
pod_root = @sandbox.root + 'BananaLib'
@sandbox.stubs(:local?).returns(true)
pod_root.mkpath
@sandbox.clean_pod('BananaLib')
pod_root.should.exist
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