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' ...@@ -4,57 +4,155 @@ require 'active_support/core_ext/array/conversions'
module Pod module Pod
module Generator module Generator
# Generates the documentation for a Pod with the appledoc tool.
#
class Documentation class Documentation
extend Executable
extend Executable
executable :appledoc executable :appledoc
attr_reader :pod, :specification, :target_path, :options
def initialize(pod) attr_reader :sandbox
@pod = pod attr_reader :specification
@specification = pod.top_specification attr_reader :path_list
@target_path = pod.sandbox.root + 'Documentation' + pod.name
@options = @specification.documentation || {} def initialize(sandbox, specification, path_list)
@sandbox = sandbox
@specification = specification.root
@path_list = path_list
end 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 def name
@specification.name + ' ' + @specification.version.to_s specification.name + ' ' + specification.version.to_s
end end
# @return [String] The company of the docset.
#
# @todo Set to CocoaPods?
#
def company def company
if @specification.authors if specification.authors
@specification.authors.keys.sort.to_sentence specification.authors.keys.sort.to_sentence
else else
'no-company' 'no-company'
end end
end end
# @return [String] The copyright of the docset.
#
def copyright def copyright
company company
end end
# @return [String] The description of the docset.
#
def description def description
@specification.description || 'Generated by CocoaPods.' specification.summary || specification.description || 'Generated by CocoaPods.'
end end
# @return [String] The id of the docset.
#
def docs_id def docs_id
'org.cocoapods' 'org.cocoapods'
end 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 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 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 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 def spec_appledoc_options
@options[:appledoc] || [] return unless specification.documentation
specification.documentation[:appledoc]
end 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 # @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 def appledoc_options
options = [ options = [
...@@ -73,39 +171,48 @@ module Pod ...@@ -73,39 +171,48 @@ module Pod
options += spec_appledoc_options options += spec_appledoc_options
end end
def already_installed? # @return [String] the arguments to pass to the appledoc command line
index = spec_appledoc_options.index('--company-id') # tool, properly escaped.
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?
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) # @param [Bool] install_docset
if `which appledoc`.strip.empty? # Whether the documentation should also be installed in Xcode.
UI.warn "[!] Skipping documentation generation because appledoc can't be found.", #
actions = [], verbose_only = true def apple_doc_command_line_arguments(install_docset)
return 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 end
options = appledoc_options #-----------------------------------------------------------------------#
options += ['--output', @target_path.to_s]
options += install ? ['--create-docset'] : ['--no-create-docset'] private
options += files
# !@group Private Helpers
@target_path.mkpath def target_path
@pod.chdir do sandbox.root + 'Documentation' + specification.name
appledoc Escape.shell_command(options)
end end
if $?.exitstatus != 0 def pod_root
UI.warn "[!] Appledoc encountered an error (exitstatus: #{$?.exitstatus}), an update might be available to solve the issue." path_list.root
end 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 end
@file_accessors
end
end end
end end
end end
...@@ -12,23 +12,24 @@ module Pod ...@@ -12,23 +12,24 @@ module Pod
# @return [Platform] the platform for which the prefix header will be # @return [Platform] the platform for which the prefix header will be
# generated. # generated.
# #
attr_reader :file_accessors
attr_reader :platform attr_reader :platform
# @return [Array<LocalPod>] the LocalPod for the target for which the # @return [Array<LocalPod>] the LocalPod for the target for which the
# prefix header needs to be generated. # prefix header needs to be generated.
# #
attr_reader :pods # attr_reader :consumers
# @return [Array<String>] any header to import (with quotes). # @return [Array<String>] any header to import (with quotes).
# #
attr_reader :imports attr_reader :imports
# @param [Platform] platform @see platform # @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 @platform = platform
@pods = pods
@imports = [] @imports = []
end end
...@@ -52,13 +53,14 @@ module Pod ...@@ -52,13 +53,14 @@ module Pod
result << %|\n#import "#{import}"| result << %|\n#import "#{import}"|
end end
pods.each do |pod| file_accessors.each do |file_accessor|
result << "\n" 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 << prefix_header_contents
result << "\n" result << "\n"
elsif prefix_header = pod.prefix_header_file end
result << prefix_header.read if prefix_header = file_accessor.prefix_header
result << Pathname(prefix_header).read
end end
end end
result result
...@@ -74,6 +76,7 @@ module Pod ...@@ -74,6 +76,7 @@ module Pod
def save_as(path) def save_as(path)
path.open('w') { |header| header.write(generate) } path.open('w') { |header| header.write(generate) }
end end
end end
end end
end end
...@@ -10,9 +10,10 @@ module Pod ...@@ -10,9 +10,10 @@ module Pod
# #
attr_reader :sandbox 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 # @return [String] the relative path of the Pods root respect the user
# project that should be integrated by this library. # project that should be integrated by this library.
...@@ -23,9 +24,9 @@ module Pod ...@@ -23,9 +24,9 @@ module Pod
# @param [Array<LocalPod>] pods @see pods # @param [Array<LocalPod>] pods @see pods
# @param [String] relative_pods_root @see relative_pods_root # @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 @sandbox = sandbox
@pods = pods @spec_consumers = spec_consumers
@relative_pods_root = relative_pods_root @relative_pods_root = relative_pods_root
end end
...@@ -45,7 +46,7 @@ module Pod ...@@ -45,7 +46,7 @@ module Pod
# #
def generate def generate
ld_flags = '-ObjC' 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' ld_flags << ' -fobjc-arc'
end end
...@@ -58,7 +59,7 @@ module Pod ...@@ -58,7 +59,7 @@ module Pod
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(sandbox.build_headers.search_paths), 'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(sandbox.build_headers.search_paths),
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(sandbox.public_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 @xcconfig
end end
......
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Generator::Documentation do module Pod
describe Generator::Documentation do
before do before do
@sandbox = temporary_sandbox sandbox = config.sandbox
@pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), @sandbox, Pod::Platform.ios) spec = fixture_spec('banana-lib/BananaLib.podspec')
copy_fixture_to_pod('banana-lib', @pod) root = fixture('banana-lib')
@doc_installer = Pod::Generator::Documentation.new(@pod) path_list = Sandbox::PathList.new(root)
end @doc_installer = Generator::Documentation.new(sandbox, spec, path_list)
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 end
it 'returns the Pod documentation header files' do it 'returns the Pod documentation header files' do
@doc_installer.files.sort.should == %w[ Classes/Banana.h ].sort @doc_installer.public_headers.sort.should == %w[ Classes/Banana.h ].sort
end end
it 'returns the Pod documentation options' do it 'returns the Pod documentation options' do
@doc_installer.appledoc_options.should == [ expected = [
'--project-name', 'BananaLib 1.0', '--project-name', 'BananaLib 1.0',
'--docset-desc', 'Full of chunky bananas.', '--docset-desc', 'Chunky bananas!',
'--project-company', 'Banana Corp and Monkey Boy', '--project-company', 'Banana Corp and Monkey Boy',
'--docset-copyright', 'Banana Corp and Monkey Boy', '--docset-copyright', 'Banana Corp and Monkey Boy',
'--company-id', 'org.cocoapods', '--company-id', 'org.cocoapods',
...@@ -38,26 +30,52 @@ describe Pod::Generator::Documentation do ...@@ -38,26 +30,52 @@ describe Pod::Generator::Documentation do
'--project-company', 'Banana Corp', '--project-company', 'Banana Corp',
'--company-id', 'com.banana' '--company-id', 'com.banana'
] ]
options = @doc_installer.appledoc_options
expected.each do |expected_option|
options.should.include?(expected_option)
end
end end
if !`which appledoc`.strip.empty? it "returns the command line arguments to pass to the appledoc tool" do
before do arguments = @doc_installer.apple_doc_command_line_arguments(install_docset=false)
@doc_installer.generate 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 end
after do #-------------------------------------------------------------------------#
@sandbox.implode
if !`which appledoc`.strip.empty?
describe "Appledoc integration" do
before do
@doc_installer.generate(false)
end end
it 'creates the html' do it 'creates the html' do
File.directory?(@sandbox.root + "Documentation/BananaLib/html").should.be.true docs_path = config.sandbox.root + "Documentation/BananaLib/html"
index = (@sandbox.root + 'Documentation/BananaLib/html/index.html').read docs_path.should.exist
index.should.include?('BananaObj') (docs_path + 'index.html').read.should.include?('BananaObj')
index = (@sandbox.root + 'Documentation/BananaLib/html/Classes/BananaObj.html').read (docs_path + 'Classes/BananaObj.html').read.should.include?('Bananas are cool')
index.should.include?('Bananas are cool') end
end end
else else
puts "[!] Skipping documentation generation specs, because appledoc can't be found." puts "[!] Skipping documentation generation specs, because appledoc can't be found."
end end
end end
end
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
describe PrefixHeader = Pod::Generator::PrefixHeader do module Pod
describe PrefixHeader = Generator::PrefixHeader do
before do before do
platform = Pod::Platform.ios file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec')
specification = fixture_spec('banana-lib/BananaLib.podspec') @spec = file_accessor.spec
@pod = Pod::LocalPod.new(specification, nil, platform) @gen = PrefixHeader.new([file_accessor], Platform.ios)
pods = [ @pod ]
@gen = PrefixHeader.new(platform, pods)
@pod.stubs(:root).returns(Pathname.new(fixture('banana-lib')))
end end
it "includes the contents of the specification's prefix header" do it "includes the contents of the specification's prefix header" do
spec = @pod.top_specification @spec.prefix_header_contents = '#import "BlocksKit.h"'
spec.prefix_header_contents = '#import "BlocksKit.h"' @spec.prefix_header_file = nil
@gen.generate.should == <<-EOS.strip_heredoc @gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__ #ifdef __OBJC__
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
...@@ -46,19 +43,6 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do ...@@ -46,19 +43,6 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do
EOS EOS
end 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 it "imports UIKit in iOS platforms" do
@gen.stubs(:platform).returns(Pod::Platform.ios) @gen.stubs(:platform).returns(Pod::Platform.ios)
@gen.generate.should.include?('#import <UIKit/UIKit.h>') @gen.generate.should.include?('#import <UIKit/UIKit.h>')
...@@ -69,8 +53,6 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do ...@@ -69,8 +53,6 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do
@gen.generate.should.include?('#import <Cocoa/Cocoa.h>') @gen.generate.should.include?('#import <Cocoa/Cocoa.h>')
end end
it "writes the prefix header file to the disk" do it "writes the prefix header file to the disk" do
path = temporary_directory + 'Test.pch' path = temporary_directory + 'Test.pch'
@gen.save_as(path) @gen.save_as(path)
...@@ -82,4 +64,5 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do ...@@ -82,4 +64,5 @@ describe PrefixHeader = Pod::Generator::PrefixHeader do
#import <BananaTree/BananaTree.h> #import <BananaTree/BananaTree.h>
EOS EOS
end end
end
end end
...@@ -3,9 +3,9 @@ require File.expand_path('../../../spec_helper', __FILE__) ...@@ -3,9 +3,9 @@ require File.expand_path('../../../spec_helper', __FILE__)
module Pod module Pod
describe Generator::XCConfig do describe Generator::XCConfig do
before do before do
specification = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
@pod = Pod::LocalPod.new(specification, config.sandbox, :ios) @consumer = @spec.consumer(:ios)
@generator = Generator::XCConfig.new(config.sandbox, [@pod], './Pods') @generator = Generator::XCConfig.new(config.sandbox, [@consumer], './Pods')
end end
...@@ -14,7 +14,7 @@ module Pod ...@@ -14,7 +14,7 @@ module Pod
end end
it "returns the pods" do it "returns the pods" do
@generator.pods.should == [@pod] names = @generator.spec_consumers.should == [@consumer]
end end
it "returns the path of the pods root relative to the user project" do it "returns the path of the pods root relative to the user project" do
...@@ -45,7 +45,7 @@ module Pod ...@@ -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 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 @generator.set_arc_compatibility_flag = true
@pod.top_specification.stubs(:requires_arc).returns(true) @consumer.stubs(:requires_arc).returns(true)
@xcconfig = @generator.generate @xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc") @xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc")
end end
...@@ -88,8 +88,6 @@ module Pod ...@@ -88,8 +88,6 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
it "saves the xcconfig" do it "saves the xcconfig" do
path = temporary_directory + 'sample.xcconfig' path = temporary_directory + 'sample.xcconfig'
@generator.save_as(path) @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