Commit 8c17615b authored by Fabio Pelosin's avatar Fabio Pelosin

Delete LocalPod (sorry to let u go my friend)

parent bcc21153
module Pod
# A {LocalPod} interfaces one or more specifications belonging to one pod
# (a library) and their concrete instance in the file system.
#
# The {LocalPod} is responsible for orchestrating the activated
# specifications of a single pod. Specifically, it keeps track of the
# activated specifications and handles issues related to duplicates
# files.
# Inheritance logic belongs to the {Specification} class.
#
# The activated specifications are used to compute the paths that can be
# safely cleaned by the pod.
#
# @example
# pod = LocalPod.new 'RestKit/Networking'
# pod.add_specification 'RestKit/UI'
#
# @note
# Unless otherwise specified in the name of the method the {LocalPod}
# returns absolute paths.
#
class LocalPod
autoload :PathList, 'cocoapods/local_pod/path_list'
# @return [Specification] The specification that describes the pod.
#
attr_reader :top_specification
# @return [Specification] The activated specifications of the pod.
#
attr_reader :specifications
# @return [Sandbox] The sandbox where the pod is installed.
#
attr_reader :sandbox
# @return [Platform] The platform that will be used to build the pod.
#
attr_reader :platform
# @return [Boolean] Wether or not the pod has been downloaded in the
# current install process and still needs its docs
# generated and be cleaned.
#
attr_accessor :downloaded
alias_method :downloaded?, :downloaded
# @param [Specification] specification The first activated specification
# of the pod.
#
# @param [Sandbox] sandbox The sandbox where the files of the
# pod will be located.
#
# @param [Platform] platform The platform that will be used to
# build the pod.
#
# @todo The local pod should be initialized with all the activated
# specifications passed as an array, in order to be able to cache the
# computed values. In other words, it should be immutable.
#
def initialize(specification, sandbox, platform)
@top_specification, @sandbox, @platform = specification.root, sandbox, platform
@specifications = [] << specification
end
# Initializes a local pod from the top specification of a podspec file.
#
# @return [LocalPod] A new local pod.
#
def self.from_podspec(podspec, sandbox, platform)
new(Specification.from_file(podspec), sandbox, platform)
end
# Activates a specification or subspecs for the pod.
# Adding specifications is idempotent.
#
# @param {Specification} spec The specification to add to the pod.
#
# @raise {Informative} If the specification is not part of the same pod.
#
def add_specification(spec)
unless spec.root == top_specification
raise Informative,
"[Local Pod] Attempt to add a specification from another pod"
end
@specifications << spec unless @specifications.include?(spec)
end
# @return [Pathname] The root directory of the pod
#
def root
@sandbox.root + top_specification.name
end
def path_list
@path_list ||= PathList.new(root)
end
# @return [String] A string representation of the pod which indicates if
# the pods comes from a local source or has a preferred
# dependency.
#
def to_s
s = top_specification.to_s
s << " defaulting to #{top_specification.default_subspec} subspec" if top_specification.default_subspec
s
end
# @return [String] The name of the Pod.
#
def name
top_specification.name
end
#--------------------------------------#
public
# @!group Installation
# Creates the root path of the pod.
#
# @return [void]
#
def create
root.mkpath unless exists?
end
# Whether the root path of the pod exists.
#
def exists?
root.exist?
end
# Executes a block in the root directory of the Pod.
#
# @return [void]
#
def chdir(&block)
create
Dir.chdir(root, &block)
end
# Deletes the pod from the file system.
#
# @return [void]
#
def implode
root.rmtree if exists?
end
def local?
false
end
# @!group Cleaning
# Deletes any path that is not used by the pod.
#
# @todo [#529] Podspecs should not be preserved anymore to prevent user
# confusion. Currently we are copying the ones form external sources
# in `Local Podspecs` and this feature is not needed anymore.
# I think that copying all the used podspecs would be helpful for
# debugging.
#
# @return [void]
#
def clean!
clean_paths.each { |path| FileUtils.rm_rf(path) }
@cleaned = true
path_list.read_file_system
end
# Finds the absolute paths, including hidden ones, of the files
# that are not used by the pod and thus can be safely deleted.
#
# @return [Array<Strings>] The paths that can be deleted.
#
# @note Implementation detail: Don't use Dir#glob as there is an
# unexplained issue (#568, #572 and #602).
#
def clean_paths
cached_used = used_files
files = Pathname.glob(root + "**/*", File::FNM_DOTMATCH | File::FNM_CASEFOLD).map(&:to_s)
files.reject! do |candidate|
candidate.end_with?('.', '..') || cached_used.any? do |path|
path.include?(candidate) || candidate.include?(path)
end
end
files
end
# @return [Array<String>] The absolute path of the files used by the pod.
#
def used_files
files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
files.compact!
files.flatten!
files.map!{ |path| path.to_s }
files
end
#--------------------------------------#
public
# @!group Files
# @return [Array<Pathname>] The paths of the source files.
#
def source_files
source_files_by_spec.values.flatten
end
# Finds the source files that every activated {Specification} requires.
#
# @note If the same file is required by two specifications the one at the
# higher level in the inheritance chain wins.
#
# @return [Hash{Specification => Array<Pathname>}] The files grouped by
# {Specification}.
#
def source_files_by_spec
options = {:glob => '*.{h,hpp,hh,m,mm,c,cpp}'}
@source_files_by_spec ||= paths_by_spec(:source_files, '*.{h,hpp,hh,m,mm,c,cpp}')
end
# @return [Array<Pathname>] The paths of the header files.
#
def header_files
header_files_by_spec.values.flatten
end
# @return [Hash{Specification => Array<Pathname>}] The paths of the header
# files grouped by {Specification}.
#
def header_files_by_spec
result = {}
source_files_by_spec.each do |spec, paths|
headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
result[spec] = headers unless headers.empty?
end
result
end
# @return [Hash{Specification => Array<Pathname>}] The paths of the header
# files grouped by {Specification} that should be copied in the public
# folder.
#
# If a spec does not match any public header it means that all the
# header files (i.e. the build ones) are intended to be public.
#
def public_header_files_by_spec
public_headers = paths_by_spec(:public_header_files, '*.{h,hpp,hh}')
build_headers = header_files_by_spec
result = {}
specifications.each do |spec|
if (public_h = public_headers[spec]) && !public_h.empty?
result[spec] = public_h
elsif (build_h = build_headers[spec]) && !build_h.empty?
result[spec] = build_h
end
end
result
end
# @return [Array<Pathname>] The paths of the resources.
#
def resource_files
specs ||= specifications
paths_by_spec = {}
processed_paths = []
specs = specs.sort_by { |s| s.name.length }
specs.each do |spec|
consumer = spec.consumer(platform)
spec_paths = consumer.resources[:resources]
paths = expanded_paths(spec_paths, '**/*', consumer.exclude_files)
unless paths.empty?
paths_by_spec[spec] = paths - processed_paths
processed_paths += paths
end
end
paths_by_spec.values.flatten
end
alias :resources :resource_files
# @return [Pathname] The absolute path of the prefix header file
#
def prefix_header_file
value = top_specification.consumer(platform).prefix_header_file
root + value if value
end
# @return [Array<Pathname>] The absolute paths of the files of the pod
# that should be preserved.
#
def preserve_files
paths = paths_by_spec(:preserve_paths).values
paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
paths.compact!
paths.uniq!
paths
end
alias :preserve_paths :preserve_files
# @return [Pathname] The automatically detected absolute path of the README
# file.
#
def readme_file
expanded_paths(%w[ readme{*,.*} ]).first
end
# @return [Pathname] The absolute path of the license file from the
# specification or automatically detected.
#
def license_file
unless @license_file
if top_specification.license && top_specification.license[:file]
@license_file = root + top_specification.license[:file]
else
@license_file = expanded_paths(%w[ licen{c,s}e{*,.*} ]).first
end
end
@license_file
end
# @return [String] The text of the license of the pod from the
# specification or from the license file.
#
def license_text
if (license_hash = top_specification.license)
if (result = license_hash[:text])
result
elsif license_file
result = IO.read(license_file)
end
end
end
#--------------------------------------#
public
# @return [Xcodeproj::Config] the configuration for the Pod.
#
def xcconfig
config = Xcodeproj::Config.new
specifications.each do |spec|
consumer = spec.consumer(platform)
config.merge!(consumer.xcconfig)
config.libraries.merge(consumer.libraries)
config.frameworks.merge(consumer.frameworks)
config.weak_frameworks.merge(consumer.weak_frameworks)
end
config
end
# Returns also weak frameworks.
#
def frameworks
result = []
specifications.each do |spec|
consumer = spec.consumer(platform)
result.concat(consumer.frameworks)
result.concat(consumer.weak_frameworks)
end
result.uniq
end
# Computes the paths of all the public headers of the pod including every
# subspec (activated or not).
# For this reason the pod must not be cleaned when calling this command.
#
# This method is used by {Generator::Documentation}.
#
# @raise [Informative] If the pod was cleaned.
#
# @return [Array<Pathname>] The path of all the public headers of the pod.
#
def documentation_headers
if @cleaned
raise Informative, "The pod is cleaned and cannot compute the " \
"header files, as some might have been deleted."
end
specs = [top_specification] + top_specification.recursive_subspecs
source_files = paths_by_spec(:source_files, '*.{h}', specs)
public_headers = paths_by_spec(:public_header_files, '*.{h}', specs)
result = []
specs.each do |spec|
if (public_h = public_headers[spec]) && !public_h.empty?
result += public_h
elsif (source_f = source_files[spec]) && !source_f.empty?
build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
result += build_h unless build_h.empty?
end
end
result
end
#--------------------------------------#
public
# @!group Xcodeproj integration
# Adds the file references, to the given `Pods.xcodeproj` project, for the
# source files of the pod. The file references are grouped by specification
# and stored in {#file_references_by_spec}.
#
# @note If the pod is locally sourced the file references are stored in the
# `Local Pods` group otherwise they are stored in the `Pods` group.
#
# @return [void]
#
def add_file_references_to_project(project)
@file_references_by_spec = {}
parent_group = local? ? project.local_pods : project.pods
source_files_by_spec.each do |spec, paths|
group = project.add_spec_group(spec.name, parent_group)
file_references = []
paths.each do |path|
relative = sandbox.relativize(path)
file_references << group.new_file(relative)
end
@file_references_by_spec[spec] = file_references
end
end
# @return [Hash{Specification => Array<PBXFileReference>}] The file
# references of the pod in the `Pods.xcodeproj` project.
#
attr_reader :file_references_by_spec
# Adds a build file for each file reference to a given target taking into
# account the compiler flags of the corresponding specification.
#
# @raise If the {#add_file_references_to_project} was not called before of
# calling this method.
#
# @return [void]
#
def add_build_files_to_target(target)
unless file_references_by_spec
raise Informative, "Local Pod needs to add the file references to the " \
"project before adding the build files to the target."
end
file_references_by_spec.each do |spec, file_reference|
consumer = spec.consumer(platform)
flags = consumer.compiler_flags.dup
flags << '-fobjc-arc' if consumer.requires_arc
flags = flags * " "
target.add_file_references(file_reference, flags)
end
end
# @return [void] Copies the pods headers to the sandbox.
#
def link_headers
sandbox.build_headers.add_search_path(headers_sandbox)
header_mappings(header_files_by_spec).each do |namespaced_path, files|
sandbox.build_headers.add_files(namespaced_path, files)
end
sandbox.public_headers.add_search_path(headers_sandbox)
header_mappings(public_header_files_by_spec).each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files)
end
end
#--------------------------------------#
private
# @!group Private helpers
# @return [Array<Pathname>] The implementation files
# (the files the need to compiled) of the pod.
#
def implementation_files
relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
end
# @return [Pathname] The path of the pod relative from the sandbox.
#
def relative_root
root.relative_path_from(@sandbox.root)
end
# @return [Hash{Pathname => Array<Pathname>}] A hash containing the headers
# folders as the keys and the absolute paths of the header files as
# the values.
#
# @todo This is being overridden in the RestKit 0.9.4 spec and that
# override should be fixed.
#
def header_mappings(files_by_spec)
mappings = {}
files_by_spec.each do |spec, paths|
paths = paths
consumer = spec.consumer(platform)
dir = consumer.header_dir ? (headers_sandbox + consumer.header_dir) : headers_sandbox
paths.each do |from|
from_relative = from.relative_path_from(root)
to = dir + (consumer.header_mappings_dir ? from.relative_path_from(consumer.header_mappings_dir) : from.basename)
(mappings[to.dirname] ||= []) << from
end
end
mappings
end
# @return [<Pathname>] The name of the folder where the headers of this pod
# will be namespaced.
#
def headers_sandbox
@headers_sandbox ||= Pathname.new(top_specification.name)
end
# @!group Paths Patterns
# The paths obtained by resolving the patterns of an attribute
# grouped by spec.
#
# @param [Symbol] accessor The accessor to use to obtain the paths patterns.
#
# @param [String] dir_pattern
# The pattern to add to directories.
#
# @param [Array<Specification>] specs
# The specification of which the patterns are needed.
# If not specifies it defaults {#specifications}.
#
def paths_by_spec(accessor, dir_pattern = nil, specs = nil)
specs ||= specifications
paths_by_spec = {}
processed_paths = []
specs = specs.sort_by { |s| s.name.length }
specs.each do |spec|
consumer = spec.consumer(platform)
paths = expanded_paths(consumer.send(accessor), dir_pattern, consumer.exclude_files)
unless paths.empty?
paths_by_spec[spec] = paths - processed_paths
processed_paths += paths
end
end
paths_by_spec
end
# Converts patterns of paths to the {Pathname} of the files present in the
# pod.
#
# @param [String, FileList, Array<String>] patterns
# The patterns to expand.
#
# @param [String] dir_pattern
# The pattern to add to directories.
#
# @param [Array<String>] exclude_patterns
# The exclude patterns to pass to the PathList.
#
# @raise [Informative] If the pod does not exists.
#
# @todo Implement case insensitive search
#
# @return [Array<Pathname>] A list of the paths.
#
def expanded_paths(patterns, dir_pattern = nil, exclude_patterns = nil)
unless exists?
raise Informative, "[Local Pod] Attempt to resolve paths for nonexistent pod.\n" \
"\tSpecifications: #{@specifications.inspect}\n" \
"\t Patterns: #{patterns.inspect}"
end
# Noticeable impact on performance
return [] if patterns.empty?
patterns = [ patterns ] if patterns.is_a?(String)
file_lists = patterns.select { |p| p.is_a?(FileList) }
unless file_lists.empty?
UI.warn "[#{name}] The usage of Rake FileList is deprecated. Use `exclude_files`."
end
glob_patterns = patterns - file_lists
result = []
result << path_list.glob(glob_patterns, dir_pattern, exclude_patterns)
result << file_lists.map do |file_list|
file_list.prepend_patterns(root)
file_list.glob
end
result.flatten.compact.uniq
end
#-------------------------------------------------------------------------#
# A {LocalSourcedPod} is a {LocalPod} that interacts with the files of
# a folder controlled by the users. As such this class does not alter
# in any way the contents of the folder.
#
class LocalSourcedPod < LocalPod
def downloaded?
true
end
def create
# No ops
end
def root
@root ||= Pathname.new(@top_specification.source[:local]).expand_path
end
def implode
# No ops
end
def clean!
# No ops
end
def to_s
super + " [LOCAL]"
end
def local?
true
end
end
end # LocalPod
end # Pod
require File.expand_path('../../spec_helper', __FILE__)
module Pod
describe LocalPod do
describe "in general" do
before do
@sandbox = temporary_sandbox
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@pod = LocalPod.new(@spec, @sandbox, Platform.new(:ios))
copy_fixture_to_pod('banana-lib', @pod)
end
it "returns the Pod root directory path" do
@pod.root.should == @sandbox.root + 'BananaLib'
end
it "creates it's own root directory if it doesn't exist" do
@pod.create
File.directory?(@pod.root).should.be.true
end
it "can execute a block within the context of it's root" do
@pod.chdir { FileUtils.touch("foo") }
Pathname(@pod.root + "foo").should.exist
end
it "can delete itself" do
@pod.create
@pod.implode
@pod.root.should.not.exist
end
it "returns an expanded list of source files, relative to the sandbox root" do
@pod.relative_source_files.sort.should == [
Pathname.new("BananaLib/Classes/Banana.m"),
Pathname.new("BananaLib/Classes/Banana.h")
].sort
end
it "returns the source files grouped by specification" do
files = @pod.source_files_by_spec[@pod.specifications.first].sort
files.should == [
@pod.root + "Classes/Banana.m",
@pod.root + "Classes/Banana.h"
].sort
end
it "returns a list of header files" do
@pod.relative_header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
end
it "returns a list of header files by specification" do
files = @pod.header_files_by_spec[@pod.specifications.first].sort
files.should == [ @pod.root + "Classes/Banana.h" ]
end
it "returns an expanded list the files to clean" do
clean_paths = @pod.clean_paths.map { |p| p.to_s.gsub(/.*Pods\/BananaLib/,'') }
clean_paths.should.include "/.git/config"
# * There are some hidden files on Travis
# * The submodule of the repo (libPusher) can be ignore, to reduce noise of this test
clean_files_without_hidden = clean_paths.reject { |p| p.to_s.include?('/.') || p.to_s.include?('libPusher') }
clean_files_without_hidden.should == %W[ /sub-dir /sub-dir/sub-dir-2 /sub-dir/sub-dir-2/somefile.txt ]
end
it "returns an expanded list of resources, relative to the sandbox root" do
@pod.relative_resource_files.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
end
it "can link it's headers into the sandbox" do
@pod.link_headers
expected_header_path = @sandbox.build_headers.root + "BananaLib/Banana.h"
expected_header_path.should.be.symlink
File.read(expected_header_path).should == (@sandbox.root + @pod.header_files[0]).read
end
it "can link it's public headers into the sandbox" do
@pod.link_headers
expected_header_path = @sandbox.public_headers.root + "BananaLib/Banana.h"
expected_header_path.should.be.symlink
File.read(expected_header_path).should == (@sandbox.root + @pod.header_files[0]).read
end
it "can add it's source files to an Xcode project target" do
project = Project.new()
@pod.add_file_references_to_project(project)
project['Pods/BananaLib/Banana.h'].path.should == "BananaLib/Classes/Banana.h"
project['Pods/BananaLib/Banana.m'].path.should == "BananaLib/Classes/Banana.m"
end
it "can add it's source files to a target with any specially configured compiler flags" do
project = Project.new()
target = project.new_target(:static, 'Pods', :ios)
@pod.top_specification.compiler_flags = '-d some_flag'
@pod.add_file_references_to_project(project)
@pod.add_build_files_to_target(target)
h_build_file = target.headers_build_phase.files.first
h_build_file.file_ref.path.should == "BananaLib/Classes/Banana.h"
h_build_file.settings.should == {"ATTRIBUTES"=>["Public"]}
m_build_file = target.source_build_phase.files.first
m_build_file.file_ref.path.should == "BananaLib/Classes/Banana.m"
m_build_file.settings.should == {"COMPILER_FLAGS"=>"-d some_flag"}
end
it "returns the platform" do
@pod.platform.should == :ios
end
it "raises if the files are accessed before creating the pod dir" do
@pod.implode
lambda { @pod.source_files }.should.raise Informative
end
end
#---------------------------------------------------------------------------#
describe "with installed source and multiple subspecs" do
def assert_array_equals(expected, computed)
delta1 = computed - expected
delta1.should == []
delta2 = expected - computed
delta2.should == []
end
before do
@sandbox = temporary_sandbox
subspecs = fixture_spec('chameleon/Chameleon.podspec').subspecs
@pod = LocalPod.new(subspecs[0], @sandbox, Platform.new(:osx))
@pod.add_specification(subspecs[1])
copy_fixture_to_pod('chameleon', @pod)
end
it "identifies the top level specification" do
@pod.top_specification.name.should == 'Chameleon'
end
it "returns the subspecs" do
@pod.specifications.map(&:name).should == %w[ Chameleon/UIKit Chameleon/StoreKit ]
end
it "resolve the source files" do
computed = @pod.relative_source_files.map(&:to_s)
expected = %w[
Chameleon/UIKit/Classes/UIKit.h
Chameleon/UIKit/Classes/UIView.h
Chameleon/UIKit/Classes/UIWindow.h
Chameleon/UIKit/Classes/UIView.m
Chameleon/UIKit/Classes/UIWindow.m
Chameleon/StoreKit/Classes/SKPayment.h
Chameleon/StoreKit/Classes/StoreKit.h
Chameleon/StoreKit/Classes/SKPayment.m ]
assert_array_equals(expected, computed)
end
it "resolve the resources" do
@pod.relative_resource_files.map(&:to_s).sort.should == [
"Chameleon/UIKit/Resources/<UITabBar> background.png",
"Chameleon/UIKit/Resources/<UITabBar> background@2x.png" ]
end
it "resolve the clean paths" do
# fake_git serves to check that source control files are deleted
expected = %w[
/.fake_git
/.fake_git/branches
/.fake_git/HEAD
/.fake_git/index
/AddressBookUI
/AddressBookUI/AddressBookUI_Prefix.pch
/AddressBookUI/Classes
/AddressBookUI/Classes/ABUnknownPersonViewController.h
/AddressBookUI/Classes/ABUnknownPersonViewController.m
/AddressBookUI/Classes/AddressBookUI.h
/AssetsLibrary
/AssetsLibrary/AssetsLibrary_Prefix.pch
/AssetsLibrary/Classes
/AssetsLibrary/Classes/ALAsset.h
/AssetsLibrary/Classes/ALAsset.m
/AssetsLibrary/Classes/ALAssetRepresentation.h
/AssetsLibrary/Classes/ALAssetRepresentation.m
/AssetsLibrary/Classes/ALAssetsFilter.h
/AssetsLibrary/Classes/ALAssetsFilter.m
/AssetsLibrary/Classes/ALAssetsGroup.h
/AssetsLibrary/Classes/ALAssetsGroup.m
/AssetsLibrary/Classes/ALAssetsLibrary.h
/AssetsLibrary/Classes/ALAssetsLibrary.m
/AssetsLibrary/Classes/AssetsLibrary.h
/AVFoundation
/AVFoundation/AVFoundation_Prefix.pch
/AVFoundation/Classes
/AVFoundation/Classes/AVAudioPlayer.h
/AVFoundation/Classes/AVAudioPlayer.m
/AVFoundation/Classes/AVAudioSession.h
/AVFoundation/Classes/AVAudioSession.m
/AVFoundation/Classes/AVFoundation.h
/MediaPlayer
/MediaPlayer/Classes
/MediaPlayer/Classes/MediaPlayer.h
/MediaPlayer/Classes/MPMediaPlayback.h
/MediaPlayer/Classes/MPMoviePlayerController.h
/MediaPlayer/Classes/MPMoviePlayerController.m
/MediaPlayer/Classes/MPMusicPlayerController.h
/MediaPlayer/Classes/MPMusicPlayerController.m
/MediaPlayer/Classes/UIInternalMovieView.h
/MediaPlayer/Classes/UIInternalMovieView.m
/MediaPlayer/MediaPlayer_Prefix.pch
/MessageUI
/MessageUI/Classes
/MessageUI/Classes/MessageUI.h
/MessageUI/Classes/MFMailComposeViewController.h
/MessageUI/Classes/MFMailComposeViewController.m
/MessageUI/MessageUI_Prefix.pch
/StoreKit/StoreKit_Prefix.pch
/UIKit/UIKit_Prefix.pch
]
root = @pod.root.to_s
computed = @pod.clean_paths.each{ |p| p.gsub!(root, '') }
assert_array_equals(expected, computed)
end
it "resolves the used files" do
expected = %w[
/UIKit/Classes/UIKit.h
/UIKit/Classes/UIView.h
/UIKit/Classes/UIWindow.h
/UIKit/Classes/UIView.m
/UIKit/Classes/UIWindow.m
/StoreKit/Classes/SKPayment.h
/StoreKit/Classes/StoreKit.h
/StoreKit/Classes/SKPayment.m
/Chameleon.podspec
/README.md
/LICENSE
] + [
"/UIKit/Resources/<UITabBar> background.png",
"/UIKit/Resources/<UITabBar> background@2x.png"
]
computed = @pod.used_files.map{ |p| p.gsub!(@pod.root.to_s, '').to_s }
assert_array_equals(expected, computed)
end
it "resolved the header files" do
expected = %w[
Chameleon/UIKit/Classes/UIKit.h
Chameleon/UIKit/Classes/UIView.h
Chameleon/UIKit/Classes/UIWindow.h
Chameleon/StoreKit/Classes/SKPayment.h
Chameleon/StoreKit/Classes/StoreKit.h ]
computed = @pod.relative_header_files.map(&:to_s)
assert_array_equals(expected, computed)
end
xit "resolves the documentation header files including not activated subspecs" do
subspecs = fixture_spec('chameleon/Chameleon.podspec').subspecs
spec = subspecs[0]
Specification::Consumer.any_instance.stubs(:public_header_files).returns("UIKit/Classes/*Kit.h")
@pod = LocalPod.new(spec, @sandbox, Platform.new(:osx))
# Note we only activated UIKit but all the specs need to be resolved
computed = @pod.documentation_headers.map { |p| p.relative_path_from(@pod.root).to_s }
# The Following headers are private:
# UIKit/Classes/UIView.h
# UIKit/Classes/UIWindow.h
expected = %w[
UIKit/Classes/UIKit.h
StoreKit/Classes/SKPayment.h
StoreKit/Classes/StoreKit.h
MessageUI/Classes/MessageUI.h
MessageUI/Classes/MFMailComposeViewController.h
MediaPlayer/Classes/MediaPlayer.h
MediaPlayer/Classes/MPMediaPlayback.h
MediaPlayer/Classes/MPMoviePlayerController.h
MediaPlayer/Classes/MPMusicPlayerController.h
MediaPlayer/Classes/UIInternalMovieView.h
AVFoundation/Classes/AVAudioPlayer.h
AVFoundation/Classes/AVAudioSession.h
AVFoundation/Classes/AVFoundation.h
AssetsLibrary/Classes/ALAsset.h
AssetsLibrary/Classes/ALAssetRepresentation.h
AssetsLibrary/Classes/ALAssetsFilter.h
AssetsLibrary/Classes/ALAssetsGroup.h
AssetsLibrary/Classes/ALAssetsLibrary.h
AssetsLibrary/Classes/AssetsLibrary.h
]
assert_array_equals(expected, computed)
end
it "merges the xcconfigs without duplicates" do
@pod.xcconfig.should == {
"OTHER_LDFLAGS"=>"-framework AppKit -framework Foundation -framework IOKit -framework QTKit -framework QuartzCore -framework SystemConfiguration -framework WebKit" }
end
it "returns a hash of mappings with a custom header dir prefix" do
mappings = @pod.send(:header_mappings, @pod.header_files_by_spec)
mappings = mappings.map do |folder, headers|
"#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}"
end
mappings.sort.should == [
"Chameleon/StoreKit > StoreKit/Classes/SKPayment.h StoreKit/Classes/StoreKit.h",
"Chameleon/UIKit > UIKit/Classes/UIKit.h UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
end
# TODO this is a stub
xit "respects the exclude files attribute of the specifications" do
@pod.stubs(:exclude_files).returns([@pod.root + 'UIKit/Classes/UIKit.h'])
mappings = @pod.send(:header_mappings, @pod.header_files_by_spec)
mappings = mappings.map do |folder, headers|
"#{folder} > #{headers.sort.map{ |p| p.relative_path_from(@pod.root).to_s }.join(' ')}"
end
mappings.sort.should == [
"Chameleon/StoreKit > StoreKit/Classes/SKPayment.h StoreKit/Classes/StoreKit.h",
"Chameleon/UIKit > UIKit/Classes/UIView.h UIKit/Classes/UIWindow.h" ]
end
xit "includes the sandbox of the pod's headers while linking" do
@sandbox.build_headers.expects(:add_search_path).with(Pathname.new('Chameleon'))
@sandbox.public_headers.expects(:add_search_path).with(Pathname.new('Chameleon'))
@pod.link_headers
end
it "differentiates among public and build headers" do
subspecs = fixture_spec('chameleon/Chameleon.podspec').subspecs
spec = subspecs[0]
Specification::Consumer.any_instance.stubs(:public_header_files).returns("UIKit/Classes/*Kit.h")
@pod = LocalPod.new(spec, @sandbox, Platform.new(:osx))
build_headers = @pod.header_files_by_spec.values.flatten.map{ |p| p.basename.to_s }
public_headers = @pod.public_header_files_by_spec.values.flatten.map{ |p| p.basename.to_s }
build_headers.sort.should == %w{ UIKit.h UIView.h UIWindow.h }
public_headers.should == %w{ UIKit.h }
end
end
#---------------------------------------------------------------------------#
describe "concerning a Pod with a local source" do
before do
@local_path = temporary_directory + 'localBanana'
@sandbox = temporary_sandbox
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@spec.source = {:local => @local_path}
@pod = LocalPod::LocalSourcedPod.new(@spec, @sandbox, Platform.new(:ios))
end
it "is marked as local" do
@pod.to_s.should.include? '[LOCAL]'
end
it "is marked as downloaded" do
@pod.downloaded?.should.be.true
end
it "correctly repports the root of the pod" do
@pod.root.should == @local_path
end
it "doesn't create the root" do
@pod.create
@local_path.exist?.should.be.false
end
before do
FileUtils.cp_r(fixture('banana-lib'), @local_path)
end
it "doesn't cleans the user files" do
useless_file = @local_path + 'useless.txt'
FileUtils.touch(useless_file)
@pod.root.should == @local_path
@pod.clean!
useless_file.exist?.should.be.true
end
it "doesn't implode" do
@pod.implode
@local_path.exist?.should.be.true
end
it "detects the files of the pod" do
@pod.source_files.map {|path| path.to_s.gsub(/.*tmp\//,'') }.sort.should == [
"localBanana/Classes/Banana.m",
"localBanana/Classes/Banana.h"
].sort
end
end
#---------------------------------------------------------------------------#
describe "concerning a Pod with a local source" do
it "supports rake file list" do
path = fixture('banana-lib')
classes_path = path + 'Classes/*.{h,m}'
file_list = Rake::FileList[classes_path.to_s]
resolved = file_list.to_a.map do |path|
File.basename(path)
end
resolved.should == ["Banana.h", "Banana.m"]
end
it "it supports rake file list" do
local_path = temporary_directory + 'localBanana'
FileUtils.cp_r(fixture('banana-lib'), local_path)
sandbox = temporary_sandbox
spec = fixture_spec('banana-lib/BananaLib.podspec')
spec.source = { :local => local_path }
spec.source_files = Rake::FileList['Classes/*.{h,m}']
pod = LocalPod::LocalSourcedPod.new(spec, sandbox, Platform.ios)
pod.source_files.map {|path| path.to_s.gsub(/.*tmp\//,'') }.sort.should == [
"localBanana/Classes/Banana.m",
"localBanana/Classes/Banana.h"
].sort
end
end
#---------------------------------------------------------------------------#
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment