Commit 65221133 authored by Fabio Pelosin's avatar Fabio Pelosin

[LocalPod] Cluster specifications.

parent 3364111c
...@@ -26,7 +26,7 @@ module Pod ...@@ -26,7 +26,7 @@ module Pod
return @project if @project return @project if @project
@project = Pod::Project.new @project = Pod::Project.new
@project.user_build_configurations = @podfile.user_build_configurations @project.user_build_configurations = @podfile.user_build_configurations
activated_pods.each do |pod| pods.each do |pod|
# Add all source files to the project grouped by pod # Add all source files to the project grouped by pod
group = @project.add_pod_group(pod.name) group = @project.add_pod_group(pod.name)
pod.source_files.each do |path| pod.source_files.each do |path|
...@@ -45,24 +45,24 @@ module Pod ...@@ -45,24 +45,24 @@ module Pod
end end
def install_dependencies! def install_dependencies!
activated_pods.each do |pod| pods.each do |pod|
marker = config.verbose ? "\n-> ".green : '' unless config.silent?
marker = config.verbose ? "\n-> ".green : ''
unless should_install = !pod.exists? && !pod.specification.local? puts pod.exists? ? "#{marker}Using #{pod}" : "#{marker}Installing #{pod}".green
puts marker + "Using #{pod}" unless config.silent? submarker = " " * marker.length << " - "
else puts "#{submarker}#{pod.subspecs.map{ |s| s.name.gsub(pod.specification.name+'/', '') }.join("\n" << submarker)}" unless pod.subspecs.empty?
puts marker + "Installing #{pod.specification}".green unless config.silent? end
unless pod.exists?
downloader = Downloader.for_pod(pod) downloader = Downloader.for_pod(pod)
downloader.download downloader.download
if config.clean if config.clean
downloader.clean downloader.clean
pod.clean pod.clean
end end
end end
if (should_install && config.generate_docs?) || config.force_doc? if (!pod.exists? && config.generate_docs?) || config.force_doc?
doc_generator = Generator::Documentation.new(pod) doc_generator = Generator::Documentation.new(pod)
if doc_generator.already_installed? if doc_generator.already_installed?
puts "Using Existing Documentation for #{pod.specification}".green if config.verbose? puts "Using Existing Documentation for #{pod.specification}".green if config.verbose?
...@@ -83,14 +83,13 @@ module Pod ...@@ -83,14 +83,13 @@ module Pod
print_title "Installing dependencies" print_title "Installing dependencies"
install_dependencies! install_dependencies!
pods = activated_pods
print_title("Generating support files\n", false) print_title("Generating support files\n", false)
target_installers.each do |target_installer| 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) target_installer.install!(pods_for_target, @sandbox)
end end
generate_lock_file!(pods) generate_lock_file!(specifications)
generate_dummy_source generate_dummy_source
puts "* Running post install hooks" if config.verbose? puts "* Running post install hooks" if config.verbose?
...@@ -107,7 +106,7 @@ module Pod ...@@ -107,7 +106,7 @@ module Pod
# we loop over target installers instead of pods, because we yield the target installer # we loop over target installers instead of pods, because we yield the target installer
# to the spec post install hook. # to the spec post install hook.
target_installers.each do |target_installer| 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) spec.post_install(target_installer)
end end
end end
...@@ -115,28 +114,28 @@ module Pod ...@@ -115,28 +114,28 @@ module Pod
@podfile.post_install!(self) @podfile.post_install!(self)
end end
def generate_lock_file!(pods) def generate_lock_file!(specs)
lock_file.open('w') do |file| lock_file.open('w') do |file|
file.puts "PODS:" file.puts "PODS:"
# Get list of [name, dependencies] pairs. # Get list of [name, dependencies] pairs.
activated_pods = pods.map do |pod| pod_and_deps = specs.map do |spec|
[pod.specification.to_s, pod.dependencies.map(&:to_s).sort] [spec.to_s, spec.dependencies.map(&:to_s).sort]
end.uniq end.uniq
# Merge dependencies of ios and osx version of the same pod. # Merge dependencies of ios and osx version of the same pod.
tmp = {} tmp = {}
activated_pods.each do |name, deps| pod_and_deps.each do |name, deps|
if tmp[name] if tmp[name]
tmp[name].concat(deps).uniq! tmp[name].concat(deps).uniq!
else else
tmp[name] = deps tmp[name] = deps
end end
end end
activated_pods = tmp pod_and_deps = tmp
# Sort by name and print # 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? if deps.empty?
file.puts " - #{name}" file.puts " - #{name}"
else else
...@@ -171,40 +170,36 @@ module Pod ...@@ -171,40 +170,36 @@ module Pod
end end
# @return [Array<Specification>] All dependencies that have been resolved. # @return [Array<Specification>] All dependencies that have been resolved.
def dependency_specifications def specifications
specs_by_target.values.flatten specs_by_target.values.flatten
end end
# @return [Array<LocalPod>] A list of LocalPod instances for each # @return [Array<LocalPod>] A list of LocalPod instances for each
# dependency that is not a download-only one. # dependency that is not a download-only one.
def activated_pods def pods
activated_pods_by_target.values.flatten pods_by_target.values.flatten
end end
def activated_pods_by_target def pods_by_target
@pods_by_spec = {}
result = {} result = {}
specs_by_target.each do |target_definition, specs| specs_by_target.each do |target_definition, specs|
@pods_by_spec[target_definition.platform] = {}
result[target_definition] = specs.map do |spec| result[target_definition] = specs.map do |spec|
LocalPod.new(spec, @sandbox, target_definition.platform) pod = pod_for_spec(spec, target_definition.platform)
end.compact pod.add_specification(spec)
pod
end.uniq.compact
end end
result result
end end
# @return [Array<Specification>] A list of specifications for each def pod_for_spec(spec, platform)
# dependency that is not a download-only @pods_by_spec[platform][spec.top_level_parent.name] ||= LocalPod.new(spec.top_level_parent, @sandbox, platform)
# one.
def activated_specifications
dependency_specifications
end
def activated_specifications_for_target(target_definition)
specs_by_target[target_definition]
end end
private private
def print_title(title, only_verbose = true) def print_title(title, only_verbose = true)
if config.verbose? if config.verbose?
puts "\n" + title.yellow puts "\n" + title.yellow
......
module Pod module Pod
class LocalPod class LocalPod
attr_reader :specification attr_reader :top_specification, :specifications
# TODO: fix accross the app
alias :specification :top_specification
attr_reader :sandbox attr_reader :sandbox
def initialize(specification, sandbox, platform) def initialize(specification, sandbox, platform)
@specification, @sandbox = specification, sandbox @top_specification, @sandbox = specification, sandbox
@specification.activate_platform(platform) @top_specification.activate_platform(platform)
@specifications = [] << specification
end end
def self.from_podspec(podspec, sandbox, platform) def self.from_podspec(podspec, sandbox, platform)
...@@ -13,23 +16,32 @@ module Pod ...@@ -13,23 +16,32 @@ module Pod
end end
def root def root
@sandbox.root + specification.name @sandbox.root + top_specification.name
end
# 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 subspecs
specifications.reject{|s| s.parent.nil? }
end end
def to_s def to_s
if specification.local? result = top_specification.to_s
"#{specification} [LOCAL]" # result << " [LOCAL]" if top_specification.local?
else result
specification.to_s
end
end end
def name def name
specification.name top_specification.name
end end
def platform def platform
specification.active_platform top_specification.active_platform
end end
def create def create
...@@ -50,29 +62,31 @@ module Pod ...@@ -50,29 +62,31 @@ module Pod
end end
def clean def clean
clean_paths.each { |path| FileUtils.rm_rf(path) } # TODO: nuke everything that is not used
# clean_paths.each { |path| FileUtils.rm_rf(path) }
end end
def prefix_header_file def prefix_header_file
if prefix_header = specification.prefix_header_file if prefix_header = top_specification.prefix_header_file
@sandbox.root + specification.name + prefix_header @sandbox.root + top_specification.name + prefix_header
end end
end end
def source_files def source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true) chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true)
end end
def absolute_source_files def absolute_source_files
expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}') chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}')
end end
def clean_paths def clean_paths
expanded_paths(specification.clean_paths) # TODO: delete
# chained_expanded_paths(:clean_paths)
end end
def resources def resources
expanded_paths(specification.resources, :relative_to_sandbox => true) chained_expanded_paths(:resources, :relative_to_sandbox => true)
end end
def header_files def header_files
...@@ -85,6 +99,15 @@ module Pod ...@@ -85,6 +99,15 @@ module Pod
end end
end end
def readme_file
expanded_paths('README.*', options = {})
end
def license
#TODO: merge with the work of will and return the text
expanded_paths(%w[ LICENSE licence.txt ], options = {})
end
def add_to_target(target) def add_to_target(target)
implementation_files.each do |file| implementation_files.each do |file|
target.add_source_file(file, nil, specification.compiler_flags.strip) target.add_source_file(file, nil, specification.compiler_flags.strip)
...@@ -120,6 +143,10 @@ module Pod ...@@ -120,6 +143,10 @@ module Pod
end end
end end
def chained_expanded_paths(accessor, options = {})
specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.reduce(:+).uniq
end
def expanded_paths(patterns, options = {}) def expanded_paths(patterns, options = {})
patterns.map do |pattern| patterns.map do |pattern|
pattern = root + pattern pattern = root + pattern
......
...@@ -320,7 +320,7 @@ else ...@@ -320,7 +320,7 @@ else
installer = SpecHelper::Installer.new(spec) installer = SpecHelper::Installer.new(spec)
target_definition = installer.target_installers.first.target_definition 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! installer.install!
contents = (config.project_pods_root + 'Pods-resources.sh').read contents = (config.project_pods_root + 'Pods-resources.sh').read
......
...@@ -42,7 +42,7 @@ describe "Pod::Installer" do ...@@ -42,7 +42,7 @@ describe "Pod::Installer" do
dependency 'ASIHTTPRequest' dependency 'ASIHTTPRequest'
end end
installer = Pod::Installer.new(podfile) 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) Pod::LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform)
end end
expected = pods.map { |pod| pod.header_files }.flatten.map { |header| config.project_pods_root + header } expected = pods.map { |pod| pod.header_files }.flatten.map { |header| config.project_pods_root + header }
......
...@@ -3,75 +3,75 @@ require File.expand_path('../../spec_helper', __FILE__) ...@@ -3,75 +3,75 @@ require File.expand_path('../../spec_helper', __FILE__)
describe Pod::LocalPod do describe Pod::LocalPod do
# a LocalPod represents a local copy of the dependency, inside the pod root, built from a spec # a LocalPod represents a local copy of the dependency, inside the pod root, built from a spec
before do before do
@sandbox = temporary_sandbox @sandbox = temporary_sandbox
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.new(:ios)) @pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.new(:ios))
copy_fixture_to_pod('banana-lib', @pod) copy_fixture_to_pod('banana-lib', @pod)
end end
it 'returns the Pod root directory path' do it 'returns the Pod root directory path' do
@pod.root.should == @sandbox.root + 'BananaLib' @pod.root.should == @sandbox.root + 'BananaLib'
end end
it "creates it's own root directory if it doesn't exist" do it "creates it's own root directory if it doesn't exist" do
@pod.create @pod.create
File.directory?(@pod.root).should.be.true File.directory?(@pod.root).should.be.true
end end
it "can execute a block within the context of it's root" do it "can execute a block within the context of it's root" do
@pod.chdir { FileUtils.touch("foo") } @pod.chdir { FileUtils.touch("foo") }
Pathname(@pod.root + "foo").should.exist Pathname(@pod.root + "foo").should.exist
end end
it 'can delete itself' do it 'can delete itself' do
@pod.create @pod.create
@pod.implode @pod.implode
@pod.root.should.not.exist @pod.root.should.not.exist
end end
it 'returns an expanded list of source files, relative to the sandbox root' do it 'returns an expanded list of source files, relative to the sandbox root' do
@pod.source_files.sort.should == [ @pod.source_files.sort.should == [
Pathname.new("BananaLib/Classes/Banana.m"), Pathname.new("BananaLib/Classes/Banana.m"),
Pathname.new("BananaLib/Classes/Banana.h") Pathname.new("BananaLib/Classes/Banana.h")
].sort ].sort
end end
it 'returns an expanded list of absolute clean paths' do xit 'returns an expanded list of absolute clean paths' do
@pod.clean_paths.should == [@sandbox.root + "BananaLib/sub-dir"] @pod.clean_paths.should == [@sandbox.root + "BananaLib/sub-dir"]
end end
it 'returns an expanded list of resources, relative to the sandbox root' do it 'returns an expanded list of resources, relative to the sandbox root' do
@pod.resources.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")] @pod.resources.should == [Pathname.new("BananaLib/Resources/logo-sidebar.png")]
end end
it 'returns a list of header files' do it 'returns a list of header files' do
@pod.header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")] @pod.header_files.should == [Pathname.new("BananaLib/Classes/Banana.h")]
end end
it 'can clean up after itself' do xit 'can clean up after itself' do
@pod.clean_paths.tap do |paths| @pod.clean_paths.tap do |paths|
@pod.clean @pod.clean
paths.each do |path| paths.each do |path|
path.should.not.exist path.should.not.exist
end end
end end
end end
it "can link it's headers into the sandbox" do it "can link it's headers into the sandbox" do
@pod.link_headers @pod.link_headers
expected_header_path = @sandbox.headers_root + "BananaLib/Banana.h" expected_header_path = @sandbox.headers_root + "BananaLib/Banana.h"
expected_header_path.should.be.symlink expected_header_path.should.be.symlink
File.read(expected_header_path).should == (@sandbox.root + @pod.header_files[0]).read File.read(expected_header_path).should == (@sandbox.root + @pod.header_files[0]).read
end end
it "can add it's source files to an Xcode project target" do it "can add it's source files to an Xcode project target" do
target = mock('target') target = mock('target')
target.expects(:add_source_file).with(Pathname.new("BananaLib/Classes/Banana.m"), anything, anything) target.expects(:add_source_file).with(Pathname.new("BananaLib/Classes/Banana.m"), anything, anything)
@pod.add_to_target(target) @pod.add_to_target(target)
end end
it "can add it's source files to a target with any specially configured compiler flags" do it "can add it's source files to a target with any specially configured compiler flags" do
@pod.specification.compiler_flags = '-d some_flag' @pod.specification.compiler_flags = '-d some_flag'
target = mock('target') target = mock('target')
......
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