Commit cfebf438 authored by Fabio Pelosin's avatar Fabio Pelosin

Merge branch 'core-extraction' into 0.17

* core-extraction: (75 commits)
  [Documenation] Clean-up.
  Fixes for core changes.
  [Gitignore] Added docs.
  [Rake] Added docs support.
  Make most of the specs green.
  [Sandbox] Added #specification.
  [Resolver] No need to pass the platform to external sources.
  [ExternalSources] Clean-up and docs.
  [Sandbox] Comments.
  [Resolver] Clean-up and specs update.
  [SpecHelper] Fine tune bacon helper.
  Updated master repo fixture.
  [Specs] Fix for master repo update & small performance improvements.
  [Gemfile] Use WebMock >= 1.8.0, < 1.9 as requested by VCR.
  Minor fixes.
  [Changelog]
  [SpecHelper] More refinement for bacon support.
  [TargetInstaller] Extracted XCConfig generation to Generator::XCConfing.
  Release 0.16.0
  [RakeFile] More fixes for release task.
  ...

Conflicts:
	CHANGELOG.md
parents a66b7cb3 042b51f9
...@@ -22,3 +22,4 @@ spec/fixtures/vcr ...@@ -22,3 +22,4 @@ spec/fixtures/vcr
.yardoc .yardoc
/doc /doc
.rbx/ .rbx/
rakelib/doc
\ No newline at end of file
...@@ -6,9 +6,6 @@ process do |files| ...@@ -6,9 +6,6 @@ process do |files|
specs = files.take_and_map do |file| specs = files.take_and_map do |file|
if file =~ %r{lib/cocoapods/(.+?)\.rb$} if file =~ %r{lib/cocoapods/(.+?)\.rb$}
s = Dir.glob("spec/**/#{File.basename(file, '.rb')}_spec.rb") s = Dir.glob("spec/**/#{File.basename(file, '.rb')}_spec.rb")
if file =~ %r{lib/cocoapods/installer.*\.rb$}
s.concat(['spec/unit/installer_spec.rb', 'spec/unit/installer/target_installer_spec.rb'])
end
s.uniq unless s.empty? s.uniq unless s.empty?
end end
end end
......
...@@ -2,8 +2,21 @@ language: ruby ...@@ -2,8 +2,21 @@ language: ruby
rvm: rvm:
- 1.8.7 - 1.8.7
- 1.9.3 - 1.9.3
# Not in Travis non-pro yet
#- 2.0.0
# Rubinius in 1.8 mode on Travis does not work. It complains about st_data_t etc in Xcodeproj. # Rubinius in 1.8 mode on Travis does not work. It complains about st_data_t etc in Xcodeproj.
#- rbx-18mode #- rbx-18mode
- rbx-19mode - rbx-19mode
matrix:
allow_failures:
- rvm: rbx-19mode
#- rvm: 2.0.0
install: NOEXEC=skip rake travis:setup install: NOEXEC=skip rake travis:setup
script: bundle exec rake spec script: bundle exec rake spec
notifications:
# email: false
campfire:
on_success: change
on_failure: always
rooms:
- secure: "qOE5zmgaHe/qQu3W9rmj7wygA5Ivl+cx50fqWGag2bdRl8ly5yj1NVoOKk/O\nZmQc4Lze+301uvTXi+r5v8A/tF6W1kUZw7yBiKuXoYFUGmDiVR9o2I/FPwkL\ngSzPJttrXTQfkQ4PbnrkX+JO+5bLWrKaO0hKXT4B2yUu4UXLVk0="
## Branch 0.17 ## Branch 0.17
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/master...0.17)
###### TODO - TODO: Dropped script for resources.
- Add `s.exclude_source_files` and related attributes to the specification class. ###### DSL Changes
- Deprecated header_mappings hook for specifications.
- `preferred_dependency` has been renamed to `default_subspec`.
- Added `s.exclude_source_files` and related attributes to the specification class.
- Added support for prefix_header_file in subspecs
- Added support for prefix_header_contents in subspecs
- Removed exclude_header_search_paths
- Added screenshot attribute
- Renamed preferred_dependency
###### Enhancements ###### Enhancements
- Released [documentation](docs.cocoapods.org).
- Adds new subcommand `pod spec cat NAME` to print a spec file to standard output.
- Added Podfile to the Pods project.
- Major clean up and refactor to the code base.
- Extrace models to [CocoaPods-Core](https://github.com/CocoaPods/Core) gem.
- Extracted command-line command & option handling into - Extracted command-line command & option handling into
[CLAide](https://github.com/CocoaPods/CLAide). [CLAide](https://github.com/CocoaPods/CLAide).
- Added PathList class. - Added PathList class.
- Added Podfile to the Pods project.
[#476](https://github.com/CocoaPods/CocoaPods/issues/476) [#476](https://github.com/CocoaPods/CocoaPods/issues/476)
- Extracted XCConfig generator.
- Adds new subcommand `pod spec cat NAME` to print a spec file to standard output. ## 0.16.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.0.rc5...master)
###### Enhancements
- Use Rake 0.9.4
[#657](https://github.com/CocoaPods/CocoaPods/issues/657)
## 0.16.0.rc5
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.0.rc4...0.16.0.rc5)
###### Deprecated
- The usage of specifications defined in a Podfile is deprecated. Use the
`:podspec` option with a file path instead. Complete removal will most
probably happen in 0.17.0.
[#549](https://github.com/CocoaPods/CocoaPods/issues/549)
[#616](https://github.com/CocoaPods/CocoaPods/issues/616)
[#525](https://github.com/CocoaPods/CocoaPods/issues/525)
###### Bug fixes
- Always consider inline podspecs as needing installation.
- Fix detection when the lib has already been integrated with the user’s target.
[#643](https://github.com/CocoaPods/CocoaPods/issues/643)
[#614](https://github.com/CocoaPods/CocoaPods/issues/614)
[#613](https://github.com/CocoaPods/CocoaPods/issues/613)
## 0.16.0.rc4
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.0.rc3...0.16.0.rc4)
###### Bug fixes
- Fix for Rake 0.9.3
[#657](https://github.com/CocoaPods/CocoaPods/issues/657)
## 0.16.0.rc3
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.0.rc2...0.16.0.rc3)[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.4.0.rc1...0.4.0.rc6)
###### Enhancements
## Master - Added support for copying frameworks to the app bundle.
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.16.0.rc2...master)[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.4.0.rc1...master) [#597](https://github.com/CocoaPods/CocoaPods/pull/597)
###### Bug fixes ###### Bug fixes
- Ignore PBXReferenceProxy while integrating into user project.
[#626](https://github.com/CocoaPods/CocoaPods/issues/626)
- Added support for PBXAggregateTarget and PBXLegacyTarget. - Added support for PBXAggregateTarget and PBXLegacyTarget.
[#615](https://github.com/CocoaPods/CocoaPods/issues/615) [#615](https://github.com/CocoaPods/CocoaPods/issues/615)
- Added support for PBXReferenceProxy. - Added support for PBXReferenceProxy.
......
...@@ -3,13 +3,15 @@ source "http://rubygems.org" ...@@ -3,13 +3,15 @@ source "http://rubygems.org"
gemspec gemspec
group :development do group :development do
# gem "cocoapods-core", :git => "git://github.com/CocoaPods/Core.git"
gem "cocoapods-core", :path => "../Core"
gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git" gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git"
gem "mocha", "~> 0.11.4" gem "mocha", "~> 0.11.4"
gem "bacon" gem "bacon"
gem "mocha-on-bacon" gem "mocha-on-bacon"
gem "rake" gem "rake"
gem "vcr" gem "vcr"
gem "webmock" gem "webmock", '>= 1.8.0', '< 1.9'
end end
group :debugging do group :debugging do
...@@ -23,5 +25,5 @@ group :documentation do ...@@ -23,5 +25,5 @@ group :documentation do
gem 'yard' gem 'yard'
gem 'redcarpet' gem 'redcarpet'
gem 'github-markup' gem 'github-markup'
gem 'pygments.rb'
end end
GIT GIT
remote: git://github.com/CocoaPods/Xcodeproj.git remote: git://github.com/CocoaPods/Xcodeproj.git
revision: 97a5a444ecfadf52e42afdbbf054f078f7c2cc5d revision: fbb5c11844b99bd954b2945098502dde0641c311
specs: specs:
xcodeproj (0.4.0.rc5) xcodeproj (0.4.0)
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
colored (~> 1.2) colored (~> 1.2)
...@@ -18,22 +18,31 @@ GIT ...@@ -18,22 +18,31 @@ GIT
PATH PATH
remote: . remote: .
specs: specs:
cocoapods (0.16.0.rc2) cocoapods (0.17.0.alpha)
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
claide (~> 0.1) claide (~> 0.1)
cocoapods-core
colored (~> 1.2) colored (~> 1.2)
escape (~> 0.0.4) escape (~> 0.0.4)
faraday (~> 0.8.1) faraday (~> 0.8.1)
json (~> 1.7.3) json (~> 1.7.3)
octokit (~> 1.7) octokit (~> 1.7)
open4 (~> 1.3.0) open4 (~> 1.3.0)
rake (~> 0.9.0) rake (~> 0.9.4)
xcodeproj (~> 0.4.0.rc1) xcodeproj (~> 0.4.0)
PATH
remote: ../Core
specs:
cocoapods-core (0.16.0.rc2)
activesupport (~> 3.2.6)
faraday (~> 0.8.1)
octokit (~> 1.7)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
specs: specs:
activesupport (3.2.8) activesupport (3.2.9)
i18n (~> 0.6) i18n (~> 0.6)
multi_json (~> 1.0) multi_json (~> 1.0)
addressable (2.3.2) addressable (2.3.2)
...@@ -52,27 +61,31 @@ GEM ...@@ -52,27 +61,31 @@ GEM
hashie (1.2.0) hashie (1.2.0)
i18n (0.6.1) i18n (0.6.1)
json (1.7.5) json (1.7.5)
listen (0.5.3) listen (0.6.0)
metaclass (0.0.1) metaclass (0.0.1)
method_source (0.8.1) method_source (0.8.1)
mocha (0.11.4) mocha (0.11.4)
metaclass (~> 0.0.1) metaclass (~> 0.0.1)
mocha-on-bacon (0.2.1) mocha-on-bacon (0.2.1)
mocha (>= 0.9.8) mocha (>= 0.9.8)
multi_json (1.3.6) multi_json (1.4.0)
multipart-post (1.1.5) multipart-post (1.1.5)
octokit (1.18.0) octokit (1.19.0)
addressable (~> 2.2) addressable (~> 2.2)
faraday (~> 0.8) faraday (~> 0.8)
faraday_middleware (~> 0.8) faraday_middleware (~> 0.9)
hashie (~> 1.2) hashie (~> 1.2)
multi_json (~> 1.3) multi_json (~> 1.3)
open4 (1.3.0) open4 (1.3.0)
posix-spawn (0.3.6)
pry (0.9.10) pry (0.9.10)
coderay (~> 1.0.5) coderay (~> 1.0.5)
method_source (~> 0.8) method_source (~> 0.8)
slop (~> 3.3.1) slop (~> 3.3.1)
rake (0.9.2.2) pygments.rb (0.3.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
rake (0.9.5)
rb-fsevent (0.9.2) rb-fsevent (0.9.2)
redcarpet (2.2.2) redcarpet (2.2.2)
slop (3.3.3) slop (3.3.3)
...@@ -81,6 +94,7 @@ GEM ...@@ -81,6 +94,7 @@ GEM
webmock (1.8.11) webmock (1.8.11)
addressable (>= 2.2.7) addressable (>= 2.2.7)
crack (>= 0.1.7) crack (>= 0.1.7)
yajl-ruby (1.1.0)
yard (0.8.3) yard (0.8.3)
PLATFORMS PLATFORMS
...@@ -90,15 +104,17 @@ DEPENDENCIES ...@@ -90,15 +104,17 @@ DEPENDENCIES
awesome_print awesome_print
bacon bacon
cocoapods! cocoapods!
cocoapods-core!
github-markup github-markup
kicker! kicker!
mocha (~> 0.11.4) mocha (~> 0.11.4)
mocha-on-bacon mocha-on-bacon
pry pry
pygments.rb
rake rake
rb-fsevent rb-fsevent
redcarpet redcarpet
vcr vcr
webmock webmock (>= 1.8.0, < 1.9)
xcodeproj! xcodeproj!
yard yard
...@@ -96,7 +96,7 @@ namespace :gem do ...@@ -96,7 +96,7 @@ namespace :gem do
diff_lines.delete('CHANGELOG.md') diff_lines.delete('CHANGELOG.md')
if diff_lines != ['lib/cocoapods.rb'] if diff_lines != ['lib/cocoapods.rb']
$stderr.puts "[!] Only change the version number in a release commit!" $stderr.puts "[!] Only change the version number in a release commit!"
# exit 1 exit 1
end end
end end
...@@ -108,7 +108,7 @@ namespace :gem do ...@@ -108,7 +108,7 @@ namespace :gem do
required_xcodeproj_version = xcodeproj.requirement.requirements.first.last.to_s required_xcodeproj_version = xcodeproj.requirement.requirements.first.last.to_s
puts "* Checking if xcodeproj #{required_xcodeproj_version} exists on the gem host" puts "* Checking if xcodeproj #{required_xcodeproj_version} exists on the gem host"
search_result = silent_sh("gem search --pre --remote xcodeproj") search_result = silent_sh("gem search --all --remote xcodeproj")
remote_xcodeproj_versions = search_result.match(/xcodeproj \((.*)\)/m)[1].split(', ') remote_xcodeproj_versions = search_result.match(/xcodeproj \((.*)\)/m)[1].split(', ')
unless remote_xcodeproj_versions.include?(required_xcodeproj_version) unless remote_xcodeproj_versions.include?(required_xcodeproj_version)
$stderr.puts "[!] The Xcodeproj version `#{required_xcodeproj_version}' required by " \ $stderr.puts "[!] The Xcodeproj version `#{required_xcodeproj_version}' required by " \
......
...@@ -26,8 +26,9 @@ Gem::Specification.new do |s| ...@@ -26,8 +26,9 @@ Gem::Specification.new do |s|
s.executables = %w{ pod } s.executables = %w{ pod }
s.require_paths = %w{ lib } s.require_paths = %w{ lib }
s.add_runtime_dependency 'cocoapods-core'
s.add_runtime_dependency 'claide', '~> 0.1' s.add_runtime_dependency 'claide', '~> 0.1'
s.add_runtime_dependency 'xcodeproj', '~> 0.4.0.rc1' s.add_runtime_dependency 'xcodeproj', '~> 0.4.0'
s.add_runtime_dependency 'faraday', '~> 0.8.1' s.add_runtime_dependency 'faraday', '~> 0.8.1'
s.add_runtime_dependency 'octokit', '~> 1.7' s.add_runtime_dependency 'octokit', '~> 1.7'
...@@ -35,7 +36,7 @@ Gem::Specification.new do |s| ...@@ -35,7 +36,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'escape', '~> 0.0.4' s.add_runtime_dependency 'escape', '~> 0.0.4'
s.add_runtime_dependency 'json', '~> 1.7.3' s.add_runtime_dependency 'json', '~> 1.7.3'
s.add_runtime_dependency 'open4', '~> 1.3.0' s.add_runtime_dependency 'open4', '~> 1.3.0'
s.add_runtime_dependency 'rake', '~> 0.9.0' s.add_runtime_dependency 'rake', '~> 0.9.4'
s.add_runtime_dependency 'activesupport', '~> 3.2.6' s.add_runtime_dependency 'activesupport', '~> 3.2.6'
s.add_development_dependency 'bacon', '~> 1.1' s.add_development_dependency 'bacon', '~> 1.1'
......
...@@ -25,26 +25,17 @@ module Pod ...@@ -25,26 +25,17 @@ module Pod
end end
autoload :Command, 'cocoapods/command' autoload :Command, 'cocoapods/command'
autoload :Config, 'cocoapods/config'
autoload :Dependency, 'cocoapods/dependency'
autoload :Downloader, 'cocoapods/downloader' autoload :Downloader, 'cocoapods/downloader'
autoload :Executable, 'cocoapods/executable' autoload :Executable, 'cocoapods/executable'
autoload :ExternalSources, 'cocoapods/external_sources'
autoload :Installer, 'cocoapods/installer' autoload :Installer, 'cocoapods/installer'
autoload :LocalPod, 'cocoapods/local_pod' autoload :LocalPod, 'cocoapods/local_pod'
autoload :Lockfile, 'cocoapods/lockfile'
autoload :Platform, 'cocoapods/platform'
autoload :Podfile, 'cocoapods/podfile'
autoload :Project, 'cocoapods/project' autoload :Project, 'cocoapods/project'
autoload :Resolver, 'cocoapods/resolver' autoload :Resolver, 'cocoapods/resolver'
autoload :Sandbox, 'cocoapods/sandbox' autoload :Sandbox, 'cocoapods/sandbox'
autoload :Source, 'cocoapods/source'
autoload :Spec, 'cocoapods/specification'
autoload :Specification, 'cocoapods/specification'
autoload :UI, 'cocoapods/user_interface' autoload :UI, 'cocoapods/user_interface'
autoload :Version, 'cocoapods/version_class'
autoload :Pathname, 'pathname' autoload :Pathname, 'pathname'
autoload :FileList, 'cocoapods/file_list'
module Generator module Generator
autoload :BridgeSupport, 'cocoapods/generator/bridge_support' autoload :BridgeSupport, 'cocoapods/generator/bridge_support'
...@@ -54,9 +45,17 @@ module Pod ...@@ -54,9 +45,17 @@ module Pod
autoload :Plist, 'cocoapods/generator/acknowledgements/plist' autoload :Plist, 'cocoapods/generator/acknowledgements/plist'
autoload :Markdown, 'cocoapods/generator/acknowledgements/markdown' autoload :Markdown, 'cocoapods/generator/acknowledgements/markdown'
autoload :DummySource, 'cocoapods/generator/dummy_source' autoload :DummySource, 'cocoapods/generator/dummy_source'
autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
autoload :XCConfig, 'cocoapods/generator/xcconfig'
end end
require 'cocoapods/file_list'
require 'cocoapods-core'
require 'cocoapods/config'
require 'cocoapods/source'
end end
if ENV['COCOA_PODS_ENV'] == 'development' if ENV['COCOA_PODS_ENV'] == 'development'
require 'awesome_print' require 'awesome_print'
require 'pry'
end end
...@@ -7,8 +7,8 @@ module Pod ...@@ -7,8 +7,8 @@ module Pod
end end
class Command < CLAide::Command class Command < CLAide::Command
autoload :ErrorReport, 'cocoapods/command/error_report' autoload :ErrorReport, 'cocoapods/command/error_report'
autoload :Linter, 'cocoapods/command/linter' autoload :AdvancedLinter, 'cocoapods/command/advanced_linter'
self.abstract_command = true self.abstract_command = true
self.command = 'pod' self.command = 'pod'
......
module Pod
class Command
# Extends the Linter from the Core to add additional which require the
# LocalPod and the Installer.
#
# In detail it checks that the file patterns defined by the user match
# actually do match at least a file and that the Pod builds, by installing
# it without integration and building the project with xcodebuild.
#
class AdvancedLinter
include Config::Mixin
# @param [Specification, Pathname, String] spec_or_path
# the Specification or the path of the `podspec` file to lint.
#
def initialize(spec_or_path)
@simple_linter = Specification::Linter.new(spec_or_path)
end
# @return [Specification] the specification to lint.
#
def spec
@simple_linter.spec
end
# @return [Pathname] the path of the `podspec` file where {#spec} is
# defined.
#
def file
@simple_linter.file
end
# @return [Specification::Linter] the linter instance from CocoaPods
# Core.
#
attr_reader :simple_linter
# Lints the specification adding a {Result} for any failed check to the
# {#results} list.
#
# @return [Bool] whether the specification passed validation.
#
def lint
# Show immediately which pod is being processed.
print " -> #{spec.name}\r" unless config.silent?
$stdout.flush
simple_linter.lint
unless quick
check_repo_path
spec.available_platforms.each do |platform|
UI.section "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed do
# current_platform = platform
# set_up_lint_environment
# install_pod
# build_pod
# check_file_patterns
# tear_down_lint_environment
end
end
end
# This overwrites the previously printed text
UI.puts " -> ".send(color) << spec.name unless config.silent?
print_messages('ERROR', simple_linter.errors)
print_messages('WARN', simple_linter.warnings)
print_messages('NOTE', simple_linter.notes)
UI.puts unless config.silent?
errors.empty? && warnings.empty? && deprecations.empty?
end
#-----------------------------------------------------------------------#
# @!group Configuration
# @return [Bool] whether the lint should skip the checks that requires
# the download or the build of the library.
#
attr_accessor :quick
# @return [Bool] whether the linter should not clean up temporary files
# for inspection.
#
attr_accessor :no_clean
# @return [Pathname] whether the lint should be performed
#
attr_accessor :repo_path
# @return [Bool] whether the lint should be performed against the root of
# the podspec instead to its original source. Uses the `:local` option
# of the Podfile.
#
attr_writer :local
def local?; @local; end
#-----------------------------------------------------------------------#
# !@group Lint results
public
# @return [Array<Result>] all the notes generated by the Linter.
#
def notes
@errors ||= results.select { |r| r.type == :note }
end
# TODO
def result_type
:note
end
#-----------------------------------------------------------------------#
private
# !@group Lint steps
def check_repo_path
return unless repo_path
expected_path = "#{spec.name}/#{spec.version}/#{spec.name}.podspec"
path = file.relative_path_from(repo_path).to_s
unless path.end_with?(expected_path)
error "Incorrect path, the path is `#{file}` and should be `#{expected_path}`"
end
end
def set_up_lint_environment
tmp_dir.rmtree if tmp_dir.exist?
tmp_dir.mkpath
@original_config = Config.instance.clone
config.project_root = tmp_dir
config.project_pods_root = tmp_dir + 'Pods'
config.silent = !config.verbose
config.integrate_targets = false
config.generate_docs = false
end
def tear_down_lint_environment
tmp_dir.rmtree unless no_clean
Config.instance = @original_config
end
# It creates a podfile in memory and builds a library containing
# the pod for all available platforms with xcodebuild.
#
def install_pod
spec.activate_platform(current_platform)
podfile = podfile_from_spec
config.verbose
config.skip_repo_update = true
sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(podfile, nil, sandbox)
installer = Installer.new(resolver)
installer.install!
@pod = installer.pods.find { |pod| pod.top_specification == spec }
config.silent
end
# Performs platform specific analysis.
# It requires to download the source at each iteration
#
# @note Treat xcodebuild warnings as notes because the spec maintainer
# might not be the author of the library
#
def build_pod
if `which xcodebuild`.strip.empty?
UI.warn "Skipping compilation with `xcodebuild' because it can't be found.\n".yellow
else
UI.message "\nBuilding with xcodebuild.\n".yellow if config.verbose? do
messages = []
output = Dir.chdir(config.project_pods_root) { `xcodebuild clean build 2>&1` }
clean_output = parse_xcodebuild_output(output)
messages += clean_output
puts(output) if config.verbose?
messages.each { |msg| ( msg.include?('error: ') ? @platform_errors[@platform] : @platform_notes[@platform] ) << msg }
end
end
end
# It checks that every file pattern specified in a spec yields
# at least one file. It requires the pods to be already present
# in the current working directory under Pods/spec.name.
#
# @return [Array<String>]
#
def check_file_patterns
error "The sources did not match any file" if !spec.source_files.empty? && @pod.source_files.empty?
error "The resources did not match any file" if !spec.resources.empty? && @pod.resource_files.empty?
error "The preserve_paths did not match any file" if !spec.preserve_paths.empty? && @pod.preserve_files.empty?
error "The exclude_header_search_paths did not match any file" if !spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty?
unless @pod.license_file || spec.license && ( spec.license[:type] == 'Public Domain' || spec.license[:text] )
warning "Unable to find a license file"
end
end
# @errors += (@platform_errors[platform] - @errors).map {|m| "[#{platform}] #{m}"}
#-----------------------------------------------------------------------#
private
# !@group Helpers
# @return [Podfile] a podfile that requires the specification on the
# current platform.
#
# @note The generated podfile takes into account whether the linter is
# in local mode.
#
def podfile_from_spec
name = spec.name
podspec = file.realpath
platform = current_platform
local = local?
podfile = Pod::Podfile.new do
platform(platform.to_sym, platform.deployment_target)
if (local)
pod name, :local => podspec.dirname.to_s
else
pod name, :podspec => podspec.to_s
end
end
podfile
end
# @return [Pathname] the temporary directory used by the linter.
#
def tmp_dir
Pathname.new('/tmp/CocoaPods/Lint')
end
# @return [Pathname] the root of the installed pod.
#
def pod_dir
tmp_dir + 'Pods' + spec.name
end
# Parse the xcode build output to identify the lines which are relevant
# to the linter. It also removes the indentation and the temporary path.
#
# @param [String] output the output generated by the xcodebuild tool.
#
# @return [Array<String>] the lines that are relevant to the linter.
#
def parse_xcodebuild_output(output)
lines = output.split("\n")
selected_lines = lines.select do |l|
l.include?('error: ') &&
(l !~ /errors? generated\./) && (l !~ /error: \(null\)/) ||
l.include?('warning: ') && (l !~ /warnings? generated\./) ||
l.include?('note: ') && (l !~ /expanded from macro/)
end
selected_lines.map do |l|
new = l.gsub(/\/tmp\/CocoaPods\/Lint\/Pods\//,'') # Remove the unnecessary tmp path
new.gsub!(/^ */,' ') # Remove indentation
"XCODEBUILD > " << new # Mark
end
end
#
#
def print_messages(type, messages)
return if config.silent?
messages.each {|msg| UI.puts " - #{type.ljust(5)} | #{msg}"}
end
end
end
end
This diff is collapsed.
...@@ -40,13 +40,14 @@ module Pod ...@@ -40,13 +40,14 @@ module Pod
self.summary = 'Lists pods introduced in the master spec-repo since the last check' self.summary = 'Lists pods introduced in the master spec-repo since the last check'
def run def run
puts "running"
update_if_necessary! update_if_necessary!
days = [1,2,3,5,8] days = [1,2,3,5,8]
dates, groups = {}, {} dates, groups = {}, {}
days.each {|d| dates[d] = Time.now - 60 * 60 * 24 * d} days.each {|d| dates[d] = Time.now - 60 * 60 * 24 * d}
sets = Source.all_sets sets = Source.all_sets
creation_dates = Pod::Specification::Statistics.instance.creation_dates(sets) creation_dates = Specification::Set::Statistics.instance.creation_dates(sets)
sets.each do |set| sets.each do |set|
set_date = creation_dates[set.name] set_date = creation_dates[set.name]
......
...@@ -19,10 +19,10 @@ module Pod ...@@ -19,10 +19,10 @@ module Pod
end end
def run_install_with_update(update) def run_install_with_update(update)
sandbox = Sandbox.new(config.project_pods_root) sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(config.podfile, config.lockfile, sandbox) installer = Installer.new(sandbox, config.podfile, config.lockfile)
resolver.update_mode = update installer.update_mode = update
Installer.new(resolver).install! installer.install!
end end
end end
......
...@@ -87,7 +87,7 @@ module Pod ...@@ -87,7 +87,7 @@ module Pod
lint_argv = ["lint"] lint_argv = ["lint"]
lint_argv << "--only-errors" if @allow_warnings lint_argv << "--only-errors" if @allow_warnings
lint_argv << "--silent" if config.silent lint_argv << "--silent" if config.silent
all_valid = true # all_valid = true
podspec_files.each do |podspec| podspec_files.each do |podspec|
Spec.parse(lint_argv + [podspec.to_s]).run Spec.parse(lint_argv + [podspec.to_s]).run
end end
......
...@@ -107,7 +107,7 @@ module Pod ...@@ -107,7 +107,7 @@ module Pod
invalid_count = 0 invalid_count = 0
podspecs.each do |podspec| podspecs.each do |podspec|
linter = Linter.new(podspec) linter = AdvancedLinter.new(podspec)
linter.quick = true linter.quick = true
linter.repo_path = dir linter.repo_path = dir
...@@ -178,6 +178,8 @@ module Pod ...@@ -178,6 +178,8 @@ module Pod
is_compatilbe(versions) is_compatilbe(versions)
end end
#--------------------------------------#
private private
def versions(dir) def versions(dir)
......
...@@ -32,7 +32,13 @@ module Pod ...@@ -32,7 +32,13 @@ module Pod
def run def run
sets = Source.search_by_name(@query.strip, @full_text_search) sets = Source.search_by_name(@query.strip, @full_text_search)
sets.each { |set| UI.pod(set, (@stats ? :stats : :normal)) } sets.each do |set|
begin
UI.pod(set, (@stats ? :stats : :normal))
rescue DSLError => e
UI.warn "Skipping `#{set.name}` because the podspec contains errors."
end
end
end end
end end
end end
......
...@@ -84,16 +84,11 @@ module Pod ...@@ -84,16 +84,11 @@ module Pod
UI.puts UI.puts
invalid_count = 0 invalid_count = 0
podspecs_to_lint.each do |podspec| podspecs_to_lint.each do |podspec|
linter = Linter.new(podspec) linter = AdvancedLinter.new(podspec)
linter.quick = @quick linter.quick = @quick
linter.local = @local linter.local = @local
linter.no_clean = @no_clean linter.no_clean = @no_clean
# Show immediatly which pod is being processed.
print " -> #{linter.spec_name}\r" unless config.silent?
$stdout.flush
linter.lint
case linter.result_type case linter.result_type
when :error when :error
invalid_count += 1 invalid_count += 1
...@@ -104,14 +99,6 @@ module Pod ...@@ -104,14 +99,6 @@ module Pod
else else
color = :green color = :green
end end
# This overwrites the previously printed text
UI.puts " -> ".send(color) << linter.spec_name unless config.silent?
print_messages('ERROR', linter.errors)
print_messages('WARN', linter.warnings)
print_messages('NOTE', linter.notes)
UI.puts unless config.silent?
end end
count = podspecs_to_lint.count count = podspecs_to_lint.count
...@@ -179,11 +166,6 @@ module Pod ...@@ -179,11 +166,6 @@ module Pod
# TODO some of the following methods can probably move to one of the subclasses. # TODO some of the following methods can probably move to one of the subclasses.
private private
def print_messages(type, messages)
return if config.silent?
messages.each {|msg| UI.puts " - #{type.ljust(5)} | #{msg}"}
end
def podspecs_to_lint def podspecs_to_lint
@podspecs_to_lint ||= begin @podspecs_to_lint ||= begin
files = [] files = []
...@@ -284,7 +266,7 @@ Pod::Spec.new do |s| ...@@ -284,7 +266,7 @@ Pod::Spec.new do |s|
# s.description = <<-DESC # s.description = <<-DESC
# An optional longer description of #{data[:name]} # An optional longer description of #{data[:name]}
# #
# * Markdonw format. # * Markdown format.
# * Don't worry about the indent, we strip it! # * Don't worry about the indent, we strip it!
# DESC # DESC
s.homepage = "#{data[:homepage]}" s.homepage = "#{data[:homepage]}"
...@@ -318,7 +300,7 @@ Pod::Spec.new do |s| ...@@ -318,7 +300,7 @@ Pod::Spec.new do |s|
# #
# s.author = '#{data[:author_name]}', 'other author' # s.author = '#{data[:author_name]}', 'other author'
# Specify the location from where the source should be retreived. # Specify the location from where the source should be retrieved.
# #
s.source = { :git => "#{data[:source_url]}", #{data[:ref_type]} => "#{data[:ref]}" } s.source = { :git => "#{data[:source_url]}", #{data[:ref_type]} => "#{data[:ref]}" }
# s.source = { :svn => 'http://EXAMPLE/#{data[:name]}/tags/1.0.0' } # s.source = { :svn => 'http://EXAMPLE/#{data[:name]}/tags/1.0.0' }
...@@ -352,9 +334,9 @@ Pod::Spec.new do |s| ...@@ -352,9 +334,9 @@ Pod::Spec.new do |s|
# made available to the application. If the pattern is a directory then the # made available to the application. If the pattern is a directory then the
# path will automatically have '*.h' appended. # path will automatically have '*.h' appended.
# #
# Also allows the use of the FileList class like `source_files does. # Also allows the use of the FileList class like `source_files' does.
# #
# If you do not explicitely set the list of public header files, # If you do not explicitly set the list of public header files,
# all headers of source_files will be made public. # all headers of source_files will be made public.
# #
# s.public_header_files = 'Classes/**/*.h' # s.public_header_files = 'Classes/**/*.h'
...@@ -362,7 +344,7 @@ Pod::Spec.new do |s| ...@@ -362,7 +344,7 @@ Pod::Spec.new do |s|
# A list of resources included with the Pod. These are copied into the # A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. # target bundle with a build phase script.
# #
# Also allows the use of the FileList class like `source_files does. # Also allows the use of the FileList class like `source_files' does.
# #
# s.resource = "icon.png" # s.resource = "icon.png"
# s.resources = "Resources/*.png" # s.resources = "Resources/*.png"
...@@ -370,7 +352,7 @@ Pod::Spec.new do |s| ...@@ -370,7 +352,7 @@ Pod::Spec.new do |s|
# A list of paths to preserve after installing the Pod. # A list of paths to preserve after installing the Pod.
# CocoaPods cleans by default any file that is not used. # CocoaPods cleans by default any file that is not used.
# Please don't include documentation, example, and test files. # Please don't include documentation, example, and test files.
# Also allows the use of the FileList class like `source_files does. # Also allows the use of the FileList class like `source_files' does.
# #
# s.preserve_paths = "FilesToSave", "MoreFilesToSave" # s.preserve_paths = "FilesToSave", "MoreFilesToSave"
......
...@@ -74,6 +74,12 @@ module Pod ...@@ -74,6 +74,12 @@ module Pod
end end
end end
# @return [Sandbox]
#
def sandbox
@sandbox ||= Sandbox.new(project_pods_root)
end
module Mixin module Mixin
def config def config
Config.instance Config.instance
......
require 'cocoapods/open_uri'
module Pod
class Dependency < Gem::Dependency
attr_reader :head
alias :head? :head
attr_accessor :specification, :external_source
def initialize(*name_and_version_requirements, &block)
if name_and_version_requirements.empty? && block
@inline_podspec = true
@specification = Specification.new(&block)
super(@specification.name, @specification.version)
elsif !name_and_version_requirements.empty? && block.nil?
version = name_and_version_requirements.last
if name_and_version_requirements.last.is_a?(Hash)
@external_source = ExternalSources.from_params(name_and_version_requirements[0].split('/').first, name_and_version_requirements.pop)
elsif version.is_a?(Symbol) && version == :head || version.is_a?(Version) && version.head?
name_and_version_requirements.pop
@head = true
end
super(*name_and_version_requirements)
if head? && !latest_version?
raise Informative, "A `:head' dependency may not specify version requirements."
end
else
raise Informative, "A dependency needs either a name and version requirements, " \
"a source hash, or a block which defines a podspec."
end
end
def latest_version?
versions = @version_requirements.requirements.map(&:last)
versions == [Gem::Version.new('0')]
end
def ==(other)
super && (head? == other.head?) && (@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
# In case this is a dependency for a subspec, e.g. 'RestKit/Networking',
# this returns 'RestKit', which is what the Pod::Source needs to know to
# retrieve the correct Set from disk.
def top_level_spec_name
subspec_dependency? ? @name.split('/').first : @name
end
# Returns a copy of the dependency, but with the name of the top level
# spec. This is used by Pod::Specification::Set to merge dependencies on
# the complete set, irrespective of what spec in the set wil be used.
def to_top_level_spec_dependency
dep = dup
dep.name = top_level_spec_name
dep
end
def to_s
version = ''
if external?
version << @external_source.description
elsif inline?
version << 'defined in Podfile'
elsif head?
version << 'HEAD'
elsif @version_requirements != Gem::Requirement.default
version << @version_requirements.to_s
end
result = @name.dup
result << " (#{version})" unless version.empty?
result
end
def specification_from_sandbox(sandbox, platform)
@external_source.specification_from_sandbox(sandbox, platform)
end
def match_version?(version)
match?(name, version) && (version.head? == head?)
end
# Taken from RubyGems 1.3.7
unless public_method_defined?(:match?)
def match?(spec_name, spec_version)
pattern = name
if Regexp === pattern
return false unless pattern =~ spec_name
else
return false unless pattern == spec_name
end
return true if requirement.to_s == ">= 0"
requirement.satisfied_by? Gem::Version.new(spec_version)
end
end
# Taken from a newer version of RubyGems
unless public_method_defined?(:merge)
def merge other
unless name == other.name then
raise ArgumentError,
"#{self} and #{other} have different names"
end
default = Gem::Requirement.default
self_req = self.requirement
other_req = other.requirement
return self.class.new name, self_req if other_req == default
return self.class.new name, other_req if self_req == default
self.class.new name, self_req.as_list.concat(other_req.as_list)
end
end
module ExternalSources
def self.from_params(name, params)
return unless name && params
if params.key?(:git)
GitSource.new(name, params)
elsif params.key?(:podspec)
PodspecSource.new(name, params)
elsif params.key?(:local)
LocalSource.new(name, params)
else
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)
specification_from_local(sandbox, platform) || specification_from_external(sandbox, platform)
end
def specification_from_local(sandbox, platform)
if local_pod = sandbox.installed_pod_named(name, platform)
local_pod.top_specification
end
end
def specification_from_external(sandbox, platform)
podspec = copy_external_source_into_sandbox(sandbox, platform)
spec = specification_from_local(sandbox, platform)
raise Informative, "No podspec found for `#{name}' in #{description}" unless spec
spec
end
# Can store from a pathname or a string
#
def store_podspec(sandbox, podspec)
output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
output_path.dirname.mkpath
if podspec.is_a?(String)
raise Informative, "No podspec found for `#{name}' in #{description}" unless podspec.include?('Spec.new')
output_path.open('w') { |f| f.puts(podspec) }
else
raise Informative, "No podspec found for `#{name}' in #{description}" unless podspec.exist?
FileUtils.copy(podspec, output_path)
end
end
def ==(other)
return if other.nil?
name == other.name && params == other.params
end
end
class GitSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox, platform)
UI.info("->".green + " Pre-downloading: '#{name}'") do
target = sandbox.root + name
target.rmtree if target.exist?
downloader = Downloader.for_target(sandbox.root + name, @params)
downloader.download
store_podspec(sandbox, target + "#{name}.podspec")
if local_pod = sandbox.installed_pod_named(name, platform)
local_pod.downloaded = true
end
end
end
def description
"from `#{@params[:git]}'".tap do |description|
description << ", commit `#{@params[:commit]}'" if @params[:commit]
description << ", branch `#{@params[:branch]}'" if @params[:branch]
description << ", tag `#{@params[:tag]}'" if @params[:tag]
end
end
end
# can be http, file, etc
class PodspecSource < AbstractExternalSource
def copy_external_source_into_sandbox(sandbox, _)
UI.info("->".green + " Fetching podspec for `#{name}' from: #{@params[:podspec]}") do
path = @params[:podspec]
path = Pathname.new(path).expand_path if path.start_with?("~")
open(path) { |io| store_podspec(sandbox, io.read) }
end
end
def description
"from `#{@params[:podspec]}'"
end
end
class LocalSource < AbstractExternalSource
def pod_spec_path
path = Pathname.new(@params[:local]).expand_path
path += "#{name}.podspec"# unless path.to_s.include?("#{name}.podspec")
raise Informative, "No podspec found for `#{name}' in `#{@params[:local]}'" unless path.exist?
path
end
def copy_external_source_into_sandbox(sandbox, _)
store_podspec(sandbox, pod_spec_path)
end
def specification_from_local(sandbox, platform)
specification_from_external(sandbox, platform)
end
def specification_from_external(sandbox, platform)
copy_external_source_into_sandbox(sandbox, platform)
spec = Specification.from_file(pod_spec_path)
spec.source = @params
spec
end
def description
"from `#{@params[:local]}'"
end
end
end
end
end
module Pod
# Provides support for initializing the correct concrete class of an external
# source.
#
module ExternalSources
# @return [AbstractExternalSource] an initialized instance of the concrete
# external source class associated with the option specified in the
# hash.
#
def self.from_dependency(dependency)
name = dependency.root_name
params = dependency.external_source
klass = if params.key?(:git) then GitSource
elsif params.key?(:podspec) then PodspecSource
elsif params.key?(:local) then LocalSource
end
if klass
klass.new(name, params)
else
msg = "Unknown external source parameters for `#{name}`: `#{params}`"
raise Informative, msg
end
end
#-------------------------------------------------------------------------#
# Abstract class that defines the common behaviour of external sources.
#
class AbstractExternalSource
# @return [String] the name of the Pod described by this external source.
#
attr_reader :name
# @return [Hash{Symbol => String}] the hash representation of the
# external source.
#
attr_reader :params
# @param [String] name @see name
# @param [Hash] params @see params
#
def initialize(name, params)
@name, @params = name, params
end
# @return [Bool] whether an external source source is equal to another
# according to the {#name} and to the {#params}.
#
def ==(other)
return false if other.nil?
name == other.name && params == other.params
end
#--------------------------------------#
# @!group Specifications
public
# @return [Specification] returns the specification, either from the
# sandbox or by fetching the remote source, associated with the
# external source.
#
def specification(sandbox)
specification_from_local(sandbox) || specification_from_external(sandbox)
end
# @return [Specification] returns the specification associated with the
# external source if available in the sandbox.
#
def specification_from_local(sandbox)
sandbox.specification(name)
end
# @return [Specification] returns the specification associated with the
# external source after fetching it from the remote source, even
# if is already present in the sandbox.
#
# @raise If not specification could be found.
#
def specification_from_external(sandbox)
copy_external_source_into_sandbox(sandbox)
spec = specification_from_local(sandbox)
unless spec
raise Informative, "No podspec found for `#{name}' in #{description}"
end
spec
end
#--------------------------------------#
# @!group Subclasses hooks
# Fetches the external source from the remote according to the params.
#
# @param [Sandbox] sandbox
# the sandbox where the specification should be stored.
#
# @return [void]
#
def copy_external_source_into_sandbox(sandbox)
raise "Abstract method"
end
# @return [String] a string representation of the source suitable for UI.
#
def description
raise "Abstract method"
end
private
# Stores a specification in the `Local Podspecs` folder.
#
# @param [Sandbox] sandbox
# the sandbox where the podspec should be stored.
#
# @param [String, Pathname] podspec
# The contents of the specification (String) or the path to a
# podspec file (Pathname).
#
# @todo This could be done by the sandbox.
# @todo Store all the specifications (including those not originating
# from external sources) so users can check them.
# @todo The check for the podspec string is a bit primitive.
#
def store_podspec(sandbox, podspec)
output_path = sandbox.root + "Local Podspecs/#{name}.podspec"
output_path.dirname.mkpath
if podspec.is_a?(String)
unless podspec.include?('Spec.new')
raise Informative, "The `#{name}.podspec` from `#{description}` appears to be invalid."
end
output_path.open('w') { |f| f.puts(podspec) }
else
unless podspec.exist?
raise Informative, "No podspec found for `#{name}` in #{description}"
end
FileUtils.copy(podspec, output_path)
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a Git remote.
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class GitSource < AbstractExternalSource
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
# @note To prevent a double download of the repository the pod is marked
# as pre-downloaded indicating to the installer that only clean
# operations are needed.
#
def copy_external_source_into_sandbox(sandbox)
UI.info("->".green + " Pre-downloading: '#{name}'") do
target = sandbox.root + name
target.rmtree if target.exist?
downloader = Downloader.for_target(sandbox.root + name, @params)
downloader.download
store_podspec(sandbox, target + "#{name}.podspec")
sandbox.predownloaded_pods << name
end
end
# @see AbstractExternalSource#description
#
def description
"from `#{@params[:git]}'".tap do |description|
description << ", commit `#{@params[:commit]}`" if @params[:commit]
description << ", branch `#{@params[:branch]}`" if @params[:branch]
description << ", tag `#{@params[:tag]}`" if @params[:tag]
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from an URL. Can be
# http, file, etc.
#
class PodspecSource < AbstractExternalSource
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
def copy_external_source_into_sandbox(sandbox)
UI.info("->".green + " Fetching podspec for `#{name}' from: #{@params[:podspec]}") do
path = @params[:podspec]
path = Pathname.new(path).expand_path if path.to_s.start_with?("~")
open(path) { |io| store_podspec(sandbox, io.read) }
end
end
# @see AbstractExternalSource#description
#
def description
"from `#{@params[:podspec]}`"
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a path local to
# the machine running the installation.
#
# Works with the {LocalPod::LocalSourcedPod} class.
#
class LocalSource < AbstractExternalSource
# @see AbstractExternalSource#copy_external_source_into_sandbox
#
def copy_external_source_into_sandbox(sandbox)
store_podspec(sandbox, pod_spec_path)
end
# @see AbstractExternalSource#description
#
def description
"from `#{@params[:local]}`"
end
# @see AbstractExternalSource#specification_from_local
#
# @note The LocalSource class always fetches podspecs from the external
# source to provide always the freshest specification. Otherwise,
# once installed, the podspec would be updated only by `pod
# update`.
#
def specification_from_local(sandbox)
specification_from_external(sandbox)
end
# @see AbstractExternalSource#specification_from_local
#
# @note The LocalSource overrides the source of the specification to
# point to the local path.
#
def specification_from_external(sandbox)
copy_external_source_into_sandbox(sandbox)
spec = Specification.from_file(pod_spec_path)
spec.source = @params
spec
end
#--------------------------------------#
# @!group Helpers
private
# @return [Pathname] the path of the podspec.
#
def pod_spec_path
path = Pathname.new(@params[:local]).expand_path
path += "#{name}.podspec"# unless path.to_s.include?("#{name}.podspec")
unless path.exist?
raise Informative, "No podspec found for `#{name}` in `#{@params[:local]}`"
end
path
end
end
end
end
...@@ -15,6 +15,10 @@ install_resource() ...@@ -15,6 +15,10 @@ install_resource()
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}" 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}" 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}"
;; ;;
*.framework)
echo "rsync -rp ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -rp "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*) *)
echo "cp -R ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" echo "cp -R ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" cp -R "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
...@@ -26,7 +30,7 @@ EOS ...@@ -26,7 +30,7 @@ EOS
attr_reader :resources attr_reader :resources
# A list of files relative to the project pods root. # A list of files relative to the project pods root.
def initialize(resources) def initialize(resources = [])
@resources = resources @resources = resources
end end
......
module Pod
module Generator
# Generates a prefix header file for a Pods library. The prefix header is
# generated according to the platform of the target and the pods.
#
# According to the platform the prefix header imports `UIKit/UIKit.h` or
# `Cocoa/Cocoa.h`.
#
class PrefixHeader
# @return [Platform] the platform for which the prefix header will be
# generated.
#
attr_reader :platform
# @return [Array<LocalPod>] the LocalPod for the target for which the
# prefix header needs to be generated.
#
attr_reader :pods
# @param [Platform] platform @see platform
#
# @param [Array<LocalPod>] @see pods
#
def initialize(platform, pods)
@platform = platform
@pods = pods
end
#--------------------------------------#
# Generates the contents of the prefix header according to the platform
# and the pods.
#
# @note If the platform is iOS an import call to `UIKit/UIKit.h` is
# added to the top of the prefix header. For OS X `Cocoa/Cocoa.h`
# is imported.
#
# @return [String]
#
# @todo Subspecs can specify prefix header information too.
#
def generate
result = "#ifdef __OBJC__\n"
result << "#import #{platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}\n"
result << "#endif\n"
pods.each do |pod|
result << "\n"
if prefix_header_contents = pod.top_specification.prefix_header_contents
result << prefix_header_contents
result << "\n"
elsif prefix_header = pod.prefix_header_file
result << prefix_header.read
end
end
result
end
# Generates and saves the prefix header to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
path.open('w') { |header| header.write(generate) }
end
end
end
end
module Pod
module Generator
# Generates an xcconfig file for each target of the Pods project. The
# configuration file should be used by the user target as well.
#
class XCConfig
# @return [Sandbox] the sandbox where the Pods project is installed.
#
attr_reader :sandbox
# @return [Array<LocalPod>] the list of LocalPods for the library.
#
attr_reader :pods
# @return [String] the relative path of the Pods root respect the user
# project that should be integrated by this library.
#
attr_reader :relative_pods_root
# @param [Platform] platform @see platform
#
# @param [Array<LocalPod>] @see pods
#
def initialize(sandbox, pods, relative_pods_root)
@sandbox = sandbox
@pods = pods
@relative_pods_root = relative_pods_root
end
# @return [Bool] whether the Podfile specifies to add the `-fobjc-arc`
# flag for compatibility.
#
attr_accessor :set_arc_compatibility_flag
#-----------------------------------------------------------------------#
# Generates the xcconfig for the library.
#
# @return [Xcodeproj::Config]
#
# @note The value `PODS_HEADERS_SEARCH_PATHS` is used to store the headers
# so xcconfig can reference the variable.
#
# @todo Add Xcodeproj::Config#[]
#
def generate
ld_flags = '-ObjC'
if set_arc_compatibility_flag && pods.any? { |pod| pod.requires_arc? }
ld_flags << ' -fobjc-arc'
end
@xcconfig = Xcodeproj::Config.new({
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags,
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
'PODS_ROOT' => relative_pods_root,
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_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.each { |pod| @xcconfig.merge!(pod.xcconfig) }
@xcconfig
end
# @return [Xcodeproj::Config] The generated xcconfig.
#
attr_reader :xcconfig
# @return [Hash] The settings of the xcconfig that the Pods project
# needs to override.
#
def self.pods_project_settings
{ 'PODS_ROOT' => '${SRCROOT}',
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_BUILD_HEADERS_SEARCH_PATHS}' }
end
# Generates and saves the xcconfig to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
path.open('w') { |file| file.write(generate) }
end
#-----------------------------------------------------------------------#
# @!group Private helpers.
private
# @return [String] the default linker flags. `-ObjC` is always included
# while `-fobjc-arc` is included only if requested in the
# Podfile.
#
def default_ld_flags
flags = %w[ -ObjC ]
requires_arc = pods.any? { |pod| pod.requires_arc? }
if requires_arc && set_arc_compatibility_flag
flags << '-fobjc-arc'
end
flags.join(" ")
end
# Converts an array of strings to a single string where the each string
# is surrounded by double quotes and separated by a space. Used to
# represent strings in a xcconfig file.
#
# @param [Array<String>] strings
# a list of strings.
#
# @return [String] the resulting string.
#
def quote(strings)
strings.map { |s| %W|"#{s}"| }.join(" ")
end
end
end
end
This diff is collapsed.
This diff is collapsed.
...@@ -60,7 +60,7 @@ module Pod ...@@ -60,7 +60,7 @@ module Pod
# computed values. In other words, it should be immutable. # computed values. In other words, it should be immutable.
# #
def initialize(specification, sandbox, platform) def initialize(specification, sandbox, platform)
@top_specification, @sandbox, @platform = specification.top_level_parent, sandbox, platform @top_specification, @sandbox, @platform = specification.root, sandbox, platform
@top_specification.activate_platform(platform) @top_specification.activate_platform(platform)
@specifications = [] << specification @specifications = [] << specification
end end
...@@ -81,7 +81,7 @@ module Pod ...@@ -81,7 +81,7 @@ module Pod
# @raise {Informative} If the specification is not part of the same pod. # @raise {Informative} If the specification is not part of the same pod.
# #
def add_specification(spec) def add_specification(spec)
unless spec.top_level_parent == top_specification unless spec.root == top_specification
raise Informative, raise Informative,
"[Local Pod] Attempt to add a specification from another pod" "[Local Pod] Attempt to add a specification from another pod"
end end
...@@ -105,7 +105,7 @@ module Pod ...@@ -105,7 +105,7 @@ module Pod
# #
def to_s def to_s
s = top_specification.to_s s = top_specification.to_s
s << " defaulting to #{top_specification.preferred_dependency} subspec" if top_specification.preferred_dependency s << " defaulting to #{top_specification.default_subspec} subspec" if top_specification.default_subspec
s s
end end
...@@ -300,7 +300,20 @@ module Pod ...@@ -300,7 +300,20 @@ module Pod
# @return [Array<Pathname>] The paths of the resources. # @return [Array<Pathname>] The paths of the resources.
# #
def resource_files def resource_files
paths_by_spec(:resources).values.flatten specs ||= specifications
paths_by_spec = {}
processed_paths = []
specs = specs.sort_by { |s| s.name.length }
specs.each do |spec|
spec_paths = spec.resources[:resources]
paths = expanded_paths(spec_paths, '**/*', spec.exclude_files)
unless paths.empty?
paths_by_spec[spec] = paths - processed_paths
processed_paths += paths
end
end
paths_by_spec.values.flatten
end end
# @return [Array<Pathname>] The *relative* paths of the resources. # @return [Array<Pathname>] The *relative* paths of the resources.
...@@ -361,7 +374,14 @@ module Pod ...@@ -361,7 +374,14 @@ module Pod
end end
def xcconfig def xcconfig
specifications.map { |s| s.xcconfig }.reduce(:merge) config = Xcodeproj::Config.new
specifications.each do |s|
config.merge(s.xcconfig)
config.libraries.merge(s.libraries)
config.frameworks.merge(s.frameworks)
config.weak_frameworks.merge(s.weak_frameworks)
end
config
end end
# Computes the paths of all the public headers of the pod including every # Computes the paths of all the public headers of the pod including every
...@@ -440,7 +460,7 @@ module Pod ...@@ -440,7 +460,7 @@ module Pod
"project before adding the build files to the target." "project before adding the build files to the target."
end end
file_references_by_spec.each do |spec, file_reference| file_references_by_spec.each do |spec, file_reference|
target.add_file_references(file_reference, spec.compiler_flags.strip) target.add_file_references(file_reference, (spec.compiler_flags * " ").strip)
end end
end end
...@@ -498,7 +518,7 @@ module Pod ...@@ -498,7 +518,7 @@ module Pod
dir = spec.header_dir ? (headers_sandbox + spec.header_dir) : headers_sandbox dir = spec.header_dir ? (headers_sandbox + spec.header_dir) : headers_sandbox
paths.each do |from| paths.each do |from|
from_relative = from.relative_path_from(root) from_relative = from.relative_path_from(root)
to = dir + spec.copy_header_mapping(from_relative) to = dir + (spec.header_mappings_dir ? from.relative_path_from(spec.header_mappings_dir) : from.basename)
(mappings[to.dirname] ||= []) << from (mappings[to.dirname] ||= []) << from
end end
end end
...@@ -516,8 +536,10 @@ module Pod ...@@ -516,8 +536,10 @@ module Pod
# included in the linker search paths. # included in the linker search paths.
# #
def headers_excluded_from_search_paths def headers_excluded_from_search_paths
paths = paths_by_spec(:exclude_header_search_paths, '*.{h,hpp,hh}') #TODO
paths.values.compact.uniq # paths = paths_by_spec(:exclude_header_search_paths, '*.{h,hpp,hh}')
# paths.values.compact.uniq
[]
end end
# @!group Paths Patterns # @!group Paths Patterns
...@@ -536,7 +558,7 @@ module Pod ...@@ -536,7 +558,7 @@ module Pod
specs = specs.sort_by { |s| s.name.length } specs = specs.sort_by { |s| s.name.length }
specs.each do |spec| specs.each do |spec|
paths = expanded_paths(spec.send(accessor), dir_pattern, spec.exclude_patterns) paths = expanded_paths(spec.send(accessor), dir_pattern, spec.exclude_files)
unless paths.empty? unless paths.empty?
paths_by_spec[spec] = paths - processed_paths paths_by_spec[spec] = paths - processed_paths
processed_paths += paths processed_paths += paths
......
module Pod module Pod
class LocalPod class LocalPod
# The {PathList} class is designed to perform multiple glob matches against # The PathList class is designed to perform multiple glob matches against
# a given directory. Basically, it generates a list of all the children # a given directory. Basically, it generates a list of all the children
# paths and matches the globs patterns against them, resulting in just # paths and matches the globs patterns against them, resulting in just one
# one access to the file system. # access to the file system.
# #
# @note A {PathList} once it has generated the list of the paths this is # @note A PathList once it has generated the list of the paths this is
# updated only if explicitly requested by calling # updated only if explicitly requested by calling
# {PathList#read_file_system} # {#read_file_system}
# #
class PathList class PathList
# @return [Pathname] The root of the list whose files and directories # @return [Pathname] The root of the list whose files and directories
# are used to perform the matching operations. # are used to perform the matching operations.
# #
attr_accessor :root attr_accessor :root
# @param [Pathname] root The root of the PathList. # @param [Pathname] root The root of the PathList.
# #
def initialize(root) def initialize(root)
@root = root @root = root
end end
# @return [Array<String>] The list of absolute the path of all the files # @return [Array<String>] The list of absolute the path of all the files
# contained in {root}. # contained in {root}.
# #
def files def files
read_file_system unless @files read_file_system unless @files
...@@ -32,7 +32,7 @@ module Pod ...@@ -32,7 +32,7 @@ module Pod
end end
# @return [Array<String>] The list of absolute the path of all the # @return [Array<String>] The list of absolute the path of all the
# directories contained in {root}. # directories contained in {root}.
# #
def dirs def dirs
read_file_system unless @dirs read_file_system unless @dirs
...@@ -40,7 +40,7 @@ module Pod ...@@ -40,7 +40,7 @@ module Pod
end end
# @return [void] Reads the file system and populates the files and paths # @return [void] Reads the file system and populates the files and paths
# lists. # lists.
# #
def read_file_system def read_file_system
root_length = root.to_s.length+1 root_length = root.to_s.length+1
...@@ -53,22 +53,22 @@ module Pod ...@@ -53,22 +53,22 @@ module Pod
end end
# @return [Array<Pathname>] Similar to {glob} but returns the absolute # @return [Array<Pathname>] Similar to {glob} but returns the absolute
# paths. # paths.
# #
def glob(patterns, dir_pattern = nil, exclude_patterns = nil) def glob(patterns, dir_pattern = nil, exclude_patterns = nil)
relative_glob(patterns, dir_pattern, exclude_patterns).map {|p| root + p } relative_glob(patterns, dir_pattern, exclude_patterns).map {|p| root + p }
end end
# @return [Array<Pathname>] The list of relative paths that are case # @return [Array<Pathname>] The list of relative paths that are case
# insensitively matched by a given pattern. This method emulates # insensitively matched by a given pattern. This method emulates
# {Dir#glob} with the {File::FNM_CASEFOLD} option. # {Dir#glob} with the {File::FNM_CASEFOLD} option.
# #
# @param [String,Array<String>] patterns A signle {Dir#glob} like # @param [String,Array<String>] patterns
# pattern, or a list of patterns. # A signle {Dir#glob} like pattern, or a list of patterns.
# #
# @param [String] dir_pattern An optional pattern to append to a # @param [String] dir_pattern
# pattern, if it is the path to a # An optional pattern to append to a pattern, if it is the path
# directory. # to a directory.
# #
def relative_glob(patterns, dir_pattern = nil, exclude_patterns = nil) def relative_glob(patterns, dir_pattern = nil, exclude_patterns = nil)
return [] if patterns.empty? return [] if patterns.empty?
...@@ -94,9 +94,10 @@ module Pod ...@@ -94,9 +94,10 @@ module Pod
end end
# @return [Bool] Wether a path is a directory. The result of this method # @return [Bool] Wether a path is a directory. The result of this method
# computed without accessing the file system and is case insensitive. # computed without accessing the file system and is case
# insensitive.
# #
# @param [String, Pathname] sub_path The path that could be a directory. # @param [String, Pathname] sub_path The path that could be a directory.
# #
def directory?(sub_path) def directory?(sub_path)
sub_path = sub_path.to_s.downcase.sub(/\/$/, '') sub_path = sub_path.to_s.downcase.sub(/\/$/, '')
...@@ -104,8 +105,9 @@ module Pod ...@@ -104,8 +105,9 @@ module Pod
end end
# @return [Array<String>] An array of patterns converted from a # @return [Array<String>] An array of patterns converted from a
# {Dir.glob} pattern to patterns that {File.fnmatch} can handle. This # {Dir.glob} pattern to patterns that {File.fnmatch} can handle.
# is used by the {#relative_glob} method to emulate {Dir.glob}. # This is used by the {#relative_glob} method to emulate
# {Dir.glob}.
# #
# The expansion provides support for: # The expansion provides support for:
# #
......
require 'digest'
module Pod
class Lockfile
# @return [Lockfile] Returns the Lockfile saved in path.
# Returns {nil} If the file can't be loaded.
#
def self.from_file(path)
return nil unless path.exist?
begin
hash = YAML.load(File.open(path))
rescue Exception => e
raise Informative, "Podfile.lock syntax error: #{e.inspect}"
end
lockfile = Lockfile.new(hash)
lockfile.defined_in_file = path
lockfile
end
# @return [Lockfile] Generates a lockfile from a {Podfile} and the
# list of {Specifications} that were installed.
#
def self.generate(podfile, specs)
Lockfile.new(generate_hash_from_podfile(podfile, specs))
end
# @return [String] The file where this Lockfile is defined.
#
attr_accessor :defined_in_file
# @return [String] The hash used to initialize the Lockfile.
#
attr_reader :to_hash
# @param [Hash] hash A Hash representation of a Lockfile.
#
def initialize(hash)
@to_hash = hash
end
# @return [Array<String, Hash{String => Array[String]}>] The pods installed
# and their dependencies.
#
def pods
@pods ||= to_hash['PODS'] || []
end
# @return [Array<Dependency>] The Podfile dependencies used during the last
# install.
#
def dependencies
@dependencies ||= to_hash['DEPENDENCIES'].map { |dep| dependency_from_string(dep) } || []
end
# @return [Hash{String => Hash}] A hash where the name of the pods are
# the keys and the values are the parameters of an {AbstractExternalSource}
# of the dependency that required the pod.
#
def external_sources
@external_sources ||= to_hash["EXTERNAL SOURCES"] || {}
end
# @return [Array<String>] The names of the installed Pods.
#
def pods_names
@pods_names ||= pods.map do |pod|
pod = pod.keys.first unless pod.is_a?(String)
name_and_version_for_pod(pod)[0]
end
end
# @return [Hash{String => Version}] A Hash containing the name
# of the installed Pods as the keys and their corresponding {Version}
# as the values.
#
def pods_versions
unless @pods_versions
@pods_versions = {}
pods.each do |pod|
pod = pod.keys.first unless pod.is_a?(String)
name, version = name_and_version_for_pod(pod)
@pods_versions[name] = version
end
end
@pods_versions
end
# @return [Dependency] A dependency that describes the exact installed version
# of a Pod.
#
def dependency_for_installed_pod_named(name)
version = pods_versions[name]
raise Informative, "Attempt to lock a Pod without an known version." unless version
dependency = Dependency.new(name, version)
if external_source = external_sources[name]
dependency.external_source = Dependency::ExternalSources.from_params(dependency.name, external_source)
end
dependency
end
# @param [String] The string that describes a {Specification} generated
# from {Specification#to_s}.
#
# @example Strings examples
# "libPusher"
# "libPusher (1.0)"
# "libPusher (HEAD based on 1.0)"
# "RestKit/JSON"
#
# @return [String, Version] The name and the version of a
# pod.
#
def name_and_version_for_pod(string)
match_data = string.match(/(\S*) \((.*)\)/)
name = match_data[1]
vers = Version.from_string(match_data[2])
[name, vers]
end
# @param [String] The string that describes a {Dependency} generated
# from {Dependency#to_s}.
#
# @example Strings examples
# "libPusher"
# "libPusher (= 1.0)"
# "libPusher (~> 1.0.1)"
# "libPusher (> 1.0, < 2.0)"
# "libPusher (HEAD)"
# "libPusher (from `www.example.com')"
# "libPusher (defined in Podfile)"
# "RestKit/JSON"
#
# @return [Dependency] The dependency described by the string.
#
def dependency_from_string(string)
match_data = string.match(/(\S*)( (.*))?/)
name = match_data[1]
version = match_data[2]
version = version.gsub(/[()]/,'') if version
case version
when nil
Dependency.new(name)
when /defined in Podfile/
# @TODO: store the whole spec?, the version?
Dependency.new(name)
when /from `(.*)'/
external_source_info = external_sources[name]
Dependency.new(name, external_source_info)
when /HEAD/
# @TODO: find a way to serialize from the Downloader the information
# necessary to restore a head version.
Dependency.new(name, :head)
else
Dependency.new(name, version)
end
end
# Analyzes the {Lockfile} and detects any changes applied to the {Podfile}
# since the last installation.
#
# For each Pod, it detects one state among the following:
#
# - added: Pods that weren't present in the Podfile.
# - changed: Pods that were present in the Podfile but changed:
# - Pods whose version is not compatible anymore with Podfile,
# - Pods that changed their head or external options.
# - removed: Pods that were removed form the Podfile.
# - unchanged: Pods that are still compatible with Podfile.
#
# @TODO: detect changes for inline dependencies?
#
# @return [Hash{Symbol=>Array[Strings]}] A hash where pods are grouped
# by the state in which they are.
#
def detect_changes_with_podfile(podfile)
previous_podfile_deps = dependencies.map(&:name)
user_installed_pods = pods_names.reject { |name| !previous_podfile_deps.include?(name) }
deps_to_install = podfile.dependencies.dup
result = {}
result[:added] = []
result[:changed] = []
result[:removed] = []
result[:unchanged] = []
user_installed_pods.each do |pod_name|
dependency = deps_to_install.find { |d| d.name == pod_name }
deps_to_install.delete(dependency)
version = pods_versions[pod_name]
external_source = Dependency::ExternalSources.from_params(pod_name, external_sources[pod_name])
if dependency.nil?
result[:removed] << pod_name
elsif !dependency.match_version?(version) || dependency.external_source != external_source
result[:changed] << pod_name
else
result[:unchanged] << pod_name
end
end
deps_to_install.each do |dependency|
result[:added] << dependency.name
end
result
end
# @return [void] Writes the Lockfile to {#path}.
#
def write_to_disk(path)
path.dirname.mkpath unless path.dirname.exist?
File.open(path, 'w') {|f| f.write(to_yaml) }
defined_in_file = path
end
# @return [String] A string useful to represent the Lockfile in a message
# presented to the user.
#
def to_s
"Podfile.lock"
end
# @return [String] The YAML representation of the Lockfile, used for
# serialization.
#
def to_yaml
to_hash.to_yaml.gsub(/^--- ?\n/,"").gsub(/^([A-Z])/,"\n\\1")
end
# @return [Hash] The Hash representation of the Lockfile generated from
# a given Podfile and the list of resolved Specifications.
#
def self.generate_hash_from_podfile(podfile, specs)
hash = {}
# Get list of [name, dependencies] pairs.
pod_and_deps = specs.map do |spec|
[spec.to_s, spec.dependencies.map(&:to_s).sort]
end.uniq
# Merge dependencies of iOS and OS X version of the same pod.
tmp = {}
pod_and_deps.each do |name, deps|
if tmp[name]
tmp[name].concat(deps).uniq!
else
tmp[name] = deps
end
end
pod_and_deps = tmp.sort_by(&:first).map do |name, deps|
deps.empty? ? name : { name => deps }
end
hash["PODS"] = pod_and_deps
hash["DEPENDENCIES"] = podfile.dependencies.map{ |d| d.to_s }.sort
external_sources = {}
deps = podfile.dependencies.select(&:external?).sort{ |d, other| d.name <=> other.name}
deps.each{ |d| external_sources[d.name] = d.external_source.params }
hash["EXTERNAL SOURCES"] = external_sources unless external_sources.empty?
checksums = {}
specs.select { |spec| !spec.defined_in_file.nil? }.each do |spec|
checksum = Digest::SHA1.hexdigest(File.read(spec.defined_in_file))
checksum = checksum.encode('UTF-8') if checksum.respond_to?(:encode)
checksums[spec.name] = checksum
end
hash["SPEC CHECKSUMS"] = checksums unless checksums.empty?
hash["COCOAPODS"] = VERSION
hash
end
end
end
module Pod
# A platform describes an SDK name and deployment target.
#
class Platform
# @return [Platform] Convenience method to initialize an iOS platform.
#
def self.ios
new :ios
end
# @return [Platform] Convenience method to initialize an OS X platform.
#
def self.osx
new :osx
end
# Constructs a platform from either another platform or by
# specifying the symbolic name and optionally the deployment target.
#
# @overload initialize(name, deployment_target)
# @param [Symbol] name The name of platform.
# @param [String, Version] deployment_target The optional deployment.
# If not provided a default value according to the platform name will
# be assigned.
#
# @note that if the name is not specified a default deployment
# target will not be assigned.
#
# @example
#
# Platform.new(:ios)
# Platform.new(:ios, '4.3')
#
# @overload initialize(platform)
# @param [Platform] platform Another {Platform}.
#
# @example
#
# platform = Platform.new(:ios)
# Platform.new(platform)
#
def initialize(input, target = nil)
if input.is_a? Platform
@symbolic_name = input.name
@deployment_target = input.deployment_target
else
@symbolic_name = input
target = target[:deployment_target] if target.is_a?(Hash)
@deployment_target = Version.create(target)
end
end
# @return [Symbol] The name of the SDK represented by the platform.
#
def name
@symbolic_name
end
# @return [Version] The deployment target of the platform.
#
attr_reader :deployment_target
# @param [Platform, Symbol] other The other platform to check.
#
# @note If a symbol is passed the comparison does not take into account
# the deployment target.
#
# @return [Boolean] Whether two platforms are the equivalent.
#
def ==(other)
if other.is_a?(Symbol)
@symbolic_name == other
else
(name == other.name) && (deployment_target == other.deployment_target)
end
end
# In the context of operating system SDKs, a platform supports another
# one if they have the same name and the other platform has a minor or
# equal deployment target.
#
# @return Whether the platform supports another platform.
#
def supports?(other)
other = Platform.new(other)
if other.deployment_target && deployment_target
(other.name == name) && (other.deployment_target <= deployment_target)
else
other.name == name
end
end
# @return [String] A string representation including the deployment target.
#
def to_s
case @symbolic_name
when :ios
s = 'iOS'
when :osx
s = 'OS X'
end
s << " #{deployment_target}" if deployment_target
s
end
# @return [Symbol] A Symbol representation of the name.
#
def to_sym
name
end
# @return Whether the platform requires legacy architectures for iOS.
#
def requires_legacy_ios_archs?
(name == :ios) && deployment_target && (deployment_target < Version.new("4.3"))
end
end
end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
require 'fileutils' require 'fileutils'
module Pod module Pod
# The sandbox provides support for the directory that CocoaPods uses for an
# installation. In this directory the Pods projects, the support files and
# the sources of the Pods are stored.
#
# CocoaPods assumes to have control of the sandbox.
#
class Sandbox class Sandbox
# The path of the build headers directory relative to the root.
#
BUILD_HEADERS_DIR = "BuildHeaders"
# The path of the public headers directory relative to the root.
#
PUBLIC_HEADERS_DIR = "Headers"
# @return [Pathname] the root of the sandbox.
#
attr_reader :root attr_reader :root
# @return [HeadersDirectory] the header directory for the Pods libraries.
#
attr_reader :build_headers attr_reader :build_headers
attr_reader :public_headers
BUILD_HEADERS_DIR = "BuildHeaders" # @return [HeadersDirectory] the header directory for the user targets.
PUBLIC_HEADERS_DIR = "Headers" #
attr_reader :public_headers
def initialize(path) # @param [String, Pathname] root @see root
@root = Pathname.new(path) #
@build_headers = HeadersDirectory.new(self, BUILD_HEADERS_DIR) # @todo the headers should be stored in a `Headers` folder.
#
def initialize(root)
@root = Pathname.new(root)
@build_headers = HeadersDirectory.new(self, BUILD_HEADERS_DIR)
@public_headers = HeadersDirectory.new(self, PUBLIC_HEADERS_DIR) @public_headers = HeadersDirectory.new(self, PUBLIC_HEADERS_DIR)
@cached_local_pods = {} @cached_local_pods = {}
@cached_locally_sourced_pods = {} @cached_locally_sourced_pods = {}
@predownloaded_pods = []
FileUtils.mkdir_p(@root) FileUtils.mkdir_p(@root)
end end
def implode # @return [Pathname] the path of the Pod project.
root.rmtree #
end
def project_path def project_path
root + "Pods.xcodeproj" root + "Pods.xcodeproj"
end end
# @return [String] a string representation suitable for debugging.
#
def inspect
"#<#{self.class}> with root #{root}"
end
#--------------------------------------#
# @!group Life cycle
public
# Cleans the sandbox for a new installation.
#
# @return [void]
#
def prepare_for_install def prepare_for_install
build_headers.prepare_for_install build_headers.prepare_for_install
public_headers.prepare_for_install public_headers.prepare_for_install
end end
def local_pod_for_spec(spec, platform) # Removes the sandbox.
key = [spec.top_level_parent.name, platform.to_sym] #
(@cached_local_pods[key] ||= LocalPod.new(spec.top_level_parent, self, platform)).tap do |pod| # @return [void]
pod.add_specification(spec) #
end def implode
root.rmtree
end end
# TODO: refactor the pods from a local source should not be chached by the sandbox #--------------------------------------#
# @!group Local Pod support
public
# @todo refactor the pods from a local source should not be cached by the
# sandbox
#
# @return [LocalPod]
# #
def locally_sourced_pod_for_spec(spec, platform) def locally_sourced_pod_for_spec(spec, platform)
key = [spec.top_level_parent.name, platform.to_sym] key = [spec.root.name, platform.to_sym]
(@cached_locally_sourced_pods[key] ||= LocalPod::LocalSourcedPod.new(spec.top_level_parent, self, platform)).tap do |pod| local_pod = @cached_locally_sourced_pods[key] ||= LocalPod::LocalSourcedPod.new(spec.root, self, platform)
local_pod.add_specification(spec)
local_pod
end
def local_pod_for_spec(spec, platform)
key = [spec.root.name, platform.to_sym]
(@cached_local_pods[key] ||= LocalPod.new(spec.root, self, platform)).tap do |pod|
pod.add_specification(spec) pod.add_specification(spec)
end end
end end
# @return [LocalPod]
#
def installed_pod_named(name, platform) def installed_pod_named(name, platform)
if spec_path = podspec_for_name(name) if spec_path = podspec_for_name(name)
key = [name, platform.to_sym] key = [name, platform.to_sym]
...@@ -54,23 +113,97 @@ module Pod ...@@ -54,23 +113,97 @@ module Pod
end end
end end
# Returns the path of the specification for the Pod with the
# given name.
#
# @param [String] name
# the name of the Pod for which the podspec file is requested.
#
# @return [Pathname] the path or nil.
#
def podspec_for_name(name) def podspec_for_name(name)
path = root + "Local Podspecs/#{name}.podspec" path = root + "Local Podspecs/#{name}.podspec"
path.exist? ? path : nil path.exist? ? path : nil
end end
# Returns the specification for the Pod with the given name.
#
# @param [String] name
# the name of the Pod for which the specification is requested.
#
# @return [Specification] the specification if the file is found.
#
def specification(name)
if file = podspec_for_name(name)
Specification.from_file(file)
end
end
# @return [Array<String>] the names of the pods that have been
# pre-downloaded from an external source.
#
# @todo the installer needs to be aware of it.
#
attr_reader :predownloaded_pods
#--------------------------------------#
# @!group Private methods
private
attr_accessor :cached_local_pods
attr_accessor :cached_locally_sourced_pods
end end
#---------------------------------------------------------------------------#
# Provides support for managing a header directory. It also keeps track of
# the header search paths.
#
class HeadersDirectory class HeadersDirectory
def initialize(sandbox, base_dir)
@sandbox = sandbox
@base_dir = base_dir
@search_paths = [base_dir]
end
# @return [Pathname] the absolute path of this header directory.
#
def root def root
@sandbox.root + @base_dir @sandbox.root + @relative_path
end end
# @param [Sandbox] sandbox
# the sandbox that contains this header dir.
#
# @param [String] relative_path
# the relative path to the sandbox root and hence to the Pods
# project.
#
def initialize(sandbox, relative_path)
@sandbox = sandbox
@relative_path = relative_path
@search_paths = [relative_path]
end
#--------------------------------------#
# @!group Life cycle
public
# Removes the directory as it is regenerated from scratch during each
# installation.
#
def prepare_for_install
root.rmtree if root.exist?
end
#--------------------------------------#
# @!group Adding headers
public
#
#
def add_file(namespace_path, relative_header_path) def add_file(namespace_path, relative_header_path)
namespaced_header_path = root + namespace_path namespaced_header_path = root + namespace_path
namespaced_header_path.mkpath unless File.exist?(namespaced_header_path) namespaced_header_path.mkpath unless File.exist?(namespaced_header_path)
...@@ -80,26 +213,27 @@ module Pod ...@@ -80,26 +213,27 @@ module Pod
namespaced_header_path + relative_header_path.basename namespaced_header_path + relative_header_path.basename
end end
#
#
def add_files(namespace_path, relative_header_paths) def add_files(namespace_path, relative_header_paths)
relative_header_paths.map { |path| add_file(namespace_path, path) } relative_header_paths.map { |path| add_file(namespace_path, path) }
end end
#
#
def search_paths def search_paths
@search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" } @search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end end
# Adds an header search path to the sandbox. # Adds an header search path to the sandbox.
# #
# @param path [Pathname] The path tho add. # @param [Pathname] path
# the path tho add.
# #
# @return [void] # @return [void]
# #
def add_search_path(path) def add_search_path(path)
@search_paths << Pathname.new(@base_dir) + path @search_paths << Pathname.new(@relative_path) + path
end
def prepare_for_install
root.rmtree if root.exist?
end end
end end
end end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
require 'yaml'
# This is to make sure Faraday doesn't warn the user about the `system_timer` gem missing.
old_warn, $-w = $-w, nil
begin
require 'faraday'
ensure
$-w = old_warn
end
require 'octokit'
module Pod
class Specification
class Statistics
def self.instance
@instance ||= new
end
def self.instance=(instance)
@instance = instance
end
attr_accessor :cache_file, :cache_expiration
def initialize
@cache_file = Config.instance.repos_dir + 'statistics.yml'
@cache_expiration = 60 * 60 * 24 * 3
end
def creation_date(set)
compute_creation_date(set)
end
def creation_dates(sets)
dates = {}
sets.each { |set| dates[set.name] = compute_creation_date(set, false) }
save_cache
dates
end
def github_watchers(set)
github_stats_if_needed(set)
get_value(set, :gh_watchers)
end
def github_forks(set)
github_stats_if_needed(set)
get_value(set, :gh_forks)
end
def github_pushed_at(set)
github_stats_if_needed(set)
get_value(set, :pushed_at)
end
private
def cache
@cache ||= cache_file && cache_file.exist? ? YAML::load(cache_file.read) : {}
end
def get_value(set, key)
if cache[set.name] && cache[set.name][key]
cache[set.name][key]
end
end
def set_value(set, key, value)
cache[set.name] ||= {}
cache[set.name][key] = value
end
def save_cache
File.open(cache_file, 'w') { |f| f.write(YAML::dump(cache)) } if cache_file
end
def compute_creation_date(set, save = true)
date = get_value(set, :creation_date)
unless date
Dir.chdir(set.sources.first.repo) do
date = Time.at(`git log --first-parent --format=%ct #{set.name}`.split("\n").last.to_i)
end
set_value(set, :creation_date, date)
end
save_cache if save
date
end
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
url = spec.source[:git] || ''
repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1]
return unless repo_id
begin
repo = Octokit.repo(repo_id)
rescue
return
end
cache[set.name] ||= {}
set_value(set, :gh_watchers, repo['watchers'])
set_value(set, :gh_forks, repo['forks'])
set_value(set, :pushed_at, repo['pushed_at'])
set_value(set, :gh_date, Time.now)
save_cache
end
end
end
end
This diff is collapsed.
This diff is collapsed.
module Pod module Pod
VERSION = '0.16.0.rc2' VERSION = '0.17.0.alpha'
end end
This diff is collapsed.
doc @ e3d65416
Subproject commit e3d65416e8678c4621c0fa22d90355c805f0b6a2
This diff is collapsed.
//
// Prefix header for all source files of the 'Sample Lib' target in the 'Sample Lib' project
//
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
This diff is collapsed.
This diff is collapsed.
Subproject commit ddda7566d193fe0e5fa1c419f5b5239ef964f263 Subproject commit 84ea24c2f3a5d463da1e7945c60fd3f33f73dee2
...@@ -8,7 +8,6 @@ Pod::Spec.new do |s| ...@@ -8,7 +8,6 @@ Pod::Spec.new do |s|
s.source = { :git => 'http://banana-corp.local/banana-lib.git', :tag => 'v1.0' } s.source = { :git => 'http://banana-corp.local/banana-lib.git', :tag => 'v1.0' }
s.source_files = 'Classes/*.{h,m}', 'Vendor' s.source_files = 'Classes/*.{h,m}', 'Vendor'
s.xcconfig = { 'OTHER_LDFLAGS' => '-framework SystemConfiguration' } s.xcconfig = { 'OTHER_LDFLAGS' => '-framework SystemConfiguration' }
s.clean_paths = "sub-dir"
s.prefix_header_file = 'Classes/BananaLib.pch' s.prefix_header_file = 'Classes/BananaLib.pch'
s.resources = "Resources/*.png" s.resources = "Resources/*.png"
s.dependency 'monkey', '~> 1.0.1', '< 1.0.9' s.dependency 'monkey', '~> 1.0.1', '< 1.0.9'
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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