Commit 6ca21338 authored by Fabio Pelosin's avatar Fabio Pelosin

Merge branch 'xcodeproj-refactor' into installer_clean_up

* xcodeproj-refactor: (48 commits)
  Changelog
  [Specs] Fix issue that lead to generation of files in the fixtures folder.
  Completed support for Xcodeproj refactor.
  [Gemfile] Use Xcodeproj refactor branch.
  Release 0.15.2
  [Bundle] Update.
  [Gemspec] Require Xcodeproj 0.3.5.
  Remove stray puts.
  Update the lockfiles of the examples.
  [Gemfile] Install and remove dependency on letters gem.
  [LocalPod] Always use Pathname::glob.
  [Gemspec] Use spermy indicator for xcodeproj.
  [Specs] Complete revert of 8e72cbe1
  Fixed a bug with the flags passed into `Dir.glob`
  Fixing a bug where `downcase` was being called on the list of used file paths
  Updated `clean_paths` and `expand_paths` methods to use `File::FNM_CASEFOLD`
  [Xcodeproj] Initial adaptation for refactor.
  [Linter/Push] Properly singularize words in output.
  [Bundler] Update.
  [UI] Support for running CocoaPods without a terminal.
  ...

Conflicts:
	lib/cocoapods/installer.rb
	spec/unit/installer_spec.rb
parents dec60494 ccdc81e6
## Master ## Master
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.14.0...master) [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.2...master)[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.3.5...master)
- Xcodeproj partial rewrite.
[#576](https://github.com/CocoaPods/CocoaPods/pull/576)
- Performance improvements in the `Generating supporting files` phase.
- Better support for editing existing projects and sorting groups.
## 0.15.2
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.1...0.15.2)
###### Enhancements
- Added support for `.hh` headers.
[#576](https://github.com/CocoaPods/CocoaPods/pull/576)
###### Bug fixes
- Restored support for running CocoaPods without a terminal.
[#575](https://github.com/CocoaPods/CocoaPods/issues/575)
[#577](https://github.com/CocoaPods/CocoaPods/issues/577)
- The git cache now always uses a barebones repo preventing a number of related issues.
[#581](https://github.com/CocoaPods/CocoaPods/issues/581)
[#569](https://github.com/CocoaPods/CocoaPods/issues/569)
- Improved fix for the issue that lead to empty directories for Pods.
[#572](https://github.com/CocoaPods/CocoaPods/issues/572)
[#602](https://github.com/CocoaPods/CocoaPods/issues/602)
- Xcodeproj robustness against invalid values, such as malformed UTF8.
[#592](https://github.com/CocoaPods/CocoaPods/issues/592)
## 0.15.1
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.15.0...0.15.1)
###### Enhancements ###### Enhancements
- Show error if syntax error in Podfile or Podfile.lock.
###### Bug fixes
- Fixed an issue that lead to empty directories for Pods.
[#519](https://github.com/CocoaPods/CocoaPods/issues/519)
[#568](https://github.com/CocoaPods/CocoaPods/issues/568)
- Fixed a crash related to the RubyGems version informative.
[#570](https://github.com/CocoaPods/CocoaPods/issues/570)
- Fixed a crash for `pod outdated`.
[#567](https://github.com/CocoaPods/CocoaPods/issues/567)
- Fixed an issue that lead to excessively slow sets computation.
## 0.15.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.14.0...0.15.0)[Xcodeproj](https://github.com/CocoaPods/Xcodeproj/compare/0.3.3...0.3.4)
###### Enhancements
- Pod `install` will update the specs repo only if needed. - Pod `install` will update the specs repo only if needed.
[#533](https://github.com/CocoaPods/CocoaPods/issues/533) [#533](https://github.com/CocoaPods/CocoaPods/issues/533)
- CocoaPods now searches for the highest version of a Pod on - CocoaPods now searches for the highest version of a Pod on all the repos.
all the repos.
[#85](https://github.com/CocoaPods/CocoaPods/issues/85) [#85](https://github.com/CocoaPods/CocoaPods/issues/85)
- Added a pre install hook to the Podfile and to root specifications. - Added a pre install hook to the Podfile and to root specifications.
[#486](https://github.com/CocoaPods/CocoaPods/issues/486) [#486](https://github.com/CocoaPods/CocoaPods/issues/486)
- Support for `header_mappings_dir` attribute in subspecs. - Support for `header_mappings_dir` attribute in subspecs.
- Added support for linting a Podspec using the files from its folder `pod spec
lint --local`
- Refactored UI. - Refactored UI.
- Added support for Podfiles named `Podfile.cocoapods` which allows to - Added support for Podfiles named `CocoaPods.podfile` which allows to
associate an editor application in Mac OS X. associate an editor application in Mac OS X.
[#528](https://github.com/CocoaPods/CocoaPods/issues/528) [#528](https://github.com/CocoaPods/CocoaPods/issues/528)
- Added config option to disable the new version available message. - Added config option to disable the new version available message.
...@@ -24,6 +77,7 @@ ...@@ -24,6 +77,7 @@
###### Bug fixes ###### Bug fixes
- Subspecs namespacing has been restored. - Subspecs namespacing has been restored.
[#541](https://github.com/CocoaPods/CocoaPods/issues/541) [#541](https://github.com/CocoaPods/CocoaPods/issues/541)
- Improvements to the git cache that should be more robust. - Improvements to the git cache that should be more robust.
...@@ -33,6 +87,8 @@ ...@@ -33,6 +87,8 @@
[#514](https://github.com/CocoaPods/CocoaPods/issues/514) [#514](https://github.com/CocoaPods/CocoaPods/issues/514)
- Forcing UTF-8 encoding on licenses generation in Ruby 1.9. - Forcing UTF-8 encoding on licenses generation in Ruby 1.9.
[#530](https://github.com/CocoaPods/CocoaPods/issues/530) [#530](https://github.com/CocoaPods/CocoaPods/issues/530)
- Added support for `.hpp` headers.
[#244](https://github.com/CocoaPods/CocoaPods/issues/244)
## 0.14.0 ## 0.14.0
...@@ -77,32 +133,26 @@ ...@@ -77,32 +133,26 @@
[#191](https://github.com/CocoaPods/CocoaPods/issues/191) [#191](https://github.com/CocoaPods/CocoaPods/issues/191)
- the external source changes. - the external source changes.
- the head status changes (from disabled to enabled or vice-versa). - the head status changes (from disabled to enabled or vice-versa).
- Introduce `pod update` command that installs the dependencies of the Podfile - Introduce `pod update` command that installs the dependencies of the Podfile
**ignoring** the lockfile `Podfile.lock`. **ignoring** the lockfile `Podfile.lock`.
[#131](https://github.com/CocoaPods/CocoaPods/issues/131) [#131](https://github.com/CocoaPods/CocoaPods/issues/131)
- Introduce `pod outdated` command that shows the pods with known updates. - Introduce `pod outdated` command that shows the pods with known updates.
- Add `:local` option for dependencies which will use the source files directly - Add `:local` option for dependencies which will use the source files directly
from a local directory. This is usually used for libraries that are being from a local directory. This is usually used for libraries that are being
developed in parallel to the end product (application/library). developed in parallel to the end product (application/library).
[#458](https://github.com/CocoaPods/CocoaPods/issues/458), [#458](https://github.com/CocoaPods/CocoaPods/issues/458),
[#415](https://github.com/CocoaPods/CocoaPods/issues/415), [#415](https://github.com/CocoaPods/CocoaPods/issues/415),
[#156](https://github.com/CocoaPods/CocoaPods/issues/156). [#156](https://github.com/CocoaPods/CocoaPods/issues/156).
- Folders of Pods which are no longer required are removed during installation. - Folders of Pods which are no longer required are removed during installation.
[#298](https://github.com/CocoaPods/CocoaPods/issues/298) [#298](https://github.com/CocoaPods/CocoaPods/issues/298)
- Add meaningful error messages
- Add meaningful error messages for when: - ia podspec can’t be found in the root of an external source.
- a podspec can’t be found in the root of an external source.
[#385](https://github.com/CocoaPods/CocoaPods/issues/385), [#385](https://github.com/CocoaPods/CocoaPods/issues/385),
[#338](https://github.com/CocoaPods/CocoaPods/issues/338), [#338](https://github.com/CocoaPods/CocoaPods/issues/338),
[#337](https://github.com/CocoaPods/CocoaPods/issues/337). [#337](https://github.com/CocoaPods/CocoaPods/issues/337).
- a subspec name is misspelled. - a subspec name is misspelled.
[#327](https://github.com/CocoaPods/CocoaPods/issues/327) [#327](https://github.com/CocoaPods/CocoaPods/issues/327)
- an unrecognized command and/or argument is provided. - an unrecognized command and/or argument is provided.
- The subversion downloader now does an export instead of a checkout, which - The subversion downloader now does an export instead of a checkout, which
makes it play nicer with SCMs that store metadata in each directory. makes it play nicer with SCMs that store metadata in each directory.
[#245](https://github.com/CocoaPods/CocoaPods/issues/245) [#245](https://github.com/CocoaPods/CocoaPods/issues/245)
......
...@@ -3,20 +3,25 @@ source "http://rubygems.org" ...@@ -3,20 +3,25 @@ source "http://rubygems.org"
gemspec gemspec
group :development do group :development do
gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git" gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git", :branch => "refactor"
gem "mocha", "~> 0.11.4" gem "mocha", "~> 0.11.4"
gem "bacon" gem "bacon"
gem "kicker", :git => "https://github.com/alloy/kicker.git", :branch => "3.0.0"
gem "mocha-on-bacon" gem "mocha-on-bacon"
gem "rake" gem "rake"
gem "rb-fsevent"
gem "vcr" gem "vcr"
gem "webmock" gem "webmock"
end
group :debugging do
gem "rb-fsevent"
gem "kicker", :git => "https://github.com/alloy/kicker.git", :branch => "3.0.0"
gem "awesome_print" gem "awesome_print"
gem "pry" gem "pry"
end
group :documentation do
gem 'yard' gem 'yard'
gem 'redcarpet' gem 'redcarpet'
gem 'github-markup' gem 'github-markup'
end end
GIT GIT
remote: git://github.com/CocoaPods/Xcodeproj.git remote: git://github.com/CocoaPods/Xcodeproj.git
revision: e3c513a66dee94b681588326bf1ce8ca4a30aef3 revision: 280a500ed5ee5a5f6bb4e3c5edcfef0240fa427b
branch: refactor
specs: specs:
xcodeproj (0.3.3) xcodeproj (0.3.5)
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
GIT GIT
...@@ -17,7 +18,7 @@ GIT ...@@ -17,7 +18,7 @@ GIT
PATH PATH
remote: . remote: .
specs: specs:
cocoapods (0.14.0) cocoapods (0.15.2)
activesupport (~> 3.2.6) activesupport (~> 3.2.6)
colored (~> 1.2) colored (~> 1.2)
escape (~> 0.0.4) escape (~> 0.0.4)
...@@ -26,7 +27,7 @@ PATH ...@@ -26,7 +27,7 @@ PATH
octokit (~> 1.7) octokit (~> 1.7)
open4 (~> 1.3.0) open4 (~> 1.3.0)
rake (~> 0.9.0) rake (~> 0.9.0)
xcodeproj (>= 0.3.3) xcodeproj (~> 0.3.5)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
...@@ -35,9 +36,9 @@ GEM ...@@ -35,9 +36,9 @@ GEM
i18n (~> 0.6) i18n (~> 0.6)
multi_json (~> 1.0) multi_json (~> 1.0)
addressable (2.3.2) addressable (2.3.2)
awesome_print (1.0.2) awesome_print (1.1.0)
bacon (1.1.0) bacon (1.1.0)
coderay (1.0.7) coderay (1.0.8)
colored (1.2) colored (1.2)
crack (0.3.1) crack (0.3.1)
escape (0.0.4) escape (0.0.4)
...@@ -49,16 +50,16 @@ GEM ...@@ -49,16 +50,16 @@ 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.0) listen (0.5.3)
metaclass (0.0.1) metaclass (0.0.1)
method_source (0.8) 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.3.6)
multipart-post (1.1.5) multipart-post (1.1.5)
octokit (1.13.0) octokit (1.18.0)
addressable (~> 2.2) addressable (~> 2.2)
faraday (~> 0.8) faraday (~> 0.8)
faraday_middleware (~> 0.8) faraday_middleware (~> 0.8)
...@@ -70,15 +71,15 @@ GEM ...@@ -70,15 +71,15 @@ GEM
method_source (~> 0.8) method_source (~> 0.8)
slop (~> 3.3.1) slop (~> 3.3.1)
rake (0.9.2.2) rake (0.9.2.2)
rb-fsevent (0.9.1) rb-fsevent (0.9.2)
redcarpet (2.1.1) redcarpet (2.2.2)
slop (3.3.3) slop (3.3.3)
terminal-notifier (1.4.2) terminal-notifier (1.4.2)
vcr (2.2.5) vcr (2.2.5)
webmock (1.8.10) webmock (1.8.11)
addressable (>= 2.2.7) addressable (>= 2.2.7)
crack (>= 0.1.7) crack (>= 0.1.7)
yard (0.8.2.1) yard (0.8.3)
PLATFORMS PLATFORMS
ruby ruby
......
Copyright (c) 2012 Eloy Durán <eloy.de.enige@gmail.com> Copyright (c) 2011 - 2012 Eloy Durán <eloy.de.enige@gmail.com>
Copyright (c) 2012 Fabio Pelosin <fabiopelosin@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
......
...@@ -33,7 +33,7 @@ namespace :travis do ...@@ -33,7 +33,7 @@ namespace :travis do
task :install do task :install do
sh "git submodule update --init" sh "git submodule update --init"
sh "sudo apt-get install subversion" sh "sudo apt-get install subversion"
sh "env CFLAGS='-I#{rvm_ruby_dir}/include' bundle install" sh "env CFLAGS='-I#{rvm_ruby_dir}/include' bundle install --without debugging documentation"
end end
task :setup => [:install_opencflite_debs, :install] task :setup => [:install_opencflite_debs, :install]
......
...@@ -7,9 +7,9 @@ Gem::Specification.new do |s| ...@@ -7,9 +7,9 @@ Gem::Specification.new do |s|
s.version = Pod::VERSION s.version = Pod::VERSION
s.date = Date.today s.date = Date.today
s.license = "MIT" s.license = "MIT"
s.email = "eloy.de.enige@gmail.com" s.email = ["eloy.de.enige@gmail.com", "fabiopelosin@gmail.com"]
s.homepage = "https://github.com/CocoaPods/CocoaPods" s.homepage = "https://github.com/CocoaPods/CocoaPods"
s.authors = ["Eloy Duran"] s.authors = ["Eloy Duran", "Fabio Pelosin"]
s.summary = "An Objective-C library package manager." s.summary = "An Objective-C library package manager."
s.description = "CocoaPods manages library dependencies for your Xcode project.\n\n" \ s.description = "CocoaPods manages library dependencies for your Xcode project.\n\n" \
...@@ -26,7 +26,7 @@ Gem::Specification.new do |s| ...@@ -26,7 +26,7 @@ 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 'xcodeproj', '>= 0.3.3' s.add_runtime_dependency 'xcodeproj', '~> 0.3.5'
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'
......
PODS: COCOAPODS: 0.15.1
- AFNetworking (0.7.0):
PODS:
- AFNetworking (0.7.0):
- JSONKit - JSONKit
- FormatterKit (1.0.0): - FormatterKit (1.0.0):
- FormatterKit/ArrayFormatter (= 1.0.0) - FormatterKit/ArrayFormatter (= 1.0.0)
- FormatterKit/LocationFormatter (= 1.0.0) - FormatterKit/LocationFormatter (= 1.0.0)
- FormatterKit/OrdinalNumberFormatter (= 1.0.0) - FormatterKit/OrdinalNumberFormatter (= 1.0.0)
...@@ -17,19 +19,17 @@ PODS: ...@@ -17,19 +19,17 @@ PODS:
- FormatterKit/UnitOfInformationFormatter (1.0.0) - FormatterKit/UnitOfInformationFormatter (1.0.0)
- JSONKit (1.5pre) - JSONKit (1.5pre)
DEPENDENCIES: SPEC CHECKSUMS:
- AFNetworking (~> 0.7.0) FormatterKit/UnitOfInformationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
- FormatterKit
SPEC CHECKSUMS:
AFNetworking: 1dd63e737768662b7180659e91846408df4ae7df
FormatterKit: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/ArrayFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/LocationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/OrdinalNumberFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/TimeIntervalFormatter: 12dea999a2df19e389f7b821962fc4088de8b821 FormatterKit/TimeIntervalFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
AFNetworking: 7bf22b0ed1d9068909cd67206db78204eb63dd2c
JSONKit: a01a22c75f27eae76b4badd55a91c20fe6e86477
FormatterKit/OrdinalNumberFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/LocationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/URLRequestFormatter: 12dea999a2df19e389f7b821962fc4088de8b821 FormatterKit/URLRequestFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/UnitOfInformationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821 FormatterKit/ArrayFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
JSONKit: 3d4708953ea7ae399a49777372d8b060a43ddd27 FormatterKit: 12dea999a2df19e389f7b821962fc4088de8b821
COCOAPODS: 0.13.0 DEPENDENCIES:
- AFNetworking (~> 0.7.0)
- FormatterKit
PODS: SPEC CHECKSUMS:
- AFNetworking (0.7.0): FormatterKit/UnitOfInformationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
AFNetworking: 7bf22b0ed1d9068909cd67206db78204eb63dd2c
JSONKit: a01a22c75f27eae76b4badd55a91c20fe6e86477
FormatterKit/URLRequestFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/OrdinalNumberFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/TimeIntervalFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/ArrayFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/LocationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
PODS:
- AFNetworking (0.7.0):
- JSONKit - JSONKit
- FormatterKit (1.0.0): - FormatterKit (1.0.0):
- FormatterKit/ArrayFormatter (= 1.0.0) - FormatterKit/ArrayFormatter (= 1.0.0)
- FormatterKit/LocationFormatter (= 1.0.0) - FormatterKit/LocationFormatter (= 1.0.0)
- FormatterKit/OrdinalNumberFormatter (= 1.0.0) - FormatterKit/OrdinalNumberFormatter (= 1.0.0)
...@@ -17,19 +28,8 @@ PODS: ...@@ -17,19 +28,8 @@ PODS:
- FormatterKit/UnitOfInformationFormatter (1.0.0) - FormatterKit/UnitOfInformationFormatter (1.0.0)
- JSONKit (1.5pre) - JSONKit (1.5pre)
DEPENDENCIES: COCOAPODS: 0.15.1
DEPENDENCIES:
- AFNetworking (~> 0.7.0) - AFNetworking (~> 0.7.0)
- FormatterKit - FormatterKit
SPEC CHECKSUMS:
AFNetworking: 1dd63e737768662b7180659e91846408df4ae7df
FormatterKit: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/ArrayFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/LocationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/OrdinalNumberFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/TimeIntervalFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/URLRequestFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
FormatterKit/UnitOfInformationFormatter: 12dea999a2df19e389f7b821962fc4088de8b821
JSONKit: 3d4708953ea7ae399a49777372d8b060a43ddd27
COCOAPODS: 0.13.0
PODS: DEPENDENCIES:
- MGSplitViewController (1.0.0)
DEPENDENCIES:
- MGSplitViewController (= 1.0.0) - MGSplitViewController (= 1.0.0)
SPEC CHECKSUMS: SPEC CHECKSUMS:
MGSplitViewController: e0b0bc01aa81e1559765c39e7a764c890dac373a MGSplitViewController: e0b0bc01aa81e1559765c39e7a764c890dac373a
COCOAPODS: 0.13.0 PODS:
- MGSplitViewController (1.0.0)
COCOAPODS: 0.15.1
PODS: COCOAPODS: 0.15.1
- AFNetworking (1.0RC1)
DEPENDENCIES: DEPENDENCIES:
- AFNetworking - AFNetworking
SPEC CHECKSUMS: SPEC CHECKSUMS:
AFNetworking: b21c1252d437fd322e7db1caa93b163d76a362cb AFNetworking: b21c1252d437fd322e7db1caa93b163d76a362cb
COCOAPODS: 0.13.0 PODS:
- AFNetworking (1.0RC1)
...@@ -7,12 +7,12 @@ require 'rubygems' ...@@ -7,12 +7,12 @@ require 'rubygems'
# #
# E.g. https://github.com/CocoaPods/CocoaPods/issues/398 # E.g. https://github.com/CocoaPods/CocoaPods/issues/398
unless Gem::Version::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new(Gem::VERSION)) unless Gem::Version::Requirement.new('>= 1.4.0').satisfied_by?(Gem::Version.new(Gem::VERSION))
STDERR.puts "Your RubyGems version (#{Gem::VERSION}) is too old, please update with: `gem update --system`".red STDERR.puts "\e[1;31m" + "Your RubyGems version (1.8.24) is too old, please update with: `gem update --system`" + "\e[0m"
exit 1 exit 1
end end
module Pod module Pod
VERSION = '0.14.0' VERSION = '0.15.2'
class PlainInformative < StandardError class PlainInformative < StandardError
end end
...@@ -57,13 +57,6 @@ module Pod ...@@ -57,13 +57,6 @@ module Pod
end end
end end
class Pathname
def glob(pattern = '')
Dir.glob((self + pattern).to_s).map { |f| Pathname.new(f) }
end
end
if ENV['COCOA_PODS_ENV'] == 'development' if ENV['COCOA_PODS_ENV'] == 'development'
require 'pry'
require 'awesome_print' require 'awesome_print'
end end
...@@ -6,6 +6,14 @@ module Pod ...@@ -6,6 +6,14 @@ module Pod
# TODO: Add check to ensure that attributes inherited by subspecs are not duplicated ? # TODO: Add check to ensure that attributes inherited by subspecs are not duplicated ?
attr_accessor :quick, :no_clean, :repo_path attr_accessor :quick, :no_clean, :repo_path
# @return [Bool] Wether the lint should be performed against the root of
# the podspec instead to its original source. Uses the `:local` option
# of the Podfile.
#
attr_accessor :local
alias :local? :local
attr_reader :spec, :file attr_reader :spec, :file
attr_reader :errors, :warnings, :notes attr_reader :errors, :warnings, :notes
...@@ -114,11 +122,16 @@ module Pod ...@@ -114,11 +122,16 @@ module Pod
def podfile_from_spec def podfile_from_spec
name = spec.name name = spec.name
podspec = file.realpath.to_s podspec = file.realpath
platform = @platform platform = @platform
local = local?
podfile = Pod::Podfile.new do podfile = Pod::Podfile.new do
platform(platform.to_sym, platform.deployment_target) platform(platform.to_sym, platform.deployment_target)
pod name, :podspec => podspec if (local)
pod name, :local => podspec.dirname.to_s
else
pod name, :podspec => podspec.to_s
end
end end
podfile podfile
end end
......
...@@ -22,7 +22,6 @@ module Pod ...@@ -22,7 +22,6 @@ module Pod
def run def run
verify_podfile_exists! verify_podfile_exists!
verify_lockfile_exists! verify_lockfile_exists!
update_spec_repos_if_necessary!
sandbox = Sandbox.new(config.project_pods_root) sandbox = Sandbox.new(config.project_pods_root)
resolver = Resolver.new(config.podfile, config.lockfile, sandbox) resolver = Resolver.new(config.podfile, config.lockfile, sandbox)
...@@ -30,6 +29,9 @@ module Pod ...@@ -30,6 +29,9 @@ module Pod
resolver.update_external_specs = false resolver.update_external_specs = false
resolver.resolve resolver.resolve
#TODO: the command report new dependencies (added to by updated ones)
# as updates.
names = resolver.pods_to_install - resolver.pods_from_external_sources names = resolver.pods_to_install - resolver.pods_from_external_sources
specs = resolver.specs.select do |spec| specs = resolver.specs.select do |spec|
names.include?(spec.name) && !spec.version.head? names.include?(spec.name) && !spec.version.head?
......
require 'fileutils' require 'fileutils'
require 'active_support/core_ext/string/inflections'
module Pod module Pod
class Command class Command
...@@ -66,12 +67,18 @@ module Pod ...@@ -66,12 +67,18 @@ module Pod
def podspec_files def podspec_files
files = Pathname.glob(@podspec || "*.podspec") files = Pathname.glob(@podspec || "*.podspec")
raise Informative, "[!] Couldn't find .podspec file in current directory".red if files.empty? raise Informative, "[!] Couldn't find any .podspec file in current directory".red if files.empty?
files files
end end
# @return [Integer] The number of the podspec files to push.
#
def count
podspec_files.count
end
def validate_podspec_files def validate_podspec_files
UI.puts "\nValidating specs".yellow unless config.silent UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow unless config.silent
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
...@@ -82,7 +89,7 @@ module Pod ...@@ -82,7 +89,7 @@ module Pod
end end
def add_specs_to_repo def add_specs_to_repo
UI.puts "\nAdding the specs to the #{@repo} repo\n".yellow unless config.silent UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow unless config.silent
podspec_files.each do |spec_file| podspec_files.each do |spec_file|
spec = Pod::Specification.from_file(spec_file) spec = Pod::Specification.from_file(spec_file)
output_path = File.join(repo_dir, spec.name, spec.version.to_s) output_path = File.join(repo_dir, spec.name, spec.version.to_s)
......
...@@ -90,7 +90,7 @@ module Pod ...@@ -90,7 +90,7 @@ module Pod
dirs.each do |dir| dirs.each do |dir|
check_versions(dir) check_versions(dir)
UI.puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow UI.puts "\nLinting spec repo `#{dir.realpath.basename}'\n".yellow
podspecs = dir.glob('**/*.podspec') podspecs = Pathname.glob( dir + '**/*.podspec')
invalid_count = 0 invalid_count = 0
podspecs.each do |podspec| podspecs.each do |podspec|
......
# encoding: utf-8 # encoding: utf-8
require 'active_support/core_ext/string/inflections'
module Pod module Pod
class Command class Command
class Spec < Command class Spec < Command
...@@ -20,6 +22,7 @@ module Pod ...@@ -20,6 +22,7 @@ module Pod
def self.options def self.options
[ ["--quick", "Lint skips checks that would require to download and build the spec"], [ ["--quick", "Lint skips checks that would require to download and build the spec"],
["--local", "Lint a podspec against the local files contained in its directory"],
["--only-errors", "Lint validates even if warnings are present"], ["--only-errors", "Lint validates even if warnings are present"],
["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super) ["--no-clean", "Lint leaves the build directory intact for inspection"] ].concat(super)
end end
...@@ -32,9 +35,10 @@ module Pod ...@@ -32,9 +35,10 @@ module Pod
super if @name_or_url.nil? super if @name_or_url.nil?
super unless argv.empty? super unless argv.empty?
elsif @action == 'lint' elsif @action == 'lint'
@quick = argv.option('--quick') @quick = argv.option('--quick')
@only_errors = argv.option('--only-errors') @local = argv.option('--local')
@no_clean = argv.option('--no-clean') @only_errors = argv.option('--only-errors')
@no_clean = argv.option('--no-clean')
@podspecs_paths = argv @podspecs_paths = argv
else else
super super
...@@ -72,8 +76,9 @@ module Pod ...@@ -72,8 +76,9 @@ 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 = Linter.new(podspec)
linter.quick = @quick linter.quick = @quick
linter.local = @local
linter.no_clean = @no_clean linter.no_clean = @no_clean
# Show immediatly which pod is being processed. # Show immediatly which pod is being processed.
...@@ -101,8 +106,8 @@ module Pod ...@@ -101,8 +106,8 @@ module Pod
UI.puts unless config.silent? UI.puts unless config.silent?
end end
UI.puts "Analyzed #{podspecs_to_lint.count} podspecs files.\n\n" unless config.silent?
count = podspecs_to_lint.count count = podspecs_to_lint.count
UI.puts "Analyzed #{count} #{'podspec'.pluralize(count)}.\n\n" unless config.silent?
if invalid_count == 0 if invalid_count == 0
lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation." lint_passed_message = count == 1 ? "#{podspecs_to_lint.first.basename} passed validation." : "All the specs passed validation."
UI.puts lint_passed_message.green << "\n\n" unless config.silent? UI.puts lint_passed_message.green << "\n\n" unless config.silent?
...@@ -133,7 +138,7 @@ module Pod ...@@ -133,7 +138,7 @@ module Pod
end end
files << output_path files << output_path
else if (pathname = Pathname.new(path)).directory? else if (pathname = Pathname.new(path)).directory?
files += pathname.glob('**/*.podspec') files += Pathname.glob(pathname + '**/*.podspec')
raise Informative, "No specs found in the current directory." if files.empty? raise Informative, "No specs found in the current directory." if files.empty?
else else
files << (pathname = Pathname.new(path)) files << (pathname = Pathname.new(path))
...@@ -171,7 +176,7 @@ module Pod ...@@ -171,7 +176,7 @@ module Pod
data = {} data = {}
data[:name] = repo['name'] data[:name] = repo['name']
data[:summary] = repo['description'].gsub(/["]/, '\"') data[:summary] = (repo['description'] || '').gsub(/["]/, '\"')
data[:homepage] = (repo['homepage'] && !repo['homepage'].empty? ) ? repo['homepage'] : repo['html_url'] data[:homepage] = (repo['homepage'] && !repo['homepage'].empty? ) ? repo['homepage'] : repo['html_url']
data[:author_name] = user['name'] || user['login'] data[:author_name] = user['name'] || user['login']
data[:author_email] = user['email'] || 'email@address.com' data[:author_email] = user['email'] || 'email@address.com'
......
...@@ -41,7 +41,7 @@ module Pod ...@@ -41,7 +41,7 @@ module Pod
def project_podfile def project_podfile
unless @project_podfile unless @project_podfile
@project_podfile = project_root + 'Podfile.cocoapods' @project_podfile = project_root + 'CocoaPods.podfile'
unless @project_podfile.exist? unless @project_podfile.exist?
@project_podfile = project_root + 'Podfile' @project_podfile = project_root + 'Podfile'
end end
......
...@@ -231,7 +231,8 @@ module Pod ...@@ -231,7 +231,8 @@ module Pod
class LocalSource < AbstractExternalSource class LocalSource < AbstractExternalSource
def pod_spec_path def pod_spec_path
path = Pathname.new(@params[:local]).expand_path + "#{name}.podspec" 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? raise Informative, "No podspec found for `#{name}' in `#{@params[:local]}'" unless path.exist?
path path
end end
......
require 'open-uri' require 'open-uri'
require 'tempfile' # require 'tempfile'
require 'zlib' require 'zlib'
require 'digest/sha1' require 'digest/sha1'
module Pod module Pod
class Downloader class Downloader
# Concreted Downloader class that provides support for specifications with
# git sources.
#
class Git < Downloader class Git < Downloader
include Config::Mixin include Config::Mixin
executable :git executable :git
MAX_CACHE_SIZE = 500
def download def download
create_cache unless cache_exist? create_cache unless cache_exist?
UI.section(' > Cloning git repo', '', 1) do UI.section(' > Cloning git repo', '', 1) do
...@@ -29,88 +31,26 @@ module Pod ...@@ -29,88 +31,26 @@ module Pod
prune_cache prune_cache
end end
def create_cache
UI.section(" > Creating cache git repo (#{cache_path})",'',1)
cache_path.rmtree if cache_path.exist?
cache_path.mkpath
git! %Q|clone --mirror "#{url}" "#{cache_path}"|
end
def prune_cache
return unless caches_dir.exist?
Dir.chdir(caches_dir) do
repos = Pathname.new(caches_dir).children.select { |c| c.directory? }.sort_by(&:ctime)
while caches_size >= MAX_CACHE_SIZE && !repos.empty?
dir = repos.shift
UI.message "#{'->'.yellow} Removing git cache for `#{origin_url(dir)}'"
dir.rmtree
end
end
end
def cache_path
@cache_path ||= caches_dir + "#{Digest::SHA1.hexdigest(url.to_s)}"
end
def cache_exist?
cache_path.exist? && origin_url(cache_path).to_s == url.to_s
end
def origin_url(dir) # @!group Download implementations
Dir.chdir(dir) { `git config remote.origin.url`.chomp }
end
def caches_dir
Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
end
# @return [Pathname] The clone URL, which resolves to the cache path.
#
def clone_url def clone_url
cache_path cache_path
end end
def caches_size # @return [void] Convenience method to perform clones operations.
# expressed in Mb #
`du -cm`.split("\n").last.to_i def clone(from, to)
end UI.section(" > Cloning to Pods folder",'',1) do
git! %Q|clone "#{from}" "#{to}"|
def update_cache
UI.section(" > Updating cache git repo (#{cache_path})",'',1) do
Dir.chdir(cache_path) do
if git("config core.bare").chomp == "true"
git! "remote update"
else
git! "reset --hard HEAD"
git! "clean -d -x -f"
git! "pull origin master"
git! "fetch --tags"
end
end
end end
end end
def ref_exists?(ref) # @return [void] Checkouts the HEAD of the git source in the destination
Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" } # path.
$? == 0 #
end
def ensure_ref_exists(ref)
return if ref_exists?(ref)
# Skip pull if not needed
update_cache
raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
end
def branch_exists?(branch)
Dir.chdir(cache_path) { git "branch --all | grep #{branch}$" } # check for remote branch and do suffix matching ($ anchor)
$? == 0
end
def ensure_remote_branch_exists(branch)
return if branch_exists?(branch)
update_cache
raise Informative, "[!] Cache unable to find git reference `#{branch}' for `#{url}' (#{$?}).".red unless branch_exists?(branch)
end
def download_head def download_head
if cache_exist? if cache_exist?
update_cache update_cache
...@@ -122,6 +62,9 @@ module Pod ...@@ -122,6 +62,9 @@ module Pod
Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules] Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules]
end end
# @return [void] Checkouts a specific tag of the git source in the
# destination path.
#
def download_tag def download_tag
ensure_ref_exists(options[:tag]) ensure_ref_exists(options[:tag])
Dir.chdir(target_path) do Dir.chdir(target_path) do
...@@ -133,6 +76,9 @@ module Pod ...@@ -133,6 +76,9 @@ module Pod
end end
end end
# @return [void] Checkouts a specific commit of the git source in the
# destination path.
#
def download_commit def download_commit
ensure_ref_exists(options[:commit]) ensure_ref_exists(options[:commit])
clone(clone_url, target_path) clone(clone_url, target_path)
...@@ -141,6 +87,9 @@ module Pod ...@@ -141,6 +87,9 @@ module Pod
end end
end end
# @return [void] Checkouts the HEAD of a specific branch of the git
# source in the destination path.
#
def download_branch def download_branch
ensure_remote_branch_exists(options[:branch]) ensure_remote_branch_exists(options[:branch])
clone(clone_url, target_path) clone(clone_url, target_path)
...@@ -152,13 +101,135 @@ module Pod ...@@ -152,13 +101,135 @@ module Pod
end end
end end
def clone(from, to)
UI.section(" > Cloning to Pods folder",'',1) do
git! %Q|clone "#{from}" "#{to}"| # @!group Checking references
# @return [Bool] Wether a reference (commit SHA or tag)
#
def ref_exists?(ref)
Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
$? == 0
end
# @return [void] Checks if a reference exists in the cache and updates
# only if necessary.
#
# @raises if after the update the reference can't be found.
#
def ensure_ref_exists(ref)
return if ref_exists?(ref)
update_cache
raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
end
# @return [Bool] Wether a branch exists in the cache.
#
def branch_exists?(branch)
Dir.chdir(cache_path) { git "branch --all | grep #{branch}$" } # check for remote branch and do suffix matching ($ anchor)
$? == 0
end
# @return [void] Checks if a branch exists in the cache and updates
# only if necessary.
#
# @raises if after the update the branch can't be found.
#
def ensure_remote_branch_exists(branch)
return if branch_exists?(branch)
update_cache
raise Informative, "[!] Cache unable to find git reference `#{branch}' for `#{url}' (#{$?}).".red unless branch_exists?(branch)
end
# @!group Cache
# The maximum allowed size for the cache expressed in Mb.
#
MAX_CACHE_SIZE = 500
# @return [Pathname] The directory where the cache for the current git
# repo is stored.
#
# @note The name of the directory is the SHA1 hash value of the URL of
# the git repo.
#
def cache_path
@cache_path ||= caches_root + "#{Digest::SHA1.hexdigest(url.to_s)}"
end
# @return [Pathname] The directory where the git caches are stored.
#
def caches_root
Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
end
# @return [Integer] The global size of the git cache expressed in Mb.
#
def caches_size
`du -cm`.split("\n").last.to_i
end
# @return [Bool] Wether the cache exits.
#
# @note The previous implementation of the cache didn't use a barebone
# git repo. This method takes into account this fact and checks
# that the cache is actually a barebone repo. If the cache was not
# barebone it will be deleted and recreated.
#
def cache_exist?
cache_path.exist? &&
cache_origin_url(cache_path).to_s == url.to_s &&
Dir.chdir(cache_path) { git("config core.bare").chomp == "true" }
end
# @return [String] The origin URL of the cache with the given directory.
#
# @param [String] dir The directory of the cache.
#
def cache_origin_url(dir)
Dir.chdir(dir) { `git config remote.origin.url`.chomp }
end
# @return [void] Creates the barebone repo that will serve as the cache
# for the current repo.
#
def create_cache
UI.section(" > Creating cache git repo (#{cache_path})",'',1) do
cache_path.rmtree if cache_path.exist?
cache_path.mkpath
git! %Q|clone --mirror "#{url}" "#{cache_path}"|
end
end
# @return [void] Updates the barebone repo used as a cache against its
# remote.
#
def update_cache
UI.section(" > Updating cache git repo (#{cache_path})",'',1) do
Dir.chdir(cache_path) { git! "remote update" }
end
end
# @return [void] Deletes the oldest caches until they the global size is
# below the maximum allowed.
#
def prune_cache
return unless caches_root.exist?
Dir.chdir(caches_root) do
repos = Pathname.new(caches_root).children.select { |c| c.directory? }.sort_by(&:ctime)
while caches_size >= MAX_CACHE_SIZE && !repos.empty?
dir = repos.shift
UI.message "#{'->'.yellow} Removing git cache for `#{cache_origin_url(dir)}'"
dir.rmtree
end
end end
end end
end end
# This class allows to download tarballs from GitHub and is not currently
# being used by CocoaPods as the git cache is preferable.
#
class GitHub < Git class GitHub < Git
def download_head def download_head
download_only? ? download_and_extract_tarball('master') : super download_only? ? download_and_extract_tarball('master') : super
......
...@@ -274,7 +274,6 @@ module Pod ...@@ -274,7 +274,6 @@ module Pod
end end
# @!group Resolution steps # @!group Resolution steps
# @return [Hash{Podfile::TargetDefinition => Array<Spec>}] # @return [Hash{Podfile::TargetDefinition => Array<Spec>}]
...@@ -487,7 +486,6 @@ module Pod ...@@ -487,7 +486,6 @@ module Pod
UI.message "- Creating Pods project" do UI.message "- Creating Pods project" do
@pods_project = Pod::Project.new @pods_project = Pod::Project.new
pods_project.user_build_configurations = podfile.user_build_configurations pods_project.user_build_configurations = podfile.user_build_configurations
pods_project.main_group.groups.new('name' => 'Targets Support Files')
end end
end end
...@@ -502,19 +500,8 @@ module Pod ...@@ -502,19 +500,8 @@ module Pod
# #
def add_source_files_to_pods_project def add_source_files_to_pods_project
UI.message "- Adding source files to Pods project" do UI.message "- Adding source files to Pods project" do
pods.each do |pod| pods.each { |p| p.add_file_references_to_project(@project) }
pod.relative_source_files_by_spec.each do |spec, paths| pods.each { |p| p.link_headers }
if pod.local?
parent_group = pods_project.local_pods
else
parent_group = pods_project.pods
end
group = pods_project.add_spec_group(spec.name, parent_group)
paths.each do |path|
group.files.new('path' => path.to_s)
end
end
end
end end
end end
...@@ -567,11 +554,8 @@ module Pod ...@@ -567,11 +554,8 @@ module Pod
filename = "#{dummy_source.class_name}.m" filename = "#{dummy_source.class_name}.m"
pathname = Pathname.new(sandbox.root + filename) pathname = Pathname.new(sandbox.root + filename)
dummy_source.save_as(pathname) dummy_source.save_as(pathname)
file = project.new_file(filename, "Targets Support Files")
project_file = pods_project.files.new('path' => filename) target_installer.target.source_build_phase.add_file_reference(file)
pods_project.group("Targets Support Files") << project_file
target_installer.target.source_build_phases.first << project_file
end end
def write_pod_project def write_pod_project
......
module Pod module Pod
class Installer class Installer
# This class is reponsible of creating and configuring the static library
# target in Pods project. Every target is generated from a target
# definition of the Podfile.
#
class TargetInstaller class TargetInstaller
include Config::Mixin include Config::Mixin
attr_reader :podfile, :project, :target_definition, :target # @return [Podfile]
attr_accessor :requires_arc #
# TODO: is really needed to pass the podfile?
#
attr_reader :podfile
# @return [Project] The Pods project.
#
attr_reader :project
# @return [TargetDefinition] The target definition whoose target needs to
# be generated.
#
attr_reader :target_definition
def initialize(podfile, project, target_definition) def initialize(podfile, project, target_definition)
@podfile, @project, @target_definition = podfile, project, target_definition @podfile = podfile
@project = project
@target_definition = target_definition
end
# @return [void] Creates the target in the Pods project and its support
# files.
#
# @param [Array<LocalPod>] pods The pods are required by the target
# definition of this installer.
#
# @param [Sandbox] sandbox The sanbox where the support files
# should be generated.
#
def install!(pods, sandbox)
self.requires_arc = pods.any? { |pod| pod.requires_arc? }
@target = @project.add_pod_target(@target_definition.label, @target_definition.platform)
source_file_descriptions = []
pods.each { |p| p.add_build_files_to_target(@target) }
support_files_group = @project.support_files_group.new_group(@target_definition.label)
target_support_files.each { |path| support_files_group.new_file(path) }
xcconfig_file = support_files_group.files.find { |f| f.path == @target_definition.xcconfig_name }
configure_build_configurations(xcconfig_file, sandbox)
create_files(pods, sandbox)
end end
def xcconfig # @return [PBXNativeTarget] The target generated by the installation
@xcconfig ||= Xcodeproj::Config.new({ # process.
# In a workspace this is where the static library headers should be found. #
'PODS_ROOT' => @target_definition.relative_pods_root, attr_reader :target
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
'ALWAYS_SEARCH_USER_PATHS' => 'YES', # needed to make EmbedReader build
'OTHER_LDFLAGS' => default_ld_flags # @return [Boold] Wether the any of the pods requires arc.
#
# TODO: This should not be an attribute reader.
#
attr_accessor :requires_arc
attr_reader :xcconfig
# In a workspace this is where the static library headers should be found.
#
def generate_xcconfig(pods, sandbox)
xcconfig = Xcodeproj::Config.new({
'ALWAYS_SEARCH_USER_PATHS' => 'YES', # needed to make EmbedReader build
'OTHER_LDFLAGS' => default_ld_flags,
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
# CocoaPods global keys
'PODS_ROOT' => @target_definition.relative_pods_root,
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quoted(sandbox.build_headers.search_paths).join(" "),
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quoted(sandbox.public_headers.search_paths).join(" "),
# Pods project specific keys
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}'
}) })
pods.each { |pod| xcconfig.merge!(pod.xcconfig) }
@xcconfig = xcconfig
end end
#
#
def copy_resources_script_for(pods) def copy_resources_script_for(pods)
@copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten) @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten)
end end
...@@ -57,37 +125,9 @@ module Pod ...@@ -57,37 +125,9 @@ module Pod
[:copy_resources_script_name, :prefix_header_name, :xcconfig_name].map { |file| @target_definition.send(file) } [:copy_resources_script_name, :prefix_header_name, :xcconfig_name].map { |file| @target_definition.send(file) }
end end
# TODO move xcconfig related code into the xcconfig method, like copy_resources_script and generate_bridge_support.
def install!(pods, sandbox)
self.requires_arc = pods.any? { |pod| pod.requires_arc? }
@target = @project.add_pod_target(@target_definition.label, @target_definition.platform)
source_file_descriptions = []
pods.each do |pod|
xcconfig.merge!(pod.xcconfig)
source_file_descriptions += pod.source_file_descriptions
# TODO: this doesn't need to be done here, it has nothing to do with the target
pod.link_headers
end
@target.add_source_files(source_file_descriptions)
xcconfig.merge!('HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}')
xcconfig.merge!('PODS_BUILD_HEADERS_SEARCH_PATHS' => quoted(sandbox.build_headers.search_paths).join(" "))
xcconfig.merge!('PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quoted(sandbox.public_headers.search_paths).join(" "))
support_files_group = @project.group("Targets Support Files").create_group(@target_definition.label)
support_files_group.create_files(target_support_files)
xcconfig_file = support_files_group.files.where(:path => @target_definition.xcconfig_name)
configure_build_configurations(xcconfig_file, sandbox)
create_files(pods, sandbox)
end
def configure_build_configurations(xcconfig_file, sandbox) def configure_build_configurations(xcconfig_file, sandbox)
@target.build_configurations.each do |config| @target.build_configurations.each do |config|
config.base_configuration = xcconfig_file config.base_configuration_reference = xcconfig_file
config.build_settings['OTHER_LDFLAGS'] = '' config.build_settings['OTHER_LDFLAGS'] = ''
config.build_settings['GCC_PREFIX_HEADER'] = @target_definition.prefix_header_name config.build_settings['GCC_PREFIX_HEADER'] = @target_definition.prefix_header_name
config.build_settings['PODS_ROOT'] = '${SRCROOT}' config.build_settings['PODS_ROOT'] = '${SRCROOT}'
...@@ -96,6 +136,8 @@ module Pod ...@@ -96,6 +136,8 @@ module Pod
end end
end end
#
#
def create_files(pods, sandbox) def create_files(pods, sandbox)
bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name bridge_support_metadata_path = sandbox.root + @target_definition.bridge_support_name
UI.message "- Generating BridgeSupport metadata file at #{UI.path bridge_support_metadata_path}" do UI.message "- Generating BridgeSupport metadata file at #{UI.path bridge_support_metadata_path}" do
...@@ -104,6 +146,7 @@ module Pod ...@@ -104,6 +146,7 @@ module Pod
end if @podfile.generate_bridge_support? end if @podfile.generate_bridge_support?
UI.message "- Generating xcconfig file at #{UI.path(sandbox.root + @target_definition.xcconfig_name)}" do UI.message "- Generating xcconfig file at #{UI.path(sandbox.root + @target_definition.xcconfig_name)}" do
generate_xcconfig(pods, sandbox)
xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name) xcconfig.save_as(sandbox.root + @target_definition.xcconfig_name)
@target_definition.xcconfig = xcconfig @target_definition.xcconfig = xcconfig
end end
......
...@@ -137,20 +137,18 @@ module Pod ...@@ -137,20 +137,18 @@ module Pod
# Default to the first, which in a simple project is probably an app target. # Default to the first, which in a simple project is probably an app target.
[user_project.targets.first] [user_project.targets.first]
end.reject do |target| end.reject do |target|
# Reject any target that already has this Pods library in one of its frameworks build phases # Reject any target that already has this Pods library in one of its frameworks build phases
target.frameworks_build_phases.any? do |phase| target.frameworks_build_phase.files.any? { |build_file| build_file.file_ref.name == @target_definition.lib_name }
phase.files.any? { |file| file.name == @target_definition.lib_name }
end
end
end end
end
end end
def add_xcconfig_base_configuration def add_xcconfig_base_configuration
xcconfig = user_project.files.new('path' => @target_definition.xcconfig_relative_path) xcconfig = user_project.new_file(@target_definition.xcconfig_relative_path)
targets.each do |target| targets.each do |target|
config_build_names_by_overriden_key = {} config_build_names_by_overriden_key = {}
target.build_configurations.each do |config| target.build_configurations.each do |config|
config_name = config.attributes["name"] config_name = config.name
if @target_definition.xcconfig if @target_definition.xcconfig
@target_definition.xcconfig.attributes.each do |key, value| @target_definition.xcconfig.attributes.each do |key, value|
target_value = config.build_settings[key] target_value = config.build_settings[key]
...@@ -161,11 +159,11 @@ module Pod ...@@ -161,11 +159,11 @@ module Pod
end end
end end
config.base_configuration = xcconfig config.base_configuration_reference = xcconfig
end end
config_build_names_by_overriden_key.each do |key, config_build_names| config_build_names_by_overriden_key.each do |key, config_build_names|
name = "#{target.attributes["name"]} [#{config_build_names.join(' - ')}]" name = "#{target.name} [#{config_build_names.join(' - ')}]"
actions = [ "Use the `$(inherited)' flag, or", "Remove the build settings from the target." ] actions = [ "Use the `$(inherited)' flag, or", "Remove the build settings from the target." ]
UI.warn("The target `#{name}' overrides the `#{key}' build setting defined in `#{@target_definition.xcconfig_relative_path}'.", actions) UI.warn("The target `#{name}' overrides the `#{key}' build setting defined in `#{@target_definition.xcconfig_relative_path}'.", actions)
end end
...@@ -173,23 +171,20 @@ module Pod ...@@ -173,23 +171,20 @@ module Pod
end end
def add_pods_library def add_pods_library
group = user_project.group("Frameworks") || user_project.main_group frameworks = user_project.frameworks_group
pods_library = group.files.new_static_library(@target_definition.label) pods_library = frameworks.new_static_library(@target_definition.label)
targets.each do |target| targets.each do |target|
target.frameworks_build_phases.each { |build_phase| build_phase << pods_library } target.frameworks_build_phase.add_file_reference(pods_library)
end end
end end
def add_copy_resources_script_phase def add_copy_resources_script_phase
targets.each do |target| targets.each do |target|
phase = target.shell_script_build_phases.new phase = target.new_shell_script_build_phase('Copy Pods Resources')
phase.name = 'Copy Pods Resources'
phase.shell_script = %{"#{@target_definition.copy_resources_script_relative_path}"\n} phase.shell_script = %{"#{@target_definition.copy_resources_script_relative_path}"\n}
end end
end end
end end
end end
end end
end end
...@@ -163,12 +163,15 @@ module Pod ...@@ -163,12 +163,15 @@ module Pod
# #
# @return [Array<Strings>] The paths that can be deleted. # @return [Array<Strings>] The paths that can be deleted.
# #
# @note Implementation detail: Don't use Dir#glob as there is an
# unexplained issue (#568, #572 and #602).
#
def clean_paths def clean_paths
cached_used_paths = used_files cached_used = used_files
files = Dir.glob(root + "**/*", File::FNM_DOTMATCH) files = Pathname.glob(root + "**/*", File::FNM_DOTMATCH | File::FNM_CASEFOLD).map(&:to_s)
files.reject! do |candidate| files.reject! do |candidate|
candidate.end_with?('.', '..') || cached_used_paths.any? do |path| candidate.end_with?('.', '..') || cached_used.any? do |path|
path.include?(candidate) || candidate.include?(path) path.include?(candidate) || candidate.include?(path)
end end
end end
...@@ -187,6 +190,27 @@ module Pod ...@@ -187,6 +190,27 @@ module Pod
# @!group Files # @!group Files
# @return [Pathname] Returns the relative path from the sandbox.
#
# @note If the two abosule paths don't share the same root directory an
# extra `../` is added to the result of {Pathname#relative_path_from}
#
# path = Pathname.new('/Users/dir')
# @sandbox
# #=> Pathname('/tmp/CocoaPods/Lint/Pods')
#
# p.relative_path_from(@sandbox
# #=> '../../../../Users/dir'
#
# relativize_from_sandbox(path)
# #=> '../../../../../Users/dir'
#
def relativize_from_sandbox(path)
result = path.relative_path_from(@sandbox.root)
result = Pathname.new('../') + result unless @sandbox.root.to_s.split('/')[1] == path.to_s.split('/')[1]
result
end
# @return [Array<Pathname>] The paths of the source files. # @return [Array<Pathname>] The paths of the source files.
# #
def source_files def source_files
...@@ -196,13 +220,13 @@ module Pod ...@@ -196,13 +220,13 @@ module Pod
# @return [Array<Pathname>] The *relative* paths of the source files. # @return [Array<Pathname>] The *relative* paths of the source files.
# #
def relative_source_files def relative_source_files
source_files.map{ |p| p.relative_path_from(@sandbox.root) } source_files.map{ |p| relativize_from_sandbox(p) }
end end
def relative_source_files_by_spec def relative_source_files_by_spec
result = {} result = {}
source_files_by_spec.each do |spec, paths| source_files_by_spec.each do |spec, paths|
result[spec] = paths.map{ |p| p.relative_path_from(@sandbox.root) } result[spec] = paths.map{ |p| relativize_from_sandbox(p) }
end end
result result
end end
...@@ -217,7 +241,7 @@ module Pod ...@@ -217,7 +241,7 @@ module Pod
# {Specification}. # {Specification}.
# #
def source_files_by_spec def source_files_by_spec
options = {:glob => '*.{h,m,mm,c,cpp}'} options = {:glob => '*.{h,hpp,hh,m,mm,c,cpp}'}
paths_by_spec(:source_files, options) paths_by_spec(:source_files, options)
end end
...@@ -230,7 +254,7 @@ module Pod ...@@ -230,7 +254,7 @@ module Pod
# @return [Array<Pathname>] The *relative* paths of the source files. # @return [Array<Pathname>] The *relative* paths of the source files.
# #
def relative_header_files def relative_header_files
header_files.map{ |p| p.relative_path_from(@sandbox.root) } header_files.map{ |p| relativize_from_sandbox(p) }
end end
# @return [Hash{Specification => Array<Pathname>}] The paths of the header # @return [Hash{Specification => Array<Pathname>}] The paths of the header
...@@ -239,7 +263,7 @@ module Pod ...@@ -239,7 +263,7 @@ module Pod
def header_files_by_spec def header_files_by_spec
result = {} result = {}
source_files_by_spec.each do |spec, paths| source_files_by_spec.each do |spec, paths|
headers = paths.select { |f| f.extname == '.h' } headers = paths.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
result[spec] = headers unless headers.empty? result[spec] = headers unless headers.empty?
end end
result result
...@@ -253,7 +277,7 @@ module Pod ...@@ -253,7 +277,7 @@ module Pod
# header files (i.e. the build ones) are intended to be public. # header files (i.e. the build ones) are intended to be public.
# #
def public_header_files_by_spec def public_header_files_by_spec
public_headers = paths_by_spec(:public_header_files, :glob => '*.h') public_headers = paths_by_spec(:public_header_files, :glob => '*.{h,hpp,hh}')
build_headers = header_files_by_spec build_headers = header_files_by_spec
result = {} result = {}
...@@ -276,7 +300,7 @@ module Pod ...@@ -276,7 +300,7 @@ module Pod
# @return [Array<Pathname>] The *relative* paths of the resources. # @return [Array<Pathname>] The *relative* paths of the resources.
# #
def relative_resource_files def relative_resource_files
resource_files.map{ |p| p.relative_path_from(@sandbox.root) } resource_files.map{ |p| relativize_from_sandbox(p) }
end end
# @return [Pathname] The absolute path of the prefix header file # @return [Pathname] The absolute path of the prefix header file
...@@ -356,14 +380,60 @@ module Pod ...@@ -356,14 +380,60 @@ module Pod
if (public_h = public_headers[spec]) && !public_h.empty? if (public_h = public_headers[spec]) && !public_h.empty?
result += public_h result += public_h
elsif (source_f = source_files[spec]) && !source_f.empty? elsif (source_f = source_files[spec]) && !source_f.empty?
build_h = source_f.select { |f| f.extname == '.h' } build_h = source_f.select { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
result += build_h unless build_h.empty? result += build_h unless build_h.empty?
end end
end end
result result
end end
# @!group Target integration # @!group Xcodeproj integration
# Adds the file references, to the given `Pods.xcodeproj` project, for the
# source files of the pod. The file references are grouped by specification
# and stored in {#file_references_by_spec}.
#
# @note If the pod is locally sourced the file references are stored in the
# `Local Pods` group otherwise they are stored in the `Pods` group.
#
# @return [void]
#
def add_file_references_to_project(project)
@file_references_by_spec = {}
parent_group = local? ? project.local_pods : project.pods
relative_source_files_by_spec.each do |spec, paths|
group = project.add_spec_group(spec.name, parent_group)
file_references = []
paths.each do |path|
file_references << group.new_file(path)
end
@file_references_by_spec[spec] = file_references
end
end
# @return [Hash{Specification => Array<PBXFileReference>}] The file
# references of the pod in the `Pods.xcodeproj` project.
#
attr_reader :file_references_by_spec
# Adds a build file for each file reference to a given target taking into
# account the compiler flags of the corresponding specification.
#
# @raise If the {#add_file_references_to_project} was not called before of
# calling this method.
#
# @return [void]
#
def add_build_files_to_target(target)
unless file_references_by_spec
raise Informative, "Local Pod needs to add the file references to the " \
"project before adding the build files to the target."
end
file_references_by_spec.each do |spec, file_reference|
target.add_file_references(file_reference, spec.compiler_flags.strip)
end
end
# @return [void] Copies the pods headers to the sandbox. # @return [void] Copies the pods headers to the sandbox.
# #
...@@ -380,26 +450,10 @@ module Pod ...@@ -380,26 +450,10 @@ module Pod
end end
end end
# @param [Xcodeproj::Project::Object::PBXNativeTarget] target
# The target to integrate.
#
# @return [void] Adds the pods source files to a given target.
#
def source_file_descriptions
result = []
source_files_by_spec.each do | spec, files |
compiler_flags = spec.compiler_flags.strip
files.each do |file|
file = file.relative_path_from(@sandbox.root)
desc = Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(file, compiler_flags, nil)
result << desc
end
end
result
end
# @return Whether the pod requires ARC. # @return Whether the pod requires ARC.
# #
# TODO: this should be not used anymore.
#
def requires_arc? def requires_arc?
top_specification.requires_arc top_specification.requires_arc
end end
...@@ -410,7 +464,7 @@ module Pod ...@@ -410,7 +464,7 @@ module Pod
# (the files the need to compiled) of the pod. # (the files the need to compiled) of the pod.
# #
def implementation_files def implementation_files
relative_source_files.select { |f| f.extname != '.h' } relative_source_files.reject { |f| f.extname == '.h' || f.extname == '.hpp' || f.extname == '.hh' }
end end
# @return [Pathname] The path of the pod relative from the sandbox. # @return [Pathname] The path of the pod relative from the sandbox.
...@@ -453,7 +507,7 @@ module Pod ...@@ -453,7 +507,7 @@ 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
options = { :glob => '*.h' } options = { :glob => '*.{h,hpp,hh}' }
paths = paths_by_spec(:exclude_header_search_paths, options) paths = paths_by_spec(:exclude_header_search_paths, options)
paths.values.compact.uniq paths.values.compact.uniq
end end
...@@ -506,15 +560,27 @@ module Pod ...@@ -506,15 +560,27 @@ module Pod
"\t Options: #{options.inspect}" "\t Options: #{options.inspect}"
end end
patterns = [ patterns ] if patterns.is_a? String return [] if patterns.empty?
patterns.map do |pattern| patterns = [ patterns ] if patterns.is_a?(String)
pattern = root + pattern file_lists = patterns.select { |p| p.is_a?(FileList) }
glob_patterns = patterns - file_lists
result = []
result << file_lists.map do |file_list|
file_list.prepend_patterns(root)
file_list.glob
end
result << glob_patterns.map do |pattern|
pattern = root + pattern
if pattern.directory? && options[:glob] if pattern.directory? && options[:glob]
pattern += options[:glob] pattern += options[:glob]
end end
Pathname.glob(pattern, File::FNM_CASEFOLD) Pathname.glob(pattern, File::FNM_CASEFOLD)
end.flatten end.flatten
result.flatten.compact.uniq
end end
# A {LocalSourcedPod} is a {LocalPod} that interacts with the files of # A {LocalSourcedPod} is a {LocalPod} that interacts with the files of
......
...@@ -8,7 +8,11 @@ module Pod ...@@ -8,7 +8,11 @@ module Pod
# #
def self.from_file(path) def self.from_file(path)
return nil unless path.exist? return nil unless path.exist?
hash = YAML.load(File.open(path)) begin
hash = YAML.load(File.open(path))
rescue Exception => e
raise Informative, "Podfile.lock syntax error: #{e.inspect}"
end
lockfile = Lockfile.new(hash) lockfile = Lockfile.new(hash)
lockfile.defined_in_file = path lockfile.defined_in_file = path
lockfile lockfile
......
...@@ -35,7 +35,7 @@ module Pod ...@@ -35,7 +35,7 @@ module Pod
if @path if @path
@path @path
else else
xcodeprojs = config.project_root.glob('*.xcodeproj') xcodeprojs = Pathname.glob(config.project_root + '*.xcodeproj')
if xcodeprojs.size == 1 if xcodeprojs.size == 1
@path = xcodeprojs.first @path = xcodeprojs.first
end end
...@@ -177,7 +177,11 @@ module Pod ...@@ -177,7 +177,11 @@ module Pod
string = File.open(path, 'r:utf-8') { |f| f.read } string = File.open(path, 'r:utf-8') { |f| f.read }
# TODO: work around for Rubinius incomplete encoding in 1.9 mode # TODO: work around for Rubinius incomplete encoding in 1.9 mode
string.encode!('UTF-8') if string.respond_to?(:encoding) && string.encoding.name != "UTF-8" string.encode!('UTF-8') if string.respond_to?(:encoding) && string.encoding.name != "UTF-8"
eval(string, nil, path.to_s) begin
eval(string, nil, path.to_s)
rescue Exception => e
raise Informative, "Podfile syntax error: #{e.inspect}"
end
end end
podfile.defined_in_file = path podfile.defined_in_file = path
podfile.validate! podfile.validate!
......
require 'xcodeproj/project' require 'xcodeproj/project'
require 'xcodeproj/project/object/build_phase'
Xcodeproj::Project::Object::PBXCopyFilesBuildPhase.instance_eval do # Xcodeproj::Project::Object::PBXCopyFilesBuildPhase.instance_eval do
def self.new_pod_dir(project, pod_name, path) # def self.new_pod_dir(project, pod_name, path)
new(project, nil, { # new(project, nil, {
"dstPath" => "Pods/#{path}", # "dstPath" => "Pods/#{path}",
"name" => "Copy #{pod_name} Public Headers", # "name" => "Copy #{pod_name} Public Headers",
}) # })
end # end
end # end
module Pod module Pod
class Project < Xcodeproj::Project class Project < Xcodeproj::Project
attr_reader :support_files_group
def initialize(*) def initialize(*)
super super
main_group << groups.new('name' => 'Pods') new_group('Pods')
@support_files_group = new_group('Targets Support Files')
@user_build_configurations = [] @user_build_configurations = []
end end
...@@ -24,40 +27,44 @@ module Pod ...@@ -24,40 +27,44 @@ module Pod
# any build settings themselves, that's left to `add_pod_target`. # any build settings themselves, that's left to `add_pod_target`.
user_build_configurations.each do |name, _| user_build_configurations.each do |name, _|
unless build_configurations.map(&:name).include?(name) unless build_configurations.map(&:name).include?(name)
build_configurations.new('name' => name) bc = new(XCBuildConfiguration)
bc.name = name
build_configurations << bc
end end
end end
end end
# Shortcut access to the `Pods' PBXGroup. # Shortcut access to the `Pods' PBXGroup.
def pods def pods
@pods ||= groups.where(:name => 'Pods') || groups.new('name' => 'Pods') @pods ||= self['Pods'] || new_group('Pods')
end end
# Shortcut access to the `Local Pods' PBXGroup. # Shortcut access to the `Local Pods' PBXGroup.
def local_pods def local_pods
@local_pods ||= groups.where(:name => 'Local Pods') || groups.new('name' => 'Local Pods') @local_pods ||= self['Local Pods'] || new_group('Local Pods')
end end
# Adds a group as child to the `Pods' group namespacing subspecs. # Adds a group as child to the `Pods' group namespacing subspecs.
def add_spec_group(name, parent_group) def add_spec_group(name, parent_group)
groups = parent_group.groups current_group = parent_group
group = nil group = nil
name.split('/').each do |name| name.split('/').each do |name|
group = groups.where(:name => name) || groups.new('name' => name) group = current_group[name] || current_group.new_group(name)
groups = group.groups current_group = group
end end
group group
end end
def add_pod_target(name, platform) def add_pod_target(name, platform)
target = targets.new_static_library(platform.name, name) target = new_target(:static_library, name, platform.name)
settings = {} settings = {}
if platform.requires_legacy_ios_archs? if platform.requires_legacy_ios_archs?
settings['ARCHS'] = "armv6 armv7" settings['ARCHS'] = "armv6 armv7"
end end
if platform == :ios && platform.deployment_target if platform == :ios && platform.deployment_target
# TODO: add for osx as well
settings['IPHONEOS_DEPLOYMENT_TARGET'] = platform.deployment_target.to_s settings['IPHONEOS_DEPLOYMENT_TARGET'] = platform.deployment_target.to_s
end end
...@@ -66,9 +73,11 @@ module Pod ...@@ -66,9 +73,11 @@ module Pod
@user_build_configurations.each do |name, type| @user_build_configurations.each do |name, type|
unless target.build_configurations.map(&:name).include?(name) unless target.build_configurations.map(&:name).include?(name)
config = target.build_configurations.new('name' => name) bc = new(XCBuildConfiguration)
bc.name = name
target.build_configurations << bc
# Copy the settings from either the Debug or the Release configuration. # Copy the settings from either the Debug or the Release configuration.
config.build_settings = target.build_settings(type.to_s.capitalize).merge(settings) bc.build_settings = target.build_settings(type.to_s.capitalize).merge(settings)
end end
end end
......
...@@ -128,10 +128,22 @@ module Pod ...@@ -128,10 +128,22 @@ module Pod
# @return [Array<Set>] The sets for all the pods available. # @return [Array<Set>] The sets for all the pods available.
# #
# @note Implementation detail: The sources don't cache their values
# because they might change in response to an update. Therefore
# this method to prevent slowness caches the values before
# processing them.
#
def all_sets def all_sets
all_pods.map do |pod| pods_by_source = {}
sources = all.select{ |s| s.pods.include?(pod) }.compact all.each do |source|
Specification::Set.new(pod, sources) pods_by_source[source] = source.pods
end
sources = pods_by_source.keys
pods = pods_by_source.values.flatten.uniq
pods.map do |pod|
pod_sources = sources.select{ |s| pods_by_source[s].include?(pod) }.compact
Specification::Set.new(pod, pod_sources)
end end
end end
......
...@@ -438,11 +438,12 @@ module Pod ...@@ -438,11 +438,12 @@ module Pod
# this to, for instance, to run any build script: # this to, for instance, to run any build script:
# #
# Pod::Spec.new do |s| # Pod::Spec.new do |s|
# def pre_install(pod, target_definition) # def s.pre_install(pod, target_definition)
# Dir.chdir(pod.root){ `sh make.sh` } # Dir.chdir(pod.root){ `sh make.sh` }
# end # end
# end # end
def pre_install(pod, target_definition) def pre_install(pod, target_definition)
FALSE
end end
# This is a convenience method which gets called after all pods have been # This is a convenience method which gets called after all pods have been
...@@ -460,6 +461,7 @@ module Pod ...@@ -460,6 +461,7 @@ module Pod
# end # end
# end # end
def post_install(target_installer) def post_install(target_installer)
FALSE
end end
def podfile? def podfile?
......
...@@ -90,7 +90,7 @@ module Pod ...@@ -90,7 +90,7 @@ module Pod
def github_stats_if_needed(set) def github_stats_if_needed(set)
return if get_value(set, :gh_date) && get_value(set, :gh_date) > Time.now - cache_expiration return if get_value(set, :gh_date) && get_value(set, :gh_date) > Time.now - cache_expiration
spec = set.specification spec = set.specification
url = spec.source.reject {|k,_| k == :commit || k == :tag }.values.first url = spec.source[:git] || ''
repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1] repo_id = url[/github.com\/([^\/\.]*\/[^\/\.]*)\.*/, 1]
return unless repo_id return unless repo_id
......
...@@ -196,8 +196,9 @@ module Pod ...@@ -196,8 +196,9 @@ module Pod
# @!group Helpers # @!group Helpers
# Wraps a string taking into account the width of the terminal and an # @return [String] Wraps a string taking into account the width of the
# option indent. Adapted from http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/ # terminal and an option indent. Adapted from
# http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
# #
# @param [String] txt The string to wrap # @param [String] txt The string to wrap
# #
...@@ -205,8 +206,12 @@ module Pod ...@@ -205,8 +206,12 @@ module Pod
# #
# @return [String] The formatted string. # @return [String] The formatted string.
# #
# @note If CocoaPods is not being run in a terminal or the width of the
# terminal is too small a width of 80 is assumed.
#
def wrap_string(txt, indent = '') def wrap_string(txt, indent = '')
width = `stty size`.split(' ')[1].to_i - indent.length width = `stty size`.split(' ')[1].to_i - indent.length
width = 80 unless width >= 10
txt.strip.gsub(/(.{1,#{width}})( +|$)\n?|(.{#{width}})/, indent + "\\1\\3\n") txt.strip.gsub(/(.{1,#{width}})( +|$)\n?|(.{#{width}})/, indent + "\\1\\3\n")
end end
end end
......
...@@ -42,7 +42,7 @@ module Pod ...@@ -42,7 +42,7 @@ module Pod
end end
def authors def authors
spec.authors.keys.to_sentence spec.authors ? spec.authors.keys.to_sentence : ''
end end
def homepage def homepage
......
...@@ -32,21 +32,13 @@ describe Pod::Installer::UserProjectIntegrator do ...@@ -32,21 +32,13 @@ describe Pod::Installer::UserProjectIntegrator do
@sample_project = Xcodeproj::Project.new(@sample_project_path) @sample_project = Xcodeproj::Project.new(@sample_project_path)
end end
it 'adds references to the Pods static libraries to the root of the project if the Frameworks group does not exist' do
@sample_project.group('Frameworks').destroy
@sample_project.save_as(@sample_project_path)
integrate!
@sample_project.main_group.files.where(:name => "libPods.a").should.not == nil
@sample_project.main_group.files.where(:name => "libPods-test_runner.a").should.not == nil
end
before do before do
integrate! integrate!
end end
it 'adds references to the Pods static libraries to the Frameworks group' do it 'adds references to the Pods static libraries to the Frameworks group' do
@sample_project.group('Frameworks').files.where(:name => "libPods.a").should.not == nil @sample_project["Frameworks/libPods.a"].should.not == nil
@sample_project.group('Frameworks').files.where(:name => "libPods-test_runner.a").should.not == nil @sample_project["Frameworks/libPods-test_runner.a"].should.not == nil
end end
it 'creates a workspace with a name matching the project' do it 'creates a workspace with a name matching the project' do
...@@ -66,26 +58,25 @@ describe Pod::Installer::UserProjectIntegrator do ...@@ -66,26 +58,25 @@ describe Pod::Installer::UserProjectIntegrator do
it 'sets the Pods xcconfig as the base config for each build configuration' do it 'sets the Pods xcconfig as the base config for each build configuration' do
@podfile.target_definitions.each do |_, definition| @podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first) target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
xcconfig_file = @sample_project.files.where(:path => "Pods/#{definition.xcconfig_name}") xcconfig_file = @sample_project.files.find { |f| f.path == "Pods/#{definition.xcconfig_name}" }
target.build_configurations.each do |config| target.build_configurations.each do |config|
config.base_configuration.should == xcconfig_file config.base_configuration_reference.should == xcconfig_file
end end
end end
end end
it 'adds the libPods static library to the "Link binary with libraries" build phase of each target' do it 'adds the libPods static library to the "Link binary with libraries" build phase of each target' do
@podfile.target_definitions.each do |_, definition| @podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first) target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
framework_build_phase = target.frameworks_build_phases.first target.frameworks_build_phase.files.find { |f| f.file_ref.name == definition.lib_name}.should.not == nil
framework_build_phase.files.where(:name => definition.lib_name).should.not == nil
end end
end end
it 'adds a Copy Pods Resources build phase to each target' do it 'adds a Copy Pods Resources build phase to each target' do
@podfile.target_definitions.each do |_, definition| @podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first) target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
phase = target.shell_script_build_phases.where(:name => "Copy Pods Resources") phase = target.shell_script_build_phases.find { |bp| bp.name == "Copy Pods Resources" }
phase.shell_script.strip.should == "\"${SRCROOT}/Pods/#{definition.copy_resources_script_name}\"" phase.shell_script.strip.should == "\"${SRCROOT}/Pods/#{definition.copy_resources_script_name}\""
end end
end end
...@@ -101,8 +92,8 @@ describe Pod::Installer::UserProjectIntegrator do ...@@ -101,8 +92,8 @@ describe Pod::Installer::UserProjectIntegrator do
# Remove libPods.a from the app target. But don't do it through TargetIntegrator#targets, # Remove libPods.a from the app target. But don't do it through TargetIntegrator#targets,
# as it will return only those that still need integration. # as it will return only those that still need integration.
app_target = app_integrator.user_project.targets.where(:name => 'SampleProject') app_target = app_integrator.user_project.targets.find { |t| t.name == 'SampleProject' }
app_target.frameworks_build_phases.first.build_files.last.destroy app_target.frameworks_build_phase.files.last.remove_from_project
app_integrator.expects(:add_pods_library) app_integrator.expects(:add_pods_library)
test_runner_integrator.expects(:add_pods_library).never test_runner_integrator.expects(:add_pods_library).never
......
...@@ -389,7 +389,9 @@ else ...@@ -389,7 +389,9 @@ else
installer.install! installer.install!
project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.source_files.should == installer.project.source_files disk_source_files = project.files.sort.reject { |f| f.build_files.empty? }
installer_source_files = installer.project.files.sort.reject { |f| f.build_files.empty? }
disk_source_files.should == installer_source_files
end end
it "creates a project with multiple targets" do it "creates a project with multiple targets" do
...@@ -409,7 +411,7 @@ else ...@@ -409,7 +411,7 @@ else
project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.targets.each do |target| project.targets.each do |target|
phase = target.build_phases.find { |phase| phase.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) } phase = target.build_phases.find { |phase| phase.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) }
files = phase.files.map(&:name) files = phase.files.map { |bf| bf.file_ref.name }
case target.product_name case target.product_name
when 'Pods' when 'Pods'
files.should.include "ASIHTTPRequest.m" files.should.include "ASIHTTPRequest.m"
...@@ -466,9 +468,9 @@ else ...@@ -466,9 +468,9 @@ else
target = project.targets.first target = project.targets.first
target.build_configurations.each do |config| target.build_configurations.each do |config|
config.base_configuration.path.should == 'Pods/Pods.xcconfig' config.base_configuration_reference.path.should == 'Pods/Pods.xcconfig'
end end
target.frameworks_build_phases.first.files.should.include libPods target.frameworks_build_phase.files.should.include libPods.build_files.first
# should be the last phase # should be the last phase
target.build_phases.last.shell_script.should == %{"${SRCROOT}/Pods/Pods-resources.sh"\n} target.build_phases.last.shell_script.should == %{"${SRCROOT}/Pods/Pods-resources.sh"\n}
end end
......
...@@ -30,9 +30,9 @@ describe "Pod::Config" do ...@@ -30,9 +30,9 @@ describe "Pod::Config" do
end end
it "returns the path to the project Podfile if specified with the extension" do it "returns the path to the project Podfile if specified with the extension" do
(temporary_directory + 'Podfile.cocoapods').open('w') { |f| f << '# Yo' } (temporary_directory + 'CocoaPods.podfile').open('w') { |f| f << '# Yo' }
Dir.chdir(temporary_directory) do Dir.chdir(temporary_directory) do
config.project_podfile.should == Pathname.pwd + 'Podfile.cocoapods' config.project_podfile.should == Pathname.pwd + 'CocoaPods.podfile'
end end
end end
......
...@@ -13,7 +13,7 @@ describe Pod::Installer::TargetInstaller do ...@@ -13,7 +13,7 @@ describe Pod::Installer::TargetInstaller do
@target_definition = @podfile.target_definitions[:default] @target_definition = @podfile.target_definitions[:default]
@project = Pod::Project.new @project = Pod::Project.new
@project.main_group.groups.new('name' => 'Targets Support Files') @project.new_group('Targets Support Files')
@installer = Pod::Installer::TargetInstaller.new(@podfile, @project, @target_definition) @installer = Pod::Installer::TargetInstaller.new(@podfile, @project, @target_definition)
...@@ -24,6 +24,7 @@ describe Pod::Installer::TargetInstaller do ...@@ -24,6 +24,7 @@ describe Pod::Installer::TargetInstaller do
end end
def do_install! def do_install!
@pods.each { |pod| pod.add_file_references_to_project(@project) }
@installer.install!(@pods, @sandbox) @installer.install!(@pods, @sandbox)
end end
...@@ -40,14 +41,15 @@ describe Pod::Installer::TargetInstaller do ...@@ -40,14 +41,15 @@ describe Pod::Installer::TargetInstaller do
end end
it 'adds each pod to the static library target' do it 'adds each pod to the static library target' do
@pods[0].expects(:source_file_descriptions).returns([]) @pods[0].expects(:add_build_files_to_target)
do_install! do_install!
end end
it 'tells each pod to link its headers' do # TODO: move to project
@pods[0].expects(:link_headers) # it 'tells each pod to link its headers' do
do_install! # @pods[0].expects(:link_headers)
end # do_install!
# end
it 'adds the sandbox header search paths to the xcconfig, with quotes' do it 'adds the sandbox header search paths to the xcconfig, with quotes' do
do_install! do_install!
...@@ -62,7 +64,7 @@ describe Pod::Installer::TargetInstaller do ...@@ -62,7 +64,7 @@ describe Pod::Installer::TargetInstaller do
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
@podfile.stubs(:set_arc_compatibility_flag? => true) @podfile.stubs(:set_arc_compatibility_flag? => true)
@specification.stubs(:requires_arc).returns(true) @specification.stubs(:requires_arc).returns(true)
@installer.install!(@pods, @sandbox) do_install!
@installer.xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc") @installer.xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc")
end end
......
...@@ -4,18 +4,47 @@ module Pod ...@@ -4,18 +4,47 @@ module Pod
describe Installer do describe Installer do
before do before do
config.repos_dir = fixture('spec-repos') config.repos_dir = fixture('spec-repos')
config.project_pods_root = fixture('integration')
end end
describe "by default" do describe "by default" do
before do
podfile = Podfile.new do
platform :ios
xcodeproj 'MyProject'
pod 'JSONKit'
end
@sandbox = temporary_sandbox
config.project_pods_root = temporary_sandbox.root
FileUtils.cp_r(fixture('integration/JSONKit'), @sandbox.root + 'JSONKit')
@installer = Installer.new(sandbox, podfile)
target_installer = @installer.target_installers.first
target_installer.generate_xcconfig([], @sandbox)
@xcconfig = target_installer.xcconfig.to_hash
end
it "sets the header search paths where installed Pod headers can be found" do
@xcconfig['ALWAYS_SEARCH_USER_PATHS'].should == 'YES'
end
it "configures the project to load all members that implement Objective-c classes or categories from the static library" do
@xcconfig['OTHER_LDFLAGS'].should == '-ObjC'
end
it "sets the PODS_ROOT build variable" do
@xcconfig['PODS_ROOT'].should.not == nil
end
it "generates a BridgeSupport metadata file from all the pod headers" do it "generates a BridgeSupport metadata file from all the pod headers" do
podfile = Podfile.new do podfile = Podfile.new do
platform :osx platform :osx
pod 'ASIHTTPRequest' pod 'ASIHTTPRequest'
end end
sandbox = Sandbox.new(fixture('integration')) FileUtils.cp_r(fixture('integration/ASIHTTPRequest'), @sandbox.root + 'ASIHTTPRequest')
installer = Installer.new(sandbox, podfile) resolver = Resolver.new(podfile, nil, @sandbox)
installer = Installer.new(resolver)
pods = installer.specifications.map do |spec| pods = installer.specifications.map do |spec|
LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform) LocalPod.new(spec, installer.sandbox, podfile.target_definitions[:default].platform)
end end
...@@ -31,7 +60,7 @@ module Pod ...@@ -31,7 +60,7 @@ module Pod
pod 'JSONKit' pod 'JSONKit'
end end
end end
resolver = Resolver.new(podfile, nil, Sandbox.new(fixture('integration'))) resolver = Resolver.new(podfile, nil, @sandbox)
installer = Installer.new(resolver) installer = Installer.new(resolver)
installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty] installer.target_installers.map(&:target_definition).map(&:name).should == [:not_empty]
end end
...@@ -130,7 +159,7 @@ module Pod ...@@ -130,7 +159,7 @@ module Pod
it "adds the files of the pod to the Pods project only once" do it "adds the files of the pod to the Pods project only once" do
@installer.install! @installer.install!
group = @installer.project.pods.groups.where(:name => 'Reachability') group = @installer.project.pods.groups.find { |g| g.name == 'Reachability' }
group.files.map(&:name).should == ["Reachability.h", "Reachability.m"] group.files.map(&:name).should == ["Reachability.h", "Reachability.m"]
end end
...@@ -158,13 +187,13 @@ module Pod ...@@ -158,13 +187,13 @@ module Pod
it "namespaces local pods" do it "namespaces local pods" do
@installer.install! @installer.install!
group = @installer.project.groups.where(:name => 'Local Pods') group = @installer.project['Local Pods']
group.groups.map(&:name).sort.should == %w| Chameleon | group.groups.map(&:name).sort.should == %w| Chameleon |
end end
it "namespaces subspecs" do it "namespaces subspecs" do
@installer.install! @installer.install!
group = @installer.project.groups.where(:name => 'Chameleon') group = @installer.project['Local Pods/Chameleon']
group.groups.map(&:name).sort.should == %w| AVFoundation AssetsLibrary MediaPlayer MessageUI StoreKit UIKit | group.groups.map(&:name).sort.should == %w| AVFoundation AssetsLibrary MediaPlayer MessageUI StoreKit UIKit |
end end
end end
......
...@@ -38,7 +38,7 @@ describe Pod::LocalPod do ...@@ -38,7 +38,7 @@ describe Pod::LocalPod do
].sort ].sort
end end
it "returns the source files groupped by specification" do it "returns the source files grouped by specification" do
files = @pod.source_files_by_spec[@pod.specifications.first].sort files = @pod.source_files_by_spec[@pod.specifications.first].sort
files.should == [ files.should == [
@pod.root + "Classes/Banana.m", @pod.root + "Classes/Banana.m",
...@@ -83,18 +83,26 @@ describe Pod::LocalPod do ...@@ -83,18 +83,26 @@ describe Pod::LocalPod do
end end
it "can add it's source files to an Xcode project target" do it "can add it's source files to an Xcode project target" do
@pod.source_file_descriptions.should == [ project = Pod::Project.new
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.h"), "", nil), @pod.add_file_references_to_project(project)
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.m"), "", nil) project['Pods/BananaLib/Banana.h'].path.should == "BananaLib/Classes/Banana.h"
] project['Pods/BananaLib/Banana.m'].path.should == "BananaLib/Classes/Banana.m"
end end
it "can add it's source files to a target with any specially configured compiler flags" do it "can add it's source files to a target with any specially configured compiler flags" do
project = Pod::Project.new
target = project.new_target(:static, 'Pods', :ios)
@pod.top_specification.compiler_flags = '-d some_flag' @pod.top_specification.compiler_flags = '-d some_flag'
@pod.source_file_descriptions.should == [ @pod.add_file_references_to_project(project)
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.h"), '-d some_flag', nil), @pod.add_build_files_to_target(target)
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.m"), '-d some_flag', nil)
] h_build_file = target.headers_build_phase.files.first
h_build_file.file_ref.path.should == "BananaLib/Classes/Banana.h"
h_build_file.settings.should == {"ATTRIBUTES"=>["Public"]}
m_build_file = target.source_build_phase.files.first
m_build_file.file_ref.path.should == "BananaLib/Classes/Banana.m"
m_build_file.settings.should == {"COMPILER_FLAGS"=>"-d some_flag"}
end end
it "returns the platform" do it "returns the platform" do
...@@ -208,7 +216,8 @@ describe Pod::LocalPod do ...@@ -208,7 +216,8 @@ describe Pod::LocalPod do
/StoreKit/StoreKit_Prefix.pch /StoreKit/StoreKit_Prefix.pch
/UIKit/UIKit_Prefix.pch /UIKit/UIKit_Prefix.pch
] ]
computed = @pod.clean_paths.each{ |p| p.gsub!(@pod.root.to_s, '') } root = @pod.root.to_s
computed = @pod.clean_paths.each{ |p| p.gsub!(root, '') }
assert_array_equals(expected, computed) assert_array_equals(expected, computed)
end end
......
...@@ -105,7 +105,7 @@ describe "Pod::Podfile" do ...@@ -105,7 +105,7 @@ describe "Pod::Podfile" do
end end
path = config.project_root + 'MyProject.xcodeproj' path = config.project_root + 'MyProject.xcodeproj'
config.project_root.expects(:glob).with('*.xcodeproj').returns([path]) Pathname.expects(:glob).with(config.project_root + '*.xcodeproj').returns([path])
podfile.target_definitions[:default].user_project.path.should == path podfile.target_definitions[:default].user_project.path.should == path
podfile.target_definitions[:another_target].user_project.path.should == path podfile.target_definitions[:another_target].user_project.path.should == path
...@@ -113,7 +113,7 @@ describe "Pod::Podfile" do ...@@ -113,7 +113,7 @@ describe "Pod::Podfile" do
it "assumes the basename of the workspace is the same as the default target's project basename" do it "assumes the basename of the workspace is the same as the default target's project basename" do
path = config.project_root + 'MyProject.xcodeproj' path = config.project_root + 'MyProject.xcodeproj'
config.project_root.expects(:glob).with('*.xcodeproj').returns([path]) Pathname.expects(:glob).with(config.project_root + '*.xcodeproj').returns([path])
Pod::Podfile.new {}.workspace.should == config.project_root + 'MyProject.xcworkspace' Pod::Podfile.new {}.workspace.should == config.project_root + 'MyProject.xcworkspace'
Pod::Podfile.new do Pod::Podfile.new do
...@@ -225,13 +225,13 @@ describe "Pod::Podfile" do ...@@ -225,13 +225,13 @@ describe "Pod::Podfile" do
it "returns a Xcode project found in the working dir when no explicit project is specified" do it "returns a Xcode project found in the working dir when no explicit project is specified" do
xcodeproj1 = config.project_root + '1.xcodeproj' xcodeproj1 = config.project_root + '1.xcodeproj'
config.project_root.expects(:glob).with('*.xcodeproj').returns([xcodeproj1]) Pathname.expects(:glob).with(config.project_root + '*.xcodeproj').returns([xcodeproj1])
Pod::Podfile::UserProject.new.path.should == xcodeproj1 Pod::Podfile::UserProject.new.path.should == xcodeproj1
end end
it "returns `nil' if more than one Xcode project was found in the working when no explicit project is specified" do it "returns `nil' if more than one Xcode project was found in the working when no explicit project is specified" do
xcodeproj1, xcodeproj2 = config.project_root + '1.xcodeproj', config.project_root + '2.xcodeproj' xcodeproj1, xcodeproj2 = config.project_root + '1.xcodeproj', config.project_root + '2.xcodeproj'
config.project_root.expects(:glob).with('*.xcodeproj').returns([xcodeproj1, xcodeproj2]) Pathname.expects(:glob).with(config.project_root + '*.xcodeproj').returns([xcodeproj1, xcodeproj2])
Pod::Podfile::UserProject.new.path.should == nil Pod::Podfile::UserProject.new.path.should == nil
end end
......
...@@ -5,44 +5,32 @@ describe 'Pod::Project' do ...@@ -5,44 +5,32 @@ describe 'Pod::Project' do
@project = Pod::Project.new @project = Pod::Project.new
end end
def find_object(conditions)
@project.objects_hash.select do |_, object|
(conditions.keys - object.keys).empty? && object.values_at(*conditions.keys) == conditions.values
end.first
end
it "adds a group to the `Pods' group" do it "adds a group to the `Pods' group" do
group = @project.add_spec_group('JSONKit', @project.pods) group = @project.add_spec_group('JSONKit', @project.pods)
@project.pods.child_references.should.include group.uuid @project.pods.children.should.include?(group)
find_object({ g = @project['Pods/JSONKit']
'isa' => 'PBXGroup', g.name.should == 'JSONKit'
'name' => 'JSONKit', g.children.should.be.empty?
'sourceTree' => '<group>',
'children' => []
}).should.not == nil
end end
it "namespaces subspecs in groups" do it "namespaces subspecs in groups" do
group = @project.add_spec_group('JSONKit/Subspec', @project.pods) group = @project.add_spec_group('JSONKit/Subspec', @project.pods)
@project.pods.groups.find { |g| g.name == 'JSONKit' }.child_references.should.include group.uuid @project.pods.groups.find { |g| g.name == 'JSONKit' }.children.should.include?(group)
find_object({ g = @project['Pods/JSONKit/Subspec']
'isa' => 'PBXGroup', g.name.should == 'Subspec'
'name' => 'Subspec', g.children.should.be.empty?
'sourceTree' => '<group>',
'children' => []
}).should.not == nil
end end
it "creates a copy build header phase which will copy headers to a specified path" do # it "creates a copy build header phase which will copy headers to a specified path" do
@project.targets.new # @project.targets.new
phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source") # phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
find_object({ # find_object({
'isa' => 'PBXCopyFilesBuildPhase', # 'isa' => 'PBXCopyFilesBuildPhase',
'dstPath' => 'Pods/Path/To/Source', # 'dstPath' => 'Pods/Path/To/Source',
'name' => 'Copy SomePod Public Headers' # 'name' => 'Copy SomePod Public Headers'
}).should.not == nil # }).should.not == nil
@project.targets.first.build_phases.should.include phase # @project.targets.first.build_phases.should.include phase
end # end
it "adds build configurations named after every configuration across all of the user's projects" do it "adds build configurations named after every configuration across all of the user's projects" do
@project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'Test' => :debug, 'AppStore' => :release } @project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'Test' => :debug, 'AppStore' => :release }
......
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