Commit da6c6e67 authored by Fabio Pelosin's avatar Fabio Pelosin

[Generators] Update for changes in architecture.

parent ae9e56a8
......@@ -4,57 +4,155 @@ require 'active_support/core_ext/array/conversions'
module Pod
module Generator
# Generates the documentation for a Pod with the appledoc tool.
#
class Documentation
extend Executable
extend Executable
executable :appledoc
attr_reader :pod, :specification, :target_path, :options
def initialize(pod)
@pod = pod
@specification = pod.top_specification
@target_path = pod.sandbox.root + 'Documentation' + pod.name
@options = @specification.documentation || {}
attr_reader :sandbox
attr_reader :specification
attr_reader :path_list
def initialize(sandbox, specification, path_list)
@sandbox = sandbox
@specification = specification.root
@path_list = path_list
end
DOC_SETS_PATH = "~/Library/Developer/Shared/Documentation/DocSets"
# @return [Bool] Whether the documentation for the current Pod is already
# installed in the system.
#
def already_installed?
index = spec_appledoc_options.index('--company-id')
company_id = index ? spec_appledoc_options[index + 1] : docs_id
docset_path = DOC_SETS_PATH + "/#{company_id}.#{name.gsub(/ /,'-')}.docset"
Pathname.new(File.expand_path(docset_path)).exist?
end
# Generates and optionally installs the documentation for the current
# Pod.
#
# @param [Bool] install_docset
# Whether the documentation should also be installed in Xcode.
#
# @note As the documentation is once per Pod to speed up the
# installation process it is generate for all the specs
# (including those not currently used). For this reason it is
# important that the documentation is generated before cleaning a
# Pod installation.
#
# @todo Passing the files explicitly clutters output and chokes on very
# long list (AWSiOSSDK). It is possible to just pass the dir of
# the pod, however this would include other files like demo
# projects.
#
# @return [void]
#
def generate(install_docset)
if `which appledoc`.strip.empty?
UI.warn "[!] Skipping documentation generation because appledoc can't be found.",
actions = [], verbose_only = true
return
end
target_path.mkpath
Dir.chdir(pod_root) do
appledoc apple_doc_command_line_arguments(install_docset)
end
if $?.exitstatus != 0
UI.warn "[!] Appledoc encountered an error (exitstatus: #{$?.exitstatus}), an update might be available to solve the issue."
end
end
#-----------------------------------------------------------------------#
public
# !@group Docset information.
# @return [String] The name of the docset
#
def name
@specification.name + ' ' + @specification.version.to_s
specification.name + ' ' + specification.version.to_s
end
# @return [String] The company of the docset.
#
# @todo Set to CocoaPods?
#
def company
if @specification.authors
@specification.authors.keys.sort.to_sentence
if specification.authors
specification.authors.keys.sort.to_sentence
else
'no-company'
end
end
# @return [String] The copyright of the docset.
#
def copyright
company
end
# @return [String] The description of the docset.
#
def description
@specification.description || 'Generated by CocoaPods.'
specification.summary || specification.description || 'Generated by CocoaPods.'
end
# @return [String] The id of the docset.
#
def docs_id
'org.cocoapods'
end
def files
@pod.documentation_headers.map{ |f| f.relative_path_from(@pod.root).to_s }
#-----------------------------------------------------------------------#
public
# !@group Paths.
# @return [Array<String>] the list of the headers to process
# with the appledoc tool.
#
def public_headers
absolute_paths = file_accessors.map(&:public_headers).flatten.uniq
absolute_paths.map { |f| f.relative_path_from(pod_root).to_s }
end
# @return [String] the path of the file to use ad index of the
# documentation relative to the root of the Pod.
#
def index_file
@pod.readme_file.relative_path_from(@pod.root).to_s if @pod.readme_file
readme_file = file_accessors.first.readme
readme_file.relative_path_from(pod_root).to_s if readme_file
end
#-----------------------------------------------------------------------#
public
# !@group Appledoc options.
# @return [Array<String>] The list of the appledoc options followed by
# their value as defined in the specification.
#
def spec_appledoc_options
@options[:appledoc] || []
return unless specification.documentation
specification.documentation[:appledoc]
end
# @return [Array<String>] The list of the appledoc options followed by
# their value.
#
# @note The appledoc tool terminates with an exits status of 1 if a
# warning was logged
# warning was logged (see `--exit-threshold` option).
#
def appledoc_options
options = [
......@@ -73,39 +171,48 @@ module Pod
options += spec_appledoc_options
end
def already_installed?
index = spec_appledoc_options.index('--company-id')
company_id = index ? spec_appledoc_options[index + 1] : docs_id
Pathname.new(File.expand_path("~/Library/Developer/Shared/Documentation/DocSets/#{company_id}.#{name.gsub(/ /,'-')}.docset")).exist?
# @return [String] the arguments to pass to the appledoc command line
# tool, properly escaped.
#
# @param [Bool] install_docset
# Whether the documentation should also be installed in Xcode.
#
def apple_doc_command_line_arguments(install_docset)
arguments = appledoc_options
arguments += ['--output', target_path.to_s]
arguments += install_docset ? ['--create-docset'] : ['--no-create-docset']
arguments += public_headers
Escape.shell_command(arguments)
end
# @todo passing the files explicitly clutters output and chokes on very
# long list (AWSiOSSDK). It is possible to just pass the dir of
# the pod, however this would include other files like demo
# projects.
#
def generate(install = false)
if `which appledoc`.strip.empty?
UI.warn "[!] Skipping documentation generation because appledoc can't be found.",
actions = [], verbose_only = true
return
end
#-----------------------------------------------------------------------#
options = appledoc_options
options += ['--output', @target_path.to_s]
options += install ? ['--create-docset'] : ['--no-create-docset']
options += files
private
@target_path.mkpath
@pod.chdir do
appledoc Escape.shell_command(options)
end
# !@group Private Helpers
if $?.exitstatus != 0
UI.warn "[!] Appledoc encountered an error (exitstatus: #{$?.exitstatus}), an update might be available to solve the issue."
end
def target_path
sandbox.root + 'Documentation' + specification.name
end
def pod_root
path_list.root
end
def file_accessors
return @file_accessors if @file_accessors
@file_accessors = []
all_specs = [specification, *specification.subspecs]
all_specs.each do |spec|
spec.available_platforms.each do |platform|
accessor = Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
@file_accessors << accessor
end
end
@file_accessors
end
end
end
end
......@@ -12,24 +12,25 @@ module Pod
# @return [Platform] the platform for which the prefix header will be
# generated.
#
attr_reader :file_accessors
attr_reader :platform
# @return [Array<LocalPod>] the LocalPod for the target for which the
# prefix header needs to be generated.
#
attr_reader :pods
# attr_reader :consumers
# @return [Array<String>] any header to import (with quotes).
#
attr_reader :imports
# @param [Platform] platform @see platform
# @param [Array<LocalPod>] pods @see pods
# @param [Array<LocalPod>] consumers @see consumers
#
def initialize(platform, pods)
def initialize(file_accessors, platform)
@file_accessors = file_accessors
@platform = platform
@pods = pods
@imports = []
@imports = []
end
# Generates the contents of the prefix header according to the platform
......@@ -52,13 +53,14 @@ module Pod
result << %|\n#import "#{import}"|
end
pods.each do |pod|
file_accessors.each do |file_accessor|
result << "\n"
if prefix_header_contents = pod.top_specification.consumer(platform).prefix_header_contents
if prefix_header_contents = file_accessor.spec_consumer.prefix_header_contents
result << prefix_header_contents
result << "\n"
elsif prefix_header = pod.prefix_header_file
result << prefix_header.read
end
if prefix_header = file_accessor.prefix_header
result << Pathname(prefix_header).read
end
end
result
......@@ -74,6 +76,7 @@ module Pod
def save_as(path)
path.open('w') { |header| header.write(generate) }
end
end
end
end
......@@ -10,9 +10,10 @@ module Pod
#
attr_reader :sandbox
# @return [Array<LocalPod>] the list of LocalPods for the library.
# @return [Array<Specification::Consumer>] the consumers for the
# specifications of the library which needs the xcconfig.
#
attr_reader :pods
attr_reader :spec_consumers
# @return [String] the relative path of the Pods root respect the user
# project that should be integrated by this library.
......@@ -23,9 +24,9 @@ module Pod
# @param [Array<LocalPod>] pods @see pods
# @param [String] relative_pods_root @see relative_pods_root
#
def initialize(sandbox, pods, relative_pods_root)
def initialize(sandbox, spec_consumers, relative_pods_root)
@sandbox = sandbox
@pods = pods
@spec_consumers = spec_consumers
@relative_pods_root = relative_pods_root
end
......@@ -45,7 +46,7 @@ module Pod
#
def generate
ld_flags = '-ObjC'
if set_arc_compatibility_flag && pods.map(&:specifications).flatten.any? { |pod| pod.requires_arc }
if set_arc_compatibility_flag && spec_consumers.any? { |consumer| consumer.requires_arc }
ld_flags << ' -fobjc-arc'
end
......@@ -58,7 +59,7 @@ module Pod
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(sandbox.build_headers.search_paths),
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(sandbox.public_headers.search_paths),
})
pods.each { |pod| @xcconfig.merge!(pod.xcconfig) }
spec_consumers.each { |consumers| @xcconfig.merge!(consumers.xcconfig) }
@xcconfig
end
......
require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Generator::Documentation do
before do
@sandbox = temporary_sandbox
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.ios)
copy_fixture_to_pod('banana-lib', @pod)
@doc_installer = Pod::Generator::Documentation.new(@pod)
end
it 'returns reads correctly the Pod documentation' do
@doc_installer.options.should == {
:html => 'http://banana-corp.local/banana-lib/docs.html',
:appledoc => [
'--project-company', 'Banana Corp',
'--company-id', 'com.banana',
]
}
end
it 'returns the Pod documentation header files' do
@doc_installer.files.sort.should == %w[ Classes/Banana.h ].sort
end
module Pod
describe Generator::Documentation do
before do
sandbox = config.sandbox
spec = fixture_spec('banana-lib/BananaLib.podspec')
root = fixture('banana-lib')
path_list = Sandbox::PathList.new(root)
@doc_installer = Generator::Documentation.new(sandbox, spec, path_list)
end
it 'returns the Pod documentation options' do
@doc_installer.appledoc_options.should == [
'--project-name', 'BananaLib 1.0',
'--docset-desc', 'Full of chunky bananas.',
'--project-company', 'Banana Corp and Monkey Boy',
'--docset-copyright', 'Banana Corp and Monkey Boy',
'--company-id', 'org.cocoapods',
'--ignore', '.m',
'--keep-undocumented-objects',
'--keep-undocumented-members',
'--keep-intermediate-files',
'--exit-threshold', '2',
'--index-desc', 'README',
'--project-company', 'Banana Corp',
'--company-id', 'com.banana'
]
end
it 'returns the Pod documentation header files' do
@doc_installer.public_headers.sort.should == %w[ Classes/Banana.h ].sort
end
if !`which appledoc`.strip.empty?
before do
@doc_installer.generate
it 'returns the Pod documentation options' do
expected = [
'--project-name', 'BananaLib 1.0',
'--docset-desc', 'Chunky bananas!',
'--project-company', 'Banana Corp and Monkey Boy',
'--docset-copyright', 'Banana Corp and Monkey Boy',
'--company-id', 'org.cocoapods',
'--ignore', '.m',
'--keep-undocumented-objects',
'--keep-undocumented-members',
'--keep-intermediate-files',
'--exit-threshold', '2',
'--index-desc', 'README',
'--project-company', 'Banana Corp',
'--company-id', 'com.banana'
]
options = @doc_installer.appledoc_options
expected.each do |expected_option|
options.should.include?(expected_option)
end
end
after do
@sandbox.implode
it "returns the command line arguments to pass to the appledoc tool" do
arguments = @doc_installer.apple_doc_command_line_arguments(install_docset=false)
arguments.should.include?("--project-name 'BananaLib 1.0' ")
arguments.should.include?(" --docset-desc 'Chunky bananas!' ")
arguments.should.include?(" --project-company 'Banana Corp and Monkey Boy' ")
arguments.should.include?(" --docset-copyright 'Banana Corp and Monkey Boy' ")
arguments.should.include?(" --company-id org.cocoapods ")
arguments.should.include?(" --ignore .m ")
arguments.should.include?(" --keep-undocumented-objects ")
arguments.should.include?(" --keep-undocumented-members ")
arguments.should.include?(" --keep-intermediate-files ")
arguments.should.include?(" --exit-threshold 2 ")
arguments.should.include?(" --index-desc README ")
arguments.should.include?(" --project-company 'Banana Corp' ")
arguments.should.include?(" --company-id com.banana ")
# arguments.should.include?(" --output tmp/Pods/Documentation/BananaLib ")
arguments.should.include?(" --no-create-docset Classes/Banana.h")
arguments.should.include?(" Classes/Banana.h")
end
it 'creates the html' do
File.directory?(@sandbox.root + "Documentation/BananaLib/html").should.be.true
index = (@sandbox.root + 'Documentation/BananaLib/html/index.html').read
index.should.include?('BananaObj')
index = (@sandbox.root + 'Documentation/BananaLib/html/Classes/BananaObj.html').read
index.should.include?('Bananas are cool')
#-------------------------------------------------------------------------#
if !`which appledoc`.strip.empty?
describe "Appledoc integration" do
before do
@doc_installer.generate(false)
end
it 'creates the html' do
docs_path = config.sandbox.root + "Documentation/BananaLib/html"
docs_path.should.exist
(docs_path + 'index.html').read.should.include?('BananaObj')
(docs_path + 'Classes/BananaObj.html').read.should.include?('Bananas are cool')
end
end
else
puts "[!] Skipping documentation generation specs, because appledoc can't be found."
end
else
puts "[!] Skipping documentation generation specs, because appledoc can't be found."
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
describe PrefixHeader = Pod::Generator::PrefixHeader do
before do
platform = Pod::Platform.ios
specification = fixture_spec('banana-lib/BananaLib.podspec')
@pod = Pod::LocalPod.new(specification, nil, platform)
pods = [ @pod ]
@gen = PrefixHeader.new(platform, pods)
@pod.stubs(:root).returns(Pathname.new(fixture('banana-lib')))
end
it "includes the contents of the specification's prefix header" do
spec = @pod.top_specification
spec.prefix_header_contents = '#import "BlocksKit.h"'
@gen.generate.should == <<-EOS.strip_heredoc
module Pod
describe PrefixHeader = Generator::PrefixHeader do
before do
file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec')
@spec = file_accessor.spec
@gen = PrefixHeader.new([file_accessor], Platform.ios)
end
it "includes the contents of the specification's prefix header" do
@spec.prefix_header_contents = '#import "BlocksKit.h"'
@spec.prefix_header_file = nil
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
EOS
end
it "includes the contents of the specification's prefix header file" do
@gen.generate.should == <<-EOS.strip_heredoc
it "includes the contents of the specification's prefix header file" do
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import <BananaTree/BananaTree.h>
EOS
end
EOS
end
it "includes the imports" do
@gen.imports << "header.h"
@gen.generate.should == <<-EOS.strip_heredoc
it "includes the imports" do
@gen.imports << "header.h"
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "header.h"
#import <BananaTree/BananaTree.h>
EOS
end
it "prefers the inline specification of the prefix header contents" do
spec = @pod.top_specification
spec.prefix_header_contents = '#import "BlocksKit.h"'
@pod.prefix_header_file.should.be.not.nil
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
it "imports UIKit in iOS platforms" do
@gen.stubs(:platform).returns(Pod::Platform.ios)
@gen.generate.should.include?('#import <UIKit/UIKit.h>')
end
it "imports Cocoa for OS X platforms" do
@gen.stubs(:platform).returns(Pod::Platform.osx)
@gen.generate.should.include?('#import <Cocoa/Cocoa.h>')
end
it "writes the prefix header file to the disk" do
path = temporary_directory + 'Test.pch'
@gen.save_as(path)
path.read.should == <<-EOS.strip_heredoc
EOS
end
it "imports UIKit in iOS platforms" do
@gen.stubs(:platform).returns(Pod::Platform.ios)
@gen.generate.should.include?('#import <UIKit/UIKit.h>')
end
it "imports Cocoa for OS X platforms" do
@gen.stubs(:platform).returns(Pod::Platform.osx)
@gen.generate.should.include?('#import <Cocoa/Cocoa.h>')
end
it "writes the prefix header file to the disk" do
path = temporary_directory + 'Test.pch'
@gen.save_as(path)
path.read.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import <BananaTree/BananaTree.h>
EOS
EOS
end
end
end
......@@ -3,9 +3,9 @@ require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe Generator::XCConfig do
before do
specification = fixture_spec('banana-lib/BananaLib.podspec')
@pod = Pod::LocalPod.new(specification, config.sandbox, :ios)
@generator = Generator::XCConfig.new(config.sandbox, [@pod], './Pods')
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@consumer = @spec.consumer(:ios)
@generator = Generator::XCConfig.new(config.sandbox, [@consumer], './Pods')
end
......@@ -14,7 +14,7 @@ module Pod
end
it "returns the pods" do
@generator.pods.should == [@pod]
names = @generator.spec_consumers.should == [@consumer]
end
it "returns the path of the pods root relative to the user project" do
......@@ -45,7 +45,7 @@ module Pod
it 'adds the -fobjc-arc to OTHER_LDFLAGS if any pods require arc (to support non-ARC projects on iOS 4.0)' do
@generator.set_arc_compatibility_flag = true
@pod.top_specification.stubs(:requires_arc).returns(true)
@consumer.stubs(:requires_arc).returns(true)
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc")
end
......@@ -88,8 +88,6 @@ module Pod
#-----------------------------------------------------------------------#
it "saves the xcconfig" do
path = temporary_directory + 'sample.xcconfig'
@generator.save_as(path)
......
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