Commit a583e50a authored by Fabio Pelosin's avatar Fabio Pelosin

[Sandbox] Clean up.

This includes a fix for an issue which caused the use of the incorrect
specification for dependencies from external sources.

Closes #548.
parent 170fa2e4
...@@ -38,6 +38,11 @@ ...@@ -38,6 +38,11 @@
- It is now possible to specify default values for the configuration in `~/.cocoapods/config.yaml`. - It is now possible to specify default values for the configuration in `~/.cocoapods/config.yaml`.
- CocoaPods now keeps track of the checksum of the specifications of the installed Pods and reinstalls them if needed. - CocoaPods now keeps track of the checksum of the specifications of the installed Pods and reinstalls them if needed.
###### Bug fixes
- CocoaPods is not confused anymore by to dependencies from external sources.
[#548](https://github.com/CocoaPods/CocoaPods/issues/548)
###### Codebase ###### Codebase
- Major clean up and refactor of the whole code base, with great reduction of - Major clean up and refactor of the whole code base, with great reduction of
......
...@@ -84,9 +84,11 @@ module Pod ...@@ -84,9 +84,11 @@ module Pod
attr_accessor :update_mode attr_accessor :update_mode
alias_method :update_mode?, :update_mode alias_method :update_mode?, :update_mode
# @return [Bool] Whether the analysis allows predownloads and thus # @return [Bool] Whether the analysis allows pre-downloads and thus
# modifications to the sandbox. # modifications to the sandbox.
# #
# @note This flag should not be used in installations.
#
# @note This is used by the `pod outdated` command to prevent # @note This is used by the `pod outdated` command to prevent
# modification of the sandbox in the resolution process. # modification of the sandbox in the resolution process.
# #
...@@ -186,7 +188,7 @@ module Pod ...@@ -186,7 +188,7 @@ module Pod
libraries = [] libraries = []
podfile.target_definitions.values.each do |target_definition| podfile.target_definitions.values.each do |target_definition|
lib = Library.new(target_definition) lib = Library.new(target_definition)
lib.support_files_root = config.sandbox.root lib.support_files_root = config.sandbox.library_support_files_dir(lib.name)
if config.integrate_targets? if config.integrate_targets?
lib.user_project_path = compute_user_project_path(target_definition) lib.user_project_path = compute_user_project_path(target_definition)
...@@ -231,8 +233,13 @@ module Pod ...@@ -231,8 +233,13 @@ module Pod
# @note As some dependencies might have external sources the resolver is # @note As some dependencies might have external sources the resolver is
# aware of the {Sandbox} and interacts with it to download the # 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 the specifications to analyze their dependencies # resolver needs their specifications to analyze their
# (which might be from external sources). # dependencies.
#
# @note The specifications of the external sources which are added,
# modified or removed need to deleted from the sandbox before the
# resolution process. Otherwise the resolver might use an 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.
...@@ -243,6 +250,14 @@ module Pod ...@@ -243,6 +250,14 @@ module Pod
def resolve_dependencies def resolve_dependencies
specs_by_target = nil specs_by_target = nil
if allow_pre_downloads?
changed_pods = podfile_state.added + podfile_state.changed + podfile_state.deleted
changed_pods.each do |pod_name|
podspec = sandbox.specification_path(pod_name)
podspec.delete if podspec
end
end
UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do
resolver = Resolver.new(sandbox, podfile, locked_dependencies) resolver = Resolver.new(sandbox, podfile, locked_dependencies)
resolver.update_external_specs = update_mode? resolver.update_external_specs = update_mode?
......
...@@ -27,6 +27,7 @@ module Pod ...@@ -27,6 +27,7 @@ module Pod
# source control. # source control.
# #
class Installer class Installer
autoload :TargetInstaller, 'cocoapods/installer/target_installer' autoload :TargetInstaller, 'cocoapods/installer/target_installer'
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator' autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
...@@ -74,9 +75,6 @@ module Pod ...@@ -74,9 +75,6 @@ module Pod
# necessary to retrieve their podspec (unless it is instructed not to # necessary to retrieve their podspec (unless it is instructed not to
# do it). # do it).
# #
# @note The order of the steps is very important and should be changed
# carefully.
#
# @return [void] # @return [void]
# #
def install! def install!
...@@ -85,9 +83,7 @@ module Pod ...@@ -85,9 +83,7 @@ module Pod
generate_names_of_pods_to_install generate_names_of_pods_to_install
prepare_for_legacy_compatibility prepare_for_legacy_compatibility
clean_global_support_files prepare_sandbox
clean_removed_pods
clean_pods_to_install
install_dependencies install_dependencies
install_targets install_targets
write_lockfiles write_lockfiles
...@@ -127,6 +123,8 @@ module Pod ...@@ -127,6 +123,8 @@ module Pod
# #
attr_reader :names_of_pods_to_install attr_reader :names_of_pods_to_install
attr_reader :libraries
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @!group Installation steps # @!group Installation steps
...@@ -137,6 +135,7 @@ module Pod ...@@ -137,6 +135,7 @@ module Pod
@analyzer = Analyzer.new(sandbox, podfile, lockfile) @analyzer = Analyzer.new(sandbox, podfile, lockfile)
@analyzer.update_mode = update_mode @analyzer.update_mode = update_mode
@analyzer.analyze @analyzer.analyze
@libraries = analyzer.libraries
end end
# Converts the specifications produced by the Resolver in local pods. # Converts the specifications produced by the Resolver in local pods.
...@@ -146,8 +145,8 @@ module Pod ...@@ -146,8 +145,8 @@ module Pod
# #
# @return [void] # @return [void]
# #
# @todo [#535] LocalPods should resolve the specification passing the # @todo [#535] LocalPods should resolve the path of the specifications
# library. # passing the library as arguments.
# #
# @todo Why the local pods are generated by the sandbox? I guess because # @todo Why the local pods are generated by the sandbox? I guess because
# some where pre-downloaded? However the sandbox should just store # some where pre-downloaded? However the sandbox should just store
...@@ -156,16 +155,27 @@ module Pod ...@@ -156,16 +155,27 @@ module Pod
def generate_local_pods def generate_local_pods
@local_pods_by_target = {} @local_pods_by_target = {}
analyzer.specs_by_target.each do |target_definition, specs| analyzer.specs_by_target.each do |target_definition, specs|
@local_pods_by_target[target_definition] = specs.map do |spec| libray = libraries.find {|l| l.target_definition == target_definition }
# TODO the sanbox cached the local pods by target definition
# take into account local? in specification#==
locally_sourced_pods = {}
local_pods = {}
libray.local_pods = specs.map do |spec|
if spec.local? if spec.local?
sandbox.locally_sourced_pod_for_spec(spec, target_definition.platform) local_pod = (locally_sourced_pods[spec.root.name] ||= LocalPod::LocalSourcedPod.new(spec.root, sandbox, target_definition.platform))
local_pod.add_specification(spec)
else else
sandbox.local_pod_for_spec(spec, target_definition.platform) local_pod = (local_pods[spec.root.name] ||= LocalPod.new(spec.root, sandbox, target_definition.platform))
local_pod.add_specification(spec)
end end
local_pod
end.uniq.compact end.uniq.compact
end end
@local_pods = local_pods_by_target.values.flatten.uniq.sort_by { |pod| pod.name.downcase } @local_pods = libraries.map(&:local_pods).flatten.uniq.sort_by { |pod| pod.name.downcase }
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
...@@ -215,36 +225,26 @@ module Pod ...@@ -215,36 +225,26 @@ module Pod
# @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.
# #
def clean_global_support_files # @todo [#247] Clean the headers of only the pods to install.
sandbox.prepare_for_install
end
# @return [void] In this step we clean all the files related to the removed
# Pods.
# #
# @todo Use the local pod implode. # @todo Use the local pod implode.
# #
# @todo [#534] Clean all the Pods folder that are not unchanged? # @todo [#534] Clean all the Pods folder that are not unchanged
# #
def clean_removed_pods def prepare_sandbox
UI.section "Removing deleted dependencies" do sandbox.build_headers.implode!
pods_deleted_from_the_lockfile.each do |pod_name| sandbox.public_headers.implode!
UI.section("Removing #{pod_name}", "-> ".red) do
path = sandbox.root + pod_name unless analyzer.sandbox_state.deleted.empty?
path.rmtree if path.exist? UI.section "Removing deleted dependencies" do
pods_deleted_from_the_lockfile.each do |pod_name|
UI.section("Removing #{pod_name}", "-> ".red) do
path = sandbox.root + pod_name
path.rmtree if path.exist?
end
end end
end end
end unless analyzer.sandbox_state.deleted.empty? end
end
# @return [void] In this step we clean the files of the Pods that will be
# installed. We clean the files that might affect the resolution
# process and the files that might not be overwritten.
#
# @todo [#247] Clean the headers of only the pods to install.
#
def clean_pods_to_install
end end
# @return [void] Install the Pods. If the resolver indicated that a Pod # @return [void] Install the Pods. If the resolver indicated that a Pod
...@@ -274,14 +274,8 @@ module Pod ...@@ -274,14 +274,8 @@ module Pod
# @note In this step we clean also the Pods that have been pre-downloaded # @note In this step we clean also the Pods that have been pre-downloaded
# in AbstractExternalSource#specification_from_sandbox. # in AbstractExternalSource#specification_from_sandbox.
# #
# @todo [#529] Podspecs should not be preserved anymore to prevent user
# confusion. Currently we are copying the ones form external sources
# in `Local Podspecs` and this feature is not needed anymore.
# I think that copying all the used podspecs would be helpful for
# debugging.
#
def install_local_pod(pod) def install_local_pod(pod)
unless pod.downloaded? unless sandbox.predownloaded_pods.include?(pod.name)
pod.implode pod.implode
download_pod(pod) download_pod(pod)
end end
...@@ -356,10 +350,12 @@ module Pod ...@@ -356,10 +350,12 @@ module Pod
# #
def prepare_pods_project def prepare_pods_project
UI.message "- Creating Pods project" do UI.message "- Creating Pods project" do
@pods_project = Pod::Project.new(config.sandbox) @pods_project = Pod::Project.new(nil)
if config.podfile_path.exist? if config.podfile_path.exist?
@pods_project.add_podfile(config.podfile_path) podfile_relative_path = config.podfile_path.relative_path_from(sandbox.project_path.dirname)
@pods_project.add_podfile(podfile_relative_path)
end end
sandbox.project = @pods_project
end end
end end
...@@ -368,10 +364,10 @@ module Pod ...@@ -368,10 +364,10 @@ module Pod
# @return [void] # @return [void]
# #
def generate_target_installers def generate_target_installers
@target_installers = podfile.target_definitions.values.map do |definition| @target_installers = libraries.map do |library|
pods_for_target = local_pods_by_target[definition] unless library.target_definition.empty?
libray = analyzer.libraries.find {|l| l.target_definition == definition } TargetInstaller.new(sandbox, library)
TargetInstaller.new(pods_project, libray, pods_for_target) unless definition.empty? end
end.compact end.compact
end end
...@@ -441,11 +437,10 @@ module Pod ...@@ -441,11 +437,10 @@ module Pod
def generate_target_support_files def generate_target_support_files
UI.message"- Installing targets" do UI.message"- Installing targets" do
target_installers.each do |target_installer| target_installers.each do |target_installer|
pods_for_target = local_pods_by_target[target_installer.library.target_definition]
target_installer.install! target_installer.install!
acknowledgements_path = target_installer.library.acknowledgements_path acknowledgements_path = target_installer.library.acknowledgements_path
Generator::Acknowledgements.new(target_installer.library.target_definition, Generator::Acknowledgements.new(target_installer.library.target_definition,
pods_for_target).save_as(acknowledgements_path) target_installer.library.local_pods).save_as(acknowledgements_path)
generate_dummy_source(target_installer) generate_dummy_source(target_installer)
end end
end end
...@@ -511,7 +506,7 @@ module Pod ...@@ -511,7 +506,7 @@ module Pod
# #
def integrate_user_project def integrate_user_project
return unless config.integrate_targets? return unless config.integrate_targets?
UserProjectIntegrator.new(podfile, pods_project, config.project_root, analyzer.libraries).integrate! UserProjectIntegrator.new(podfile, sandbox, config.project_root, analyzer.libraries).integrate!
end end
end end
end end
...@@ -7,27 +7,21 @@ module Pod ...@@ -7,27 +7,21 @@ module Pod
# #
class TargetInstaller class TargetInstaller
# @return [Project] The Pods project. # @return [Sandbox] sandbox the sandbox where the support files should
# be generated.
# #
attr_reader :project attr_reader :sandbox
# @return [Library] The library whose target needs to be generated. # @return [Library] The library whose target needs to be generated.
# #
attr_reader :library attr_reader :library
# @return [Array<LocalPod>] The pods are required by the target
# definition of this installer.
#
attr_reader :pods
# @param [Project] project @see project # @param [Project] project @see project
# @param [TargetDefinition] target_definition @see target_definition # @param [TargetDefinition] target_definition @see target_definition
# @param [Array<LocalPod>] pods @see pods
# #
def initialize(project, library, pods) def initialize(sandbox, library)
@project = project @sandbox = sandbox
@library = library @library = library
@pods = pods
end end
# Creates the target in the Pods project and its support files. # Creates the target in the Pods project and its support files.
...@@ -211,11 +205,14 @@ module Pod ...@@ -211,11 +205,14 @@ module Pod
attr_reader :xcconfig_file_ref attr_reader :xcconfig_file_ref
# @return [Sandbox] sandbox the sandbox where the support files should # @return [Project] the Pods project of the sandbox.
# be generated.
# #
def sandbox def project
project.sandbox sandbox.project
end
def pods
library.local_pods
end end
# @return [TargetDefinition] the target definition of the library. # @return [TargetDefinition] the target definition of the library.
......
...@@ -21,7 +21,9 @@ module Pod ...@@ -21,7 +21,9 @@ module Pod
# @return [Project] the pods project which contains the libraries to # @return [Project] the pods project which contains the libraries to
# integrate. # integrate.
# #
attr_reader :pods_project # attr_reader :pods_project
attr_reader :sandbox
# @return [Pathname] the path of the installation. # @return [Pathname] the path of the installation.
# #
...@@ -35,16 +37,16 @@ module Pod ...@@ -35,16 +37,16 @@ module Pod
# #
attr_reader :libraries attr_reader :libraries
# @param [Podfile] podfile @see #podfile. # @param [Podfile] podfile @see #podfile
# @param [Project] pods_project @see #pods_project. # @param [Sandbox] sandbox @see #sandbox
# @param [Pathname] project_root @see #project_root. # @param [Pathname] project_root @see #project_root
# @param [Library] libraries @see #libraries. # @param [Library] libraries @see #libraries
# #
# @todo Too many initialization arguments # @todo Too many initialization arguments
# #
def initialize(podfile, pods_project, project_root, libraries) def initialize(podfile, sandbox, project_root, libraries)
@podfile = podfile @podfile = podfile
@pods_project = pods_project @sandbox = sandbox
@project_root = project_root @project_root = project_root
@libraries = libraries @libraries = libraries
end end
...@@ -73,7 +75,7 @@ module Pod ...@@ -73,7 +75,7 @@ module Pod
# #
def create_workspace def create_workspace
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
[pods_project.path, *user_project_paths].each do |project_path| [sandbox.project_path, *user_project_paths].each do |project_path|
path = project_path.relative_path_from(workspace_path.dirname).to_s path = project_path.relative_path_from(workspace_path.dirname).to_s
workspace << path unless workspace.include?(path) workspace << path unless workspace.include?(path)
end end
...@@ -191,7 +193,7 @@ module Pod ...@@ -191,7 +193,7 @@ module Pod
@targets ||= library.user_targets.reject do |target| @targets ||= library.user_targets.reject do |target|
target.frameworks_build_phase.files.any? do |build_file| target.frameworks_build_phase.files.any? do |build_file|
file_ref = build_file.file_ref file_ref = build_file.file_ref
!file_ref.proxy? && file_ref.display_name == library.name !file_ref.proxy? && file_ref.display_name == library.product_name
end end
end end
end end
...@@ -311,7 +313,7 @@ module Pod ...@@ -311,7 +313,7 @@ module Pod
# integration. # integration.
# #
def integration_message def integration_message
"Integrating `#{library.name}' into " \ "Integrating `#{library.product_name}` into " \
"#{'target'.pluralize(targets.size)} " \ "#{'target'.pluralize(targets.size)} " \
"`#{targets.map(&:name).to_sentence}` " \ "`#{targets.map(&:name).to_sentence}` " \
"of project #{UI.path library.user_project_path}." "of project #{UI.path library.user_project_path}."
......
...@@ -29,6 +29,12 @@ module Pod ...@@ -29,6 +29,12 @@ module Pod
# @return [String] the name of the library. # @return [String] the name of the library.
# #
def name def name
target_definition.label.to_s
end
# @return [String] the name of the library.
#
def product_name
"lib#{target_definition.label}.a" "lib#{target_definition.label}.a"
end end
...@@ -82,6 +88,10 @@ module Pod ...@@ -82,6 +88,10 @@ module Pod
# #
attr_accessor :specs attr_accessor :specs
# @return [Array<LocalPod>] the pods of the library.
#
attr_accessor :local_pods
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @!group Support files # @!group Support files
......
...@@ -160,6 +160,12 @@ module Pod ...@@ -160,6 +160,12 @@ module Pod
# Deletes any path that is not used by the pod. # Deletes any path that is not used by the pod.
# #
# @todo [#529] Podspecs should not be preserved anymore to prevent user
# confusion. Currently we are copying the ones form external sources
# in `Local Podspecs` and this feature is not needed anymore.
# I think that copying all the used podspecs would be helpful for
# debugging.
#
# @return [void] # @return [void]
# #
def clean! def clean!
...@@ -491,15 +497,14 @@ module Pod ...@@ -491,15 +497,14 @@ module Pod
# @return [void] Copies the pods headers to the sandbox. # @return [void] Copies the pods headers to the sandbox.
# #
def link_headers def link_headers
@sandbox.build_headers.add_search_path(headers_sandbox) sandbox.build_headers.add_search_path(headers_sandbox)
@sandbox.public_headers.add_search_path(headers_sandbox)
header_mappings(header_files_by_spec).each do |namespaced_path, files| header_mappings(header_files_by_spec).each do |namespaced_path, files|
@sandbox.build_headers.add_files(namespaced_path, files) sandbox.build_headers.add_files(namespaced_path, files)
end end
sandbox.public_headers.add_search_path(headers_sandbox)
header_mappings(public_header_files_by_spec).each do |namespaced_path, files| header_mappings(public_header_files_by_spec).each do |namespaced_path, files|
@sandbox.public_headers.add_files(namespaced_path, files) sandbox.public_headers.add_files(namespaced_path, files)
end end
end end
......
...@@ -11,23 +11,17 @@ module Pod ...@@ -11,23 +11,17 @@ module Pod
# @return [Sandbox] the sandbox that contains the project. # @return [Sandbox] the sandbox that contains the project.
# #
attr_reader :sandbox # attr_reader :sandbox
# @param [Sandbox] sandbox @see #sandbox # @param [Sandbox] sandbox @see #sandbox
# #
def initialize(sandbox) def initialize(xcodeproj = nil)
super(nil) super
@sandbox = sandbox # @sandbox = sandbox
@support_files_group = new_group('Targets Support Files') @support_files_group = new_group('Targets Support Files')
@libraries = [] @libraries = []
end end
# @return [Pathname] the path of the Pods project.
#
def path
sandbox.project_path
end
# @return [String] a string representation suited for debugging. # @return [String] a string representation suited for debugging.
# #
def inspect def inspect
...@@ -90,7 +84,7 @@ module Pod ...@@ -90,7 +84,7 @@ module Pod
# #
def add_podfile(podfile_path) def add_podfile(podfile_path)
podfile_path = Pathname.new(podfile_path) podfile_path = Pathname.new(podfile_path)
podfile_ref = new_file(podfile_path.relative_path_from(path.dirname)) podfile_ref = new_file(podfile_path)
podfile_ref.xc_language_specification_identifier = 'xcode.lang.ruby' podfile_ref.xc_language_specification_identifier = 'xcode.lang.ruby'
podfile_ref podfile_ref
end end
......
...@@ -35,71 +35,40 @@ module Pod ...@@ -35,71 +35,40 @@ module Pod
# | # |
# +-- Pods.xcodeproj # +-- Pods.xcodeproj
# #
# @todo outdated pods triggers the resolution process which might pre-download
# some pods.
#
class Sandbox class Sandbox
# The path of the build headers directory relative to the root.
#
BUILD_HEADERS_DIR = "BuildHeaders"
# The path of the public headers directory relative to the root.
#
PUBLIC_HEADERS_DIR = "Headers"
# @return [Pathname] the root of the sandbox. # @return [Pathname] the root of the sandbox.
# #
attr_reader :root attr_reader :root
# @return [HeadersDirectory] the header directory for the Pods libraries. # @return [HeadersStore] the header directory for the Pods libraries.
# #
attr_reader :build_headers attr_reader :build_headers
# @return [HeadersDirectory] the header directory for the user targets. # @return [HeadersStore] the header directory for the user targets.
# #
attr_reader :public_headers attr_reader :public_headers
# @param [String, Pathname] root @see root # @param [String, Pathname] root @see root
# #
# @todo the headers should be stored in a `Headers` folder.
#
def initialize(root) def initialize(root)
@root = Pathname.new(root) @root = Pathname.new(root)
@build_headers = HeadersDirectory.new(self, BUILD_HEADERS_DIR) @build_headers = HeadersStore.new(self, "BuildHeaders")
@public_headers = HeadersDirectory.new(self, PUBLIC_HEADERS_DIR) @public_headers = HeadersStore.new(self, "Headers")
@cached_local_pods = {}
@cached_locally_sourced_pods = {}
@predownloaded_pods = [] @predownloaded_pods = []
FileUtils.mkdir_p(@root) FileUtils.mkdir_p(@root)
end end
# @return [Pathname] the path of the Pod project. # @return [Lockfile] the manifest which contains the information about the
# installed pods.
# #
def project_path def manifest
root + "Pods.xcodeproj" Lockfile.from_file(manifest_path) if manifest_path.exist?
end
# @return [String] a string representation suitable for debugging.
#
def inspect
"#<#{self.class}> with root #{root}"
end end
#--------------------------------------# # @return [Project] the Pods project.
# @!group Life cycle
public
# Cleans the sandbox for a new installation.
#
# @return [void]
# #
def prepare_for_install attr_accessor :project
build_headers.prepare_for_install
public_headers.prepare_for_install
end
# Removes the sandbox. # Removes the sandbox.
# #
...@@ -109,52 +78,59 @@ module Pod ...@@ -109,52 +78,59 @@ module Pod
root.rmtree root.rmtree
end end
#--------------------------------------# # @return [String] a string representation suitable for debugging.
#
def inspect
"#<#{self.class}> with root #{root}"
end
# @!group Manifest #--------------------------------------#
public # @!group Paths
# @return [Pathname] the path of the manifest.
#
def manifest_path def manifest_path
root + "Manifest.lock" root + "Manifest.lock"
end end
def manifest # @return [Pathname] the path of the Pods project.
Lockfile.from_file(manifest_path) if manifest_path.exist? #
def project_path
root + "Pods.xcodeproj"
end end
#--------------------------------------# # Returns the path for the Pod with the given name.
# @!group Local Pod support
public
# @todo Refactor the pods from a local source should not be cached by the
# sandbox.
# #
# @return [LocalPod] # @param [String] name
# The name of the Pod.
#
# @return [Pathname] the path of the Pod.
# #
def locally_sourced_pod_for_spec(spec, platform) def pod_dir(name)
key = [spec.root.name, platform.to_sym] # root + "Sources/#{name}"
local_pod = @cached_locally_sourced_pods[key] ||= LocalPod::LocalSourcedPod.new(spec.root, self, platform) root + name
local_pod.add_specification(spec)
local_pod
end end
def local_pod_for_spec(spec, platform) # Returns the path for the directory where to store the support files of
key = [spec.root.name, platform.to_sym] # a target.
(@cached_local_pods[key] ||= LocalPod.new(spec.root, self, platform)).tap do |pod| #
pod.add_specification(spec) # @param [String] name
end # The name of the target.
#
# @return [Pathname] the path of the support files.
#
def library_support_files_dir(name)
# root + "Target Support Files/#{name}"
root
end end
# @return [LocalPod] # @return [Pathname] the path for the directory where to store the
# specifications.
# #
def installed_pod_named(name, platform) def specifications_dir
if spec_path = podspec_for_name(name) # root + "Specifications"
key = [name, platform.to_sym] root + "Local Podspecs"
@cached_local_pods[key] ||= LocalPod.from_podspec(spec_path, self, platform)
end
end end
# Returns the path of the specification for the Pod with the # Returns the path of the specification for the Pod with the
...@@ -165,11 +141,15 @@ module Pod ...@@ -165,11 +141,15 @@ module Pod
# #
# @return [Pathname] the path or nil. # @return [Pathname] the path or nil.
# #
def podspec_for_name(name) def specification_path(name)
path = root + "Local Podspecs/#{name}.podspec" path = specifications_dir + "#{name}.podspec"
path.exist? ? path : nil path.exist? ? path : nil
end end
#--------------------------------------#
# @!group Pods Installation
# Returns the specification for the Pod with the given name. # Returns the specification for the Pod with the given name.
# #
# @param [String] name # @param [String] name
...@@ -178,7 +158,7 @@ module Pod ...@@ -178,7 +158,7 @@ module Pod
# @return [Specification] the specification if the file is found. # @return [Specification] the specification if the file is found.
# #
def specification(name) def specification(name)
if file = podspec_for_name(name) if file = specification_path(name)
Specification.from_file(file) Specification.from_file(file)
end end
end end
...@@ -186,115 +166,101 @@ module Pod ...@@ -186,115 +166,101 @@ module Pod
# @return [Array<String>] the names of the pods that have been # @return [Array<String>] the names of the pods that have been
# pre-downloaded from an external source. # pre-downloaded from an external source.
# #
# @todo The installer needs to be aware of it.
#
attr_reader :predownloaded_pods attr_reader :predownloaded_pods
#--------------------------------------# #-------------------------------------------------------------------------#
# @!group Private methods
private
attr_accessor :cached_local_pods
attr_accessor :cached_locally_sourced_pods # Provides support for managing a header directory. It also keeps track of
end # the header search paths.
#---------------------------------------------------------------------------#
# Provides support for managing a header directory. It also keeps track of
# the header search paths.
#
class HeadersDirectory
# @return [Pathname] the absolute path of this header directory.
# #
def root class HeadersStore
@sandbox.root + @relative_path
end
# @param [Sandbox] sandbox # @return [Pathname] the absolute path of this header directory.
# the sandbox that contains this header dir. #
# def root
# @param [String] relative_path @sandbox.root + @relative_path
# the relative path to the sandbox root and hence to the Pods end
# project.
#
def initialize(sandbox, relative_path)
@sandbox = sandbox
@relative_path = relative_path
@search_paths = [relative_path]
end
#--------------------------------------#
# @!group Life cycle
public
# Removes the directory as it is regenerated from scratch during each
# installation.
#
# @return [void]
#
def prepare_for_install
root.rmtree if root.exist?
end
#--------------------------------------# # @return [Sandbox] the sandbox where this header directory is stored.
#
attr_reader :sandbox
# @param [Sandbox] @see sandbox
#
# @param [String] relative_path
# the relative path to the sandbox root and hence to the Pods
# project.
#
def initialize(sandbox, relative_path)
@sandbox = sandbox
@relative_path = relative_path
@search_paths = [relative_path]
end
# @!group Adding headers # @return [Array<String>] All the search paths of the header directory in
# xcconfig format. The paths are specified relative to the pods
# root with the `${PODS_ROOT}` variable.
#
def search_paths
@search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end
public # Removes the directory as it is regenerated from scratch during each
# installation.
#
# @return [void]
#
def implode!
root.rmtree if root.exist?
end
# Adds a header to the directory. #--------------------------------------#
#
# @param [Pathname] namespace_path public
# the path where the header file should be stored relative to the
# headers directory. # @!group Adding headers
#
# @param [Pathname] relative_header_path # Adds a header to the directory.
# the path of the header file relative to the sandbox. #
# # @param [Pathname] namespace_path
# @note This method adds the files are added to the search paths. # the path where the header file should be stored relative to the
# # headers directory.
# @return [void] #
# # @param [Pathname] relative_header_path
def add_file(namespace_path, relative_header_path) # the path of the header file relative to the sandbox.
namespaced_header_path = root + namespace_path #
namespaced_header_path.mkpath unless File.exist?(namespaced_header_path) # @note This method adds the files are added to the search paths.
source = (@sandbox.root + relative_header_path).relative_path_from(namespaced_header_path) #
Dir.chdir(namespaced_header_path) { FileUtils.ln_sf(source, relative_header_path.basename)} # @return [Pathname]
@search_paths << namespaced_header_path.relative_path_from(@sandbox.root) #
namespaced_header_path + relative_header_path.basename def add_files(namespace, relative_header_paths)
end add_search_path(namespace)
namespaced_path = root + namespace
namespaced_path.mkpath unless File.exist?(namespaced_path)
relative_header_paths.map do |relative_header_path|
source = (@sandbox.root + relative_header_path).relative_path_from(namespaced_path)
Dir.chdir(namespaced_path) do
FileUtils.ln_sf(source, relative_header_path.basename)
end
namespaced_path + relative_header_path.basename
end
end
# @todo Why this variant exits? # Adds an header search path to the sandbox.
# #
def add_files(namespace_path, relative_header_paths) # @param [Pathname] path
relative_header_paths.map { |path| add_file(namespace_path, path) } # the path tho add.
#
# @return [void]
#
def add_search_path(path)
@search_paths << Pathname.new(@relative_path) + path
end
end end
# @return [Array<String>] All the search paths of the header directory in #-------------------------------------------------------------------------#
# xcconfig format. The paths are specified relative to the pods
# root with the `${PODS_ROOT}` variable.
#
def search_paths
@search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end
# Adds an header search path to the sandbox.
#
# @param [Pathname] path
# the path tho add.
#
# @return [void]
#
# @todo Why this variant exits?
#
def add_search_path(path)
@search_paths << Pathname.new(@relative_path) + path
end
end end
end end
...@@ -76,7 +76,7 @@ module Pod ...@@ -76,7 +76,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 @analyzer.analyze
libs = @analyzer.libraries libs = @analyzer.libraries
libs.map(&:name).should == ['libPods.a'] 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
...@@ -124,6 +124,15 @@ module Pod ...@@ -124,6 +124,15 @@ module Pod
] ]
end end
it "removes the specifications of the changed pods to prevent confusion in the resolution process" do
@analyzer.allow_pre_downloads = true
podspec = @analyzer.sandbox.root + 'Local Podspecs/JSONKit.podspec'
podspec.dirname.mkpath
File.open(podspec, "w") { |f| f.puts('test') }
@analyzer.analyze
podspec.should.not.exist?
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
@analyzer.libraries.first.specs.map(&:to_s).should == [ @analyzer.libraries.first.specs.map(&:to_s).should == [
......
...@@ -12,18 +12,19 @@ module Pod ...@@ -12,18 +12,19 @@ module Pod
xcodeproj 'dummy' xcodeproj 'dummy'
end end
@target_definition = @podfile.target_definitions[:default] @target_definition = @podfile.target_definitions[:default]
@project = Project.new(config.sandbox) @project = Project.new
config.sandbox.project = @project
@library = Library.new(@target_definition) @library = Library.new(@target_definition)
@library.platform = Platform.new(:ios, '6.0') @library.platform = Platform.new(:ios, '6.0')
@library.support_files_root = config.sandbox.root @library.support_files_root = config.sandbox.root
@library.user_project_path = config.sandbox.root + '../user_project.xcodeproj' @library.user_project_path = config.sandbox.root + '../user_project.xcodeproj'
@library.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug } @library.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
specification = fixture_spec('banana-lib/BananaLib.podspec') specification = fixture_spec('banana-lib/BananaLib.podspec')
@pod = LocalPod.new(specification, config.sandbox, @library.platform) @pod = LocalPod.new(specification, config.sandbox, @library.platform)
@library.local_pods = [@pod]
@installer = TargetInstaller.new(@project, @library, [@pod]) @installer = TargetInstaller.new(config.sandbox, @library)
specification.prefix_header_contents = '#import "BlocksKit.h"' specification.prefix_header_contents = '#import "BlocksKit.h"'
@pod.stubs(:root).returns(Pathname.new(fixture('banana-lib'))) @pod.stubs(:root).returns(Pathname.new(fixture('banana-lib')))
......
...@@ -21,7 +21,8 @@ module Pod ...@@ -21,7 +21,8 @@ module Pod
end end
@project_root = @sample_project_path.dirname @project_root = @sample_project_path.dirname
@pods_project = Project.new(config.sandbox) @pods_project = Project.new()
config.sandbox.project = @pods_project
@libraries = @podfile.target_definitions.values.map do |target_definition| @libraries = @podfile.target_definitions.values.map do |target_definition|
lib = Library.new(target_definition) lib = Library.new(target_definition)
lib.user_project_path = sample_project_path lib.user_project_path = sample_project_path
...@@ -31,7 +32,7 @@ module Pod ...@@ -31,7 +32,7 @@ module Pod
lib.user_project = sample_project lib.user_project = sample_project
lib lib
end end
@integrator = Installer::UserProjectIntegrator.new(@podfile, @pods_project, @project_root, @libraries) @integrator = Installer::UserProjectIntegrator.new(@podfile, config.sandbox, @project_root, @libraries)
end end
it "uses the path of the workspace defined in the podfile" do it "uses the path of the workspace defined in the podfile" do
...@@ -82,11 +83,11 @@ module Pod ...@@ -82,11 +83,11 @@ module Pod
sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject') sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
@sample_project = Xcodeproj::Project.new sample_project_path @sample_project = Xcodeproj::Project.new sample_project_path
@target = @sample_project.targets.first @target = @sample_project.targets.first
@pods_project = Project.new(config.sandbox)
target_definition = Podfile::TargetDefinition.new(:default, nil, nil) target_definition = Podfile::TargetDefinition.new(:default, nil, nil)
@lib = Library.new(target_definition) @lib = Library.new(target_definition)
@lib.user_project_path = sample_project_path @lib.user_project_path = sample_project_path
@lib.target = @pods_project.new_target(:static_library, target_definition.label, :ios) pods_project = Project.new()
@lib.target = pods_project.new_target(:static_library, target_definition.label, :ios)
@lib.user_targets = [@target] @lib.user_targets = [@target]
@lib.support_files_root = config.sandbox.root @lib.support_files_root = config.sandbox.root
@lib.user_project = @sample_project @lib.user_project = @sample_project
......
...@@ -222,3 +222,9 @@ module Pod ...@@ -222,3 +222,9 @@ module Pod
# end # end
end end
end end
# it 'clears out its headers root when preparing for install' do
# @sandbox.prepare_for_install
# @sandbox.build_headers.root.should.not.exist
# end
...@@ -17,8 +17,12 @@ module Pod ...@@ -17,8 +17,12 @@ module Pod
@lib.label.should == 'Pods' @lib.label.should == 'Pods'
end end
it "returns its name" do
@lib.name.should == 'Pods'
end
it "returns the name of its product" do it "returns the name of its product" do
@lib.name.should == 'libPods.a' @lib.product_name.should == 'libPods.a'
end end
end end
......
...@@ -81,14 +81,14 @@ describe Pod::LocalPod do ...@@ -81,14 +81,14 @@ describe Pod::LocalPod do
end end
it "can add it's source files to an Xcode project target" do it "can add it's source files to an Xcode project target" do
project = Pod::Project.new(@sandbox) project = Pod::Project.new()
@pod.add_file_references_to_project(project) @pod.add_file_references_to_project(project)
project['Pods/BananaLib/Banana.h'].path.should == "BananaLib/Classes/Banana.h" project['Pods/BananaLib/Banana.h'].path.should == "BananaLib/Classes/Banana.h"
project['Pods/BananaLib/Banana.m'].path.should == "BananaLib/Classes/Banana.m" project['Pods/BananaLib/Banana.m'].path.should == "BananaLib/Classes/Banana.m"
end end
it "can add it's source files to a target with any specially configured compiler flags" do it "can add it's source files to a target with any specially configured compiler flags" do
project = Pod::Project.new(@sandbox) project = Pod::Project.new()
target = project.new_target(:static, 'Pods', :ios) target = project.new_target(:static, 'Pods', :ios)
@pod.top_specification.compiler_flags = '-d some_flag' @pod.top_specification.compiler_flags = '-d some_flag'
@pod.add_file_references_to_project(project) @pod.add_file_references_to_project(project)
...@@ -303,8 +303,9 @@ describe Pod::LocalPod do ...@@ -303,8 +303,9 @@ describe Pod::LocalPod do
"Chameleon/UIKit > UIKit/Classes/UIKit.h UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ] "Chameleon/UIKit > UIKit/Classes/UIKit.h UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
end end
it "respects the headers excluded from the search paths" do # TODO this is a stub
@pod.stubs(:headers_excluded_from_search_paths).returns([@pod.root + 'UIKit/Classes/UIKit.h']) xit "respects the exclude files attribute of the specifications" do
@pod.stubs(:exclude_files).returns([@pod.root + 'UIKit/Classes/UIKit.h'])
mappings = @pod.send(:header_mappings, @pod.header_files_by_spec) mappings = @pod.send(:header_mappings, @pod.header_files_by_spec)
mappings = mappings.map do |folder, headers| mappings = mappings.map do |folder, headers|
"#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}" "#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}"
...@@ -314,8 +315,7 @@ describe Pod::LocalPod do ...@@ -314,8 +315,7 @@ describe Pod::LocalPod do
"Chameleon/UIKit > UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ] "Chameleon/UIKit > UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
end end
# @TODO: This is done by the sandbox and this test should be moved xit "includes the sandbox of the pod's headers while linking" do
it "includes the sandbox of the pod's headers while linking" do
@sandbox.build_headers.expects(:add_search_path).with(Pathname.new('Chameleon')) @sandbox.build_headers.expects(:add_search_path).with(Pathname.new('Chameleon'))
@sandbox.public_headers.expects(:add_search_path).with(Pathname.new('Chameleon')) @sandbox.public_headers.expects(:add_search_path).with(Pathname.new('Chameleon'))
@pod.link_headers @pod.link_headers
......
...@@ -3,21 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__) ...@@ -3,21 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__)
describe Pod::Project do describe Pod::Project do
describe "In general" do describe "In general" do
before do before do
@project = Pod::Project.new(config.sandbox) @project = Pod::Project.new(nil)
end
it "returns the sandbox used for the project" do
@project.sandbox.should == config.sandbox
end end
it "creates the support file group on initialization" do it "creates the support file group on initialization" do
@project.support_files_group.name.should == 'Targets Support Files' @project.support_files_group.name.should == 'Targets Support Files'
end end
it "returns its path" do
@project.path.should == config.sandbox.project_path
end
it "returns the `Pods` group" do it "returns the `Pods` group" do
@project.pods.name.should == 'Pods' @project.pods.name.should == 'Pods'
end end
...@@ -43,7 +35,7 @@ describe Pod::Project do ...@@ -43,7 +35,7 @@ describe Pod::Project do
end end
it "adds the Podfile configured as a Ruby file" do it "adds the Podfile configured as a Ruby file" do
@project.add_podfile(config.podfile_path) @project.add_podfile('../Podfile')
f = @project['Podfile'] f = @project['Podfile']
f.name.should == 'Podfile' f.name.should == 'Podfile'
f.source_tree.should == 'SOURCE_ROOT' f.source_tree.should == 'SOURCE_ROOT'
......
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
require 'tmpdir'
TMP_POD_ROOT = ROOT + "tmp" + "podroot" unless defined? TMP_POD_ROOT module Pod
describe Pod::Sandbox do describe Sandbox do
extend SpecHelper::TemporaryDirectory
before do before do
@sandbox = Pod::Sandbox.new(TMP_POD_ROOT) @sandbox = Pod::Sandbox.new(temporary_directory + 'Sandbox')
end end
after do it "automatically creates its root if it doesn't exist" do
@sandbox.implode File.directory?(temporary_directory + 'Sandbox').should.be.true
end end
it "automatically creates the TMP_POD_ROOT if it doesn't exist" do it "returns the manifest" do
File.directory?(TMP_POD_ROOT).should.be.true @sandbox.manifest.should == nil
end end
it "deletes the entire root directory on implode" do it "returns the project" do
@sandbox.implode @sandbox.project.should == nil
File.directory?(TMP_POD_ROOT).should.be.false end
FileUtils.mkdir(TMP_POD_ROOT) # put it back again
end
it "returns it's headers root" do it "returns the public headers store" do
@sandbox.build_headers.root.should == Pathname.new(File.join(TMP_POD_ROOT, "BuildHeaders")) @sandbox.public_headers.root.should == temporary_directory + 'Sandbox/Headers'
end end
it "returns it's public headers root" do it "returns the build headers store" do
@sandbox.public_headers.root.should == Pathname.new(File.join(TMP_POD_ROOT, "Headers")) @sandbox.build_headers.root.should == temporary_directory + 'Sandbox/BuildHeaders'
end end
it "can add namespaced headers to it's header path using symlinks and return the relative path" do it "deletes the entire root directory on implode" do
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/BuildHeaders") @sandbox.implode
namespace_path = Pathname.new("ExampleLib") File.directory?(temporary_directory + 'Sandbox').should.be.false
relative_header_path = Pathname.new("ExampleLib/BuildHeaders/MyHeader.h") end
File.open(@sandbox.root + relative_header_path, "w") { |file| file.write('hello') }
symlink_path = @sandbox.build_headers.add_file(namespace_path, relative_header_path)
symlink_path.should.be.symlink
File.read(symlink_path).should == 'hello'
end
it 'can add multiple headers at once and return the relative symlink paths' do #--------------------------------------#
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/BuildHeaders")
namespace_path = Pathname.new("ExampleLib") it "returns the path of the manifest" do
relative_header_paths = [ @sandbox.manifest_path.should == temporary_directory + 'Sandbox/Manifest.lock'
Pathname.new("ExampleLib/BuildHeaders/MyHeader.h"),
Pathname.new("ExampleLib/BuildHeaders/MyOtherHeader.h")
]
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end
symlink_paths = @sandbox.build_headers.add_files(namespace_path, relative_header_paths)
symlink_paths.each do |path|
path.should.be.symlink
File.read(path).should == "hello"
end end
end
it 'keeps a list of unique header search paths when headers are added' do it "returns the path of the Pods project" do
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/BuildHeaders") @sandbox.project_path.should == temporary_directory + 'Sandbox/Pods.xcodeproj'
namespace_path = Pathname.new("ExampleLib") end
relative_header_paths = [
Pathname.new("ExampleLib/BuildHeaders/MyHeader.h"),
Pathname.new("ExampleLib/BuildHeaders/MyOtherHeader.h")
]
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end
@sandbox.build_headers.add_files(namespace_path, relative_header_paths)
@sandbox.build_headers.search_paths.should.include("${PODS_ROOT}/BuildHeaders/ExampleLib")
end
it 'always adds the Headers root to the header search paths' do it "returns the path for a Pod" do
@sandbox.build_headers.search_paths.should.include("${PODS_ROOT}/BuildHeaders") @sandbox.pod_dir('JSONKit').should == temporary_directory + 'Sandbox/JSONKit'
end end
it 'clears out its headers root when preparing for install' do it "returns the directory for the support files of a library" do
@sandbox.prepare_for_install @sandbox.library_support_files_dir('Pods').should == temporary_directory + 'Sandbox'
@sandbox.build_headers.root.should.not.exist end
end
it "returns the path to a spec file in the 'Local Podspecs' dir" do it "returns the directory where to store the specifications" do
(@sandbox.root + 'Local Podspecs').mkdir @sandbox.specifications_dir.should == temporary_directory + 'Sandbox/Local Podspecs'
FileUtils.cp(fixture('banana-lib') + 'BananaLib.podspec', @sandbox.root + 'Local Podspecs') end
@sandbox.podspec_for_name('BananaLib').should == @sandbox.root + 'Local Podspecs/BananaLib.podspec'
end
it "returns a LocalPod for a spec file in the sandbox" do it "returns the path to a spec file in the 'Local Podspecs' dir" do
(@sandbox.root + 'Local Podspecs').mkdir (@sandbox.root + 'Local Podspecs').mkdir
FileUtils.cp(fixture('banana-lib') + 'BananaLib.podspec', @sandbox.root + 'Local Podspecs') FileUtils.cp(fixture('banana-lib/BananaLib.podspec'), @sandbox.root + 'Local Podspecs')
pod = @sandbox.installed_pod_named('BananaLib', Pod::Platform.ios) @sandbox.specification_path('BananaLib').should == @sandbox.root + 'Local Podspecs/BananaLib.podspec'
pod.should.be.instance_of Pod::LocalPod end
pod.top_specification.name.should == 'BananaLib'
end #--------------------------------------#
it "returns a LocalPod for a spec instance which source is expected to be in the sandbox" do it "loads the stored specification with the given name" do
(@sandbox.root + 'Local Podspecs').mkdir (@sandbox.root + 'Local Podspecs').mkdir
FileUtils.cp(fixture('banana-lib') + 'BananaLib.podspec', @sandbox.root + 'Local Podspecs') FileUtils.cp(fixture('banana-lib/BananaLib.podspec'), @sandbox.root + 'Local Podspecs')
spec = Pod::Specification.from_file(fixture('banana-lib') + 'BananaLib.podspec') @sandbox.specification('BananaLib').name.should == 'BananaLib'
pod = @sandbox.local_pod_for_spec(spec, Pod::Platform.ios) end
pod.should.be.instance_of Pod::LocalPod
pod.top_specification.name.should == 'BananaLib' it "stores the list of the names of the pre-downloaded pods" do
@sandbox.predownloaded_pods << 'JSONKit'
@sandbox.predownloaded_pods.should == ['JSONKit']
end
end end
it "always returns the same cached LocalPod instance for the same spec and platform" do #---------------------------------------------------------------------------#
(@sandbox.root + 'Local Podspecs').mkdir
FileUtils.cp(fixture('banana-lib') + 'BananaLib.podspec', @sandbox.root + 'Local Podspecs')
spec = Pod::Specification.from_file(@sandbox.root + 'Local Podspecs/BananaLib.podspec')
pod = @sandbox.installed_pod_named('BananaLib', Pod::Platform.ios) describe Sandbox::HeadersStore do
@sandbox.installed_pod_named('BananaLib', Pod::Platform.ios).should.eql pod extend SpecHelper::TemporaryDirectory
@sandbox.local_pod_for_spec(spec, Pod::Platform.ios).should.eql pod
before do
@sandbox = Pod::Sandbox.new(temporary_directory + 'Sandbox')
@header_dir = Sandbox::HeadersStore.new(@sandbox, 'Headers')
end
it "returns it's headers root" do
@header_dir.root.should == temporary_directory + 'Sandbox/Headers'
end
it "can add namespaced headers to it's header path using symlinks and return the relative path" do
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/")
namespace_path = Pathname.new("ExampleLib")
relative_header_paths = [
Pathname.new("ExampleLib/MyHeader.h"),
Pathname.new("ExampleLib/MyOtherHeader.h")
]
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end
symlink_paths = @header_dir.add_files(namespace_path, relative_header_paths)
symlink_paths.each do |path|
path.should.be.symlink
File.read(path).should == "hello"
end
end
it 'keeps a list of unique header search paths when headers are added' do
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/Dir")
namespace_path = Pathname.new("ExampleLib")
relative_header_paths = [
Pathname.new("ExampleLib/Dir/MyHeader.h"),
Pathname.new("ExampleLib/Dir/MyOtherHeader.h")
]
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end
@header_dir.add_files(namespace_path, relative_header_paths)
@header_dir.search_paths.should.include("${PODS_ROOT}/Headers/ExampleLib")
end
it 'always adds the Headers root to the header search paths' do
@header_dir.search_paths.should.include("${PODS_ROOT}/Headers")
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