Commit 504bfd33 authored by Fabio Pelosin's avatar Fabio Pelosin

Improved architecture.

- Moved Project::Library to Pod::Library.
- Removed logic from Pod::Library.
- Restored logic for user build configurations.
- CocoaPods now can infer the platform from the user targets.
parent 5cdcf8a8
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
- Adds new subcommand `pod spec cat NAME` to print a spec file to standard output. - Adds new subcommand `pod spec cat NAME` to print a spec file to standard output.
- Added Podfile to the Pods project. - Added Podfile to the Pods project.
- The `--no-clean` option of the `pod spec lint` command now displays the Pods project for inspection. - The `--no-clean` option of the `pod spec lint` command now displays the Pods project for inspection.
- CocoaPods now can infer the platform from the integrated targets.
- Major clean up and refactor to the code base. - Major clean up and refactor to the code base.
- Extrace models to [CocoaPods-Core](https://github.com/CocoaPods/Core) gem. - Extrace models to [CocoaPods-Core](https://github.com/CocoaPods/Core) gem.
......
...@@ -9,7 +9,7 @@ GIT ...@@ -9,7 +9,7 @@ GIT
GIT GIT
remote: git://github.com/CocoaPods/Xcodeproj.git remote: git://github.com/CocoaPods/Xcodeproj.git
revision: df3755dd51a7dce5151b8862d834bf047b5bc60d revision: e3dc945c7fdbbd9f977f6bc14b3e6023b99dc5e1
specs: specs:
xcodeproj (0.4.0) xcodeproj (0.4.0)
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
......
...@@ -27,6 +27,7 @@ module Pod ...@@ -27,6 +27,7 @@ module Pod
autoload :Executable, 'cocoapods/executable' autoload :Executable, 'cocoapods/executable'
autoload :ExternalSources, 'cocoapods/external_sources' autoload :ExternalSources, 'cocoapods/external_sources'
autoload :Installer, 'cocoapods/installer' autoload :Installer, 'cocoapods/installer'
autoload :Library, 'cocoapods/library'
autoload :LocalPod, 'cocoapods/local_pod' autoload :LocalPod, 'cocoapods/local_pod'
autoload :Project, 'cocoapods/project' autoload :Project, 'cocoapods/project'
autoload :Resolver, 'cocoapods/resolver' autoload :Resolver, 'cocoapods/resolver'
......
...@@ -39,7 +39,7 @@ module Pod ...@@ -39,7 +39,7 @@ module Pod
elsif url = options.delete(:http) elsif url = options.delete(:http)
Http.new(target_path, url, options) Http.new(target_path, url, options)
else else
raise "Unsupported download strategy `#{options.inspect}'." raise "Unsupported download strategy `#{options.inspect}`."
end end
end end
end end
......
...@@ -28,7 +28,7 @@ module Pod ...@@ -28,7 +28,7 @@ module Pod
licenses_string = "#{title_from_string(header_title, 1)}\n#{header_text}\n" licenses_string = "#{title_from_string(header_title, 1)}\n#{header_text}\n"
@pods.each do |pod| @pods.each do |pod|
if (license = string_for_pod(pod)) if (license = string_for_pod(pod))
license = license.force_encoding("UTF-8") if license.respond_to?(:force_encoding) license = license.force_encoding("UTF-8") if license.respond_to?(:force_encoding)
licenses_string += license licenses_string += license
end end
end end
......
...@@ -121,6 +121,7 @@ module Pod ...@@ -121,6 +121,7 @@ module Pod
# @return [void] # @return [void]
# #
def analyze def analyze
create_libraries
generate_pods_by_podfile_state generate_pods_by_podfile_state
update_repositories_if_needed update_repositories_if_needed
generate_locked_dependencies generate_locked_dependencies
...@@ -207,12 +208,141 @@ module Pod ...@@ -207,12 +208,141 @@ module Pod
# #
attr_reader :target_installers attr_reader :target_installers
#---------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @!group Pre-installation computations # @!group Pre-installation computations
attr_reader :libraries
private private
def create_libraries
@libraries = []
podfile.target_definitions.values.each do |target_definition|
lib = Library.new(target_definition)
lib.support_files_root = config.sandbox.root
if config.integrate_targets?
lib.user_project_path = compute_user_project_path(target_definition)
lib.user_project = Xcodeproj::Project.new(lib.user_project_path)
lib.user_targets = compute_user_project_targets(target_definition, lib.user_project)
lib.user_build_configurations = compute_user_build_configurations(target_definition, lib.user_targets)
lib.platform = compute_platform_for_taget_definition(target_definition, lib.user_targets)
else
lib.user_project_path = config.project_root
lib.user_targets = []
lib.user_build_configurations = {}
lib.platform = target_definition.platform
end
@libraries << lib
end
end
####################################################################################################
# Returns the path of the user project that the {TargetDefinition}
# should integrate.
#
# @raise If the project is implicit and there are multiple projects.
#
# @raise If the path doesn't exits.
#
# @return [Pathname] the path of the user project.
#
def compute_user_project_path(target_definition)
if target_definition.user_project_path
user_project_path = Pathname.new(config.project_root + target_definition.user_project_path)
unless user_project_path.exist?
raise Informative, "Unable to find the Xcode project `#{user_project_path}` for the target `#{target_definition.label}`."
end
else
xcodeprojs = Pathname.glob(config.project_root + '*.xcodeproj')
if xcodeprojs.size == 1
user_project_path = xcodeprojs.first
else
raise Informative, "Could not automatically select an Xcode project. " \
"Specify one in your Podfile like so:\n\n" \
" xcodeproj 'path/to/Project.xcodeproj'\n"
end
end
user_project_path
end
# Returns a list of the targets from the project of {TargetDefinition}
# that needs to be integrated.
#
# @note The method first looks if there is a target specified with
# the `link_with` option of the {TargetDefinition}. Otherwise
# it looks for the target that has the same name of the target
# definition. Finally if no target was found the first
# encountered target is returned (it is assumed to be the one
# to integrate in simple projects).
#
# @note This will only return targets that do **not** already have
# the Pods library in their frameworks build phase.
#
#
def compute_user_project_targets(target_definition, user_project)
return [] unless user_project
if link_with = target_definition.link_with
targets = user_project.targets.select { |t| link_with.include? t.name }
raise Informative, "Unable to find a target named `#{link_with.to_sentence}` to link with target definition `#{target_definition.name}`" if targets.empty?
elsif target_definition.name != :default
target = user_project.targets.find { |t| t.name == target_definition.name.to_s }
targets = [ target ].compact
raise Informative, "Unable to find a target named `#{target_definition.name.to_s}`" if targets.empty?
else
targets = [ user_project.targets.first ].compact
raise Informative, "Unable to find a target" if targets.empty?
end
targets
end
# @todo Robustness for installations without integration.
#
def compute_user_build_configurations(target_definition, user_targets)
if user_targets
user_targets.map { |t| t.build_configurations.map(&:name) }.flatten.inject({}) do |hash, name|
unless name == 'Debug' || name == 'Release'
hash[name] = :release
end
hash
end.merge(target_definition.build_configurations || {})
else
target_definition.build_configurations || {}
end
end
# Returns the platform for the library.
#
# @note This resolves to the lowest deployment target across the user targets.
#
# @todo Finish implementation
#
def compute_platform_for_taget_definition(target_definition, user_targets)
return target_definition.platform if target_definition.platform
if user_targets
name = nil
deployment_target = nil
user_targets.each do |target|
name ||= target.platform_name
raise "Targets with different platforms" unless name == target.platform_name
if !deployment_target || deployment_target > Version.new(target.deployment_target)
deployment_target = Version.new(target.deployment_target)
end
end
platform = Platform.new(name, deployment_target)
# TODO
target_definition.platform = platform
else
raise Informative, "Missing platform for #{target_definition}."\
"If no integrating it is necessary to specify a platform."
end
platform
end
####################################################################################################
# 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.
# #
...@@ -542,8 +672,9 @@ module Pod ...@@ -542,8 +672,9 @@ 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(config.sandbox)
@pods_project.add_podfile(config.project_podfile) if config.project_podfile.exist?
# pods_project.user_build_configurations = podfile.user_build_configurations @pods_project.add_podfile(config.project_podfile)
end
end end
end end
...@@ -554,7 +685,8 @@ module Pod ...@@ -554,7 +685,8 @@ module Pod
def generate_target_installers def generate_target_installers
@target_installers = podfile.target_definitions.values.map do |definition| @target_installers = podfile.target_definitions.values.map do |definition|
pods_for_target = local_pods_by_target[definition] pods_for_target = local_pods_by_target[definition]
TargetInstaller.new(pods_project, definition, pods_for_target) unless definition.empty? libray = libraries.find {|l| l.target_definition == definition }
TargetInstaller.new(pods_project, libray, pods_for_target) unless definition.empty?
end.compact end.compact
end end
...@@ -599,14 +731,14 @@ module Pod ...@@ -599,14 +731,14 @@ module Pod
# Runs the post install hooks of the installed specs and of the Podfile. # Runs the post install hooks of the installed specs and of the Podfile.
# #
# @todo Run the hooks only for the installed pods. # @todo Run the hooks only for the installed pods.
# @todo Print a messsage with the names of the specs. # @todo Print a message with the names of the specs.
# #
# @return [void] # @return [void]
# #
def run_post_install_hooks def run_post_install_hooks
UI.message "- Running post install hooks" do UI.message "- Running post install hooks" do
target_installers.each do |target_installer| target_installers.each do |target_installer|
specs_by_target[target_installer.target_definition].each do |spec| specs_by_target[target_installer.library.target_definition].each do |spec|
spec.post_install!(target_installer) spec.post_install!(target_installer)
end end
end end
...@@ -622,10 +754,10 @@ module Pod ...@@ -622,10 +754,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.target_definition] 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.target_definition, Generator::Acknowledgements.new(target_installer.library.target_definition,
pods_for_target).save_as(acknowledgements_path) pods_for_target).save_as(acknowledgements_path)
generate_dummy_source(target_installer) generate_dummy_source(target_installer)
end end
...@@ -633,12 +765,12 @@ module Pod ...@@ -633,12 +765,12 @@ module Pod
end end
# Generates a dummy source file for each target so libraries that contain # Generates a dummy source file for each target so libraries that contain
# only cathegories build. # only categories build.
# #
# @todo Move to the target installer? # @todo Move to the target installer?
# #
def generate_dummy_source(target_installer) def generate_dummy_source(target_installer)
class_name_identifier = target_installer.target_definition.label class_name_identifier = target_installer.library.label
dummy_source = Generator::DummySource.new(class_name_identifier) dummy_source = Generator::DummySource.new(class_name_identifier)
filename = "#{dummy_source.class_name}.m" filename = "#{dummy_source.class_name}.m"
pathname = Pathname.new(sandbox.root + filename) pathname = Pathname.new(sandbox.root + filename)
...@@ -691,7 +823,7 @@ module Pod ...@@ -691,7 +823,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).integrate! UserProjectIntegrator.new(podfile, pods_project, config.project_root, libraries).integrate!
end end
end end
end end
module Pod module Pod
class Installer class Installer
# This class is responsible of creating and configuring the static library # Controller class responsible of creating and configuring the static
# target in Pods project. Every target is generated from a target # library target in Pods project. Every target is generated from a target
# definition of the Podfile. # definition of the Podfile.
# #
class TargetInstaller class TargetInstaller
...@@ -11,24 +11,23 @@ module Pod ...@@ -11,24 +11,23 @@ module Pod
# #
attr_reader :project attr_reader :project
# @return [TargetDefinition] The target definition whose target needs to # @return [Library] The library whose target needs to be generated.
# be generated.
# #
attr_reader :target_definition attr_reader :library
# @param [Array<LocalPod>] pods the pods are required by the target # @return [Array<LocalPod>] The pods are required by the target
# definition of this installer. # definition of this installer.
# #
attr_reader :pods 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 # @param [Array<LocalPod>] pods @see pods
# #
def initialize(project, target_definition, pods) def initialize(project, library, pods)
@project = project @project = project
@target_definition = target_definition @library = library
@pods = pods @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.
...@@ -36,10 +35,9 @@ module Pod ...@@ -36,10 +35,9 @@ module Pod
# @return [void] # @return [void]
# #
def install! def install!
add_file_reference_for_support_files
add_target add_target
add_build_files_to_target add_build_files_to_target
add_file_reference_for_support_files
configure_target
create_xcconfig_file create_xcconfig_file
create_prefix_header create_prefix_header
...@@ -56,27 +54,22 @@ module Pod ...@@ -56,27 +54,22 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
# @!group Installation steps # @!group Installation products.
private public
# Adds the library for the {#target_definition} to the Pods # @return [PBXNativeTarget] the target generated by the installation
# project. # process.
# #
# @return [void] # @note Generated by the {#add_target} step.
# #
def add_target attr_reader :target
@library = @project.add_pod_library(target_definition)
@target = @library.target
end
# Adds the build files of the pods to the target. #-----------------------------------------------------------------------#
#
# @return [void] # @!group Installation steps
#
def add_build_files_to_target private
pods.each { |p| p.add_build_files_to_target(target) }
end
# Adds the file references for the support files that are generated by # Adds the file references for the support files that are generated by
# the installation process to the Pods project. # the installation process to the Pods project.
...@@ -87,31 +80,58 @@ module Pod ...@@ -87,31 +80,58 @@ module Pod
g = project.support_files_group.new_group(target_definition.label) g = project.support_files_group.new_group(target_definition.label)
g.new_file(library.copy_resources_script_name) g.new_file(library.copy_resources_script_name)
g.new_file(library.prefix_header_name) g.new_file(library.prefix_header_name)
g.new_file(library.xcconfig_name).tap { |f| @xcconfig_file_ref = f } @xcconfig_file_ref = g.new_file(library.xcconfig_name)
end end
# Configures the build settings of the target. # Adds the target for the library to the Pods project with the
# appropriate build configurations.
# #
# @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig. # @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig.
# #
# @todo Should we add the build configurations only to the target?
#
# @return [void] # @return [void]
# #
def configure_target def add_target
set = { name = library.label
'GCC_PREFIX_HEADER' => library.prefix_header_name platform = library.platform.name
} settings = build_settings_for_platform(library.platform)
if @target_definition.inhibit_all_warnings? settings['GCC_PREFIX_HEADER'] = library.prefix_header_name
set['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES' if target_definition.inhibit_all_warnings?
settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES'
end end
Generator::XCConfig.pods_project_settings.each do |key, value| Generator::XCConfig.pods_project_settings.each do |key, value|
set[key] = value settings[key] = value
end
@target = project.new_target(:static_library, name, platform)
@target.build_settings('Debug').merge!(settings)
@target.build_settings('Release').merge!(settings)
library.user_build_configurations.each do |name, type|
unless @target.build_configurations.map(&:name).include?(name)
build_config = project.new(Xcodeproj::Project::XCBuildConfiguration)
build_config.name = name
settings = @target.build_settings(type.to_s.capitalize)
build_config.build_settings = settings
target.build_configurations << build_config
project.build_configurations << build_config
end
end end
@target.build_configurations.each do |c| @target.build_configurations.each do |c|
c.base_configuration_reference = xcconfig_file_ref c.base_configuration_reference = xcconfig_file_ref
c.build_settings.merge!(set)
end end
library.target = @target
end
# Adds the build files of the pods to the target.
#
# @return [void]
#
def add_build_files_to_target
pods.each { |p| p.add_build_files_to_target(target) }
end end
# Generates the contents of the xcconfig file and saves it to disk. # Generates the contents of the xcconfig file and saves it to disk.
...@@ -179,22 +199,9 @@ module Pod ...@@ -179,22 +199,9 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
# @!group Installation products. # @!group Private helpers.
public
# @return [Library] the library for the target definition.
#
# @note Generated by the {#add_target} step.
#
attr_reader :library
# @return [PBXNativeTarget] the target generated by the installation private
# process.
#
# @note Generated by the {#add_target} step.
#
attr_reader :target
# @return [PBXFileReference] the file reference to the xcconfig file of # @return [PBXFileReference] the file reference to the xcconfig file of
# the target. # the target.
...@@ -203,11 +210,6 @@ module Pod ...@@ -203,11 +210,6 @@ module Pod
# #
attr_reader :xcconfig_file_ref attr_reader :xcconfig_file_ref
#-----------------------------------------------------------------------#
# @!group Private helpers.
private
# @return [Sandbox] sandbox the sandbox where the support files should # @return [Sandbox] sandbox the sandbox where the support files should
# be generated. # be generated.
...@@ -216,6 +218,12 @@ module Pod ...@@ -216,6 +218,12 @@ module Pod
project.sandbox project.sandbox
end end
# @return [TargetDefinition] the target definition of the library.
#
def target_definition
library.target_definition
end
# Creates and caches the copy resource script. # Creates and caches the copy resource script.
# #
# @return [CopyResourcesScript] # @return [CopyResourcesScript]
...@@ -223,6 +231,30 @@ module Pod ...@@ -223,6 +231,30 @@ module Pod
def copy_resources_script def copy_resources_script
@copy_resources_script ||= Generator::CopyResourcesScript.new @copy_resources_script ||= Generator::CopyResourcesScript.new
end end
# Returns the Xcode build settings for a target with the given platform.
#
# @param [Platform] platform
# the platform for which the build settings are needed.
#
# @return [Hash] the build settings.
#
def build_settings_for_platform(platform)
settings = {}
settings['ARCHS'] = "armv6 armv7" if platform.requires_legacy_ios_archs?
if dt = platform.deployment_target
if platform == :ios
settings['IPHONEOS_DEPLOYMENT_TARGET'] = dt.to_s
elsif platform == :osx
settings['MACOSX_DEPLOYMENT_TARGET'] = dt.to_s
else
raise Informative, "Unknown platform #{platform}"
end
end
settings
end
end end
end end
end end
......
...@@ -31,12 +31,22 @@ module Pod ...@@ -31,12 +31,22 @@ module Pod
# #
attr_reader :project_root attr_reader :project_root
# @param [Podfile] podfile @see #podfile. # @return [Library] the libraries generated by the installer.
# #
def initialize(podfile, pods_project, project_root) attr_reader :libraries
# @param [Podfile] podfile @see #podfile.
# @param [Project] pods_project @see #pods_project.
# @param [Pathname] project_root @see #project_root.
# @param [Library] libraries @see #libraries.
#
# @todo Too many initialization arguments
#
def initialize(podfile, pods_project, project_root, libraries)
@podfile = podfile @podfile = podfile
@pods_project = pods_project @pods_project = pods_project
@project_root = project_root @project_root = project_root
@libraries = libraries
end end
# Integrates the user projects associated with the {TargetDefinitions} # Integrates the user projects associated with the {TargetDefinitions}
...@@ -83,7 +93,7 @@ module Pod ...@@ -83,7 +93,7 @@ module Pod
# @return [void] # @return [void]
# #
def integrate_user_targets def integrate_user_targets
pods_project.libraries.each do |lib| libraries.each do |lib|
next if lib.target_definition.empty? next if lib.target_definition.empty?
TargetIntegrator.new(lib).integrate! TargetIntegrator.new(lib).integrate!
end end
...@@ -101,7 +111,7 @@ module Pod ...@@ -101,7 +111,7 @@ module Pod
# @return [void] # @return [void]
# #
def warn_about_empty_podfile def warn_about_empty_podfile
unless podfile.target_definitions.values.any?{ |td| !td.empty? } if podfile.target_definitions.values.all?{ |td| td.empty? }
UI.warn "[!] The Podfile does not contain any dependency." UI.warn "[!] The Podfile does not contain any dependency."
end end
end end
...@@ -134,9 +144,7 @@ module Pod ...@@ -134,9 +144,7 @@ module Pod
# @note Empty target definitions are ignored. # @note Empty target definitions are ignored.
# #
def user_project_paths def user_project_paths
pods_project.libraries.map do |lib| libraries.map do |lib|
# TODO: remove
next if lib.target_definition.empty?
lib.user_project_path lib.user_project_path
end.compact.uniq end.compact.uniq
end end
...@@ -180,8 +188,8 @@ module Pod ...@@ -180,8 +188,8 @@ module Pod
# @note A target is considered integrated if it already references # @note A target is considered integrated if it already references
# #
def targets def targets
@targets ||= library.user_targets.reject do |t| @targets ||= library.user_targets.reject do |target|
t.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.name
end end
...@@ -290,10 +298,10 @@ module Pod ...@@ -290,10 +298,10 @@ module Pod
name = "#{target.name} [#{config_names.join(' - ')}]" name = "#{target.name} [#{config_names.join(' - ')}]"
actions = [ actions = [
"Use the `$(inherited)' flag, or", "Use the `$(inherited)' flag, or",
"Remove the build settings from the target." "Remove the build settings from the target."
] ]
UI.warn("The target `#{name}' overrides the `#{key}' build " \ UI.warn("The target `#{name}' overrides the `#{key}' build " \
"setting defined in `#{xcconfig_relative_path}'.", "setting defined in `#{library.xcconfig_relative_path}'.",
actions) actions)
end end
end end
......
module Pod
# Model class which describes a Pods library.
#
# The Library class stores and provides the information necessary for
# working with a library in the Pods project and in the user projects
# through the installation process.
#
class Library
# @return [PBXNativeTarget] the target definition of the Podfile that
# generated this library.
#
attr_reader :target_definition
# @param [TargetDefinition] target_definition @see target_definition
# @param [PBXNativeTarget] target @see target
#
def initialize(target_definition)
@target_definition = target_definition
end
# @return [String] the label for the library.
#
def label
target_definition.label.to_s
end
# @return [String] the name of the library.
#
def name
"lib#{target_definition.label}.a"
end
#-------------------------------------------------------------------------#
# @!group Information storage
# @return [Pathname] the folder where to store the support files of this
# library.
#
attr_accessor :support_files_root
# @return [Pathname] the path of the user project that this library will
# integrate.
#
attr_accessor :user_project_path
# @return [Xcodeproj::Project] The project that will be integrated.
#
attr_accessor :user_project
# @return [Array<PBXNativeTarget>] the list of the user targets that will
# be integrated by this library.
#
attr_accessor :user_targets
# @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a
# configuration and its value to its type (`:debug` or `:release`).
#
attr_accessor :user_build_configurations
# @return [Platform] the platform for this library.
#
attr_accessor :platform
# @return [PBXNativeTarget] the target generated in the Pods project for
# this library.
#
attr_accessor :target
# @return [Xcodeproj::Config] the configuration file of the library
#
# @note The configuration is generated by the {TargetInstaller} and
# used by {UserProjectIntegrator} to check for any overridden
# values.
#
attr_accessor :xcconfig
# @todo
#
attr_accessor :specifications
#-------------------------------------------------------------------------#
# @!group Support files
# @return [String] The xcconfig path of the root from the `$(SRCROOT)`
# variable of the user's project.
#
def relative_pods_root
"${SRCROOT}/#{relative_to_srcroot}"
end
# @return [String] the name of the xcconfig file relative to this target.
#
def xcconfig_name
"#{label}.xcconfig"
end
# @return [Pathname] the absolute path of the xcconfig file.
#
def xcconfig_path
support_files_root + xcconfig_name
end
# @return [String] the path of the xcconfig file relative to the root of
# the user project.
#
def xcconfig_relative_path
relative_to_srcroot("#{xcconfig_name}").to_s
end
# @return [String] the name of the copy resources script relative to this
# target.
#
def copy_resources_script_name
"#{label}-resources.sh"
end
# @return [Pathname] the absolute path of the copy resources script.
#
def copy_resources_script_path
support_files_root + copy_resources_script_name
end
# @return [String] the path of the copy resources script relative to the
# root of the user project.
#
def copy_resources_script_relative_path
"${SRCROOT}/#{relative_to_srcroot("#{copy_resources_script_name}")}"
end
# @return [String] the name of the prefix header file relative to this
# target.
#
def prefix_header_name
"#{label}-prefix.pch"
end
# @return [Pathname] the absolute path of the prefix header file.
#
def prefix_header_path
support_files_root + prefix_header_name
end
# @return [String] the name of the bridge support file relative to this
# target.
#
def bridge_support_name
"#{label}.bridgesupport"
end
# @return [Pathname] the absolute path of the bridge support file.
#
def bridge_support_path
support_files_root + bridge_support_name
end
# @return [Pathname] the absolute path of acknowledgements file.
#
# @note The acknowledgements generators add the extension according to
# the file type.
#
def acknowledgements_path
support_files_root + "#{label}-Acknowledgements"
end
#-------------------------------------------------------------------------#
# @!group Private Helpers
private
# Computes the relative path of a sandboxed file from the `$(SRCROOT)`
# variable of the user's project.
#
# @param [Pathname] path
# A relative path from the root of the sandbox.
#
# @return [String] the computed path.
#
def relative_to_srcroot(path = nil)
base_path = path ? support_files_root + path : support_files_root
base_path.relative_path_from(user_project_path.dirname).to_s
end
end
end
require 'open-uri' require 'open-uri'
# Allow open-uri to follow http to https redirects.
#
# Inspiration from: https://gist.github.com/1271420 # Inspiration from: https://gist.github.com/1271420
# Relevant issue: http://redmine.ruby-lang.org/issues/3719
# Source here: https://github.com/ruby/ruby/blob/trunk/lib/open-uri.rb
# #
# Allow open-uri to follow http to https redirects.
# Relevant issue:
# http://redmine.ruby-lang.org/issues/3719
# Source here:
# https://github.com/ruby/ruby/blob/trunk/lib/open-uri.rb
module OpenURI module OpenURI
def OpenURI.redirectable?(uri1, uri2) # :nodoc:
# This test is intended to forbid a redirection from http://... to # This test is intended to forbid a redirection from http://... to
# file:///etc/passwd, file:///dev/zero, etc. CVE-2011-1521 # file:///etc/passwd, file:///dev/zero, etc. CVE-2011-1521
# https to http redirect is also forbidden intentionally. # https to http redirect is also forbidden intentionally.
# It avoids sending secure cookie or referer by non-secure HTTP protocol. # It avoids sending secure cookie or referer by non-secure HTTP protocol.
# (RFC 2109 4.3.1, RFC 2965 3.3, RFC 2616 15.1.3) # (RFC 2109 4.3.1, RFC 2965 3.3, RFC 2616 15.1.3)
# However this is ad hoc. It should be extensible/configurable. # However this is ad hoc. It should be extensible/configurable.
#
def OpenURI.redirectable?(uri1, uri2)
uri1.scheme.downcase == uri2.scheme.downcase || uri1.scheme.downcase == uri2.scheme.downcase ||
(/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:https?|ftp)\z/i =~ uri2.scheme) (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:https?|ftp)\z/i =~ uri2.scheme)
end end
......
This diff is collapsed.
...@@ -55,14 +55,14 @@ module Pod ...@@ -55,14 +55,14 @@ module Pod
perform_linting perform_linting
begin # begin
if spec if spec
check_repo_path if repo_path check_repo_path if repo_path
perform_extensive_analysis unless quick perform_extensive_analysis unless quick
end end
rescue Exception => e # rescue Exception => e
error "The specification is malformed and crashed the linter." # error "The specification is malformed and crashed the linter."
end # end
unless disable_ui_output unless disable_ui_output
UI.puts " -> ".send(result_color) << (spec ? spec.name : file.basename.to_s) UI.puts " -> ".send(result_color) << (spec ? spec.name : file.basename.to_s)
......
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
# @return [Lockfile]
#
def generate_lockfile
hash = {}
hash['PODS'] = []
hash['DEPENDENCIES'] = []
hash['SPEC CHECKSUMS'] = []
hash['COCOAPODS'] = Pod::VERSION
Pod::Lockfile.new(hash)
end
# it 'tells each pod to link its headers' do # @return [Podfile]
# @pods[0].expects(:link_headers) #
# do_install! def generate_podfile(pods = ['JSONKit'])
# end podfile = Pod::Podfile.new do
platform :ios
xcodeproj 'SampleProject/SampleProject'
pods.each { |name| pod name }
end
end
# it 'tells each pod to link its headers' do
# @pods[0].expects(:link_headers)
# do_install!
# end
module Pod module Pod
describe Installer do describe Installer do
before do
@sandbox = temporary_sandbox
config.repos_dir = fixture('spec-repos')
config.project_pods_root = @sandbox.root
FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
end
describe "Concerning pre-installation computations" do
def generate_podfile(pods = ['JSONKit'])
podfile = Podfile.new do
platform :ios
xcodeproj 'MyProject'
pods.each { |name| pod name }
end
# before do
# @sandbox = temporary_sandbox
# config.repos_dir = fixture('spec-repos')
# config.project_pods_root = @sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
# end
describe "Concerning pre-installation computations" do
# @sandbox = temporary_sandbox # @sandbox = temporary_sandbox
# config.project_pods_root = temporary_sandbox.root # config.project_pods_root = temporary_sandbox.root
# FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit') # FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
...@@ -32,25 +47,14 @@ module Pod ...@@ -32,25 +47,14 @@ module Pod
# @installer = Installer.new(resolver) # @installer = Installer.new(resolver)
# target_installer = @installer.target_installers.first # target_installer = @installer.target_installers.first
# target_installer.install # target_installer.install
end
def generate_lockfile
hash = {}
hash['PODS'] = []
hash['DEPENDENCIES'] = []
hash['SPEC CHECKSUMS'] = []
hash['COCOAPODS'] = Pod::VERSION
Pod::Lockfile.new(hash)
end
before do before do
podfile = generate_podfile podfile = generate_podfile
lockfile = generate_lockfile lockfile = generate_lockfile
@installer = Installer.new(@sandbox, podfile, lockfile) @installer = Installer.new(config.sandbox, podfile, lockfile)
Project::Library.any_instance.stubs(:user_project_path).returns(config.project_root + 'test.xcodeproj') SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
# TODO
config.integrate_targets = false
@installer.install! @installer.install!
end end
...@@ -146,8 +150,8 @@ module Pod ...@@ -146,8 +150,8 @@ module Pod
# before do # before do
# sandbox = temporary_sandbox # sandbox = temporary_sandbox
# Pod::Config.instance.project_pods_root = sandbox.root # Config.instance.project_pods_root = sandbox.root
# Pod::Config.instance.integrate_targets = false # Config.instance.integrate_targets = false
# podspec_path = fixture('integration/Reachability/Reachability.podspec') # podspec_path = fixture('integration/Reachability/Reachability.podspec')
# podfile = Podfile.new do # podfile = Podfile.new do
# platform :osx # platform :osx
...@@ -194,8 +198,8 @@ module Pod ...@@ -194,8 +198,8 @@ module Pod
# before do # before do
# sandbox = temporary_sandbox # sandbox = temporary_sandbox
# Pod::Config.instance.project_pods_root = sandbox.root # Config.instance.project_pods_root = sandbox.root
# Pod::Config.instance.integrate_targets = false # Config.instance.integrate_targets = false
# podspec_path = fixture('chameleon') # podspec_path = fixture('chameleon')
# podfile = Podfile.new do # podfile = Podfile.new do
# platform :osx # platform :osx
......
require File.expand_path('../../spec_helper', __FILE__)
module Pod
describe Pod::Library do
describe "In general" do
before do
@target_definition = Podfile::TargetDefinition.new(:default, nil, nil)
@lib = Library.new(@target_definition)
end
it "returns the target_definition that generated it" do
@lib.target_definition.should == @target_definition
end
it "returns the label of the target definition" do
@lib.label.should == 'Pods'
end
it "returns the name of its product" do
@lib.name.should == 'libPods.a'
end
end
describe "Support files" do
before do
@target_definition = Podfile::TargetDefinition.new(:default, nil, nil)
@lib = Library.new(@target_definition)
@lib.support_files_root = config.sandbox.root
@lib.user_project_path = config.sandbox.root + '../user_project.xcodeproj'
end
it "returns the xcconfig name" do
@lib.xcconfig_name.should == 'Pods.xcconfig'
end
it "returns the absolute path of the xcconfig file" do
@lib.xcconfig_path.to_s.should.include?('Pods/Pods.xcconfig')
end
it "returns the path of the xcconfig file relative to the user project" do
@lib.xcconfig_relative_path.should == 'Pods/Pods.xcconfig'
end
it "returns the resources script name" do
@lib.copy_resources_script_name.should == 'Pods-resources.sh'
end
it "returns the absolute path of the resources script" do
@lib.copy_resources_script_path.to_s.should.include?('Pods/Pods-resources.sh')
end
it "returns the path of the resources script relative to the user project" do
@lib.copy_resources_script_relative_path.should == '${SRCROOT}/Pods/Pods-resources.sh'
end
it "returns the prefix header file name" do
@lib.prefix_header_name.should == 'Pods-prefix.pch'
end
it "returns the absolute path of the prefix header file" do
@lib.prefix_header_path.to_s.should.include?('Pods/Pods-prefix.pch')
end
it "returns the bridge support file name" do
@lib.bridge_support_name.should == 'Pods.bridgesupport'
end
it "returns the absolute path of the bridge support file" do
@lib.bridge_support_path.to_s.should.include?('Pods/Pods.bridgesupport')
end
it "returns the absolute path of the acknowledgements file" do
@lib.acknowledgements_path.to_s.should.include?('Pods/Pods-Acknowledgements')
end
end
end
end
...@@ -50,229 +50,8 @@ describe Pod::Project do ...@@ -50,229 +50,8 @@ describe Pod::Project do
f.xc_language_specification_identifier.should == 'xcode.lang.ruby' f.xc_language_specification_identifier.should == 'xcode.lang.ruby'
f.path.should == '../Podfile' f.path.should == '../Podfile'
end end
it "adds build configurations named after every configuration across all of the user's projects" do
@project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'Test' => :debug, 'AppStore' => :release }
@project.build_configurations.map(&:name).sort.should == %w{ AppStore Debug Release Test }
end
end
describe "Libraries" do
before do
@project = Pod::Project.new(config.sandbox)
podfile = Pod::Podfile.new do
platform :ios, '4.3'
pod 'JSONKit'
end
@target_definition = podfile.target_definitions.values.first
end
it "adds build configurations named after every configuration across all of the user's projects to a target" do
@project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'Test' => :debug, 'AppStore' => :release }
library = @project.add_pod_library(@target_definition)
target = library.target
target.build_settings('Test')["VALIDATE_PRODUCT"].should == nil
target.build_settings('AppStore')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets ARCHS to 'armv6 armv7' for both configurations if the deployment target is less than 4.3 for iOS targets" do
@target_definition.platform = Pod::Platform.new(:ios, '4.2')
library = @project.add_pod_library(@target_definition)
target = library.target
target.build_settings('Debug')["ARCHS"].should == "armv6 armv7"
target.build_settings('Release')["ARCHS"].should == "armv6 armv7"
end
before do
@lib = @project.add_pod_library(@target_definition)
@target = @lib.target
end
it "uses standard ARCHs if deployment target is 4.3 or above" do
@target.build_settings('Debug')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
@target.build_settings('Release')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
end
it "sets VALIDATE_PRODUCT to YES for the Release configuration for iOS targets" do
@lib.target.build_settings('Release')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets IPHONEOS_DEPLOYMENT_TARGET for iOS targets" do
@target.build_settings('Debug')["IPHONEOS_DEPLOYMENT_TARGET"].should == "4.3"
@target.build_settings('Release')["IPHONEOS_DEPLOYMENT_TARGET"].should == "4.3"
end
it "returns the added libraries" do
@project.libraries.should == [ @lib ]
end
end end
end end
#-----------------------------------------------------------------------------#
describe Pod::Project::Library do
describe "In general" do
before do
project = Pod::Project.new(config.sandbox)
podfile = Pod::Podfile.new do
platform :ios
pod 'JSONKit'
end
@target_definition = podfile.target_definitions.values.first
@lib = project.add_pod_library(@target_definition)
end
it "returns the target_definition that generated it" do
@lib.target_definition.should == @target_definition
end
it "returns it target in the Pods project" do
@lib.target.name.should == 'Pods'
end
it "returns the label of the target definition" do
@lib.label.should == 'Pods'
end
end
#---------------------------------------#
describe "User project" do
before do
user_project_path = fixture('SampleProject/SampleProject.xcodeproj')
project = Pod::Project.new(config.sandbox)
podfile = Pod::Podfile.new do
platform :ios
xcodeproj user_project_path
pod 'JSONKit'
end
@target_definition = podfile.target_definitions.values.first
@lib = project.add_pod_library(@target_definition)
end
it "returns the user project path" do
path = fixture('SampleProject/SampleProject.xcodeproj')
@lib.user_project_path.should == path
end
it "raises if no project could be selected" do
@target_definition.stubs(:user_project_path).returns(nil)
Pathname.any_instance.stubs(:exist?).returns(true)
lambda { @lib.user_project_path }.should.raise Pod::Informative
end
it "raises if the project path doesn't exist" do
Pathname.any_instance.stubs(:exist?).returns(false)
lambda { @lib.user_project_path }.should.raise Pod::Informative
end
it "returns the user project" do
@lib.user_project.class.should == Xcodeproj::Project
end
it "returns the user targets associated with the target definition" do
@lib.user_targets.all? { |t| t.isa == 'PBXNativeTarget' }.should.be.true
@lib.user_targets.map(&:name).should == [ 'SampleProject' ]
end
it "uses the targets specified to link with by the target definition" do
@target_definition.stubs(:link_with).returns(['TestRunner'])
@target_definition.stubs(:name).returns('NON-EXISTING')
@lib.user_targets.first.name.should == 'TestRunner'
end
it "it raises if it can't find any target specified to link with by the target definition" do
@target_definition.stubs(:link_with).returns(['NON-EXISTING'])
lambda { @lib.user_targets }.should.raise Pod::Informative
end
it "uses the target with the same name if the target definition name is different from `:default'" do
@target_definition.stubs(:name).returns('TestRunner')
@lib.user_targets.first.name.should == 'TestRunner'
end
it "it raises if it can't find a target with the same name of the target definition" do
@target_definition.stubs(:name).returns('NON-EXISTING')
lambda { @lib.user_targets }.should.raise Pod::Informative
end
it "uses the first target in the user's project if no explicit target is specified for the default target definition" do
project = Xcodeproj::Project.new(@lib.user_project_path)
@lib.user_targets.should == [ project.targets.first ]
end
end
#---------------------------------------#
describe "TargetInstaller & UserProjectIntegrator" do
before do
user_project_path = fixture('SampleProject/SampleProject.xcodeproj')
project = Pod::Project.new(config.sandbox)
podfile = Pod::Podfile.new do
platform :ios
xcodeproj user_project_path
pod 'JSONKit'
end
@target_definition = podfile.target_definitions.values.first
@lib = project.add_pod_library(@target_definition)
end
#---------------------------------------#
it "returns the name of its product" do
@lib.name.should == 'libPods.a'
end
it "returns it Pods project" do
@lib.project.path.should == config.sandbox.project_path
end
#---------------------------------------#
it "stores the xcconfig" do
@lib.xcconfig = Xcodeproj::Config.new({'PODS_ROOT' => '${SRCROOT}'})
@lib.xcconfig.to_hash['PODS_ROOT'].should == '${SRCROOT}'
end
it "returns the xcconfig name" do
@lib.xcconfig_name.should == 'Pods.xcconfig'
end
it "returns the absolute path of the xcconfig file" do
@lib.xcconfig_path.to_s.should.include?('Pods/Pods.xcconfig')
end
it "returns the path of the xcconfig file relative to the user project" do
@lib.xcconfig_relative_path.should == '../../../tmp/Pods/Pods.xcconfig'
end
it "returns the resources script name" do
@lib.copy_resources_script_name.should == 'Pods-resources.sh'
end
it "returns the absolute path of the resources script" do
@lib.copy_resources_script_path.to_s.should.include?('Pods/Pods-resources.sh')
end
it "returns the path of the resources script relative to the user project" do
@lib.copy_resources_script_relative_path.should == '${SRCROOT}/../../../tmp/Pods/Pods-resources.sh'
end
it "returns the prefix header file name" do
@lib.prefix_header_name.should == 'Pods-prefix.pch'
end
it "returns the absolute path of the prefix header file" do
@lib.prefix_header_path.to_s.should.include?('Pods/Pods-prefix.pch')
end
it "returns the bridge support file name" do
@lib.bridge_support_name.should == 'Pods.bridgesupport'
end
it "returns the absolute path of the bridge support file" do
@lib.bridge_support_path.to_s.should.include?('Pods/Pods.bridgesupport')
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