Commit 4b4bd467 authored by Will Pragnell's avatar Will Pragnell

Merged branch 'master' into 'acknowledgements'

parents 2837753d 809745bd
......@@ -19,7 +19,7 @@ link_with ['MyAppTarget', 'MyOtherAppTarget']
dependency 'JSONKit'
target :test, :exclusive => true do
xcodeproj 'TestProject'
xcodeproj 'TestProject', 'Test' => :debug
link_with 'TestRunnerTarget'
dependency 'Kiwi'
end
......@@ -42,6 +42,16 @@ need to specify the target to link with.
See [#76](https://github.com/CocoaPods/CocoaPods/issues/76) for more info.
Finally, CocoaPods will add build configurations to the Pods project for all
configurations in the other projects in the workspace. By default the
configurations are based on the `Release` configuration, to base them on the
`Debug` configuration you will have to explicitely specify them as can be seen
above in the following line:
```ruby
xcodeproj 'TestProject', 'Test' => :debug
```
### Documentation
......
......@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'xcodeproj', '~> 0.1.0'
s.add_runtime_dependency 'colored', '~> 1.2'
s.add_runtime_dependency 'escape', '~> 0.0.4'
s.add_runtime_dependency 'rake', '~> 0.9.0'
s.add_development_dependency 'bacon', '~> 1.1'
## Make sure you can build the gem on older versions of RubyGems too:
......
......@@ -4,6 +4,10 @@ module Pod
VERSION = '0.6.0rc1'
class Informative < StandardError
def message
#TODO: remove formatting from raise calls and remove conditional
super !~ /\[!\]/ ? "[!] #{super}\n".red : super
end
end
autoload :Command, 'cocoapods/command'
......
......@@ -25,9 +25,8 @@ module Pod
def self.options
[
["--no-clean", "Leave SCM dirs like `.git' and `.svn' in tact after downloading"],
["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"],
["--no-doc", "Skip documentation generation with appledoc"],
["--force-doc", "Force the generation of documentation"],
["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"],
["--no-update", "Skip running `pod repo update` before install"],
].concat(super)
......@@ -36,7 +35,6 @@ module Pod
def initialize(argv)
config.clean = !argv.option('--no-clean')
config.generate_docs = !argv.option('--no-doc')
config.force_doc = argv.option('--force-doc')
config.integrate_targets = !argv.option('--no-integrate')
@update_repo = !argv.option('--no-update')
super unless argv.empty?
......
......@@ -23,7 +23,7 @@ module Pod
# specification information
def spec
@spec ||= @set.specification.part_of_other_pod? ? @set.specification.part_of_specification : @set.specification
@set.specification
end
def authors
......@@ -47,7 +47,7 @@ module Pod
end
def platform
spec.platform.to_s
spec.available_platforms.sort { |a,b| a.to_s.downcase <=> b.to_s.downcase }.join(' - ')
end
def license
......@@ -98,6 +98,7 @@ module Pod
end
def distance_from_now_in_words(from_time)
return nil unless from_time
from_time = Time.parse(from_time)
to_time = Time.now
distance_in_days = (((to_time - from_time).abs)/60/60/24).round
......
......@@ -92,7 +92,8 @@ module Pod
FileUtils.cp(Pathname.new(spec.name+'.podspec'), output_path)
Dir.chdir(repo_dir) do
git("add #{spec.name}")
git("commit -m '#{message}'")
# Bypass the pre-commit hook because we already performed validation
git("commit --no-verify -m '#{message}'")
end
end
end
......
This diff is collapsed.
......@@ -12,20 +12,20 @@ module Pod
attr_accessor :repos_dir, :project_root, :project_pods_root
attr_accessor :clean, :verbose, :silent
attr_accessor :generate_docs, :doc_install, :force_doc
attr_accessor :generate_docs, :doc_install
attr_accessor :integrate_targets
attr_accessor :git_cache_size
alias_method :clean?, :clean
alias_method :verbose?, :verbose
alias_method :silent?, :silent
alias_method :generate_docs?, :generate_docs
alias_method :doc_install?, :doc_install
alias_method :force_doc?, :force_doc
alias_method :integrate_targets?, :integrate_targets
def initialize
@repos_dir = Pathname.new(File.expand_path("~/.cocoapods"))
@verbose = @silent = @force_doc = false
@verbose = @silent = false
@clean = @generate_docs = @doc_install = @integrate_targets = true
end
......
......@@ -5,8 +5,6 @@ require 'open-uri'
module Pod
class Dependency < Gem::Dependency
attr_accessor :only_part_of_other_pod
alias_method :only_part_of_other_pod?, :only_part_of_other_pod
attr_reader :external_source
attr_accessor :specification
......@@ -19,7 +17,7 @@ module Pod
elsif !name_and_version_requirements.empty? && block.nil?
if name_and_version_requirements.last.is_a?(Hash)
@external_source = ExternalSources.from_params(name_and_version_requirements[0], name_and_version_requirements.pop)
@external_source = ExternalSources.from_params(name_and_version_requirements[0].split('/').first, name_and_version_requirements.pop)
end
super(*name_and_version_requirements)
......@@ -27,23 +25,20 @@ module Pod
raise Informative, "A dependency needs either a name and version requirements, " \
"a source hash, or a block which defines a podspec."
end
@only_part_of_other_pod = false
end
def ==(other)
super &&
@only_part_of_other_pod == other.only_part_of_other_pod &&
(@specification ? @specification == other.specification : @external_source == other.external_source)
super && (@specification ? @specification == other.specification : @external_source == other.external_source)
end
def subspec_dependency?
@name.include?('/')
end
def inline?
@inline_podspec
end
def external?
!@external_source.nil?
end
......@@ -75,7 +70,7 @@ module Pod
end
version.empty? ? @name : "#{@name} (#{version})"
end
def specification_from_sandbox(sandbox, platform)
@external_source.specification_from_sandbox(sandbox, platform)
end
......@@ -126,42 +121,41 @@ module Pod
raise Informative, "Unknown external source parameters for #{name}: #{params}"
end
end
class AbstractExternalSource
include Config::Mixin
attr_reader :name, :params
def initialize(name, params)
@name, @params = name, params
end
def specification_from_sandbox(sandbox, platform)
if local_pod = sandbox.installed_pod_named(name, platform)
local_pod.specification
local_pod.top_specification
else
copy_external_source_into_sandbox(sandbox)
local_pod = sandbox.installed_pod_named(name, platform)
local_pod.clean if config.clean?
local_pod.specification
local_pod.top_specification
end
end
def ==(other_source)
return if other_source.nil?
name == other_source.name && params == other_source.params
end
end
class GitSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox)
puts " * Pre-downloading: '#{name}'" unless config.silent?
Downloader.for_target(sandbox.root + name, @params).tap do |downloader|
downloader.download
downloader.clean if config.clean?
end
end
def description
"from `#{@params[:git]}'".tap do |description|
description << ", commit `#{@params[:commit]}'" if @params[:commit]
......@@ -180,7 +174,7 @@ module Pod
output_path.open('w') { |f| f << io.read }
end
end
def description
"from `#{@params[:podspec]}'"
end
......
......@@ -11,8 +11,7 @@ module Pod
extend Executable
def self.for_pod(pod)
spec = pod.specification
spec = spec.part_of_specification if spec.part_of_other_pod?
spec = pod.top_specification
for_target(pod.root, spec.source.dup)
end
......@@ -23,12 +22,8 @@ module Pod
@target_path.mkpath
end
def clean
# implement in sub-classes
end
private
def self.for_target(target_path, options)
options = options.dup
if url = options.delete(:git)
......
require 'open-uri'
require 'tempfile'
require 'zlib'
require 'digest/sha1'
module Pod
class Downloader
class Git < Downloader
include Config::Mixin
executable :git
MAX_CACHE_SIZE = 500
def download
create_cache unless cache_exist?
puts '-> Cloning git repo' if config.verbose?
if options[:tag]
download_tag
elsif options[:commit]
......@@ -15,16 +21,84 @@ module Pod
else
download_head
end
removed_cached_repos_if_needed
end
def create_cache
puts "-> Creating cache git repo (#{cache_path})" if config.verbose?
cache_path.rmtree if cache_path.exist?
cache_path.mkpath
git "clone '#{url}' #{cache_path}"
end
def removed_cached_repos_if_needed
return unless caches_dir.exist?
Dir.chdir(caches_dir) do
repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime)
while caches_size >= MAX_CACHE_SIZE && !repos.empty?
dir = repos.shift
puts '->'.yellow << " Removing git cache for `#{origin_url(dir)}'" if config.verbose?
dir.rmtree
end
end
end
def cache_path
@cache_path ||= caches_dir + "#{Digest::SHA1.hexdigest(url.to_s)}"
end
def cache_exist?
cache_path.exist? && origin_url(cache_path).to_s == url.to_s
end
def origin_url(dir)
Dir.chdir(dir) { `git config remote.origin.url`.chomp }
end
def caches_dir
Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
end
def clone_url
cache_path
end
def caches_size
# expressed in Mb
`du -cm`.split("\n").last.to_i
end
def update_cache
puts "-> Updating cache git repo (#{cache_path})" if config.verbose?
Dir.chdir(cache_path) do
git "reset --hard HEAD"
git "clean -d -x -f"
git "pull"
end
end
def ref_exists?(ref)
Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
$? == 0
end
def ensure_ref_exists(ref)
return if ref_exists?(ref)
# Skip pull if not needed
update_cache
raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
end
def download_head
git "clone '#{url}' '#{target_path}'"
update_cache
git "clone '#{clone_url}' '#{target_path}'"
end
def download_tag
ensure_ref_exists(options[:tag])
Dir.chdir(target_path) do
git "init"
git "remote add origin '#{url}'"
git "remote add origin '#{clone_url}'"
git "fetch origin tags/#{options[:tag]}"
git "reset --hard FETCH_HEAD"
git "checkout -b activated-pod-commit"
......@@ -32,16 +106,12 @@ module Pod
end
def download_commit
git "clone '#{url}' '#{target_path}'"
ensure_ref_exists(options[:commit])
git "clone '#{clone_url}' '#{target_path}'"
Dir.chdir(target_path) do
git "checkout -b activated-pod-commit #{options[:commit]}"
end
end
def clean
(target_path + '.git').rmtree
end
end
class GitHub < Git
......@@ -50,28 +120,18 @@ module Pod
end
def download_tag
super unless download_only?
download_only? ? download_and_extract_tarball(options[:tag]) : super
end
def download_commit
super unless download_only?
download_only? ? download_and_extract_tarball(options[:commit]) : super
end
def clean
if download_only?
FileUtils.rm_f(tmp_path)
else
super
end
end
def tarball_url_for(id)
original_url, username, reponame = *(url.match(/[:\/]([\w\-]+)\/([\w\-]+)\.git/).to_a)
"https://github.com/#{username}/#{reponame}/tarball/#{id}"
end
def tmp_path
target_path + "tarball.tar.gz"
end
......
......@@ -11,7 +11,7 @@ module Pod
executable :curl
executable :unzip
executable :tar
attr_accessor :filename, :download_path
def download
@filename = filename_with_type type
......@@ -25,10 +25,6 @@ module Pod
options[:type] || type_with_url(url)
end
def clean
FileUtils.rm @download_path
end
private
def type_with_url(url)
if url =~ /.zip$/
......@@ -41,7 +37,7 @@ module Pod
nil
end
end
def filename_with_type(type=:zip)
case type
when :zip
......@@ -54,7 +50,7 @@ module Pod
raise UnsupportedFileTypeError.new "Unsupported file type: #{type}"
end
end
def download_file(full_filename)
curl "-L -o '#{full_filename}' '#{url}'"
end
......
......@@ -18,10 +18,6 @@ module Pod
def download_revision
hg "clone '#{url}' --rev '#{options[:revision]}' '#{target_path}'"
end
def clean
(target_path + '.hg').rmtree
end
end
end
end
......
......@@ -18,10 +18,6 @@ module Pod
def download_revision
svn "checkout '#{url}' -r '#{options[:revision]}' '#{target_path}'"
end
def clean
target_path.glob('**/.svn').each(&:rmtree)
end
end
end
end
......@@ -7,8 +7,14 @@ module Pod
raise Informative, "Unable to locate the executable `#{name}'"
end
if Config.instance.verbose?
puts "-> #{bin} #{command}"
`#{bin} #{command} 1>&2`
print " $ #{name}...\r"
$stdout.flush
output = `#{bin} #{command} 2>&1`
puts " #{$?.exitstatus.zero? ? '-' : '!'.red} #{name} #{command}"
output = output.gsub(/ */,' ').gsub(/^ */,' ')
puts output unless output.strip.empty?
else
`#{bin} #{command} 2> /dev/null`
end
......
......@@ -7,6 +7,10 @@ module Pod
install_resource()
{
case $1 in
*\.storyboard)
echo "ibtool --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*\.xib)
echo "ibtool --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename $1 .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
......
......@@ -12,9 +12,9 @@ module Pod
def initialize(pod)
@pod = pod
@specification = pod.specification
@specification = pod.top_specification
@target_path = pod.sandbox.root + 'Documentation' + pod.name
@options = pod.specification.documentation || {}
@options = @specification.documentation || {}
end
def name
......@@ -42,13 +42,11 @@ module Pod
end
def files
@pod.absolute_source_files.map(&:to_s)
@pod.all_specs_public_header_files.map{ |f| f.relative_path_from(@pod.root).to_s }
end
def index_file
@pod.chdir do
Dir.glob('README*', File::FNM_CASEFOLD).first
end
@pod.readme_file.relative_path_from(@pod.root).to_s if @pod.readme_file
end
def spec_appledoc_options
......@@ -66,11 +64,9 @@ module Pod
'--keep-undocumented-objects',
'--keep-undocumented-members',
'--keep-intermediate-files',
'--exit-threshold', '2'
# appledoc exits with 1 if a warning was logged
'--exit-threshold', '2' # appledoc terminates with an exits status of 1 if a warning was logged
]
index = index_file
options += ['--index-desc', index] if index
options += ['--index-desc', index_file] if index_file
options += spec_appledoc_options
end
......@@ -82,6 +78,8 @@ module Pod
options = appledoc_options
options += ['--output', @target_path.to_s]
options += install ? ['--create-docset'] : ['--no-create-docset']
# TODO: passing the files explicitly clutters output and chokes on very long list (AWSiOSSDK Spec).
# It is possible to just pass the dir of the pod, however this would include other files like demo projects.
options += files
@target_path.mkpath
......
......@@ -25,7 +25,8 @@ module Pod
def project
return @project if @project
@project = Pod::Project.new
activated_pods.each do |pod|
@project.user_build_configurations = @podfile.user_build_configurations
pods.each do |pod|
# Add all source files to the project grouped by pod
group = @project.add_pod_group(pod.name)
pod.source_files.each do |path|
......@@ -44,32 +45,32 @@ module Pod
end
def install_dependencies!
activated_pods.each do |pod|
marker = config.verbose ? "\n-> ".green : ''
unless should_install = !pod.exists? && !pod.specification.local?
puts marker + "Using #{pod}" unless config.silent?
else
puts marker + "Installing #{pod.specification}".green unless config.silent?
pods.each do |pod|
unless config.silent?
marker = config.verbose ? "\n-> ".green : ''
name = pod.top_specification.preferred_dependency ? "#{pod.top_specification.name}/#{pod.top_specification.preferred_dependency} (#{pod.top_specification.version})" : pod.to_s
puts marker << ( pod.exists? ? "Using #{name}" : "Installing #{name}".green )
end
unless pod.exists?
downloader = Downloader.for_pod(pod)
downloader.download
if config.clean
downloader.clean
pod.clean
end
# The docs need to be generated before cleaning because
# the documentation is created for all the subspecs.
generate_docs(pod)
pod.clean if config.clean
end
end
end
if (should_install && config.generate_docs?) || config.force_doc?
doc_generator = Generator::Documentation.new(pod)
if doc_generator.already_installed?
puts "Using Existing Documentation for #{pod.specification}".green if config.verbose?
else
puts "Installing Documentation for #{pod.specification}".green if config.verbose?
doc_generator.generate(config.doc_install?)
end
end
#TODO: move to generator ?
def generate_docs(pod)
doc_generator = Generator::Documentation.new(pod)
if ( config.generate_docs? && !doc_generator.already_installed? )
puts "-> Installing documentation" if config.verbose?
doc_generator.generate(config.doc_install?)
else
puts "-> Using existing documentation" if config.verbose?
end
end
......@@ -82,24 +83,23 @@ module Pod
print_title "Installing dependencies"
install_dependencies!
pods = activated_pods
print_title("Generating support files\n", false)
target_installers.each do |target_installer|
pods_for_target = activated_pods_by_target[target_installer.target_definition]
pods_for_target = pods_by_target[target_installer.target_definition]
target_installer.install!(pods_for_target, @sandbox)
acknowledgements_path = target_installer.target_definition.acknowledgements_path
Generator::Acknowledgements.new(target_installer.target_definition,
pods_for_target).save_as(acknowledgements_path)
end
generate_lock_file!(pods)
generate_lock_file!(specifications)
generate_dummy_source
puts "* Running post install hooks" if config.verbose?
puts "- Running post install hooks" if config.verbose?
# Post install hooks run _before_ saving of project, so that they can alter it before saving.
run_post_install_hooks
puts "* Writing Xcode project file to `#{@sandbox.project_path}'\n\n" if config.verbose?
puts "- Writing Xcode project file to `#{@sandbox.project_path}'\n\n" if config.verbose?
project.save_as(@sandbox.project_path)
UserProjectIntegrator.new(@podfile).integrate! if config.integrate_targets?
......@@ -109,7 +109,7 @@ module Pod
# we loop over target installers instead of pods, because we yield the target installer
# to the spec post install hook.
target_installers.each do |target_installer|
activated_specifications_for_target(target_installer.target_definition).each do |spec|
specs_by_target[target_installer.target_definition].each do |spec|
spec.post_install(target_installer)
end
end
......@@ -117,28 +117,28 @@ module Pod
@podfile.post_install!(self)
end
def generate_lock_file!(pods)
def generate_lock_file!(specs)
lock_file.open('w') do |file|
file.puts "PODS:"
# Get list of [name, dependencies] pairs.
activated_pods = pods.map do |pod|
[pod.specification.to_s, pod.dependencies.map(&:to_s).sort]
pod_and_deps = specs.map do |spec|
[spec.to_s, spec.dependencies.map(&:to_s).sort]
end.uniq
# Merge dependencies of ios and osx version of the same pod.
tmp = {}
activated_pods.each do |name, deps|
pod_and_deps.each do |name, deps|
if tmp[name]
tmp[name].concat(deps).uniq!
else
tmp[name] = deps
end
end
activated_pods = tmp
pod_and_deps = tmp
# Sort by name and print
activated_pods.sort_by(&:first).each do |name, deps|
pod_and_deps.sort_by(&:first).each do |name, deps|
if deps.empty?
file.puts " - #{name}"
else
......@@ -147,14 +147,6 @@ module Pod
end
end
unless download_only_specifications.empty?
file.puts
file.puts "DOWNLOAD_ONLY:"
download_only_specifications.map(&:to_s).sort.each do |name|
file.puts " - #{name}"
end
end
file.puts
file.puts "DEPENDENCIES:"
@podfile.dependencies.map(&:to_s).sort.each do |dep|
......@@ -181,49 +173,36 @@ module Pod
end
# @return [Array<Specification>] All dependencies that have been resolved.
def dependency_specifications
def specifications
specs_by_target.values.flatten
end
# @return [Array<LocalPod>] A list of LocalPod instances for each
# dependency that is not a download-only one.
def activated_pods
activated_pods_by_target.values.flatten
def pods
pods_by_target.values.flatten
end
def activated_pods_by_target
def pods_by_target
@pods_by_spec = {}
result = {}
specs_by_target.each do |target_definition, specs|
@pods_by_spec[target_definition.platform] = {}
result[target_definition] = specs.map do |spec|
LocalPod.new(spec, @sandbox, target_definition.platform) if activated_spec?(spec)
end.compact
pod = pod_for_spec(spec, target_definition.platform)
pod.add_specification(spec)
pod
end.uniq.compact
end
result
end
# @return [Array<Specification>] A list of specifications for each
# dependency that is not a download-only
# one.
def activated_specifications
dependency_specifications.select { |spec| activated_spec?(spec) }
end
def activated_specifications_for_target(target_definition)
specs_by_target[target_definition].select { |spec| activated_spec?(spec) }
end
def download_only_specifications
dependency_specifications - activated_specifications
def pod_for_spec(spec, platform)
@pods_by_spec[platform][spec.top_level_parent.name] ||= LocalPod.new(spec, @sandbox, platform)
end
private
def activated_spec?(spec)
# Don't activate specs which are only wrappers of subspecs, or share
# source with another pod but aren't activated themselves.
!spec.wrapper? && !@resolver.cached_sets[spec.name].only_part_of_other_pod?
end
def print_title(title, only_verbose = true)
if config.verbose?
puts "\n" + title.yellow
......
......@@ -41,7 +41,7 @@ module Pod
header.puts "#import #{@target_definition.platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}"
header.puts "#endif"
pods.each do |pod|
if prefix_header_contents = pod.specification.prefix_header_contents
if prefix_header_contents = pod.top_specification.prefix_header_contents
header.puts
header.puts prefix_header_contents
elsif prefix_header = pod.prefix_header_file
......@@ -63,19 +63,18 @@ module Pod
@target = @project.add_pod_target(@target_definition.label, @target_definition.platform)
pods.each do |pod|
# TODO add methods like xcconfig to LocalPod as well? (which returns the correct platform)
xcconfig.merge!(pod.specification.xcconfig[@target_definition.platform.name])
xcconfig.merge!(pod.xcconfig)
pod.add_to_target(@target)
# TODO: this doesn't need to be done here, it has nothing to do with the target
pod.link_headers
end
xcconfig.merge!('HEADER_SEARCH_PATHS' => quoted(sandbox.header_search_paths).join(" "))
support_files_group = @project.group("Targets Support Files").create_group(@target_definition.label)
support_files_group.create_files(target_support_files)
xcconfig_file = support_files_group.files.where(:path => @target_definition.xcconfig_name)
configure_build_configurations(xcconfig_file)
create_files(pods, sandbox)
......@@ -93,24 +92,24 @@ module Pod
def create_files(pods, sandbox)
if @podfile.generate_bridge_support?
bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name
puts "* Generating BridgeSupport metadata file at `#{bridge_support_metadata_path}'" if config.verbose?
puts "- Generating BridgeSupport metadata file at `#{bridge_support_metadata_path}'" if config.verbose?
bridge_support_generator_for(pods, sandbox).save_as(bridge_support_metadata_path)
copy_resources_script_for(pods).resources << @target_definition.bridge_support_name
end
puts "* Generating xcconfig file at `#{sandbox.root + @target_definition.xcconfig_name}'" if config.verbose?
puts "- Generating xcconfig file at `#{sandbox.root + @target_definition.xcconfig_name}'" if config.verbose?
xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name)
puts "* Generating prefix header at `#{sandbox.root + @target_definition.prefix_header_name}'" if config.verbose?
puts "- Generating prefix header at `#{sandbox.root + @target_definition.prefix_header_name}'" if config.verbose?
save_prefix_header_as(sandbox.root + @target_definition.prefix_header_name, pods)
puts "* Generating copy resources script at `#{sandbox.root + @target_definition.copy_resources_script_name}'" if config.verbose?
puts "- Generating copy resources script at `#{sandbox.root + @target_definition.copy_resources_script_name}'" if config.verbose?
copy_resources_script_for(pods).save_as(sandbox.root + @target_definition.copy_resources_script_name)
end
private
def quoted(strings)
strings.map { |s| "\"#{s}\"" }
end
def default_ld_flags
flags = %w{-ObjC}
flags << '-fobjc-arc' if @podfile.set_arc_compatibility_flag? && self.requires_arc
......
......@@ -34,13 +34,17 @@ module Pod
end.compact
end
def user_projects
@podfile.target_definitions.values.map(&:xcodeproj)
def user_project_paths
@podfile.target_definitions.values.map do |td|
next if td.empty?
td.user_project.path #|| raise(Informative, "Could not resolve the Xcode project in which the " \
# "`#{td.name}' target should be integrated.")
end.compact
end
def create_workspace!
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
[pods_project_path, *user_projects].each do |project_path|
[pods_project_path, *user_project_paths].each do |project_path|
project_path = project_path.relative_path_from(config.project_root).to_s
workspace << project_path unless workspace.include?(project_path)
end
......@@ -74,11 +78,11 @@ module Pod
add_xcconfig_base_configuration
add_pods_library
add_copy_resources_script_phase
user_project.save_as(@target_definition.xcodeproj)
user_project.save_as(@target_definition.user_project.path)
end
def user_project_path
if path = @target_definition.xcodeproj
if path = @target_definition.user_project.path
unless path.exist?
raise Informative, "The Xcode project `#{path}' does not exist."
end
......
module Pod
class LocalPod
attr_reader :specification
attr_reader :top_specification, :specifications
attr_reader :sandbox
attr_reader :platform
def initialize(specification, sandbox, platform)
@specification, @sandbox, @platform = specification, sandbox, platform
@top_specification, @sandbox = specification.top_level_parent, sandbox
@top_specification.activate_platform(platform)
@specifications = [] << specification
end
def self.from_podspec(podspec, sandbox, platform)
new(Specification.from_file(podspec), sandbox, platform)
end
# Method to add the specifications sharing the same top level
# parent. With this information the local pod can determine the
# paths to clean and avoid duplication in file processing.
# Adding specifications is idempotent.
def add_specification(spec)
raise Informative, "[Local Pod] Attempt to add a specification from another pod" unless spec.top_level_parent == top_specification
spec.activate_platform(platform)
@specifications << spec unless @specifications.include?(spec)
end
def root
@sandbox.root + specification.name
@sandbox.root + top_specification.name
end
def subspecs
specifications.reject{|s| s.parent.nil? }
end
def to_s
if specification.local?
"#{specification} [LOCAL]"
else
specification.to_s
end
result = top_specification.to_s
result << " [LOCAL]" if top_specification.local?
result
end
def name
specification.name
top_specification.name
end
def platform
top_specification.active_platform
end
# Installation methods
def create
root.mkpath unless exists?
end
......@@ -45,30 +64,55 @@ module Pod
root.rmtree if exists?
end
# It deletes all the files identified by clean_paths, then it removes
# all the empty folders or symlinks.
def clean
clean_paths.each { |path| FileUtils.rm_rf(path) }
Dir.glob("#{root}/**/{*,.*}").
sort_by(&:length).reverse. # Clean the deepest paths first to determine if the containing folders are empty
reject { |d| d =~ /\/\.\.?$/ }. # Remove the `.` and `..` paths
select { |d| File.directory?(d) }. # Get only directories or symlinks to directories
each do |d|
FileUtils.rm_rf(d) if File.symlink?(d) || (Dir.entries(d) == %w[ . .. ]) # Remove the symlink and the empty dirs
end
end
# File attributes
def prefix_header_file
if prefix_header = specification.prefix_header_file
@sandbox.root + specification.name + prefix_header
if prefix_header = top_specification.prefix_header_file
@sandbox.root + top_specification.name + prefix_header
end
end
def source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true)
def source_files(relative = true)
chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => relative)
end
def absolute_source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}')
def resources(relative = true)
chained_expanded_paths(:resources, :relative_to_sandbox => relative)
end
def clean_paths
expanded_paths(specification.clean_paths)
expanded_paths('**/{*,.*}').reject { |p| p.directory? } - used_files
end
def used_files
source_files(false) + resources(false) + [ readme_file, license_file, prefix_header_file ] + preserve_paths
end
def readme_file
expanded_paths(%w[ README{*,.*} readme{*,.*} ]).first
end
def license_file
file = top_specification.license[:file] if top_specification.license
file || expanded_paths(%w[ LICENSE{*,.*} licence{*,.*} ]).first
end
def resources
expanded_paths(specification.resources, :relative_to_sandbox => true)
# TODO: implement case insensitive search
def preserve_paths
chained_expanded_paths(:preserve_paths) + expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
end
def header_files
......@@ -85,6 +129,20 @@ module Pod
end
end
def xcconfig
specifications.map { |s| s.xcconfig }.reduce(:merge)
end
# Method used by documentation generator. It return the source files
# of all the specs.
def all_specs_public_header_files
#TODO: merge with #221
specs = top_specification.recursive_subspecs << top_specification
specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }.compact.flatten.select { |f| f.extname == '.h' }.uniq
end
# Integration methods
def link_headers
copy_header_mappings.each do |namespaced_path, files|
@sandbox.add_header_files(namespaced_path, files)
......@@ -92,17 +150,17 @@ module Pod
end
def add_to_target(target)
implementation_files.each do |file|
target.add_source_file(file, nil, specification.compiler_flags[@platform.name].strip)
sources_files_by_specification.each do | spec, files |
files.each do |file|
# TODO: Xcodeproj::Project::Object::PBXNativeTarget#add_source_file is quite slow
# The issus appears to be related to the find call in line 107.
target.add_source_file(file, nil, spec.compiler_flags.strip)
end
end
end
def requires_arc?
specification.requires_arc
end
def dependencies
specification.dependencies[@platform.name]
top_specification.requires_arc
end
private
......@@ -117,17 +175,46 @@ module Pod
# TODO this is being overriden in the RestKit 0.9.4 spec, need to do
# something with that, and this method also still exists in Specification.
#
# This is not overriden anymore in specification refactor and the code
# Pod::Specification#copy_header_mapping can be moved here.
def copy_header_mappings
header_files.inject({}) do |mappings, from|
search_path_headers = header_files - headers_excluded_from_search_paths
search_path_headers.inject({}) do |mappings, from|
from_without_prefix = from.relative_path_from(relative_root)
to = specification.header_dir + specification.copy_header_mapping(from_without_prefix)
to = top_specification.header_dir + top_specification.copy_header_mapping(from_without_prefix)
(mappings[to.dirname] ||= []) << from
mappings
end
end
def expanded_paths(platforms_with_patterns, options = {})
patterns = platforms_with_patterns.is_a?(Hash) ? platforms_with_patterns[@platform.name] : platforms_with_patterns
# returns an hash where the source_files are groupped by specification.
# If the same file is required by two specifications the one at the
# higher level in the inheritance chain wins.
def sources_files_by_specification
files_by_spec = {}
processed_files = []
specifications.sort_by { |s| s.name.length }.each do |spec|
files = []
expanded_paths(spec.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true).each do | file |
files << file unless processed_files.include?(file)
end
files_by_spec[spec] = files
processed_files += files
end
files_by_spec
end
def headers_excluded_from_search_paths
chained_expanded_paths(:exclude_header_search_paths, :relative_to_sandbox => true)
end
def chained_expanded_paths(accessor, options = {})
specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.flatten.uniq
end
def expanded_paths(patterns, options = {})
patterns = [ patterns ] if patterns.is_a? String
patterns.map do |pattern|
pattern = root + pattern
......
......@@ -10,7 +10,7 @@ module Pod
attr_reader :deployment_target
def initialize(symbolic_name, deployment_target = nil)
def initialize(symbolic_name = nil, deployment_target = nil)
@symbolic_name = symbolic_name
if deployment_target
version = deployment_target.is_a?(Hash) ? deployment_target[:deployment_target] : deployment_target # backwards compatibility from 0.6
......@@ -34,9 +34,11 @@ module Pod
end
end
def support?(other)
def supports?(other)
return true if @symbolic_name.nil? || other.nil?
@symbolic_name == other.name && (deployment_target.nil? || other.deployment_target.nil? || deployment_target >= other.deployment_target)
os_check = @symbolic_name == other.name
version_check = (deployment_target.nil? || other.deployment_target.nil? || deployment_target >= other.deployment_target)
os_check && version_check
end
def to_s
......
module Pod
class Podfile
class UserProject
include Config::Mixin
DEFAULT_BUILD_CONFIGURATIONS = { 'Debug' => :debug, 'Release' => :release }.freeze
def initialize(path = nil, build_configurations = {})
self.path = path if path
@build_configurations = build_configurations.merge(DEFAULT_BUILD_CONFIGURATIONS)
end
def path=(path)
path = path.to_s
@path = Pathname.new(File.extname(path) == '.xcodeproj' ? path : "#{path}.xcodeproj")
@path = config.project_root + @path unless @path.absolute?
@path
end
def path
if @path
@path
else
xcodeprojs = config.project_root.glob('*.xcodeproj')
if xcodeprojs.size == 1
@path = xcodeprojs.first
end
end
end
def project
Xcodeproj::Project.new(path) if path && path.exist?
end
def build_configurations
if project
project.build_configurations.map(&:name).inject({}) do |hash, name|
hash[name] = :release; hash
end.merge(@build_configurations)
else
@build_configurations
end
end
end
class TargetDefinition
include Config::Mixin
attr_reader :name, :target_dependencies
attr_accessor :xcodeproj, :link_with, :platform, :parent, :exclusive
attr_accessor :user_project, :link_with, :platform, :parent, :exclusive
def initialize(name, options = {})
@name, @target_dependencies = name, []
......@@ -27,20 +70,8 @@ module Pod
end
alias_method :exclusive?, :exclusive
def xcodeproj=(path)
path = path.to_s
@xcodeproj = config.project_root + (File.extname(path) == '.xcodeproj' ? path : "#{path}.xcodeproj")
end
def xcodeproj
if @xcodeproj
@xcodeproj
elsif @parent
@parent.xcodeproj
else
xcodeprojs = config.project_root.glob('*.xcodeproj')
@xcodeproj = xcodeprojs.first if xcodeprojs.size == 1
end
def user_project
@user_project || @parent.user_project
end
def link_with=(targets)
......@@ -48,16 +79,16 @@ module Pod
end
def platform
@platform || @parent.platform
@platform || (@parent.platform if @parent)
end
def label
if name == :default
"Pods"
elsif @parent
"#{@parent.label}-#{name}"
else
elsif exclusive?
"Pods-#{name}"
else
"#{@parent.label}-#{name}"
end
end
......@@ -68,8 +99,13 @@ module Pod
# Returns a path, which is relative to the project_root, relative to the
# `$(SRCROOT)` of the user's project.
def relative_to_srcroot(path)
raise Informative, "[!] Unable to find an Xcode project to integrate".red unless xcodeproj || !config.integrate_targets
xcodeproj ? (config.project_root + path).relative_path_from(xcodeproj.dirname) : path
if user_project.path.nil?
# TODO this is not in the right place
raise Informative, "[!] Unable to find an Xcode project to integrate".red if config.integrate_targets
path
else
(config.project_root + path).relative_path_from(user_project.path.dirname)
end
end
def relative_pods_root
......@@ -127,7 +163,9 @@ module Pod
include Config::Mixin
def initialize(&block)
@target_definitions = { :default => (@target_definition = TargetDefinition.new(:default, :exclusive => true)) }
@target_definition = TargetDefinition.new(:default, :exclusive => true)
@target_definition.user_project = UserProject.new
@target_definitions = { :default => @target_definition }
instance_eval(&block)
end
......@@ -163,8 +201,8 @@ module Pod
elsif @workspace
@workspace
else
projects = @target_definitions.map { |_, td| td.xcodeproj }.uniq
if projects.size == 1 && (xcodeproj = @target_definitions[:default].xcodeproj)
projects = @target_definitions.map { |_, td| td.user_project.path }.uniq
if projects.size == 1 && (xcodeproj = @target_definitions[:default].user_project.path)
config.project_root + "#{xcodeproj.basename('.xcodeproj')}.xcworkspace"
end
end
......@@ -188,8 +226,8 @@ module Pod
# xcodeproj 'TestProject'
# end
#
def xcodeproj(path)
@target_definition.xcodeproj = path
def xcodeproj(path, build_configurations = {})
@target_definition.user_project = UserProject.new(path, build_configurations)
end
# Specifies the target(s) in the user’s project that this Pods library
......@@ -407,6 +445,11 @@ module Pod
@set_arc_compatibility_flag
end
def user_build_configurations
configs_array = @target_definitions.values.map { |td| td.user_project.build_configurations }
configs_array.inject({}) { |hash, config| hash.merge(config) }
end
def post_install!(installer)
@post_install_callback.call(installer) if @post_install_callback
end
......
......@@ -15,6 +15,18 @@ module Pod
def initialize(*)
super
main_group << groups.new('name' => 'Pods')
@user_build_configurations = []
end
def user_build_configurations=(user_build_configurations)
@user_build_configurations = user_build_configurations
# The configurations at the top level only need to exist, they don't hold
# any build settings themselves, that's left to `add_pod_target`.
user_build_configurations.each do |name, _|
unless build_configurations.map(&:name).include?(name)
build_configurations.new('name' => name)
end
end
end
# Shortcut access to the `Pods' PBXGroup.
......@@ -41,6 +53,14 @@ module Pod
target.build_settings('Debug').merge!(settings)
target.build_settings('Release').merge!(settings)
@user_build_configurations.each do |name, type|
unless target.build_configurations.map(&:name).include?(name)
config = target.build_configurations.new('name' => name)
# Copy the settings from either the Debug or the Release configuration.
config.build_settings = target.build_settings(type.to_s.capitalize).merge(settings)
end
end
target
end
end
......
......@@ -22,26 +22,19 @@ module Pod
@podfile.target_definitions.values.each do |target_definition|
puts "\nResolving dependencies for target `#{target_definition.name}' (#{target_definition.platform})".green if config.verbose?
@loaded_specs = []
# TODO @podfile.platform will change to target_definition.platform
find_dependency_sets(@podfile, target_definition.dependencies, target_definition)
find_dependency_specs(@podfile, target_definition.dependencies, target_definition)
targets_and_specs[target_definition] = @specs.values_at(*@loaded_specs).sort_by(&:name)
end
# Specification doesn't need to know more about the context, so we assign
# the other specification, of which this pod is a part, to the spec.
@specs.values.sort_by(&:name).each do |spec|
if spec.part_of_other_pod?
spec.part_of_specification = @cached_sets[spec.part_of.name].specification
end
end
@specs.values.sort_by(&:name)
targets_and_specs
end
private
def find_cached_set(dependency, platform)
@cached_sets[dependency.name] ||= begin
set_name = dependency.name.split('/').first
@cached_sets[set_name] ||= begin
if dependency.specification
Specification::Set::External.new(dependency.specification)
elsif external_source = dependency.external_source
......@@ -49,14 +42,18 @@ module Pod
# that's being used behind the scenes, but passing it anyways for
# completeness sake.
specification = external_source.specification_from_sandbox(@sandbox, platform)
Specification::Set::External.new(specification)
set = Specification::Set::External.new(specification)
if dependency.subspec_dependency?
@cached_sets[dependency.top_level_spec_name] ||= set
end
set
else
@cached_sources.search(dependency)
end
end
end
def find_dependency_sets(dependent_specification, dependencies, target_definition)
def find_dependency_specs(dependent_specification, dependencies, target_definition)
@log_indent += 1
dependencies.each do |dependency|
puts ' ' * @log_indent + "- #{dependency}" if config.verbose?
......@@ -64,19 +61,12 @@ module Pod
set.required_by(dependent_specification)
# Ensure we don't resolve the same spec twice for one target
unless @loaded_specs.include?(dependency.name)
# Get a reference to the spec that’s actually being loaded.
# If it’s a subspec dependency, e.g. 'RestKit/Network', then
# find that subspec.
spec = set.specification
if dependency.subspec_dependency?
spec = spec.subspec_by_name(dependency.name)
end
spec = set.specification_by_name(dependency.name)
@loaded_specs << spec.name
@specs[spec.name] = spec
spec.activate_platform(target_definition.platform)
# And recursively load the dependencies of the spec.
# TODO fix the need to return an empty arrayf if there are no deps for the given platform
find_dependency_sets(spec, (spec.dependencies[target_definition.platform.to_sym] || []), target_definition)
find_dependency_specs(spec, spec.dependencies, target_definition) if spec.dependencies
end
validate_platform!(spec || @specs[dependency.name], target_definition)
end
......@@ -84,8 +74,8 @@ module Pod
end
def validate_platform!(spec, target)
unless spec.platforms.any? { |platform| target.platform.support?(platform) }
raise Informative, "[!] The platform of the target `#{target.name}' (#{target.platform}) is not compatible with `#{spec}' which has a minimun requirement of #{spec.platforms.join(' - ')}.".red
unless spec.available_platforms.any? { |platform| target.platform.supports?(platform) }
raise Informative, "[!] The platform of the target `#{target.name}' (#{target.platform}) is not compatible with `#{spec}' which has a minimun requirement of #{spec.available_platforms.join(' - ')}.".red
end
end
end
......
......@@ -68,7 +68,7 @@ module Pod
set.name == dependency.top_level_spec_name &&
# Now either check if it's a dependency on the top level spec, or if it's not
# check if the requested subspec exists in the top level spec.
(!dependency.subspec_dependency? || !set.specification.subspec_by_name(dependency.name).nil?)
set.specification.subspec_by_name(dependency.name)
end
end
......
This diff is collapsed.
......@@ -9,6 +9,9 @@ module Pod
end
def required_by(specification)
# Skip subspecs because the can't require a different version of the top level parent
return if !specification.podfile? && specification.top_level_parent.name == name
dependency = specification.dependency_by_top_level_spec_name(name)
# TODO we don’t actually do anything in our Version subclass. Maybe we should just remove that.
unless @required_by.empty? || dependency.requirement.satisfied_by?(Gem::Version.new(required_version.to_s))
......@@ -21,16 +24,16 @@ module Pod
@required_by << specification
end
def specification_by_name(name)
specification.top_level_parent.subspec_by_name(name)
end
def dependency
@required_by.inject(Dependency.new(name)) do |previous, spec|
previous.merge(spec.dependency_by_top_level_spec_name(name).to_top_level_spec_dependency)
end
end
def only_part_of_other_pod?
@required_by.all? { |spec| spec.dependency_by_top_level_spec_name(name).only_part_of_other_pod? }
end
def name
@pod_dir.basename.to_s
end
......@@ -74,7 +77,7 @@ module Pod
end
def name
@specification.name
@specification.top_level_parent.name
end
def ==(other)
......@@ -88,10 +91,6 @@ module Pod
@specification = before
end
def only_part_of_other_pod?
false
end
def specification_path
raise "specification_path"
end
......
......@@ -81,7 +81,7 @@ module Pod
def github_stats_if_needed(set)
return if get_value(set, :gh_date) && get_value(set, :gh_date) > Time.now - cache_expiration
spec = set.specification.part_of_other_pod? ? set.specification.part_of_specification : set.specification
spec = set.specification
url = spec.source.reject {|k,_| k == :commit || k == :tag }.values.first
repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1]
return unless repo_id
......
......@@ -288,6 +288,101 @@
};
name = Release;
};
517F031C154C379000D46FE2 /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
SDKROOT = iphoneos;
};
name = Test;
};
517F031D154C379000D46FE2 /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SampleProject/SampleProject-Prefix.pch";
INFOPLIST_FILE = "SampleProject/SampleProject-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = Test;
};
517F031E154C379000D46FE2 /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestRunner/TestRunner-Prefix.pch";
INFOPLIST_FILE = "TestRunner/TestRunner-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
name = Test;
};
517F0320154C379700D46FE2 /* App Store */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = "App Store";
};
517F0321154C379700D46FE2 /* App Store */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "SampleProject/SampleProject-Prefix.pch";
INFOPLIST_FILE = "SampleProject/SampleProject-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
name = "App Store";
};
517F0322154C379700D46FE2 /* App Store */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "TestRunner/TestRunner-Prefix.pch";
INFOPLIST_FILE = "TestRunner/TestRunner-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
name = "App Store";
};
A346498314F9BE9A0080D870 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
......@@ -362,15 +457,20 @@
isa = XCConfigurationList;
buildConfigurations = (
51075D5C1521D0C100E39B41 /* Debug */,
517F031E154C379000D46FE2 /* Test */,
51075D5D1521D0C100E39B41 /* Release */,
517F0322154C379700D46FE2 /* App Store */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A346496714F9BE990080D870 /* Build configuration list for PBXProject "SampleProject" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A346498314F9BE9A0080D870 /* Debug */,
517F031C154C379000D46FE2 /* Test */,
A346498414F9BE9A0080D870 /* Release */,
517F0320154C379700D46FE2 /* App Store */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
......@@ -379,7 +479,9 @@
isa = XCConfigurationList;
buildConfigurations = (
A346498614F9BE9A0080D870 /* Debug */,
517F031D154C379000D46FE2 /* Test */,
A346498714F9BE9A0080D870 /* Release */,
517F0321154C379700D46FE2 /* App Store */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
......
Subproject commit 7e96b1af54872aba6e474ea5860e84f1ce534fb1
Subproject commit 5f39221d0bf69ebc0a2dc5879deae271f208877b
require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Install" do
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
it "should include instructions on how to reference the xcode project" do
Pod::Command::Install.banner.should.match %r{xcodeproj 'path/to/XcodeProject'}
end
end
it "tells the user that no Podfile or podspec was found in the current working dir" do
exception = lambda { run_command('install','--no-update') }.should.raise Pod::Informative
exception.message.should.include "No `Podfile' found in the current working directory."
end
end
require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::List" do
extend SpecHelper::Git
extend SpecHelper::TemporaryRepos
before do
config.repos_dir = fixture('spec-repos')
end
after do
config.repos_dir = tmp_repos_path
end
def command(arguments = argv)
command = Pod::Command::List.new(arguments)
end
......
......@@ -2,8 +2,12 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Command::Push do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
def master_repo
fixture('spec-repos/master')
end
it "complains for wrong parameters" do
lambda { run_command('push') }.should.raise Pod::Command::Help
......@@ -12,19 +16,19 @@ describe Pod::Command::Push do
end
it "complains if it can't find the repo" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
repo1 = add_repo('repo1', master_repo)
Dir.chdir(fixture('banana-lib')) do
lambda { run_command('push', 'repo2') }.should.raise Pod::Informative
end
end
it "complains if it can't find a spec" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
repo1 = add_repo('repo1', master_repo)
lambda { run_command('push', 'repo1') }.should.raise Pod::Informative
end
it "it raises if the pod is not validated" do
repo1 = add_repo('repo1', fixture('spec-repos/master'))
repo1 = add_repo('repo1', master_repo)
git('repo1', 'checkout master') # checkout master, because the fixture is a submodule
repo2 = add_repo('repo2', repo1.dir)
git_config('repo2', 'remote.origin.url').should == (tmp_repos_path + 'repo1').to_s
......@@ -36,7 +40,7 @@ describe Pod::Command::Push do
before do
# prepare the repos
@upstream = add_repo('upstream', fixture('spec-repos/master'))
@upstream = add_repo('upstream', master_repo)
git('upstream', 'checkout -b master') # checkout master, because the fixture is a submodule
@local_repo = add_repo('local_repo', @upstream.dir)
git_config('local_repo', 'remote.origin.url').should == (tmp_repos_path + 'upstream').to_s
......
......@@ -2,8 +2,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Repo" do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
it "runs with correct parameters" do
lambda { run_command('repo', 'add', 'NAME', 'URL') }.should.not.raise
......@@ -42,6 +42,7 @@ describe "Pod::Command::Repo" do
before do
add_repo('repo1', fixture('spec-repos/master'))
FileUtils.rm_rf(versions_file)
versions_file.should.not.exist?
end
......
......@@ -2,18 +2,13 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Search" do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
before do
config.repos_dir = fixture('spec-repos')
end
after do
config.repos_dir = tmp_repos_path
end
it "runs with correct parameters" do
lambda { run_command('search', 'table') }.should.not.raise
lambda { run_command('search', 'table', '--full') }.should.not.raise
......
......@@ -3,8 +3,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Pod::Command::Setup" do
extend SpecHelper::Command
extend SpecHelper::Git
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
it "runs with correct parameters" do
lambda { run_command('setup') }.should.not.raise
......
......@@ -18,21 +18,22 @@ describe "Pod::Command::Spec#create" do
extend SpecHelper::Command
extend SpecHelper::Github
extend SpecHelper::TemporaryDirectory
extend SpecHelper::Git
extend SpecHelper::TemporaryRepos
it "creates a new podspec stub file" do
run_command('spec', 'create', 'Bananas')
path = temporary_directory + 'Bananas.podspec'
spec = Pod::Specification.from_file(path)
spec.name.should == 'Bananas'
spec.license.should == { :type => "MIT", :file => "LICENSE" }
spec.version.should == Pod::Version.new('0.0.1')
spec.summary.should == 'A short description of Bananas.'
spec.homepage.should == 'http://EXAMPLE/Bananas'
spec.authors.should == { `git config --get user.name`.strip => `git config --get user.email`.strip}
spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' }
spec.description.should == 'An optional longer description of Bananas.'
spec.source_files[:ios].should == ['Classes', 'Classes/**/*.{h,m}']
spec = Pod::Specification.from_file(path).activate_platform(:ios)
spec.name.should == 'Bananas'
spec.license.should == { :type => "MIT", :file => "LICENSE" }
spec.version.should == Pod::Version.new('0.0.1')
spec.summary.should == 'A short description of Bananas.'
spec.homepage.should == 'http://EXAMPLE/Bananas'
spec.authors.should == { `git config --get user.name`.strip => `git config --get user.email`.strip}
spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' }
spec.description.should == 'An optional longer description of Bananas.'
spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}']
end
it "correctly creates a podspec from github" do
......@@ -93,21 +94,16 @@ end
describe "Pod::Command::Spec#lint" do
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::Git
extend SpecHelper::TemporaryRepos
before do
config.repos_dir = fixture('spec-repos')
end
after do
config.repos_dir = tmp_repos_path
end
it "lints a repo" do
# The fixture has an error due to a name mismatch
# The fixture has warnings so it raises
cmd = command('spec', 'lint', 'master')
lambda { cmd.run }.should.raise Pod::Informative
cmd.output.should.include "InAppSettingKit (0.0.1)\n - ERROR | The name of the spec should match the name of the file"
cmd.output.should.include "WARN"
end
......@@ -124,17 +120,23 @@ describe "Pod::Command::Spec#lint" do
end
end
before do
text = (fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec').read
text.gsub!(/.*license.*/, "")
file = temporary_directory + 'JSONKit.podspec'
File.open(file, 'w') {|f| f.write(text) }
@spec_path = file.to_s
end
it "lints a givent podspec" do
spec_file = fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec'
cmd = command('spec', 'lint', '--quick', spec_file.to_s)
cmd = command('spec', 'lint', '--quick', @spec_path)
lambda { cmd.run }.should.raise Pod::Informative
cmd.output.should.include "Missing license[:file] or [:text]"
cmd.output.should.include "Missing license type"
end
it "respects the -only--errors option" do
spec_file = fixture('spec-repos') + 'master/JSONKit/1.4/JSONKit.podspec'
cmd = command('spec', 'lint', '--quick', '--only-errors', spec_file.to_s)
cmd = command('spec', 'lint', '--quick', '--only-errors', @spec_path)
lambda { cmd.run }.should.not.raise
cmd.output.should.include "Missing license[:file] or [:text]"
cmd.output.should.include "Missing license type"
end
end
......@@ -2,8 +2,8 @@ require File.expand_path('../../spec_helper', __FILE__)
# describe "Pod::Command" do
# extend SpecHelper::Command
# extend SpecHelper::Git
# extend SpecHelper::TemporaryDirectory
# extend SpecHelper::TemporaryRepos
#
# TODO:
# it "raises help informative if an unknown parameter is passed"
......
This diff is collapsed.
......@@ -4,6 +4,7 @@ describe Pod::Installer::UserProjectIntegrator do
extend SpecHelper::TemporaryDirectory
before do
config.silent = true
@sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
config.project_root = @sample_project_path.dirname
......@@ -11,7 +12,7 @@ describe Pod::Installer::UserProjectIntegrator do
@podfile = Pod::Podfile.new do
platform :ios
xcodeproj sample_project_path
xcodeproj sample_project_path, 'Test' => :debug
link_with 'SampleProject' # this is an app target!
dependency 'JSONKit'
......@@ -28,10 +29,6 @@ describe Pod::Installer::UserProjectIntegrator do
@sample_project = Xcodeproj::Project.new(@sample_project_path)
end
after do
config.project_root = nil
end
it 'creates a workspace with a name matching the project' do
workspace_path = @sample_project_path.dirname + "SampleProject.xcworkspace"
workspace_path.should.exist
......@@ -41,12 +38,12 @@ describe Pod::Installer::UserProjectIntegrator do
workspace = Xcodeproj::Workspace.new_from_xcworkspace(@sample_project_path.dirname + "SampleProject.xcworkspace")
workspace.projpaths.sort.should == %w{ Pods/Pods.xcodeproj SampleProject.xcodeproj }
end
it 'adds the Pods project to the workspace' do
workspace = Xcodeproj::Workspace.new_from_xcworkspace(@sample_project_path.dirname + "SampleProject.xcworkspace")
workspace.projpaths.find { |path| path =~ /Pods.xcodeproj/ }.should.not.be.nil
end
it 'sets the Pods xcconfig as the base config for each build configuration' do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
......@@ -69,7 +66,7 @@ describe Pod::Installer::UserProjectIntegrator do
framework_build_phase.files.where(:name => definition.lib_name).should.not == nil
end
end
it 'adds a Copy Pods Resources build phase to each target' do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
......
......@@ -9,11 +9,9 @@ module SpecHelper
def specs_by_target
@specs_by_target ||= super.tap do |hash|
hash.values.flatten.each do |spec|
unless spec.part_of_other_pod?
source = spec.source
source[:git] = SpecHelper.fixture("integration/#{spec.name}").to_s
spec.source = source
end
source = spec.source
source[:git] = SpecHelper.fixture("integration/#{spec.name}").to_s
spec.source = source
end
end
end
......@@ -28,37 +26,14 @@ else
extend SpecHelper::TemporaryDirectory
def create_config!
Pod::Config.instance = nil
if ENV['VERBOSE_SPECS']
config.verbose = true
else
config.silent = true
end
config.repos_dir = fixture('spec-repos')
config.project_root = temporary_directory
config.doc_install = false
config.integrate_targets = false
end
before do
fixture('spec-repos/master') # ensure the archive is unpacked
@config_before = config
create_config!
config.generate_docs = false
end
after do
Pod::Config.instance = @config_before
end
# This is so we can run at least the specs that don't use xcodebuild on Travis.
def with_xcodebuild_available
unless `which xcodebuild`.strip.empty?
yield
else
puts "\n[!] Skipping xcodebuild, because it can't be found."
end
end
def should_successfully_perform(command)
......@@ -67,11 +42,14 @@ else
$?.should.be.success
end
puts " ! ".red << "Skipping xcodebuild based checks, because it can't be found." if `which xcodebuild`.strip.empty?
def should_xcodebuild(target_definition)
return if `which xcodebuilda`.strip.empty?
target = target_definition
with_xcodebuild_available do
Dir.chdir(config.project_pods_root) do
puts "\n[!] Compiling #{target.label} static library..."
print "[!] Compiling #{target.label}...\r"
should_successfully_perform "xcodebuild -target '#{target.label}'"
lib_path = config.project_pods_root + "build/Release#{'-iphoneos' if target.platform == :ios}" + target.lib_name
`lipo -info '#{lib_path}'`.should.include "architecture: #{target.platform == :ios ? 'armv7' : 'x86_64'}"
......@@ -113,13 +91,13 @@ else
installer.install!
YAML.load(installer.lock_file.read).should == {
'PODS' => [{ 'Reachability (1.2.3)' => ["ASIHTTPRequest (>= 1.8)"] }],
'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'PODS' => [ 'Reachability (1.2.3)' ],
# 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'DEPENDENCIES' => ["Reachability (from `#{url}')"]
}
end
it "install a dummy source file" do
it "installs a dummy source file" do
create_config!
podfile = Pod::Podfile.new do
self.platform :ios
......@@ -131,7 +109,7 @@ else
s.source_files = 'JSONKit.*'
end
end
installer = SpecHelper::Installer.new(podfile)
installer.install!
......@@ -157,6 +135,7 @@ else
end
end
Pod::Specification.any_instance.stubs(:preserve_paths).returns(['CHANGELOG.md'])
installer = SpecHelper::Installer.new(podfile)
installer.install!
......@@ -199,7 +178,16 @@ else
unless `which appledoc`.strip.empty?
it "generates documentation of all pods by default" do
create_config!
::Pod::Config.instance = nil
::Pod::Config.instance.tap do |c|
ENV['VERBOSE_SPECS'] ? c.verbose = true : c.silent = true
c.doc_install = false
c.repos_dir = fixture('spec-repos')
c.project_root = temporary_directory
c.integrate_targets = false
end
Pod::Generator::Documentation.any_instance.stubs(:already_installed?).returns(false)
podfile = Pod::Podfile.new do
self.platform :ios
......@@ -207,19 +195,16 @@ else
dependency 'JSONKit', '1.4'
dependency 'SSToolkit'
end
Pod::Generator::Documentation.any_instance.stubs(:already_installed?).returns(false)
installer = SpecHelper::Installer.new(podfile)
installer.install!
doc = (config.project_pods_root + 'Documentation/JSONKit/html/index.html').read
doc.should.include?('<title>JSONKit 1.4 Reference</title>')
doc = (config.project_pods_root + 'Documentation/SSToolkit/html/index.html').read
doc.should.include?('<title>SSToolkit 0.1.2 Reference</title>')
doc.should.include?('<title>SSToolkit 1.0.0 Reference</title>')
end
else
puts "[!] Skipping documentation generation specs, because appledoc can't be found."
puts " ! ".red << "Skipping documentation generation specs, because appledoc can't be found."
end
end
......@@ -249,12 +234,13 @@ else
end
# TODO add a simple source file which uses the compiled lib to check that it really really works
# TODO update for specification refactor
it "activates required pods and create a working static library xcode project" do
podfile = Pod::Podfile.new do
self.platform platform
xcodeproj 'dummy'
dependency 'Reachability', '> 2.0.5' if platform == :ios
dependency 'ASIWebPageRequest', '>= 1.8.1'
# dependency 'ASIWebPageRequest', '>= 1.8.1'
dependency 'JSONKit', '>= 1.0'
dependency 'SSZipArchive', '< 2'
end
......@@ -264,14 +250,14 @@ else
lock_file_contents = {
'PODS' => [
{ 'ASIHTTPRequest (1.8.1)' => ["Reachability"] },
{ 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] },
# { 'ASIHTTPRequest (1.8.1)' => ["Reachability"] },
# { 'ASIWebPageRequest (1.8.1)' => ["ASIHTTPRequest (= 1.8.1)"] },
'JSONKit (1.5pre)',
'Reachability (3.0.0)',
'SSZipArchive (0.1.2)',
'SSZipArchive (0.2.1)',
],
'DEPENDENCIES' => [
"ASIWebPageRequest (>= 1.8.1)",
# "ASIWebPageRequest (>= 1.8.1)",
"JSONKit (>= 1.0)",
"Reachability (> 2.0.5)",
"SSZipArchive (< 2)",
......@@ -279,9 +265,9 @@ else
}
unless platform == :ios
# No Reachability is required by ASIHTTPRequest on OSX
lock_file_contents['DEPENDENCIES'].delete_at(2)
lock_file_contents['PODS'].delete_at(3)
lock_file_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)'
lock_file_contents['DEPENDENCIES'].delete_at(1)
lock_file_contents['PODS'].delete_at(1)
# lock_file_contents['PODS'][0] = 'ASIHTTPRequest (1.8.1)'
end
YAML.load(installer.lock_file.read).should == lock_file_contents
......@@ -294,6 +280,7 @@ else
end
if platform == :ios
# TODO: update for Specification Refactor
it "does not activate pods that are only part of other pods" do
spec = Pod::Podfile.new do
self.platform platform
......@@ -305,8 +292,9 @@ else
installer.install!
YAML.load(installer.lock_file.read).should == {
'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }],
'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
# 'PODS' => [{ 'Reachability (2.0.4)' => ["ASIHTTPRequest (>= 1.8)"] }],
'PODS' => [ 'Reachability (2.0.4)' ],
# 'DOWNLOAD_ONLY' => ["ASIHTTPRequest (1.8.1)"],
'DEPENDENCIES' => ["Reachability (= 2.0.4)"]
}
end
......@@ -321,7 +309,7 @@ else
installer = SpecHelper::Installer.new(spec)
target_definition = installer.target_installers.first.target_definition
installer.activated_specifications_for_target(target_definition).first.resources = 'LICEN*', 'Readme.*'
installer.specs_by_target[target_definition].first.resources = 'LICEN*', 'Readme.*'
installer.install!
contents = (config.project_pods_root + 'Pods-resources.sh').read
......
......@@ -12,47 +12,30 @@ $:.unshift((ROOT + 'lib').to_s)
require 'cocoapods'
$:.unshift((ROOT + 'spec').to_s)
require 'spec_helper/color_output'
require 'spec_helper/bacon'
require 'spec_helper/command'
require 'spec_helper/fixture'
require 'spec_helper/git'
require 'spec_helper/github'
require 'spec_helper/temporary_directory'
require 'spec_helper/temporary_repos'
require 'spec_helper/config'
module Bacon
extend ColorOutput
summary_at_exit
module FilterBacktraces
def handle_summary
ErrorLog.replace(ErrorLog.split("\n").reject do |line|
line =~ %r{(gems/mocha|spec_helper)}
end.join("\n").lstrip << "\n\n")
super
end
end
extend FilterBacktraces
class Context
include Pod::Config::Mixin
include SpecHelper::Fixture
def argv(*argv)
Pod::Command::ARGV.new(argv)
end
require 'colored'
def xit(description, *args)
puts "- #{description} [DISABLED]".yellow
ErrorLog << "[DISABLED] #{self.name} #{description}\n\n"
end
end
end
config = Pod::Config.instance
config.silent = true
config.repos_dir = SpecHelper.tmp_repos_path
config.silent = true
config.repos_dir = SpecHelper.tmp_repos_path
config.project_root = SpecHelper.temporary_directory
Pod::Specification::Statistics.instance.cache_file = nil
require 'tmpdir'
......@@ -85,5 +68,3 @@ VCR.configure do |c|
c.allow_http_connections_when_no_cassette = true
end
Pod::Specification::Statistics.instance.cache_file = nil
module Bacon
summary_at_exit
@needs_first_put = true
module ColorOutput
# Graciously yanked from https://github.com/zen-cms/Zen-Core and subsequently modified
# MIT License
# Thanks, YorickPeterse! #:nodoc:
def handle_specification(name)
if @needs_first_put
@needs_first_put = false
puts
end
@specs_depth = @specs_depth || 0
puts spaces + name
@specs_depth += 1
yield
@specs_depth -= 1
puts if @specs_depth.zero?
end
#:nodoc:
def handle_requirement(description, disabled = false)
error = yield
if !error.empty?
puts "#{spaces}\e[31m- #{description} [FAILED]\e[0m"
elsif disabled
puts "#{spaces}\e[33m- #{description} [DISABLED]\e[0m"
else
puts "#{spaces}\e[32m- #{description}\e[0m"
end
end
#:nodoc:
def handle_summary
print ErrorLog if Backtraces
puts "\e[33m#{Counter[:disabled]} disabled specifications\n\e[0m" unless Counter[:disabled].zero?
puts "%d specifications (%d requirements), %d failures, %d errors" %
Counter.values_at(:specifications, :requirements, :failed, :errors)
end
#:nodoc:
def spaces
return ' ' * @specs_depth
end
end
extend ColorOutput
module FilterBacktraces
def handle_summary
ErrorLog.replace(ErrorLog.split("\n").reject do |line|
line =~ %r{(gems/mocha|spec_helper)}
end.join("\n").lstrip << "\n\n")
super
end
end
extend FilterBacktraces
class Context
def xit(description, *args)
Counter[:disabled] += 1
Bacon.handle_requirement(description, true) {[]}
end
end
end
# Graciously yanked from https://github.com/zen-cms/Zen-Core
# MIT License
# Thanks, YorickPeterse!
#:nodoc:
module Bacon
#:nodoc:
module ColorOutput
#:nodoc:
def handle_specification(name)
puts spaces + name
yield
puts if Counter[:context_depth] == 1
end
#:nodoc:
def handle_requirement(description)
error = yield
if !error.empty?
puts "#{spaces} \e[31m- #{description} [FAILED]\e[0m"
else
puts "#{spaces} \e[32m- #{description}\e[0m"
end
end
#:nodoc:
def handle_summary
print ErrorLog if Backtraces
puts "%d specifications (%d requirements), %d failures, %d errors" %
Counter.values_at(:specifications, :requirements, :failed, :errors)
end
#:nodoc:
def spaces
if Counter[:context_depth] == 0
Counter[:context_depth] = 1
end
return ' ' * (Counter[:context_depth] - 1)
end
end # ColorOutput
end # Bacon
# Restores the config to the default state before each requirement
module Bacon
class Context
old_run_requirement = instance_method(:run_requirement)
define_method(:run_requirement) do |description, spec|
::Pod::Config.instance = nil
::Pod::Config.instance.tap do |c|
ENV['VERBOSE_SPECS'] ? c.verbose = true : c.silent = true
c.repos_dir = SpecHelper.tmp_repos_path
c.project_root = SpecHelper.temporary_directory
c.doc_install = false
c.generate_docs = false
end
old_run_requirement.bind(self).call(description, spec)
end
end
end
......@@ -2,22 +2,18 @@ require 'spec_helper/temporary_directory'
module SpecHelper
def self.tmp_repos_path
Git.tmp_repos_path
TemporaryRepos.tmp_repos_path
end
module Git
module TemporaryRepos
extend Pod::Executable
executable :git
def tmp_repos_path
SpecHelper.temporary_directory + 'cocoapods'
end
module_function :tmp_repos_path
def tmp_master_repo_path
tmp_repos_path + 'master'
end
extend Pod::Executable
executable :git
alias_method :git_super, :git
def git(repo, command)
Dir.chdir(tmp_repos_path + repo) do
......@@ -42,5 +38,12 @@ module SpecHelper
git(name, 'add README')
git(name, 'commit -m "changed"')
end
def self.extended(base)
base.before do
tmp_repos_path.mkpath
end
end
end
end
......@@ -19,7 +19,7 @@ describe "Pod::Command::Spec::Linter" do
it "fails a specifications that does not contain the minimum required attributes" do
spec, file = write_podspec('Pod::Spec.new do |s| end')
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.join(' | ') =~ /name.*version.*summary.*homepage.*authors.*(source.*part_of).*source_files/
......@@ -27,7 +27,7 @@ describe "Pod::Command::Spec::Linter" do
it "fails specifications if the name does not match the name of the file" do
spec, file = write_podspec(stub_podspec(/s.name *= 'JSONKit'/, "s.name = 'JSONKitAAA'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
......@@ -36,16 +36,16 @@ describe "Pod::Command::Spec::Linter" do
it "fails a specification if a path starts with a slash" do
spec, file = write_podspec(stub_podspec(/s.source_files = 'JSONKit\.\*'/, "s.source_files = '/JSONKit.*'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
linter.errors[0].should =~ /Paths cannot start with a slash/
end
it "fails a specification if the plafrom is unrecognized" do
it "fails a specification if the platform is unrecognized" do
spec, file = write_podspec(stub_podspec(/s.name *= 'JSONKit'/, "s.name = 'JSONKit'\ns.platform = :iososx\n"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = true, true
linter.lint.should == false
linter.errors.count.should == 1
......@@ -53,8 +53,8 @@ describe "Pod::Command::Spec::Linter" do
end
it "fails validation if the specification contains warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
spec, file = write_podspec(stub_podspec(/.*license.*/, ""))
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = false, true
linter.lint.should == false
linter.errors.should.be.empty
......@@ -62,8 +62,8 @@ describe "Pod::Command::Spec::Linter" do
end
it "validates in lenient mode if there are no erros but there are warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
spec, file = write_podspec(stub_podspec(/.*license.*/, ""))
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = true, true
linter.lint.should == true
linter.errors.should.be.empty
......@@ -72,7 +72,7 @@ describe "Pod::Command::Spec::Linter" do
it "respects quick mode" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.expects(:peform_multiplatform_analysis).never
linter.expects(:install_pod).never
linter.expects(:xcodebuild_output_for_platfrom).never
......@@ -83,16 +83,16 @@ describe "Pod::Command::Spec::Linter" do
it "produces deprecation notices" do
spec, file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\n if config.ios?\nend"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = false, true
linter.lint.should == false
linter.errors.should.be.empty
linter.warnings.join(' | ').should =~ /`config.ios\?' and `config.osx\?' are deprecated and will be removed in version 0.7/
linter.warnings.join(' | ').should =~ /`config.ios\?' and `config.osx\?' are deprecated/
end
it "uses xcodebuild to generate notes and warnings" do
spec, file = write_podspec(stub_podspec)
linter = Pod::Command::Spec::Linter.new(spec, file)
linter = Pod::Command::Spec::Linter.new(spec)
linter.lenient, linter.quick = false, false
linter.lint.should == false
linter.notes.join(' | ').should.include "JSONKit/JSONKit.m:1640:27: warning: equality comparison with extraneous parentheses" unless `which xcodebuild`.strip.empty?
......@@ -100,10 +100,10 @@ describe "Pod::Command::Spec::Linter" do
it "checks for file patterns" do
spec, file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'JSONKit.*'\ns.resources = 'WRONG_FOLDER'"))
linter = Pod::Command::Spec::Linter.new(spec, file)
linter.stubs(:xcodebuild_output_for_platfrom).returns([])
linter = Pod::Command::Spec::Linter.new(spec)
linter.stubs(:xcodebuild_output).returns([])
linter.lenient, linter.quick = false, false
linter.lint.should == false
linter.errors.join(' | ').should.include "[resources = 'WRONG_FOLDER'] -> did not match any file"
linter.errors.join(' | ').should.include "The resources did not match any file"
end
end
......@@ -15,12 +15,3 @@ describe "Pod::Command::Repo" do
end
end
describe "Pod::Command::Install" do
it "tells the user that no Podfile or podspec was found in the current working dir" do
command = Pod::Command::Install.new(argv)
exception = lambda {
command.run
}.should.raise Pod::Informative
exception.message.should.include "No `Podfile' found in the current working directory."
end
end
......@@ -2,14 +2,9 @@ require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Config" do
before do
@original_config = config
Pod::Config.instance = nil
end
after do
Pod::Config.instance = @original_config
end
it "returns the singleton config instance" do
config.should.be.instance_of Pod::Config
end
......@@ -22,7 +17,9 @@ describe "Pod::Config" do
extend SpecHelper::TemporaryDirectory
it "returns the path to the project root" do
config.project_root = nil
config.project_root.should == Pathname.pwd
config.project_root = temporary_directory
end
it "returns the path to the project Podfile if it exists" do
......
......@@ -7,15 +7,6 @@ describe "Pod::Dependency" do
dep1.merge(dep2).should == Pod::Dependency.new('bananas', '>= 1.8', '1.9')
end
it "is equal to another dependency if `part_of_other_pod' is the same" do
dep1 = Pod::Dependency.new('bananas', '>= 1')
dep1.only_part_of_other_pod = true
dep2 = Pod::Dependency.new('bananas', '>= 1')
dep1.should.not == dep2
dep2.only_part_of_other_pod = true
dep1.should == dep2
end
it "returns the name of the dependency, or the name of the pod of which this is a subspec" do
dep = Pod::Dependency.new('RestKit')
dep.top_level_spec_name.should == 'RestKit'
......
......@@ -2,12 +2,11 @@ require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(
:part_of_other_pod? => false,
:source => source_options
)
stub('pod') do
stubs(:root).returns(temporary_sandbox.root)
stubs(:specification).returns(specification)
stubs(:top_specification).returns(specification)
end
end
......@@ -19,10 +18,10 @@ describe "Pod::Downloader" do
downloader.url.should == 'http://banana-corp.local/banana-lib.git'
downloader.options.should == { :tag => 'v1.0' }
end
it 'returns a github downloader when the :git URL is on github' do
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Pod::Platform.ios)
pod.specification.stubs(:source).returns(:git => "git://github.com/CocoaPods/CocoaPods")
pod.top_specification.stubs(:source).returns(:git => "git://github.com/CocoaPods/CocoaPods")
downloader = Pod::Downloader.for_pod(pod)
downloader.should.be.instance_of Pod::Downloader::GitHub
end
......@@ -36,21 +35,21 @@ describe Pod::Downloader::GitHub do
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert private HTTP repository URLs to the tarball URL' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:git => "https://lukeredpath@github.com/CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert private SSH repository URLs to the tarball URL' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:git => "git@github.com:CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert public git protocol repository URLs to the tarball URL' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:git => "git://github.com/CocoaPods/CocoaPods.git"
......
......@@ -18,11 +18,8 @@ describe Pod::Generator::Documentation do
}
end
it 'returns the Pod documentation documentation files' do
@doc_installer.files.sort.should == [
(@pod.root + "Classes/Banana.m").to_s,
(@pod.root + "Classes/Banana.h").to_s,
].sort
it 'returns the Pod documentation header files' do
@doc_installer.files.sort.should == %w[ Classes/Banana.h ].sort
end
it 'returns the Pod documentation options' do
......
......@@ -6,7 +6,7 @@ describe Pod::Generator::DummySource do
before do
setup_temporary_directory
end
after do
teardown_temporary_directory
end
......@@ -21,5 +21,5 @@ describe Pod::Generator::DummySource do
@implementation PodsDummy
@end
EOS
end
end
end
......@@ -2,12 +2,11 @@ require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(
:part_of_other_pod? => false,
:source => source_options
)
stub('pod') do
stubs(:root).returns(temporary_sandbox.root)
stubs(:specification).returns(specification)
stubs(:top_specification).returns(specification)
end
end
......@@ -19,20 +18,20 @@ describe Pod::Downloader::Http do
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :zip
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tar'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :tar
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tgz'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :tgz
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0',
:type => :zip
......@@ -40,7 +39,7 @@ describe Pod::Downloader::Http do
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :zip
end
it 'should download file and extract it with proper type' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.zip'
......@@ -48,28 +47,28 @@ describe Pod::Downloader::Http do
downloader.expects(:download_file).with(anything())
downloader.expects(:extract_with_type).with(anything(), :zip).at_least_once
downloader.download
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tgz'
))
downloader.expects(:download_file).with(anything())
downloader.expects(:extract_with_type).with(anything(), :tgz).at_least_once
downloader.download
downloader.download
end
it 'should raise error when unsupported filetype is pass' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.rar'
))
downloader.expects(:download).raises(Pod::Downloader::Http::UnsupportedFileTypeError)
downloader.download rescue nil
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0',
:type => :rar
))
downloader.expects(:download).raises(Pod::Downloader::Http::UnsupportedFileTypeError)
downloader.download rescue nil
end
end
......@@ -22,38 +22,43 @@ describe Pod::Installer::TargetInstaller do
@specification = fixture_spec('banana-lib/BananaLib.podspec')
@pods = [Pod::LocalPod.new(@specification, @sandbox, Pod::Platform.ios)]
end
def do_install!
@installer.install!(@pods, @sandbox)
end
it 'adds a new static library target to the project' do
do_install!
@project.targets.count.should == 1
@project.targets.first.name.should == @target_definition.label
end
it "adds the user's build configurations to the target" do
@project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
do_install!
@project.targets.first.build_configurations.map(&:name).sort.should == %w{ AppStore Debug Release Test }
end
it 'adds each pod to the static library target' do
@pods[0].expects(:add_to_target).with(instance_of(Xcodeproj::Project::Object::PBXNativeTarget))
do_install!
end
it 'tells each pod to link its headers' do
@pods[0].expects(:link_headers)
do_install!
end
it 'adds the sandbox header search paths to the xcconfig, with quotes' do
do_install!
@installer.xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include("\"#{@sandbox.header_search_paths.join('" "')}\"")
end
it 'does not add the -fobjc-arc to OTHER_LDFLAGS by default as Xcode 4.3.2 does not support it' do
do_install!
@installer.xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.not.include("-fobjc-arc")
end
it 'adds the -fobjc-arc to OTHER_LDFLAGS if any pods require arc (to support non-ARC projects on iOS 4.0)' do
@podfile.stubs(:set_arc_compatibility_flag? => true)
@specification.stubs(:requires_arc).returns(true)
......
......@@ -21,10 +21,6 @@ describe Pod::Installer::UserProjectIntegrator do
@integrator = Pod::Installer::UserProjectIntegrator.new(@podfile)
end
after do
config.project_root = nil
end
it "returns the path to the workspace from the Podfile" do
@integrator.workspace_path.should == config.project_root + 'SampleProject.xcworkspace'
end
......@@ -52,12 +48,12 @@ describe Pod::Installer::UserProjectIntegrator do
end
it "raises if no project could be selected" do
@target_integrator.target_definition.stubs(:xcodeproj).returns(nil)
@target_integrator.target_definition.user_project.stubs(:path).returns(nil)
lambda { @target_integrator.user_project_path }.should.raise Pod::Informative
end
it "raises if the project path doesn't exist" do
@target_integrator.target_definition.xcodeproj.stubs(:exist?).returns(false)
@target_integrator.target_definition.user_project.path.stubs(:exist?).returns(false)
lambda { @target_integrator.user_project_path }.should.raise Pod::Informative
end
......
......@@ -2,24 +2,18 @@ require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Installer" do
before do
@config_before = config
Pod::Config.instance = nil
config.silent = true
config.repos_dir = fixture('spec-repos')
config.project_pods_root = fixture('integration')
end
after do
Pod::Config.instance = @config_before
end
describe ", by default," do
describe "by default" do
before do
@xcconfig = Pod::Installer.new(Pod::Podfile.new do
podfile = Pod::Podfile.new do
platform :ios
xcodeproj 'MyProject'
dependency 'JSONKit'
end).target_installers.first.xcconfig.to_hash
end
@xcconfig = Pod::Installer.new(podfile).target_installers.first.xcconfig.to_hash
end
it "sets the header search paths where installed Pod headers can be found" do
......@@ -41,7 +35,7 @@ describe "Pod::Installer" do
dependency 'ASIHTTPRequest'
end
installer = Pod::Installer.new(podfile)
pods = installer.activated_specifications.map do |spec|
pods = installer.specifications.map do |spec|
Pod::LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform)
end
expected = pods.map { |pod| pod.header_files }.flatten.map { |header| config.project_pods_root + header }
......@@ -59,4 +53,14 @@ describe "Pod::Installer" do
installer = Pod::Installer.new(podfile)
installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty]
end
it "adds the user's build configurations" do
path = fixture('SampleProject/SampleProject.xcodeproj')
podfile = Pod::Podfile.new do
platform :ios
xcodeproj path, 'App Store' => :release
end
installer = Pod::Installer.new(podfile)
installer.project.build_configurations.map(&:name).sort.should == ['App Store', 'Debug', 'Release', 'Test']
end
end
This diff is collapsed.
require File.expand_path('../../spec_helper', __FILE__)
describe Pod::Platform do
it "returns a new Platform instance" do
Pod::Platform.ios.should == Pod::Platform.new(:ios)
Pod::Platform.osx.should == Pod::Platform.new(:osx)
end
before do
@platform = Pod::Platform.ios
end
it "exposes it's symbolic name" do
@platform.name.should == :ios
end
it "can be compared for equality with another platform with the same symbolic name" do
@platform.should == Pod::Platform.new(:ios)
end
it "can be compared for equality with another platform with the same symbolic name and the same deployment target" do
@platform.should.not == Pod::Platform.new(:ios, '4.0')
Pod::Platform.new(:ios, '4.0').should == Pod::Platform.new(:ios, '4.0')
end
it "can be compared for equality with a matching symbolic name (backwards compatibility reasons)" do
@platform.should == :ios
end
it "presents an accurate string representation" do
@platform.to_s.should == "iOS"
Pod::Platform.new(:osx).to_s.should == 'OS X'
Pod::Platform.new(nil).to_s.should == "iOS - OS X"
Pod::Platform.new(:ios, '5.0.0').to_s.should == 'iOS 5.0.0'
Pod::Platform.new(:osx, '10.7').to_s.should == 'OS X 10.7'
end
it "uses it's name as it's symbold version" do
@platform.to_sym.should == :ios
end
it "allows to specify the deployment target on initialization" do
p = Pod::Platform.new(:ios, '4.0.0')
p.deployment_target.should == Pod::Version.new('4.0.0')
end
it "allows to specify the deployment target in a hash on initialization (backwards compatibility from 0.6)" do
p = Pod::Platform.new(:ios, { :deployment_target => '4.0.0' })
p.deployment_target.should == Pod::Version.new('4.0.0')
end
it "allows to specify the deployment target after initialization" do
p = Pod::Platform.new(:ios, '4.0.0')
p.deployment_target = '4.0.0'
p.deployment_target.should == Pod::Version.new('4.0.0')
p.deployment_target = Pod::Version.new('4.0.0')
p.deployment_target.should == Pod::Version.new('4.0.0')
end
end
describe "Pod::Platform with a nil value" do
before do
@platform = Pod::Platform.new(nil)
end
it "behaves like a nil object" do
@platform.should.be.nil
end
end
describe "Pod::Platform#support?" do
it "supports another platform is with the same operating system" do
p1 = Pod::Platform.new(:ios)
p2 = Pod::Platform.new(:ios)
p1.should.support?(p2)
p1 = Pod::Platform.new(:osx)
p2 = Pod::Platform.new(:osx)
p1.should.support?(p2)
end
it "supports a nil platform" do
p1 = Pod::Platform.new(:ios)
p1.should.support?(nil)
end
it "supports a platform with a lower or equal deployment_target" do
p1 = Pod::Platform.new(:ios, '5.0')
p2 = Pod::Platform.new(:ios, '4.0')
p1.should.support?(p1)
p1.should.support?(p2)
p2.should.not.support?(p1)
end
it "supports a platform regardless of the deployment_target if one of the two does not specify it" do
p1 = Pod::Platform.new(:ios)
p2 = Pod::Platform.new(:ios, '4.0')
p1.should.support?(p2)
p2.should.support?(p1)
describe "by default" do
it "returns a new Platform instance" do
Pod::Platform.ios.should == Pod::Platform.new(:ios)
Pod::Platform.osx.should == Pod::Platform.new(:osx)
end
before do
@platform = Pod::Platform.ios
end
it "exposes it's symbolic name" do
@platform.name.should == :ios
end
it "can be compared for equality with another platform with the same symbolic name" do
@platform.should == Pod::Platform.new(:ios)
end
it "can be compared for equality with another platform with the same symbolic name and the same deployment target" do
@platform.should.not == Pod::Platform.new(:ios, '4.0')
Pod::Platform.new(:ios, '4.0').should == Pod::Platform.new(:ios, '4.0')
end
it "can be compared for equality with a matching symbolic name (backwards compatibility reasons)" do
@platform.should == :ios
end
it "presents an accurate string representation" do
@platform.to_s.should == "iOS"
Pod::Platform.new(:osx).to_s.should == 'OS X'
Pod::Platform.new(nil).to_s.should == "iOS - OS X"
Pod::Platform.new(:ios, '5.0.0').to_s.should == 'iOS 5.0.0'
Pod::Platform.new(:osx, '10.7').to_s.should == 'OS X 10.7'
end
it "uses it's name as it's symbold version" do
@platform.to_sym.should == :ios
end
it "allows to specify the deployment target on initialization" do
p = Pod::Platform.new(:ios, '4.0.0')
p.deployment_target.should == Pod::Version.new('4.0.0')
end
it "allows to specify the deployment target in a hash on initialization (backwards compatibility from 0.6)" do
p = Pod::Platform.new(:ios, { :deployment_target => '4.0.0' })
p.deployment_target.should == Pod::Version.new('4.0.0')
end
it "allows to specify the deployment target after initialization" do
p = Pod::Platform.new(:ios, '4.0.0')
p.deployment_target = '4.0.0'
p.deployment_target.should == Pod::Version.new('4.0.0')
p.deployment_target = Pod::Version.new('4.0.0')
p.deployment_target.should == Pod::Version.new('4.0.0')
end
end
describe "with a nil value" do
before do
@platform = Pod::Platform.new(nil)
end
it "behaves like a nil object" do
@platform.should.be.nil
end
end
describe "regarding supporting platforms" do
it "supports platforms with the same operating system" do
p1 = Pod::Platform.new(:ios)
p2 = Pod::Platform.new(:ios)
p1.should.supports?(p2)
p1 = Pod::Platform.new(:osx)
p2 = Pod::Platform.new(:osx)
p1.should.supports?(p2)
end
it "supports a nil platform" do
p1 = Pod::Platform.new(:ios)
p1.should.supports?(nil)
end
it "supports a platform with a lower or equal deployment_target" do
p1 = Pod::Platform.new(:ios, '5.0')
p2 = Pod::Platform.new(:ios, '4.0')
p1.should.supports?(p1)
p1.should.supports?(p2)
p2.should.not.supports?(p1)
end
it "supports a platform regardless of the deployment_target if one of the two does not specify it" do
p1 = Pod::Platform.new(:ios)
p2 = Pod::Platform.new(:ios, '4.0')
p1.should.supports?(p2)
p2.should.supports?(p1)
end
it "doesn't supports a platform with a different operating system" do
p1 = Pod::Platform.new(:ios)
p2 = Pod::Platform.new(:osx)
p1.should.not.supports?(p2)
end
end
end
......@@ -26,6 +26,14 @@ describe "Pod::Podfile" do
dep.external_source.params.should == { :git => 'GIT-URL', :commit => '1234' }
end
it "adds a subspec dependency on a Pod repo outside of a spec repo (the repo is expected to contain a podspec)" do
podfile = Pod::Podfile.new do
dependency 'MainSpec/FirstSubSpec', :git => 'GIT-URL', :commit => '1234'
end
dep = podfile.dependency_by_top_level_spec_name('MainSpec')
dep.external_source.name.should == 'MainSpec'
end
it "adds a dependency on a library outside of a spec repo (the repo does not need to contain a podspec)" do
podfile = Pod::Podfile.new do
dependency 'SomeExternalPod', :podspec => 'http://gist/SomeExternalPod.podspec'
......@@ -71,8 +79,8 @@ describe "Pod::Podfile" do
path = config.project_root + 'MyProject.xcodeproj'
config.project_root.expects(:glob).with('*.xcodeproj').returns([path])
podfile.target_definitions[:default].xcodeproj.should == path
podfile.target_definitions[:another_target].xcodeproj.should == path
podfile.target_definitions[:default].user_project.path.should == path
podfile.target_definitions[:another_target].user_project.path.should == path
end
it "assumes the basename of the workspace is the same as the default target's project basename" do
......@@ -117,7 +125,7 @@ describe "Pod::Podfile" do
before do
@podfile = Pod::Podfile.new do
platform :ios
xcodeproj 'iOS Project'
xcodeproj 'iOS Project', 'iOS App Store' => :release, 'Test' => :debug
target :debug do
dependency 'SSZipArchive'
......@@ -133,7 +141,7 @@ describe "Pod::Podfile" do
target :osx_target do
platform :osx
xcodeproj 'OSX Project.xcodeproj'
xcodeproj 'OSX Project.xcodeproj', 'Mac App Store' => :release, 'Test' => :debug
link_with 'OSXTarget'
dependency 'ASIHTTPRequest'
target :nested_osx_target do
......@@ -178,26 +186,24 @@ describe "Pod::Podfile" do
it "returns the Xcode project that contains the target to link with" do
[:default, :debug, :test, :subtarget].each do |target_name|
target = @podfile.target_definitions[target_name]
target.xcodeproj.should == config.project_root + 'iOS Project.xcodeproj'
target.user_project.path.should == config.project_root + 'iOS Project.xcodeproj'
end
[:osx_target, :nested_osx_target].each do |target_name|
target = @podfile.target_definitions[target_name]
target.xcodeproj.should == config.project_root + 'OSX Project.xcodeproj'
target.user_project.path.should == config.project_root + 'OSX Project.xcodeproj'
end
end
it "returns a Xcode project found in the working dir when no explicit project is specified" do
xcodeproj1 = config.project_root + '1.xcodeproj'
target = Pod::Podfile::TargetDefinition.new(:implicit)
config.project_root.expects(:glob).with('*.xcodeproj').returns([xcodeproj1])
target.xcodeproj.should == xcodeproj1
Pod::Podfile::UserProject.new.path.should == xcodeproj1
end
it "returns `nil' if more than one Xcode project was found in the working when no explicit project is specified" do
xcodeproj1, xcodeproj2 = config.project_root + '1.xcodeproj', config.project_root + '2.xcodeproj'
target = Pod::Podfile::TargetDefinition.new(:implicit)
config.project_root.expects(:glob).with('*.xcodeproj').returns([xcodeproj1, xcodeproj2])
target.xcodeproj.should == nil
Pod::Podfile::UserProject.new.path.should == nil
end
it "leaves the name of the target, to link with, to be automatically resolved" do
......@@ -250,10 +256,25 @@ describe "Pod::Podfile" do
@podfile.target_definitions[:nested_osx_target].should.not.be.exclusive
end
it "returns the specified configurations and wether it should be based on a debug or a release build" do
Pod::Podfile::UserProject.any_instance.stubs(:project)
all = { 'Release' => :release, 'Debug' => :debug, 'Test' => :debug }
@podfile.target_definitions[:default].user_project.build_configurations.should == all.merge('iOS App Store' => :release)
@podfile.target_definitions[:test].user_project.build_configurations.should == all.merge('iOS App Store' => :release)
@podfile.target_definitions[:osx_target].user_project.build_configurations.should == all.merge('Mac App Store' => :release)
@podfile.target_definitions[:nested_osx_target].user_project.build_configurations.should == all.merge('Mac App Store' => :release)
@podfile.user_build_configurations.should == all.merge('iOS App Store' => :release, 'Mac App Store' => :release)
end
it "defaults, for unspecified configurations, to a release build" do
project = Pod::Podfile::UserProject.new(fixture('SampleProject/SampleProject.xcodeproj'), 'Test' => :debug)
project.build_configurations.should == { 'Release' => :release, 'Debug' => :debug, 'Test' => :debug, 'App Store' => :release }
end
describe "with an Xcode project that's not in the project_root" do
before do
@target_definition = @podfile.target_definitions[:default]
@target_definition.stubs(:xcodeproj).returns(config.project_root + 'subdir/iOS Project.xcodeproj')
@target_definition.user_project.stubs(:path).returns(config.project_root + 'subdir/iOS Project.xcodeproj')
end
it "returns the $(PODS_ROOT) relative to the project's $(SRCROOT)" do
......@@ -264,7 +285,7 @@ describe "Pod::Podfile" do
config.integrate_targets.should.equal true
config.integrate_targets = false
@target_definition.relative_pods_root.should == '${SRCROOT}/../Pods'
@target_definition.stubs(:xcodeproj).returns(nil)
@target_definition.user_project.stubs(:path).returns(nil)
@target_definition.relative_pods_root.should == '${SRCROOT}/Pods'
config.integrate_targets = true
end
......@@ -282,9 +303,9 @@ describe "Pod::Podfile" do
describe "concerning validations" do
it "raises if it should integrate and can't find an xcodeproj" do
config.integrate_targets.should.equal true
config.integrate_targets = true
target_definition = Pod::Podfile.new {}.target_definitions[:default]
target_definition.stubs(:xcodeproj).returns(nil)
target_definition.user_project.stubs(:path).returns(nil)
exception = lambda {
target_definition.relative_pods_root
}.should.raise Pod::Informative
......
......@@ -33,6 +33,18 @@ describe 'Pod::Project' do
@project.targets.first.build_phases.should.include phase
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
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 }
target = @project.add_pod_target('SomeTarget', Pod::Platform.ios)
target.build_settings('Test')["VALIDATE_PRODUCT"].should == nil
target.build_settings('AppStore')["VALIDATE_PRODUCT"].should == "YES"
end
describe "concerning its :ios targets" do
it "sets VALIDATE_PRODUCT to YES for the Release configuration" do
target = Pod::Project.new.add_pod_target('Pods', Pod::Platform.ios)
......
......@@ -2,34 +2,28 @@ require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Resolver" do
before do
@config_before = config
Pod::Config.instance = nil
config.silent = true
config.repos_dir = fixture('spec-repos')
@podfile = Pod::Podfile.new do
platform :ios
dependency 'ASIWebPageRequest'
dependency 'BlocksKit'
# dependency 'ASIWebPageRequest'
end
@resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
end
after do
Pod::Config.instance = @config_before
end
it "holds the context state, such as cached specification sets" do
@resolver.resolve
@resolver.cached_sets.values.sort_by(&:name).should == [
Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest'),
Pod::Spec::Set.new(config.repos_dir + 'master/ASIWebPageRequest'),
Pod::Spec::Set.new(config.repos_dir + 'master/Reachability'),
Pod::Spec::Set.new(config.repos_dir + 'master/A2DynamicDelegate'),
Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit'),
].sort_by(&:name)
end
it "returns all specs needed for the dependency" do
specs = @resolver.resolve.values.flatten
specs.map(&:class).uniq.should == [Pod::Specification]
specs.map(&:name).sort.should == %w{ ASIHTTPRequest ASIWebPageRequest Reachability }
specs.map(&:name).sort.should == %w{ A2DynamicDelegate BlocksKit }
end
it "does not raise if all dependencies match the platform of the root spec (Podfile)" do
......@@ -40,8 +34,8 @@ describe "Pod::Resolver" do
end
it "raises once any of the dependencies does not match the platform of its podfile target" do
set = Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest')
@resolver.cached_sets['ASIHTTPRequest'] = set
set = Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit')
@resolver.cached_sets['BlocksKit'] = set
def set.stub_platform=(platform); @stubbed_platform = platform; end
def set.specification; spec = super; spec.platform = @stubbed_platform; spec; end
......@@ -60,14 +54,14 @@ describe "Pod::Resolver" do
end
it "raises once any of the dependencies does not have a deployment_target compatible with its podfile target" do
set = Pod::Spec::Set.new(config.repos_dir + 'master/ASIHTTPRequest')
@resolver.cached_sets['ASIHTTPRequest'] = set
set = Pod::Spec::Set.new(config.repos_dir + 'master/BlocksKit')
@resolver.cached_sets['BlocksKit'] = set
@podfile.platform :ios, "4.0"
Pod::Specification.any_instance.stubs(:platforms).returns([ Pod::Platform.new(:ios, '4.0'), Pod::Platform.new(:osx, '10.7') ])
Pod::Specification.any_instance.stubs(:available_platforms).returns([ Pod::Platform.new(:ios, '4.0'), Pod::Platform.new(:osx, '10.7') ])
lambda { @resolver.resolve }.should.not.raise
Pod::Specification.any_instance.stubs(:platforms).returns([ Pod::Platform.new(:ios, '5.0'), Pod::Platform.new(:osx, '10.7') ])
Pod::Specification.any_instance.stubs(:available_platforms).returns([ Pod::Platform.new(:ios, '5.0'), Pod::Platform.new(:osx, '10.7') ])
lambda { @resolver.resolve }.should.raise Pod::Informative
end
......@@ -75,20 +69,111 @@ describe "Pod::Resolver" do
@podfile = Pod::Podfile.new do
platform :ios
dependency 'RestKit/Network'
dependency 'RestKit/ObjectMapping'
dependency 'RestKit/ObjectMapping/XML'
end
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash
ISO8601DateFormatter
LibComponentLogging-Core
LibComponentLogging-NSLog
NSData+Base64
RestKit/Network
RestKit/ObjectMapping/XML
SOCKit
XMLReader
cocoa-oauth
}
end
it "includes all the subspecs of a specification node" do
@podfile = Pod::Podfile.new do
platform :ios
dependency 'RestKit'
end
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
FileMD5Hash
ISO8601DateFormatter
JSONKit
LibComponentLogging-Core
LibComponentLogging-NSLog
NSData+Base64
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
SOCKit
UDTableView
cocoa-oauth
}
end
it "if defined it includes only the main subspec of of a specification node" do
@podfile = Pod::Podfile.new do
platform :ios
dependency do |s|
s.name = 'RestKit'
s.version = '0.10.0'
s.preferred_dependency = 'JSON'
s.subspec 'JSON' do |js|
js.dependency 'RestKit/Network'
js.dependency 'RestKit/UI'
js.dependency 'RestKit/ObjectMapping/JSON'
js.dependency 'RestKit/ObjectMapping/CoreData'
end
s.subspec 'Network' do |ns|
ns.dependency 'LibComponentLogging-NSLog', '>= 1.0.4'
end
s.subspec 'UI'
s.subspec 'ObjectMapping' do |os|
os.subspec 'JSON'
os.subspec 'XML'
os.subspec 'CoreData'
end
end
end
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{
LibComponentLogging-Core
LibComponentLogging-NSLog
RestKit
RestKit/JSON
RestKit/Network
RestKit/ObjectMapping/CoreData
RestKit/ObjectMapping/JSON
RestKit/UI
}
it "resolves subspecs with external constraints" do
@podfile = Pod::Podfile.new do
platform :ios
dependency 'MainSpec/FirstSubSpec', :git => 'GIT-URL'
end
spec = Pod::Spec.new do |s|
s.name = 'MainSpec'
s.version = '1.2.3'
s.platform = :ios
s.license = 'MIT'
s.author = 'Joe the Plumber'
s.summary = 'A spec with subspecs'
s.source = { :git => '/some/url' }
s.requires_arc = true
s.subspec 'FirstSubSpec' do |fss|
fss.source_files = 'some/file'
fss.subspec 'SecondSubSpec'
end
end
@podfile.dependencies.first.external_source.stubs(:specification_from_sandbox).returns(spec)
resolver = Pod::Resolver.new(@podfile, stub('sandbox'))
resolver.resolve.values.flatten.map(&:name).sort.should == %w{ MainSpec/FirstSubSpec MainSpec/FirstSubSpec/SecondSubSpec }
end
end
end
This diff is collapsed.
require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Source" do
extend SpecHelper::Git
extend SpecHelper::Command
extend SpecHelper::TemporaryDirectory
extend SpecHelper::TemporaryRepos
before do
add_repo('repo1', fixture('spec-repos/master'))
......
......@@ -10,7 +10,7 @@ describe "Pod::Specification::Set" do
end
it "returns the versions available for this pod ordered from highest to lowest" do
@set.versions.should == %w[1.3.2 1.3.1 1.3 1.2.3 1.2.2 1.2.1 1.2 1.1 1.0].map { |v| Pod::Version.new(v) }
@set.versions.should == %w[1.3.3 1.3.2 1.3.1 1.3 1.2.3 1.2.2 1.2.1 1.2 1.1 1.0].map { |v| Pod::Version.new(v) }
end
it "checks if the dependency of the specification is compatible with existing requirements" do
......@@ -29,12 +29,6 @@ describe "Pod::Specification::Set" do
lambda { @set.required_version }.should.raise Pod::Informative
end
it "returns that this set is only part for other pods" do
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.should.be.only_part_of_other_pod
end
before do
@set.required_by(Pod::Spec.new { |s| s.dependency 'CocoaLumberjack', '< 1.2.1' })
end
......@@ -51,11 +45,6 @@ describe "Pod::Specification::Set" do
@set.specification.should == Pod::Spec.new { |s| s.name = 'CocoaLumberjack'; s.version = '1.2' }
end
it "returns that this set is not only part for other pods" do
@set.required_by(Pod::Spec.new { |s| s.part_of = 'CocoaLumberjack' })
@set.should.not.be.only_part_of_other_pod
end
it "ignores dotfiles when getting the version directories" do
`touch #{fixture('spec-repos/master/CocoaLumberjack/.DS_Store')}`
lambda { @set.versions }.should.not.raise
......
This diff is collapsed.
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