Commit 064085ec authored by Fabio Pelosin's avatar Fabio Pelosin

Merge branch 'master' into lookback-pods-by-config

* master: (294 commits)
  Bundle: update cocoapods-core
  Bundle: update Xcodeproj
  Validator: check license only in root spec
  Bundle: udpate cocoapods-core
  Integration: update for Xcodeproj
  Specs: fix for changes to Xcodeproj
  Update integration specs for Xcodeproj
  Gem: update Xcodeproj dependency
  Integration: update acknowledgements
  Bundle: make xcodeproj faster on mac
  Update integration specs for Xcodeproj
  Bundle:update
  CI: disable Ruby 1.8.7 for now
  Xcodeproj: udpate
  Bundle: update cocoapods-trunk version
  [Sandbox] Evaluate podspecs from their original path
  [Install/Update] Clarify command description. Relates to #2270.
  [README] Flatten badges
  [Gemspec] Update to nap 0.8
  Pod::Command::Spec::Lint::description update
  ...

Conflicts:
	CHANGELOG.md
	Gemfile.lock
	spec/cocoapods-integration-specs
parents a009895b c2366c33
...@@ -30,4 +30,14 @@ examples/RelativePathProject/RelativePathProject/RelativePathProject.xcodeproj ...@@ -30,4 +30,14 @@ examples/RelativePathProject/RelativePathProject/RelativePathProject.xcodeproj
coverage/ coverage/
.coveralls.yml .coveralls.yml
# IDEs
*.xccheckout *.xccheckout
.idea/
# RVM files
/.rvmrc
/.ruby-version
/.ruby-gemset
# Bundler files
/.bundle
[submodule "spec/fixtures/integration/ASIHTTPRequest"]
path = spec/fixtures/integration/ASIHTTPRequest
url = https://github.com/pokeb/asi-http-request.git
[submodule "spec/fixtures/integration/SSZipArchive"]
path = spec/fixtures/integration/SSZipArchive
url = https://github.com/samsoffes/ssziparchive.git
[submodule "spec/fixtures/integration/JSONKit"] [submodule "spec/fixtures/integration/JSONKit"]
path = spec/fixtures/integration/JSONKit path = spec/fixtures/integration/JSONKit
url = https://github.com/johnezang/JSONKit.git url = https://github.com/johnezang/JSONKit.git
[submodule "spec/fixtures/integration/sstoolkit"]
path = spec/fixtures/integration/sstoolkit
url = https://github.com/samsoffes/sstoolkit.git
ignore = dirty
[submodule "spec/fixtures/spec-repos/master"] [submodule "spec/fixtures/spec-repos/master"]
path = spec/fixtures/spec-repos/master path = spec/fixtures/spec-repos/master
url = https://github.com/CocoaPods/Specs.git url = https://github.com/CocoaPods/Specs.git
......
recipe :ruby recipe :ruby
Kicker::Recipes::Ruby.runner_bin = 'bacon' Kicker::Recipes::Ruby.runner_bin = 'bacon --quiet'
process do |files| process do |files|
specs = files.take_and_map do |file| specs = files.take_and_map do |file|
......
# Sets Travis to run the Ruby specs on OS X machines which are required to
# build the native extensions of Xcodeproj.
#
language: objective-c language: objective-c
env: env:
# This is what 10.8.x comes with and we want to support that. - RVM_RUBY_VERSION=system
- RVM_RUBY_VERSION=system NOEXEC_DISABLE=1 XCODEPROJ_BUILD=1 BUNDLE_WITHOUT='debugging:documentation' RUBY_VERSION_SPECIFIC='sudo ln -s /usr/bin/llvm-gcc-4.2 /usr/bin/gcc-4.2' SSL_CERT_FILE=/usr/local/share/cacert.pem GIT_AUTHOR_NAME=CocoaPods GIT_AUTHOR_EMAIL=cocoapods@example.com PYTHONPATH=/usr/local/lib/python2.7/site-packages # - RVM_RUBY_VERSION=1.8.7-p358
- RVM_RUBY_VERSION=2.0.0-p247 NOEXEC_DISABLE=1 XCODEPROJ_BUILD=1 BUNDLE_WITHOUT='debugging:documentation' RUBY_VERSION_SPECIFIC='sudo gem install bundler --no-ri --no-rdoc' GIT_AUTHOR_NAME=CocoaPods GIT_AUTHOR_EMAIL=cocoapods@example.com PYTHONPATH=/usr/local/lib/python2.7/site-packages
before_install: before_install:
- export LANG=en_US.UTF-8
- curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem - curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
# - sh -c 'if [ "$RVM_RUBY_VERSION" != "system" ]; then rvm install $RVM_RUBY_VERSION --without-tcl --without-tk; fi' - source ~/.rvm/scripts/rvm
- source ~/.rvm/scripts/rvm && rvm use $RVM_RUBY_VERSION - if [[ $RVM_RUBY_VERSION != 'system' ]]; then rvm install $RVM_RUBY_VERSION; fi
- brew update && brew install bzr - rvm use $RVM_RUBY_VERSION
install: eval $RUBY_VERSION_SPECIFIC && rake bootstrap[use_bundle_dir] - if [[ $RVM_RUBY_VERSION == 'system' ]]; then export ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future; fi
script: bundle exec rake spec:ci - if [[ $RVM_RUBY_VERSION == 'system' ]]; then sudo gem install bundler --no-ri --no-rdoc; else gem install bundler --no-ri --no-rdoc; fi
install:
- bundle install --without=debugging documentation --path ./travis_bundle_dir
# CocoaPods/CocoaPods specific
- ./bin/pod repo update --silent
script: rake spec
notifications: notifications:
campfire: campfire:
on_success: change on_success: change
on_failure: always on_failure: always
rooms: rooms:
- secure: "qOE5zmgaHe/qQu3W9rmj7wygA5Ivl+cx50fqWGag2bdRl8ly5yj1NVoOKk/O\nZmQc4Lze+301uvTXi+r5v8A/tF6W1kUZw7yBiKuXoYFUGmDiVR9o2I/FPwkL\ngSzPJttrXTQfkQ4PbnrkX+JO+5bLWrKaO0hKXT4B2yUu4UXLVk0=" - secure: "qOE5zmgaHe/qQu3W9rmj7wygA5Ivl+cx50fqWGag2bdRl8ly5yj1NVoOKk/O\nZmQc4Lze+301uvTXi+r5v8A/tF6W1kUZw7yBiKuXoYFUGmDiVR9o2I/FPwkL\ngSzPJttrXTQfkQ4PbnrkX+JO+5bLWrKaO0hKXT4B2yUu4UXLVk0="
This diff is collapsed.
# Do’s and Don’ts # Do’s and Don’ts
* **Search the solutions in the [troubleshooting guide](http://guides.cocoapods.org/using/troubleshooting.html).** Or any of the many other [guides](http://guides.cocoapods.org).
* **Search tickets before you file a new one.** Add to tickets if you have new information about the issue. * **Search tickets before you file a new one.** Add to tickets if you have new information about the issue.
* **Only file tickets about the CocoaPods tool itself.** This includes [CocoaPods](https://github.com/CocoaPods/CocoaPods/issues), * **Only file tickets about the CocoaPods tool itself.** This includes [CocoaPods](https://github.com/CocoaPods/CocoaPods/issues),
[CocoaPods/Core](https://github.com/CocoaPods/Core/issues), and [Xcodeproj](https://github.com/CocoaPods/Xcodeproj/issues). [CocoaPods/Core](https://github.com/CocoaPods/Core/issues), and [Xcodeproj](https://github.com/CocoaPods/Xcodeproj/issues).
...@@ -48,7 +49,7 @@ Should you require a feature isn't suited for mainstream users, consider suggest ...@@ -48,7 +49,7 @@ Should you require a feature isn't suited for mainstream users, consider suggest
## Pull Requests ## Pull Requests
We **love** pull requests and if a contribution is significant we tend to offer We **love** pull requests and if a contribution is significant we tend to offer
push access. push access. We suggest you take a look at our [Contributing guide](http://guides.cocoapods.org/contributing/contribute-to-cocoapods.html) for info on development setup, and some of our best practices.
All contributions _will_ be licenced under the MIT license. All contributions _will_ be licenced under the MIT license.
......
...@@ -10,31 +10,41 @@ group :development do ...@@ -10,31 +10,41 @@ group :development do
# For more info see http://bundler.io/git.html#local # For more info see http://bundler.io/git.html#local
gem 'cocoapods-core', :git => "https://github.com/CocoaPods/Core.git", :branch => 'lookback-pods-by-config' gem 'cocoapods-core', :git => "https://github.com/CocoaPods/Core.git", :branch => 'lookback-pods-by-config'
gem 'xcodeproj', :git => "https://github.com/CocoaPods/Xcodeproj.git", :branch => 'master' gem 'xcodeproj', :git => "https://github.com/CocoaPods/Xcodeproj.git", :branch => 'master'
gem 'cocoapods-downloader', :git => "https://github.com/CocoaPods/cocoapods-downloader.git", :branch => 'master'
gem 'claide', :git => 'https://github.com/CocoaPods/CLAide.git', :branch => 'master' gem 'claide', :git => 'https://github.com/CocoaPods/CLAide.git', :branch => 'master'
gem 'cocoapods-downloader', :git => "https://github.com/CocoaPods/cocoapods-downloader.git", :branch => 'master'
gem 'cocoapods-try', :git => 'https://github.com/CocoaPods/cocoapods-try.git', :branch => 'master'
gem 'cocoapods-plugins', :git => 'https://github.com/CocoaPods/cocoapods-plugins.git', :branch => 'master'
gem 'cocoapods-trunk', :git => 'https://github.com/CocoaPods/cocoapods-trunk.git', :branch => 'master'
gem "mocha" gem 'rake', '~> 10.1.0' # Ruby 1.8.7
gem "mocha", '~> 1.0.0' # Issues with Ruby 2.0.0 on Travis
gem "bacon" gem "bacon"
gem "mocha-on-bacon" gem "mocha-on-bacon"
gem 'prettybacon', :git => 'https://github.com/irrationalfab/PrettyBacon.git', :branch => 'master' gem 'prettybacon'
gem "rake" gem 'webmock', "< 1.16"
# For the integration tests # For the integration tests
gem "diffy" gem "diffy"
# Lock the current lowest requirement for ActiveSupport 3 to ensure we don't
# re-introduce https://github.com/CocoaPods/CocoaPods/issues/1950
gem 'i18n', '0.6.4'
gem 'mime-types', '< 2' # v2 is 1.9.x only gem 'mime-types', '< 2' # v2 is 1.9.x only
gem 'coveralls', :require => false gem 'coveralls', :require => false
# Explicitly add this, otherwise it might sometimes be missing: # Explicitly add this, otherwise it might sometimes be missing:
# https://github.com/lemurheavy/coveralls-ruby/blob/master/coveralls-ruby.gemspec#L23. # https://github.com/lemurheavy/coveralls-ruby/blob/master/coveralls-ruby.gemspec#L23.
gem 'simplecov' gem 'simplecov'
if RUBY_PLATFORM.include?('darwin')
# Make Xcodeproj faster
gem 'libxml-ruby'
end
end end
group :debugging do group :debugging do
# Only while we test the trunk app.
gem 'cocoapods-trunk', :git => "https://github.com/alloy/cocoapods-trunk.git"
gem "rb-fsevent" gem "rb-fsevent"
gem "kicker", :git => "https://github.com/alloy/kicker.git", :branch => "master" gem "kicker"
gem "awesome_print" gem "awesome_print"
gem "pry" gem "pry"
# The released gem leads to stack too deep when profiling a full run. # The released gem leads to stack too deep when profiling a full run.
......
GIT GIT
remote: https://github.com/CocoaPods/CLAide.git remote: https://github.com/CocoaPods/CLAide.git
revision: f5e4752d8cc4ba055e1d96713275e9955fea9f37 revision: 2d1ade5e062be937e630920c7399dbe1bee48d93
branch: master branch: master
specs: specs:
claide (0.4.0) claide (0.6.1)
GIT GIT
remote: https://github.com/CocoaPods/Core.git remote: https://github.com/CocoaPods/Core.git
revision: 6d775a30b10246ee0f87dc241788ab0b5fe89447 revision: 1f6273aeb346b9d21008438b37594106fca4b7f6
branch: lookback-pods-by-config branch: lookback-pods-by-config
specs: specs:
cocoapods-core (0.29.0) cocoapods-core (0.33.1)
activesupport (>= 3.2.15, < 4) activesupport (>= 3.2.15)
fuzzy_match (~> 2.0.4) fuzzy_match (~> 2.0.4)
json_pure (~> 1.8) json_pure (~> 1.8)
nap (~> 0.5) nap (~> 0.5)
GIT GIT
remote: https://github.com/CocoaPods/Xcodeproj.git remote: https://github.com/CocoaPods/Xcodeproj.git
revision: 0704b7772370feb8be154ace0ce48e09f215aeaf revision: f835e6e1145812ac04ac4b658321c727c2967547
branch: master branch: master
specs: specs:
xcodeproj (0.14.1) xcodeproj (0.18.0)
CFPropertyList (~> 2.2)
activesupport (~> 3.0) activesupport (~> 3.0)
colored (~> 1.2) colored (~> 1.2)
rake
GIT GIT
remote: https://github.com/CocoaPods/cocoapods-downloader.git remote: https://github.com/CocoaPods/cocoapods-downloader.git
revision: 4a95877b20893b374dfd43624e12bac167feef05 revision: 27a5c58d7d7aaf8886c47624260d167fa776175c
branch: master branch: master
specs: specs:
cocoapods-downloader (0.3.0) cocoapods-downloader (0.6.1)
GIT GIT
remote: https://github.com/alloy/cocoapods-trunk.git remote: https://github.com/CocoaPods/cocoapods-plugins.git
revision: 20b9a8bb60ad6e59df4df7d4a960a4dd4a41afa0 revision: 0740e01bc8b99cbd8249e766fc4a87eae71e995e
branch: master
specs: specs:
cocoapods-trunk (0.0.1) cocoapods-plugins (0.2.0)
json (~> 1.8) nap
nap (>= 0.6)
netrc
GIT GIT
remote: https://github.com/alloy/kicker.git remote: https://github.com/CocoaPods/cocoapods-trunk.git
revision: 87b0047202c0320d4ef62e1f1a4b2cbdefadf008 revision: c62f86f83bf77faf8baf80359cc511dd1014fcfb
branch: master branch: master
specs: specs:
kicker (3.0.0) cocoapods-trunk (0.1.4)
listen (~> 1.3.0) json_pure (~> 1.8)
notify (~> 0.5.2) nap (>= 0.6)
netrc
GIT GIT
remote: https://github.com/irrationalfab/PrettyBacon.git remote: https://github.com/CocoaPods/cocoapods-try.git
revision: eaf7e6c786fd5ccc6fb88e943bf7c5e6c27569a3 revision: 754e53f3c3eec4c5ba129d6955484fb27631d1d5
branch: master branch: master
specs: specs:
prettybacon (0.0.1) cocoapods-try (0.3.0)
bacon (~> 1.2)
GIT GIT
remote: https://github.com/ruby-prof/ruby-prof.git remote: https://github.com/ruby-prof/ruby-prof.git
revision: b56c1268ba001f5eb55f940ca1c83bc6b83a9752 revision: e3317c4bf0b58dceee86e5dd9cf03165fcfd964f
specs: specs:
ruby-prof (0.14.2) ruby-prof (0.15.1)
PATH PATH
remote: . remote: .
specs: specs:
cocoapods (0.29.0) cocoapods (0.33.1)
activesupport (>= 3.2.15, < 4) activesupport (>= 3.2.15, < 4)
claide (~> 0.4.0) claide (~> 0.6.1)
cocoapods-core (= 0.29.0) cocoapods-core (= 0.33.1)
cocoapods-downloader (~> 0.3.0) cocoapods-downloader (~> 0.6.1)
cocoapods-try-release-fix (~> 0.1.1) cocoapods-plugins (~> 0.2.0)
cocoapods-trunk (~> 0.1.4)
cocoapods-try (~> 0.3.0)
colored (~> 1.2) colored (~> 1.2)
escape (~> 0.0.4) escape (~> 0.0.4)
json_pure (~> 1.8) json_pure (~> 1.8)
nap (~> 0.5) nap (~> 0.8)
open4 (~> 1.3) open4 (~> 1.3)
xcodeproj (~> 0.14.1) xcodeproj (~> 0.18.0)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
specs: specs:
activesupport (3.2.16) CFPropertyList (2.2.8)
activesupport (3.2.19)
i18n (~> 0.6, >= 0.6.4) i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0) multi_json (~> 1.0)
addressable (2.3.6)
awesome_print (1.2.0) awesome_print (1.2.0)
bacon (1.2.0) bacon (1.2.0)
cocoapods-try-release-fix (0.1.1)
coderay (1.1.0) coderay (1.1.0)
colored (1.2) colored (1.2)
coveralls (0.7.0) coveralls (0.7.0)
...@@ -98,60 +100,73 @@ GEM ...@@ -98,60 +100,73 @@ GEM
simplecov (>= 0.7) simplecov (>= 0.7)
term-ansicolor term-ansicolor
thor thor
diffy (3.0.1) crack (0.4.2)
docile (1.1.3) safe_yaml (~> 1.0.0)
diffy (3.0.6)
docile (1.1.5)
escape (0.0.4) escape (0.0.4)
ffi (1.9.3) ffi (1.9.3)
fuzzy_match (2.0.4) fuzzy_match (2.0.4)
github-markup (1.0.1) github-markup (1.2.1)
i18n (0.6.9) posix-spawn (~> 0.3.8)
json (1.8.1) i18n (0.6.4)
json_pure (1.8.1) json_pure (1.8.1)
kicker (3.0.0)
listen (~> 1.3.0)
notify (~> 0.5.2)
libxml-ruby (2.7.0)
listen (1.3.1) listen (1.3.1)
rb-fsevent (>= 0.9.3) rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9) rb-inotify (>= 0.9)
rb-kqueue (>= 0.2) rb-kqueue (>= 0.2)
metaclass (0.0.2) metaclass (0.0.4)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
mocha (1.0.0) mocha (1.0.0)
metaclass (~> 0.0.1) metaclass (~> 0.0.1)
mocha-on-bacon (0.2.2) mocha-on-bacon (0.2.2)
mocha (>= 0.13.0) mocha (>= 0.13.0)
multi_json (1.8.4) multi_json (1.10.1)
nap (0.6.0) nap (0.8.0)
netrc (0.7.7) netrc (0.7.7)
notify (0.5.2) notify (0.5.2)
open4 (1.3.0) open4 (1.3.4)
posix-spawn (0.3.8) posix-spawn (0.3.8)
pry (0.9.12.6) prettybacon (0.0.2)
coderay (~> 1.0) bacon (~> 1.2)
method_source (~> 0.8) pry (0.10.0)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
pygments.rb (0.5.4) pygments.rb (0.6.0)
posix-spawn (~> 0.3.6) posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0) yajl-ruby (~> 1.1.0)
rake (10.1.1) rake (10.1.1)
rb-fsevent (0.9.4) rb-fsevent (0.9.4)
rb-inotify (0.9.3) rb-inotify (0.9.5)
ffi (>= 0.5.0) ffi (>= 0.5.0)
rb-kqueue (0.2.0) rb-kqueue (0.2.3)
ffi (>= 0.5.0) ffi (>= 0.5.0)
redcarpet (2.3.0) redcarpet (2.3.0)
rest-client (1.6.7) rest-client (1.7.2)
mime-types (>= 1.16) mime-types (>= 1.16, < 3.0)
simplecov (0.8.2) netrc (~> 0.7)
safe_yaml (1.0.3)
simplecov (0.9.0)
docile (~> 1.1.0) docile (~> 1.1.0)
multi_json multi_json
simplecov-html (~> 0.8.0) simplecov-html (~> 0.8.0)
simplecov-html (0.8.0) simplecov-html (0.8.0)
slop (3.4.7) slop (3.6.0)
term-ansicolor (1.2.2) term-ansicolor (1.3.0)
tins (~> 0.8) tins (~> 1.0)
thor (0.18.1) thor (0.19.1)
tins (0.13.2) tins (1.3.0)
webmock (1.15.2)
addressable (>= 2.2.7)
crack (>= 0.3.2)
yajl-ruby (1.1.0) yajl-ruby (1.1.0)
yard (0.8.7.3) yard (0.8.7.4)
PLATFORMS PLATFORMS
ruby ruby
...@@ -163,21 +178,26 @@ DEPENDENCIES ...@@ -163,21 +178,26 @@ DEPENDENCIES
cocoapods! cocoapods!
cocoapods-core! cocoapods-core!
cocoapods-downloader! cocoapods-downloader!
cocoapods-plugins!
cocoapods-trunk! cocoapods-trunk!
cocoapods-try!
coveralls coveralls
diffy diffy
github-markup github-markup
kicker! i18n (= 0.6.4)
kicker
libxml-ruby
mime-types (< 2) mime-types (< 2)
mocha mocha (~> 1.0.0)
mocha-on-bacon mocha-on-bacon
prettybacon! prettybacon
pry pry
pygments.rb pygments.rb
rake rake (~> 10.1.0)
rb-fsevent rb-fsevent
redcarpet (< 3.0.0) redcarpet (< 3.0.0)
ruby-prof! ruby-prof!
simplecov simplecov
webmock (< 1.16)
xcodeproj! xcodeproj!
yard yard
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
### CocoaPods: The Objective-C dependency manager ### CocoaPods: The Objective-C dependency manager
[![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg)](https://travis-ci.org/CocoaPods/CocoaPods) [![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg?style=flat)](https://travis-ci.org/CocoaPods/CocoaPods)
[![Gem Version](http://img.shields.io/gem/v/cocoapods.svg)](http://badge.fury.io/rb/cocoapods) [![Gem Version](http://img.shields.io/gem/v/cocoapods.svg?style=flat)](http://badge.fury.io/rb/cocoapods)
[![Code Climate](http://img.shields.io/codeclimate/github/CocoaPods/CocoaPods.svg)](https://codeclimate.com/github/CocoaPods/CocoaPods) [![Code Climate](http://img.shields.io/codeclimate/github/CocoaPods/CocoaPods.svg?style=flat)](https://codeclimate.com/github/CocoaPods/CocoaPods)
CocoaPods manages dependencies for your Xcode projects. CocoaPods manages dependencies for your Xcode projects.
...@@ -50,10 +50,10 @@ CocoaPods is composed by the following projects: ...@@ -50,10 +50,10 @@ CocoaPods is composed by the following projects:
| Status | Project | Description | Info | | Status | Project | Description | Info |
| :----- | :------ | :--- | :--- | | :----- | :------ | :--- | :--- |
| [![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg)](http://travis-ci.org/CocoaPods/CocoaPods) | [CocoaPods](https://github.com/CocoaPods/CocoaPods) | The CocoaPods command line tool. | [docs](http://docs.cocoapods.org/cocoapods) | [![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg?style=flat)](http://travis-ci.org/CocoaPods/CocoaPods) | [CocoaPods](https://github.com/CocoaPods/CocoaPods) | The CocoaPods command line tool. | [docs](http://docs.cocoapods.org/cocoapods)
| [![Build Status](http://img.shields.io/travis/CocoaPods/Core/master.svg)](http://travis-ci.org/CocoaPods/Core) | [CocoaPods Core](https://github.com/CocoaPods/Core) | Support for working with specifications and podfiles. | [docs](http://docs.cocoapods.org/cocoapods_core) | [![Build Status](http://img.shields.io/travis/CocoaPods/Core/master.svg?style=flat)](http://travis-ci.org/CocoaPods/Core) | [CocoaPods Core](https://github.com/CocoaPods/Core) | Support for working with specifications and podfiles. | [docs](http://docs.cocoapods.org/cocoapods_core)
| [![Build Status](http://img.shields.io/travis/CocoaPods/cocoapods-downloader/master.svg)](http://travis-ci.org/CocoaPods/cocoapods-downloader) |[CocoaPods Downloader](https://github.com/CocoaPods/cocoapods-downloader) | Downloaders for various source types. | [docs](http://docs.cocoapods.org/cocoapods_downloader/index.html) | [![Build Status](http://img.shields.io/travis/CocoaPods/cocoapods-downloader/master.svg?style=flat)](http://travis-ci.org/CocoaPods/cocoapods-downloader) |[CocoaPods Downloader](https://github.com/CocoaPods/cocoapods-downloader) | Downloaders for various source types. | [docs](http://docs.cocoapods.org/cocoapods_downloader/index.html)
| [![Build Status](http://img.shields.io/travis/CocoaPods/Xcodeproj/master.svg)](https://travis-ci.org/CocoaPods/Xcodeproj) | [Xcodeproj](https://github.com/CocoaPods/Xcodeproj) | Create and modify Xcode projects from Ruby. | [docs](http://docs.cocoapods.org/xcodeproj/index.html) | [![Build Status](http://img.shields.io/travis/CocoaPods/Xcodeproj/master.svg?style=flat)](https://travis-ci.org/CocoaPods/Xcodeproj) | [Xcodeproj](https://github.com/CocoaPods/Xcodeproj) | Create and modify Xcode projects from Ruby. | [docs](http://docs.cocoapods.org/xcodeproj/index.html)
| [![Build Status](http://img.shields.io/travis/CocoaPods/CLAide/master.svg)](https://travis-ci.org/CocoaPods/CLAide) | [CLAide](https://github.com/CocoaPods/CLAide) | A small command-line interface framework. | [docs](http://docs.cocoapods.org/claide/index.html) | [![Build Status](http://img.shields.io/travis/CocoaPods/CLAide/master.svg?style=flat)](https://travis-ci.org/CocoaPods/CLAide) | [CLAide](https://github.com/CocoaPods/CLAide) | A small command-line interface framework. | [docs](http://docs.cocoapods.org/claide/index.html)
| [![Build Status](http://img.shields.io/travis/CocoaPods/Specs/master.svg)](http://travis-ci.org/CocoaPods/Specs) | [Master Repo ](https://github.com/CocoaPods/Specs) | Master repository of specifications. | [guide](http://docs.cocoapods.org/guides/contributing_to_the_master_repo.html) | | [Master Repo ](https://github.com/CocoaPods/Specs) | Master repository of specifications. | [guide](http://docs.cocoapods.org/guides/contributing_to_the_master_repo.html)
This diff is collapsed.
#!/usr/bin/env ruby #!/usr/bin/env ruby
if RUBY_VERSION > '1.8.7' && Encoding.default_external != Encoding::UTF_8 if RUBY_VERSION > '1.8.7' && Encoding.default_external != Encoding::UTF_8
puts <<-DOC puts "\e[33mWARNING: CocoaPods requires your terminal to be using UTF-8 encoding."
\e[33mWARNING: CocoaPods requires your terminal to be using UTF-8 encoding. if ENV["TRAVIS"]
puts <<-DOC
Consider adding the following settings to .travis.yml
before_script:
- export LANG=en_US.UTF-8\e[0m\n
DOC
else
puts <<-DOC
See https://github.com/CocoaPods/guides.cocoapods.org/issues/26 for See https://github.com/CocoaPods/guides.cocoapods.org/issues/26 for
possible solutions.\e[0m\n possible solutions.\e[0m\n
DOC DOC
end
end end
if $PROGRAM_NAME == __FILE__ && !ENV['COCOAPODS_NO_BUNDLER'] if $PROGRAM_NAME == __FILE__ && !ENV['COCOAPODS_NO_BUNDLER']
......
...@@ -27,18 +27,20 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA ...@@ -27,18 +27,20 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA
s.require_paths = %w{ lib } s.require_paths = %w{ lib }
# Link with the version of CocoaPods-Core # Link with the version of CocoaPods-Core
s.add_runtime_dependency 'cocoapods-core', "= #{Pod::VERSION}" s.add_runtime_dependency 'cocoapods-core', "= #{Pod::VERSION}"
s.add_runtime_dependency 'claide', '~> 0.4.0' s.add_runtime_dependency 'claide', '~> 0.6.1'
s.add_runtime_dependency 'cocoapods-downloader', '~> 0.3.0' s.add_runtime_dependency 'xcodeproj', '~> 0.18.0'
s.add_runtime_dependency 'xcodeproj', '~> 0.14.1' s.add_runtime_dependency 'cocoapods-downloader', '~> 0.6.1'
s.add_runtime_dependency 'cocoapods-try-release-fix', '~> 0.1.1' s.add_runtime_dependency 'cocoapods-plugins', '~> 0.2.0'
s.add_runtime_dependency 'cocoapods-try', '~> 0.3.0'
s.add_runtime_dependency 'cocoapods-trunk', '~> 0.1.4'
s.add_runtime_dependency 'colored', '~> 1.2' s.add_runtime_dependency 'colored', '~> 1.2'
s.add_runtime_dependency 'escape', '~> 0.0.4' s.add_runtime_dependency 'escape', '~> 0.0.4'
s.add_runtime_dependency 'json_pure', '~> 1.8' s.add_runtime_dependency 'json_pure', '~> 1.8'
s.add_runtime_dependency 'open4', '~> 1.3' s.add_runtime_dependency 'open4', '~> 1.3'
s.add_runtime_dependency 'activesupport', '>= 3.2.15', '< 4' s.add_runtime_dependency 'activesupport', '>= 3.2.15', '< 4'
s.add_runtime_dependency 'nap', '~> 0.5' s.add_runtime_dependency 'nap', '~> 0.8'
s.add_development_dependency 'bacon', '~> 1.1' s.add_development_dependency 'bacon', '~> 1.1'
......
...@@ -9,7 +9,10 @@ require 'active_support/core_ext/string/inflections' ...@@ -9,7 +9,10 @@ require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/array/conversions'
# TODO check what this actually does by the time we're going to add support for # TODO check what this actually does by the time we're going to add support for
# other locales. # other locales.
I18n.enforce_available_locales = false require 'i18n'
if I18n.respond_to?(:enforce_available_locales=)
I18n.enforce_available_locales = false
end
module Pod module Pod
require 'pathname' require 'pathname'
...@@ -19,6 +22,11 @@ module Pod ...@@ -19,6 +22,11 @@ module Pod
require 'cocoapods/config' require 'cocoapods/config'
require 'cocoapods/downloader' require 'cocoapods/downloader'
# Loaded immediately after dependencies to ensure proper override of their
# UI methods.
#
require 'cocoapods/user_interface'
# Indicates an user error. This is defined in cocoapods-core. # Indicates an user error. This is defined in cocoapods-core.
# #
class Informative < PlainInformative class Informative < PlainInformative
...@@ -38,7 +46,6 @@ module Pod ...@@ -38,7 +46,6 @@ module Pod
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 :UI, 'cocoapods/user_interface'
autoload :Validator, 'cocoapods/validator' autoload :Validator, 'cocoapods/validator'
module Generator module Generator
......
...@@ -14,23 +14,24 @@ module Pod ...@@ -14,23 +14,24 @@ module Pod
require 'cocoapods/command/list' require 'cocoapods/command/list'
require 'cocoapods/command/outdated' require 'cocoapods/command/outdated'
require 'cocoapods/command/project' require 'cocoapods/command/project'
require 'cocoapods/command/push'
require 'cocoapods/command/repo' require 'cocoapods/command/repo'
require 'cocoapods/command/search' require 'cocoapods/command/search'
require 'cocoapods/command/setup' require 'cocoapods/command/setup'
require 'cocoapods/command/spec' require 'cocoapods/command/spec'
require 'cocoapods/command/init' require 'cocoapods/command/init'
# TODO: remove
require 'cocoapods/command/push'
self.abstract_command = true self.abstract_command = true
self.default_subcommand = 'install'
self.command = 'pod' self.command = 'pod'
self.version = VERSION
self.description = 'CocoaPods, the Objective-C library package manager.' self.description = 'CocoaPods, the Objective-C library package manager.'
self.plugin_prefix = 'cocoapods' self.plugin_prefix = 'cocoapods'
def self.options def self.options
[ [
['--silent', 'Show nothing'], ['--silent', 'Show nothing'],
['--version', 'Show the version of CocoaPods'],
].concat(super) ].concat(super)
end end
...@@ -43,11 +44,7 @@ module Pod ...@@ -43,11 +44,7 @@ module Pod
end end
def self.run(argv) def self.run(argv)
argv = CLAide::ARGV.new(argv) help! "You cannot run CocoaPods as root." if Process.uid == 0
if argv.flag?('version')
UI.puts VERSION
exit 0
end
super(argv) super(argv)
UI.print_warnings UI.print_warnings
end end
......
...@@ -2,7 +2,9 @@ module Pod ...@@ -2,7 +2,9 @@ module Pod
class Command class Command
class Help < Command class Help < Command
self.summary = 'Show help for the given command.' self.summary = 'Show help for the given command.'
self.arguments = '[COMMAND]' self.arguments = [
CLAide::Argument.new('COMMAND', false)
]
def initialize(argv) def initialize(argv)
@help_command = Pod::Command.parse(argv) @help_command = Pod::Command.parse(argv)
......
...@@ -8,16 +8,18 @@ module Pod ...@@ -8,16 +8,18 @@ module Pod
self.summary = 'Generate a Podfile for the current directory.' self.summary = 'Generate a Podfile for the current directory.'
self.description = <<-DESC self.description = <<-DESC
Creates a Podfile for the current directory if none currently exists. If Creates a Podfile for the current directory if none currently exists. If
an Xcode project file is specified or if there is only a single project an `XCODEPROJ` project file is specified or if there is only a single
file in the current directory, targets will be automatically generated project file in the current directory, targets will be automatically
based on targets defined in the project. generated based on targets defined in the project.
It is possible to specify a list of dependencies which will be used by It is possible to specify a list of dependencies which will be used by
the template in the `Podfile.default` (normal targets) `Podfile.test` the template in the `Podfile.default` (normal targets) `Podfile.test`
(test targets) files which should be stored in the (test targets) files which should be stored in the
`~/.cocoapods/templates` folder. `~/.cocoapods/templates` folder.
DESC DESC
self.arguments = '[XCODEPROJ]' self.arguments = [
CLAide::Argument.new('XCODEPROJ', :false)
]
def initialize(argv) def initialize(argv)
@podfile_path = Pathname.pwd + "Podfile" @podfile_path = Pathname.pwd + "Podfile"
...@@ -31,12 +33,13 @@ module Pod ...@@ -31,12 +33,13 @@ module Pod
raise Informative, "Existing Podfile found in directory" unless config.podfile.nil? raise Informative, "Existing Podfile found in directory" unless config.podfile.nil?
if @project_path if @project_path
help! "Xcode project at #{@project_path} does not exist" unless File.exist? @project_path help! "Xcode project at #{@project_path} does not exist" unless File.exist? @project_path
project_path = @project_path
else else
raise Informative, "No xcode project found, please specify one" unless @project_paths.length > 0 raise Informative, "No xcode project found, please specify one" unless @project_paths.length > 0
raise Informative, "Multiple xcode projects found, please specify one" unless @project_paths.length == 1 raise Informative, "Multiple xcode projects found, please specify one" unless @project_paths.length == 1
@project_path = @project_paths.first project_path = @project_paths.first
end end
@xcode_project = Xcodeproj::Project.open(@project_path) @xcode_project = Xcodeproj::Project.open(project_path)
end end
def run def run
...@@ -51,7 +54,9 @@ module Pod ...@@ -51,7 +54,9 @@ module Pod
# @return [String] the text of the Podfile for the provided project # @return [String] the text of the Podfile for the provided project
# #
def podfile_template(project) def podfile_template(project)
podfile = <<-PLATFORM.strip_heredoc podfile = ''
podfile << "xcodeproj '#{@project_path}'\n\n" if @project_path
podfile << <<-PLATFORM.strip_heredoc
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
# platform :ios, "6.0" # platform :ios, "6.0"
PLATFORM PLATFORM
......
...@@ -15,7 +15,9 @@ module Pod ...@@ -15,7 +15,9 @@ module Pod
self.summary = 'Converts a podspec to JSON.' self.summary = 'Converts a podspec to JSON.'
self.description = 'Converts a podspec to JSON and prints it to STDOUT.' self.description = 'Converts a podspec to JSON and prints it to STDOUT.'
self.arguments = 'PATH' self.arguments = [
CLAide::Argument.new('PATH', true)
]
def initialize(argv) def initialize(argv)
@path = argv.shift_argument @path = argv.shift_argument
...@@ -40,7 +42,9 @@ module Pod ...@@ -40,7 +42,9 @@ module Pod
self.summary = 'Converts a Podfile to YAML.' self.summary = 'Converts a Podfile to YAML.'
self.description = 'Converts a Podfile to YAML and prints it to STDOUT.' self.description = 'Converts a Podfile to YAML and prints it to STDOUT.'
self.arguments = 'PATH' self.arguments = [
CLAide::Argument.new('PATH', true)
]
def initialize(argv) def initialize(argv)
@path = argv.shift_argument @path = argv.shift_argument
...@@ -63,11 +67,11 @@ module Pod ...@@ -63,11 +67,11 @@ module Pod
class List < IPC class List < IPC
self.summary = 'Lists the specifications know to CocoaPods.' self.summary = 'Lists the specifications known to CocoaPods.'
self.description = <<-DESC self.description = <<-DESC
Prints to STDOUT a YAML dictionary where the keys are the name of the Prints to STDOUT a YAML dictionary where the keys are the name of the
specifications and the values are a dictionary with the following specifications and each corresponding value is a dictionary with
keys. the following keys:
- defined_in_file - defined_in_file
- version - version
......
...@@ -10,13 +10,20 @@ module Pod ...@@ -10,13 +10,20 @@ module Pod
self.summary = 'Creates a new Pod' self.summary = 'Creates a new Pod'
self.description = <<-DESC self.description = <<-DESC
Creates a new Pod with the given name from the template in the working directory. Creates a scaffold for the development of a new Pod named `NAME`
according to the CocoaPods best practices.
If a `TEMPLATE_URL`, pointing to a git repo containing a compatible
template, is specified, it will be used in place of the default one.
DESC DESC
self.arguments = '[NAME]' self.arguments = [
CLAide::Argument.new('NAME', true),
CLAide::Argument.new('TEMPLATE_URL', false)
]
def initialize(argv) def initialize(argv)
@name = argv.shift_argument @name = argv.shift_argument
@template_url = argv.shift_argument
super super
end end
...@@ -24,6 +31,7 @@ module Pod ...@@ -24,6 +31,7 @@ module Pod
super super
help! "A name for the Pod is required." unless @name help! "A name for the Pod is required." unless @name
help! "The Pod name cannot contain spaces." if @name.match(/\s/) help! "The Pod name cannot contain spaces." if @name.match(/\s/)
help! "The Pod name cannot begin with a '.'" if @name[0, 1] == '.'
end end
def run def run
...@@ -52,8 +60,8 @@ module Pod ...@@ -52,8 +60,8 @@ module Pod
# @return [void] # @return [void]
# #
def clone_template def clone_template
UI.section("Creating `#{@name}` Pod") do UI.section("Cloning `#{template_repo_url}` into `#{@name}`.") do
git!"clone '#{TEMPLATE_REPO}' #{@name}" git!"clone '#{template_repo_url}' #{@name}"
end end
end end
...@@ -62,9 +70,13 @@ module Pod ...@@ -62,9 +70,13 @@ module Pod
# @return [void] # @return [void]
# #
def configure_template def configure_template
UI.section("Configuring template") do UI.section("Configuring #{@name} template.") do
Dir.chdir(@name) do Dir.chdir(@name) do
ruby! "_CONFIGURE.rb #{@name}" if File.exists? "configure"
system "./configure #{@name}"
else
UI.warn "Template does not have a configure file."
end
end end
end end
end end
...@@ -74,10 +86,17 @@ module Pod ...@@ -74,10 +86,17 @@ module Pod
# @return [void] # @return [void]
# #
def print_info def print_info
UI.puts "\nTo learn more about the template see `#{TEMPLATE_INFO_URL}`." UI.puts "\nTo learn more about the template see `#{template_repo_url}`."
UI.puts "To learn more about creating a new pod, see `#{CREATE_NEW_POD_INFO_URL}`." UI.puts "To learn more about creating a new pod, see `#{CREATE_NEW_POD_INFO_URL}`."
end end
# Checks if a template URL is given else returns the TEMPLATE_REPO URL
#
# @return String
#
def template_repo_url
@template_url || TEMPLATE_REPO
end
end end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -24,7 +24,7 @@ module Pod ...@@ -24,7 +24,7 @@ module Pod
update_if_necessary! update_if_necessary!
sets = SourcesManager.all_sets sets = SourcesManager.all_sets
sets.each { |set| UI.pod(set, :name) } sets.each { |set| UI.pod(set, :name_and_version) }
UI.puts "\n#{sets.count} pods were found" UI.puts "\n#{sets.count} pods were found"
end end
......
...@@ -23,21 +23,6 @@ module Pod ...@@ -23,21 +23,6 @@ module Pod
# @todo fix. # @todo fix.
# #
def run def run
verify_podfile_exists!
verify_lockfile_exists!
lockfile = config.lockfile
pods = lockfile.pod_names
updates = []
pods.each do |pod_name|
set = SourcesManager.search(Dependency.new(pod_name))
next unless set
source_version = set.versions.first
lockfile_version = lockfile.version(pod_name)
if source_version > lockfile_version
updates << [pod_name, lockfile_version, source_version]
end
end
if updates.empty? if updates.empty?
UI.puts "No updates are available.".yellow UI.puts "No updates are available.".yellow
...@@ -48,7 +33,71 @@ module Pod ...@@ -48,7 +33,71 @@ module Pod
end end
end end
end end
if deprecated_pods.any?
UI.section 'The following pods are deprecated:' do
deprecated_pods.each do |spec|
if spec.deprecated_in_favor_of
UI.puts "- #{spec.name}" \
" (in favor of #{spec.deprecated_in_favor_of})"
else
UI.puts "- #{spec.name}"
end
end
end
end
end
private
def updates
@updates ||= begin
spec_sets.map do |set|
spec = set.specification
source_version = set.versions.first
pod_name = spec.root.name
lockfile_version = lockfile.version(pod_name)
if source_version > lockfile_version
[pod_name, lockfile_version, source_version]
else
nil
end
end.compact.uniq
end
end
def deprecated_pods
@deprecated_pods ||= begin
spec_sets.map(&:specification).select do |spec|
spec.deprecated || spec.deprecated_in_favor_of
end.compact.uniq
end
end end
def spec_sets
@spec_sets ||= begin
installed_pods.map do |pod_name|
SourcesManager.search(Dependency.new(pod_name))
end.compact.uniq
end
end
def installed_pods
@installed_pods ||= begin
verify_podfile_exists!
lockfile.pod_names
end
end
def lockfile
@lockfile ||= begin
verify_lockfile_exists!
config.lockfile
end
end
end end
end end
end end
......
...@@ -8,7 +8,7 @@ module Pod ...@@ -8,7 +8,7 @@ module Pod
module Options module Options
def options def options
[ [
["--no-clean", "Leave SCM dirs like `.git' and `.svn' intact after downloading"], ["--no-clean", "Leave SCM dirs like `.git` and `.svn` intact after downloading"],
["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"], ["--no-integrate", "Skip integration of the Pods libraries in the Xcode project(s)"],
["--no-repo-update", "Skip running `pod repo update` before install"], ["--no-repo-update", "Skip running `pod repo update` before install"],
].concat(super) ].concat(super)
...@@ -28,13 +28,15 @@ module Pod ...@@ -28,13 +28,15 @@ module Pod
# Runs the installer. # Runs the installer.
# #
# @param [update] whether the installer should be run in update mode. # @param [Hash, Boolean, nil] update
# Pods that have been requested to be updated or true if all Pods
# should be updated
# #
# @return [void] # @return [void]
# #
def run_install_with_update(update) def run_install_with_update(update)
installer = Installer.new(config.sandbox, config.podfile, config.lockfile) installer = Installer.new(config.sandbox, config.podfile, config.lockfile)
installer.update_mode = update installer.update = update
installer.install! installer.install!
end end
end end
...@@ -44,18 +46,18 @@ module Pod ...@@ -44,18 +46,18 @@ module Pod
class Install < Command class Install < Command
include Project include Project
self.summary = 'Install project dependencies' self.summary = 'Install project dependencies to Podfile.lock versions'
self.description = <<-DESC self.description = <<-DESC
Downloads all dependencies defined in `Podfile' and creates an Xcode Downloads all dependencies defined in `Podfile` and creates an Xcode
Pods library project in `./Pods'. Pods library project in `./Pods`.
The Xcode project file should be specified in your `Podfile` like this: The Xcode project file should be specified in your `Podfile` like this:
xcodeproj 'path/to/XcodeProject' xcodeproj 'path/to/XcodeProject'
If no xcodeproj is specified, then a search for an Xcode project will If no xcodeproj is specified, then a search for an Xcode project will
be made. If more than one Xcode project is found, the command will be made. If more than one Xcode project is found, the command will
raise an error. raise an error.
This will configure the project to reference the Pods static library, This will configure the project to reference the Pods static library,
...@@ -74,12 +76,45 @@ module Pod ...@@ -74,12 +76,45 @@ module Pod
class Update < Command class Update < Command
include Project include Project
self.summary = 'Update outdated project dependencies' self.summary = 'Update outdated project dependencies and create new Podfile.lock'
self.description = <<-DESC
Updates the Pods identified by the specified `POD_NAMES`. If no
`POD_NAMES` are specified it updates all the Pods ignoring the contents
of the Podfile.lock.
This command is reserved to the update of dependencies and pod install
should be used to install changes to the Podfile.
DESC
self.arguments = [
CLAide::Argument.new('POD_NAMES', false, true),
]
def initialize(argv)
@pods = argv.arguments! unless argv.arguments.empty?
super
end
def run def run
verify_podfile_exists! verify_podfile_exists!
verify_lockfile_exists!
run_install_with_update(true) if @pods
verify_lockfile_exists!
# Check if all given pods are installed
missing_pods = @pods.select { |pod| !config.lockfile.pod_names.include?(pod) }
if missing_pods.length > 0
raise Informative, (missing_pods.length > 1 \
? "Pods %s are not installed and cannot be updated" \
: "Pod %s is not installed and cannot be updated"
) % missing_pods.map { |p| "`#{p}`" }.join(', ')
end
run_install_with_update(:pods => @pods)
else
UI.puts "Update all pods".yellow unless @pods
run_install_with_update(true)
end
end end
end end
......
require 'fileutils'
require 'active_support/core_ext/string/inflections'
module Pod module Pod
class Command class Command
class Push < Command class Push < Command
self.summary = 'Push new specifications to a spec-repo' self.summary = 'Temporary alias for the `pod repo push` command'
self.description = <<-DESC
Validates NAME.podspec or `*.podspec' in the current working dir, creates
a directory and version folder for the pod in the local copy of
REPO (~/.cocoapods/repos/[REPO]), copies the podspec file into the version
directory, and finally it pushes REPO to its remote.
DESC
self.arguments = 'REPO [NAME.podspec]'
def self.options
[ ["--allow-warnings", "Allows pushing even if there are warnings"],
["--local-only", "Does not perform the step of pushing REPO to its remote"] ].concat(super)
end
def initialize(argv) def initialize(argv)
@allow_warnings = argv.flag?('allow-warnings') @push_command = Repo::Push.new(argv)
@local_only = argv.flag?('local-only')
@repo = argv.shift_argument
if @repo.nil?
@repo = "master"
elsif @repo.end_with? ".podspec"
@podspec = @repo
@repo = "master"
else
@podspec = argv.shift_argument
end
super super
end end
def validate! def validate!
super UI.puts '[!] The `pod push` command has been moved to `pod repo push`.'.ansi.yellow
help! "A spec-repo name is required." unless @repo @push_command.validate!
end end
def run def run
validate_podspec_files @push_command.run
test_trunk
check_repo_status
update_repo
add_specs_to_repo
push_repo unless @local_only
end
#-----------------------------------------------------------------------#
private
# @!group Push sub-steps
extend Executable
executable :git
# @return [void] Silently test the CocoaPods trunk service.
#
def test_trunk
return unless @repo == "master"
require 'rest'
base_url = 'https://trunk.cocoapods.org/api/v1'
podspec_files.each do |spec_file|
spec = Pod::Specification.from_file(spec_file)
REST.post("#{base_url}/pods", spec.to_json, 'Content-Type' => 'application/json; charset=utf-8',
'Authorization' => "Token 9300632274827cd3e6dde24bf9c608c3")
end
rescue Exception
# Nothing
end
# Performs a full lint against the podspecs.
#
def validate_podspec_files
UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow
podspec_files.each do |podspec|
validator = Validator.new(podspec)
validator.only_errors = @allow_warnings
begin
validator.validate
rescue Exception
raise Informative, "The `#{podspec}` specification does not validate."
end
raise Informative, "The `#{podspec}` specification does not validate." unless validator.validated?
end
end
# Checks that the repo is clean.
#
# @raise If the repo is not clean.
#
# @todo Add specs for staged and unstaged files.
#
# @todo Gracefully handle the case where source is not under git
# source control.
#
# @return [void]
#
def check_repo_status
clean = Dir.chdir(repo_dir) { `git status --porcelain 2>&1` } == ''
raise Informative, "The repo `#{@repo}` is not clean" unless clean
end
# Updates the git repo against the remote.
#
# @return [void]
#
def update_repo
UI.puts "Updating the `#{@repo}' repo\n".yellow
Dir.chdir(repo_dir) { UI.puts `git pull 2>&1` }
end end
# Commits the podspecs to the source, which should be a git repo.
#
# @note The pre commit hook of the repo is skipped as the podspecs have
# already been linted.
#
# @return [void]
#
def add_specs_to_repo
UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow
podspec_files.each do |spec_file|
spec = Pod::Specification.from_file(spec_file)
output_path = File.join(repo_dir, spec.name, spec.version.to_s)
if Pathname.new(output_path).exist?
message = "[Fix] #{spec}"
elsif Pathname.new(File.join(repo_dir, spec.name)).exist?
message = "[Update] #{spec}"
else
message = "[Add] #{spec}"
end
FileUtils.mkdir_p(output_path)
FileUtils.cp(spec_file, output_path)
Dir.chdir(repo_dir) do
# only commit if modified
if git!("status --porcelain 2>&1") =~ /#{spec.name}/
UI.puts " - #{message}"
git!("add #{spec.name}")
git!("commit --no-verify -m '#{message}'")
else
UI.puts " - [No change] #{spec}"
end
end
end
end
# Pushes the git repo against the remote.
#
# @return [void]
#
def push_repo
UI.puts "\nPushing the `#{@repo}' repo\n".yellow
Dir.chdir(repo_dir) { UI.puts `git push origin master 2>&1` }
end
#-----------------------------------------------------------------------#
private
# @!group Private helpers
# @return [Pathname] The directory of the repository.
#
def repo_dir
dir = config.repos_dir + @repo
raise Informative, "`#{@repo}` repo not found" unless dir.exist?
dir
end
# @return [Array<Pathname>] The path of the specifications to push.
#
def podspec_files
files = Pathname.glob(@podspec || "*.podspec")
raise Informative, "Couldn't find any .podspec file in current directory" if files.empty?
files
end
# @return [Integer] The number of the podspec files to push.
#
def count
podspec_files.count
end
#-----------------------------------------------------------------------#
end end
end end
end end
require 'fileutils' require 'fileutils'
require 'cocoapods/command/repo/push'
module Pod module Pod
class Command class Command
...@@ -17,9 +18,20 @@ module Pod ...@@ -17,9 +18,20 @@ module Pod
remote can later be referred to by `NAME`. remote can later be referred to by `NAME`.
DESC DESC
self.arguments = 'NAME URL [BRANCH]' self.arguments = [
CLAide::Argument.new('NAME', true),
CLAide::Argument.new('URL', true),
CLAide::Argument.new('BRANCH', false)
]
def self.options
[
["--shallow", "Create a shallow clone (fast clone, but no push capabilities)"],
].concat(super)
end
def initialize(argv) def initialize(argv)
@shallow = argv.flag?('shallow', false)
@name, @url, @branch = argv.shift_argument, argv.shift_argument, argv.shift_argument @name, @url, @branch = argv.shift_argument, argv.shift_argument, argv.shift_argument
super super
end end
...@@ -32,9 +44,14 @@ module Pod ...@@ -32,9 +44,14 @@ module Pod
end end
def run def run
UI.section("Cloning spec repo `#{@name}` from `#{@url}`#{" (branch `#{@branch}`)" if @branch}") do prefix = @shallow ? 'Creating shallow clone of' : 'Cloning'
UI.section("#{prefix} spec repo `#{@name}` from `#{@url}`#{" (branch `#{@branch}`)" if @branch}") do
config.repos_dir.mkpath config.repos_dir.mkpath
Dir.chdir(config.repos_dir) { git!("clone '#{@url}' #{@name}") } Dir.chdir(config.repos_dir) do
command = "clone '#{@url}' #{@name}"
command << ' --depth=1' if @shallow
git!(command)
end
Dir.chdir(dir) { git!("checkout #{@branch}") } if @branch Dir.chdir(dir) { git!("checkout #{@branch}") } if @branch
SourcesManager.check_version_information(dir) SourcesManager.check_version_information(dir)
end end
...@@ -51,7 +68,9 @@ module Pod ...@@ -51,7 +68,9 @@ module Pod
this will update all spec-repos in `~/.cocoapods/repos`. this will update all spec-repos in `~/.cocoapods/repos`.
DESC DESC
self.arguments = '[NAME]' self.arguments = [
CLAide::Argument.new('NAME', false)
]
def initialize(argv) def initialize(argv)
@name = argv.shift_argument @name = argv.shift_argument
...@@ -74,7 +93,9 @@ module Pod ...@@ -74,7 +93,9 @@ module Pod
will lint all the spec-repos known to CocoaPods. will lint all the spec-repos known to CocoaPods.
DESC DESC
self.arguments = '[ NAME | DIRECTORY ]' self.arguments = [
CLAide::Argument.new(%w(NAME DIRECTORY), false)
]
def self.options def self.options
[["--only-errors", "Lint presents only the errors"]].concat(super) [["--only-errors", "Lint presents only the errors"]].concat(super)
...@@ -140,7 +161,9 @@ module Pod ...@@ -140,7 +161,9 @@ module Pod
Deletes the remote named `NAME` from the local spec-repos directory at `~/.cocoapods/repos/.` Deletes the remote named `NAME` from the local spec-repos directory at `~/.cocoapods/repos/.`
DESC DESC
self.arguments = 'NAME' self.arguments = [
CLAide::Argument.new('NAME', true)
]
def initialize(argv) def initialize(argv)
@name = argv.shift_argument @name = argv.shift_argument
...@@ -151,6 +174,8 @@ module Pod ...@@ -151,6 +174,8 @@ module Pod
super super
help! 'Deleting a repo needs a `NAME`.' unless @name help! 'Deleting a repo needs a `NAME`.' unless @name
help! "repo #{@name} does not exist" unless File.directory?(dir) help! "repo #{@name} does not exist" unless File.directory?(dir)
help! "You do not have permission to delete the #{@name} repository." \
"Perhaps try prefixing this command with sudo." unless File.writable?(dir)
end end
def run def run
......
require 'fileutils'
require 'active_support/core_ext/string/inflections'
module Pod
class Command
class Repo < Command
class Push < Repo
self.summary = 'Push new specifications to a spec-repo'
self.description = <<-DESC
Validates `NAME.podspec` or `*.podspec` in the current working dir,
creates a directory and version folder for the pod in the local copy of
`REPO` (~/.cocoapods/repos/[REPO]), copies the podspec file into the
version directory, and finally it pushes `REPO` to its remote.
DESC
self.arguments = [
CLAide::Argument.new('REPO', true),
CLAide::Argument.new('NAME.podspec', false)
]
def self.options
[ ["--allow-warnings", "Allows pushing even if there are warnings"],
["--local-only", "Does not perform the step of pushing REPO to its remote"] ].concat(super)
end
def initialize(argv)
@allow_warnings = argv.flag?('allow-warnings')
@local_only = argv.flag?('local-only')
@repo = argv.shift_argument
@podspec = argv.shift_argument
super
end
def validate!
super
help! "A spec-repo name is required." unless @repo
end
def run
check_if_master_repo
validate_podspec_files
check_repo_status
update_repo
add_specs_to_repo
push_repo unless @local_only
end
#---------------------------------------------------------------------#
private
# @!group Push sub-steps
extend Executable
executable :git
# Temporary check to ensure that users do not push accidentally private
# specs to the master repo.
#
def check_if_master_repo
remotes = Dir.chdir(repo_dir) { `git remote -v 2>&1` }
master_repo_urls = [
'git@github.com:CocoaPods/Specs.git',
'https://github.com/CocoaPods/Specs.git',
]
is_master_repo = master_repo_urls.any? do |url|
remotes.include?(url)
end
if is_master_repo
raise Informative, "To push to the CocoaPods master repo use " \
"the `pod trunk push` command.\n\nIf you are using a fork of " \
"the master repo for private purposes we recommend to migrate " \
"to a clean private repo. To disable this check remove the " \
"remote pointing to the CocoaPods master repo."
end
end
# Performs a full lint against the podspecs.
#
def validate_podspec_files
UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow
podspec_files.each do |podspec|
validator = Validator.new(podspec)
validator.only_errors = @allow_warnings
begin
validator.validate
rescue Exception
raise Informative, "The `#{podspec}` specification does not validate."
end
raise Informative, "The `#{podspec}` specification does not validate." unless validator.validated?
end
end
# Checks that the repo is clean.
#
# @raise If the repo is not clean.
#
# @todo Add specs for staged and unstaged files.
#
# @todo Gracefully handle the case where source is not under git
# source control.
#
# @return [void]
#
def check_repo_status
clean = Dir.chdir(repo_dir) { `git status --porcelain 2>&1` } == ''
raise Informative, "The repo `#{@repo}` is not clean" unless clean
end
# Updates the git repo against the remote.
#
# @return [void]
#
def update_repo
UI.puts "Updating the `#{@repo}' repo\n".yellow
Dir.chdir(repo_dir) { UI.puts `git pull 2>&1` }
end
# Commits the podspecs to the source, which should be a git repo.
#
# @note The pre commit hook of the repo is skipped as the podspecs have
# already been linted.
#
# @return [void]
#
def add_specs_to_repo
UI.puts "\nAdding the #{'spec'.pluralize(count)} to the `#{@repo}' repo\n".yellow
podspec_files.each do |spec_file|
spec = Pod::Specification.from_file(spec_file)
output_path = File.join(repo_dir, spec.name, spec.version.to_s)
if Pathname.new(output_path).exist?
message = "[Fix] #{spec}"
elsif Pathname.new(File.join(repo_dir, spec.name)).exist?
message = "[Update] #{spec}"
else
message = "[Add] #{spec}"
end
FileUtils.mkdir_p(output_path)
FileUtils.cp(spec_file, output_path)
Dir.chdir(repo_dir) do
# only commit if modified
if git!("status --porcelain 2>&1").include?(spec.name)
UI.puts " - #{message}"
git!("add #{spec.name}")
git!("commit --no-verify -m '#{message}'")
else
UI.puts " - [No change] #{spec}"
end
end
end
end
# Pushes the git repo against the remote.
#
# @return [void]
#
def push_repo
UI.puts "\nPushing the `#{@repo}' repo\n".yellow
Dir.chdir(repo_dir) { UI.puts `git push origin master 2>&1` }
end
#---------------------------------------------------------------------#
private
# @!group Private helpers
# @return [Pathname] The directory of the repository.
#
def repo_dir
specs_dir = Pathname.new(File.join(config.repos_dir, @repo, 'Specs'))
dir = config.repos_dir + @repo
if specs_dir.exist?
dir = specs_dir
elsif dir.exist?
dir
else
raise Informative, "`#{@repo}` repo not found either in #{specs_dir} or #{dir}"
end
dir
end
# @return [Array<Pathname>] The path of the specifications to push.
#
def podspec_files
files = Pathname.glob(@podspec || "*.podspec")
raise Informative, "Couldn't find any .podspec file in current directory" if files.empty?
files
end
# @return [Integer] The number of the podspec files to push.
#
def count
podspec_files.count
end
#---------------------------------------------------------------------#
end
end
end
end
...@@ -4,12 +4,14 @@ module Pod ...@@ -4,12 +4,14 @@ module Pod
self.summary = 'Searches for pods' self.summary = 'Searches for pods'
self.description = <<-DESC self.description = <<-DESC
Searches for pods, ignoring case, whose name matches `QUERY'. If the Searches for pods, ignoring case, whose name matches `QUERY`. If the
`--full' option is specified, this will also search in the summary and `--full` option is specified, this will also search in the summary and
description of the pods. description of the pods.
DESC DESC
self.arguments = '[QUERY]' self.arguments = [
CLAide::Argument.new('QUERY', true)
]
def self.options def self.options
[ [
...@@ -35,6 +37,14 @@ module Pod ...@@ -35,6 +37,14 @@ module Pod
def validate! def validate!
super super
help! "A search query is required." unless @query help! "A search query is required." unless @query
unless @web
begin
/#{@query.join(' ').strip}/
rescue RegexpError
help! "A valid regular expression is required."
end
end
end end
def run def run
...@@ -50,11 +60,11 @@ module Pod ...@@ -50,11 +60,11 @@ module Pod
def web_search def web_search
query_parameter = [ query_parameter = [
('on%3Aosx' if @supported_on_osx), ('on:osx' if @supported_on_osx),
('on%3Aios' if @supported_on_ios), ('on:ios' if @supported_on_ios),
@query @query
].compact.flatten.join('%20') ].compact.flatten.join(' ')
url = "http://cocoapods.org/?q=#{query_parameter}" url = "http://cocoapods.org/?q=#{CGI.escape(query_parameter).gsub("+", "%20")}"
UI.puts("Opening #{url}") UI.puts("Opening #{url}")
open!(url) open!(url)
end end
......
...@@ -15,14 +15,18 @@ module Pod ...@@ -15,14 +15,18 @@ module Pod
DESC DESC
def self.options def self.options
[["--push", "Use this option to enable push access once granted"]].concat(super) [
["--no-shallow", "Clone full history so push will work"],
["--push", "Use this option to enable push access once granted"],
].concat(super)
end end
extend Executable extend Executable
executable :git executable :git
def initialize(argv) def initialize(argv)
@push_option = argv.flag?('push') @push_option = argv.flag?('push')
@shallow = argv.flag?('shallow', !@push_option)
super super
end end
...@@ -77,7 +81,9 @@ module Pod ...@@ -77,7 +81,9 @@ module Pod
# @return [void] # @return [void]
# #
def add_master_repo def add_master_repo
@command ||= Repo::Add.parse(['master', url, 'master']).run cmd = ['master', url, 'master']
cmd << '--shallow' if @shallow
Repo::Add.parse(cmd).run
end end
# Updates the master repo against the remote. # Updates the master repo against the remote.
...@@ -109,7 +115,7 @@ module Pod ...@@ -109,7 +115,7 @@ module Pod
# be enabled. # be enabled.
# #
def url def url
(push?) ? read_write_url : read_only_url push? ? read_write_url : read_only_url
end end
# @return [String] the read only url of the master repo. # @return [String] the read only url of the master repo.
......
...@@ -18,7 +18,9 @@ module Pod ...@@ -18,7 +18,9 @@ module Pod
If a GitHub url is passed the spec is prepopulated. If a GitHub url is passed the spec is prepopulated.
DESC DESC
self.arguments = '[ NAME | https://github.com/USER/REPO ]' self.arguments = [
CLAide::Argument.new(%w(NAME https://github.com/USER/REPO), false)
]
def initialize(argv) def initialize(argv)
@name_or_url, @url = argv.shift_argument, argv.shift_argument @name_or_url, @url = argv.shift_argument, argv.shift_argument
...@@ -51,12 +53,14 @@ module Pod ...@@ -51,12 +53,14 @@ module Pod
self.summary = 'Validates a spec file.' self.summary = 'Validates a spec file.'
self.description = <<-DESC self.description = <<-DESC
Validates `NAME.podspec'. If a directory is provided it validates Validates `NAME.podspec`. If a `DIRECTORY` is provided, it validates
the podspec files found, including subfolders. In case the podspec files found, including subfolders. In case
the argument is omitted, it defaults to the current working dir. the argument is omitted, it defaults to the current working dir.
DESC DESC
self.arguments = '[ NAME.podspec | DIRECTORY | http://PATH/NAME.podspec, ... ]' self.arguments = [
CLAide::Argument.new(%w(NAME.podspec DIRECTORY http://PATH/NAME.podspec), false, true),
]
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"],
...@@ -122,17 +126,17 @@ module Pod ...@@ -122,17 +126,17 @@ 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(pathname + '**/*.podspec') files += Pathname.glob(pathname + '**/*.podspec{.json,}')
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))
raise Informative, "Unable to find a spec named `#{path}'." unless pathname.exist? && path.include?('.podspec') raise Informative, "Unable to find a spec named `#{path}'." unless pathname.exist? && path.include?('.podspec')
end
end end
end end
files
end end
files
end end
end
def podspecs_tmp_dir def podspecs_tmp_dir
Pathname.new(File.join(Pathname.new('/tmp').realpath, '/CocoaPods/Lint_podspec')) Pathname.new(File.join(Pathname.new('/tmp').realpath, '/CocoaPods/Lint_podspec'))
...@@ -148,7 +152,9 @@ module Pod ...@@ -148,7 +152,9 @@ module Pod
Prints the path of 'NAME.podspec' Prints the path of 'NAME.podspec'
DESC DESC
self.arguments = '[ NAME ]' self.arguments = [
CLAide::Argument.new('NAME', false)
]
def self.options def self.options
[["--show-all", "Print all versions of the given podspec"]].concat(super) [["--show-all", "Print all versions of the given podspec"]].concat(super)
...@@ -180,7 +186,9 @@ module Pod ...@@ -180,7 +186,9 @@ module Pod
Prints 'NAME.podspec' to standard output. Prints 'NAME.podspec' to standard output.
DESC DESC
self.arguments = '[ NAME ]' self.arguments = [
CLAide::Argument.new('NAME', false)
]
def self.options def self.options
[["--show-all", "Pick from all versions of the given podspec"]].concat(super) [["--show-all", "Pick from all versions of the given podspec"]].concat(super)
...@@ -207,7 +215,7 @@ module Pod ...@@ -207,7 +215,7 @@ module Pod
get_path_of_spec(@spec) get_path_of_spec(@spec)
end end
UI.puts File.open(filepath).read UI.puts File.read(filepath)
end end
end end
...@@ -220,7 +228,9 @@ module Pod ...@@ -220,7 +228,9 @@ module Pod
Opens 'NAME.podspec' to be edited. Opens 'NAME.podspec' to be edited.
DESC DESC
self.arguments = '[ NAME ]' self.arguments = [
CLAide::Argument.new('NAME', false)
]
def self.options def self.options
[["--show-all", "Pick which spec to edit from all available versions of the given podspec"]].concat(super) [["--show-all", "Pick which spec to edit from all available versions of the given podspec"]].concat(super)
...@@ -342,7 +352,7 @@ module Pod ...@@ -342,7 +352,7 @@ module Pod
# @return [Pathname] the absolute path of the given spec and source # @return [Pathname] the absolute path of the given spec and source
# #
def pathname_from_spec(spec, source) def pathname_from_spec(spec, source)
config.repos_dir + "#{source}/#{spec.name}/#{spec.version}/#{spec.name}.podspec" Pathname(spec.defined_in_file)
end end
# @return [String] of spec paths one on each line # @return [String] of spec paths one on each line
...@@ -370,16 +380,21 @@ module Pod ...@@ -370,16 +380,21 @@ module Pod
def spec_and_source_from_set(set) def spec_and_source_from_set(set)
sources = set.sources sources = set.sources
best_source = sources.first best_source = best_version = nil
best_version = best_source.versions(set.name).first
sources.each do |source| sources.each do |source|
version = source.versions(set.name).first versions = source.versions(set.name)
if version > best_version versions.each do |version|
if !best_version or version > best_version
best_source = source best_source = source
best_version = version best_version = version
end
end end
end end
if !best_source or !best_version
raise Informative, "Unable to locate highest known specification for `#{ set.name }'"
end
return best_source.specification(set.name, best_version), best_source return best_source.specification(set.name, best_version), best_source
end end
...@@ -475,7 +490,7 @@ Pod::Spec.new do |s| ...@@ -475,7 +490,7 @@ Pod::Spec.new do |s|
DESC DESC
s.homepage = "#{data[:homepage]}" s.homepage = "#{data[:homepage]}"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
...@@ -485,24 +500,24 @@ Pod::Spec.new do |s| ...@@ -485,24 +500,24 @@ Pod::Spec.new do |s|
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
# #
s.license = 'MIT (example)' s.license = "MIT (example)"
# s.license = { :type => 'MIT', :file => 'FILE_LICENSE' } # s.license = { :type => "MIT", :file => "FILE_LICENSE" }
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# #
# Specify the authors of the library, with email addresses. Email addresses # Specify the authors of the library, with email addresses. Email addresses
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
# accepts just a name if you'd rather not provide an email addresses. # accepts just a name if you'd rather not provide an email address.
# #
# Specify a social_media_url where others can refer to, for example a twitter # Specify a social_media_url where others can refer to, for example a twitter
# profile URL. # profile URL.
# #
s.author = { "#{data[:author_name]}" => "#{data[:author_email]}" } s.author = { "#{data[:author_name]}" => "#{data[:author_email]}" }
# Or just: s.author = '#{data[:author_name]}' # Or just: s.author = "#{data[:author_name]}"
# s.authors = { "#{data[:author_name]}" => "#{data[:author_email]}" } # s.authors = { "#{data[:author_name]}" => "#{data[:author_email]}" }
# s.social_media_url = "http://twitter.com/#{data[:author_name]}" # s.social_media_url = "http://twitter.com/#{data[:author_name]}"
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# #
...@@ -511,11 +526,11 @@ Pod::Spec.new do |s| ...@@ -511,11 +526,11 @@ Pod::Spec.new do |s|
# #
# s.platform = :ios # s.platform = :ios
# s.platform = :ios, '5.0' # s.platform = :ios, "5.0"
# When using multiple platforms # When using multiple platforms
# s.ios.deployment_target = '5.0' # s.ios.deployment_target = "5.0"
# s.osx.deployment_target = '10.7' # s.osx.deployment_target = "10.7"
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
...@@ -535,10 +550,10 @@ Pod::Spec.new do |s| ...@@ -535,10 +550,10 @@ Pod::Spec.new do |s|
# Not including the public_header_files will make all headers public. # Not including the public_header_files will make all headers public.
# #
s.source_files = 'Classes', 'Classes/**/*.{h,m}' s.source_files = "Classes", "Classes/**/*.{h,m}"
s.exclude_files = 'Classes/Exclude' s.exclude_files = "Classes/Exclude"
# s.public_header_files = 'Classes/**/*.h' # s.public_header_files = "Classes/**/*.h"
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
...@@ -561,11 +576,11 @@ Pod::Spec.new do |s| ...@@ -561,11 +576,11 @@ Pod::Spec.new do |s|
# the lib prefix of their name. # the lib prefix of their name.
# #
# s.framework = 'SomeFramework' # s.framework = "SomeFramework"
# s.frameworks = 'SomeFramework', 'AnotherFramework' # s.frameworks = "SomeFramework", "AnotherFramework"
# s.library = 'iconv' # s.library = "iconv"
# s.libraries = 'iconv', 'xml2' # s.libraries = "iconv", "xml2"
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
...@@ -576,8 +591,8 @@ Pod::Spec.new do |s| ...@@ -576,8 +591,8 @@ Pod::Spec.new do |s|
# s.requires_arc = true # s.requires_arc = true
# s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2' } # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
# s.dependency 'JSONKit', '~> 1.4' # s.dependency "JSONKit", "~> 1.4"
end end
SPEC SPEC
......
...@@ -71,7 +71,7 @@ module Pod ...@@ -71,7 +71,7 @@ module Pod
output = stdout.join("\n") + stderr.join("\n") output = stdout.join("\n") + stderr.join("\n")
unless status.success? unless status.success?
if raise_on_failure if raise_on_failure
raise Informative, "#{name} #{command}\n\n#{output}" raise Informative, "#{full_command}\n\n#{output}"
else else
UI.message("[!] Failed: #{full_command}".red) UI.message("[!] Failed: #{full_command}".red)
end end
......
This diff is collapsed.
module Pod
module ExternalSources
# 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
# @return [String] the path where the podfile is defined to resolve
# relative paths.
#
attr_reader :podfile_path
# @param [String] name @see name
# @param [Hash] params @see params
# @param [String] podfile_path @see podfile_path
#
def initialize(name, params, podfile_path)
@name = name
@params = params
@podfile_path = podfile_path
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
public
# @!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 fetch(sandbox)
raise "Abstract method"
end
# @return [String] a string representation of the source suitable for UI.
#
def description
raise "Abstract method"
end
protected
# @return [String] The uri of the podspec appending the name of the file
# and expanding it if necessary.
#
# @note If the declared path is expanded only if the represents a path
# relative to the file system.
#
def normalized_podspec_path(declared_path)
extension = File.extname(declared_path)
if extension == '.podspec' || extension == '.json'
path_with_ext = declared_path
else
path_with_ext = "#{declared_path}/#{name}.podspec"
end
podfile_dir = File.dirname(podfile_path || '')
File.expand_path(path_with_ext, podfile_dir)
end
private
# @! Subclasses helpers
# Pre-downloads a Pod passing the options to the downloader and informing
# the sandbox.
#
# @param [Sandbox] sandbox
# The sandbox where the Pod should be downloaded.
#
# @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.
#
# @todo The downloader configuration is the same of the
# #{PodSourceInstaller} and it needs to be kept in sync.
#
# @return [void]
#
def pre_download(sandbox)
title = "Pre-downloading: `#{name}` #{description}"
UI.titled_section(title, { :verbose_prefix => "-> " }) do
target = sandbox.root + name
target.rmtree if target.exist?
downloader = Config.instance.downloader(target, params)
downloader.download
store_podspec(sandbox, target + "#{name}.podspec")
sandbox.store_pre_downloaded_pod(name)
if downloader.options_specific?
source = params
else
source = downloader.checkout_options
end
sandbox.store_checkout_source(name, source)
end
end
# Stores the podspec in the sandbox and marks it as from an external
# source.
#
# @param [Sandbox] sandbox
# The sandbox where the specification should be stored.
#
# @param [Pathname, String] spec
# The path of the specification or its contents.
#
# @note All the concrete implementations of #{fetch} should invoke this
# method.
#
# @note The sandbox ensures that the podspec exists and that the names
# match.
#
# @return [void]
#
def store_podspec(sandbox, spec, json = false)
sandbox.store_podspec(name, spec, true, json)
end
end
end
end
module Pod
module ExternalSources
# Provides support for fetching a specification file from a source handled
# by the downloader. Supports all the options of the downloader
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class DownloaderSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
pre_download(sandbox)
end
# @see AbstractExternalSource#description
#
def description
strategy = Downloader.strategy_from_options(params)
options = params.dup
url = options.delete(strategy)
result = "from `#{url}`"
options.each do |key, value|
result << ", #{key} `#{value}`"
end
result
end
end
end
end
module Pod
module ExternalSources
# Provides support for fetching a specification file from a path local to
# the machine running the installation.
#
# Works with the {LocalPod::LocalSourcedPod} class.
#
class PathSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
title = "Fetching podspec for `#{name}` #{description}"
UI.titled_section(title, { :verbose_prefix => "-> " }) do
podspec = podspec_path
unless podspec.exist?
raise Informative, "No podspec found for `#{name}` in " \
"`#{declared_path}`"
end
store_podspec(sandbox, podspec)
is_absolute = absolute?(declared_path)
sandbox.store_local_path(name, podspec.dirname, is_absolute)
end
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:path] || params[:local]}`"
end
private
# @!group Helpers
# @return [String] The path as declared by the user.
#
def declared_path
result = params[:path] || params[:local]
result.to_s if result
end
# @return [Pathname] The absolute path of the podspec.
#
def podspec_path
Pathname(normalized_podspec_path(declared_path))
end
# @return [Bool]
#
def absolute?(path)
Pathname(path).absolute? || path.to_s.start_with?('~')
end
end
end
end
module Pod
module ExternalSources
# Provides support for fetching a specification file from an URL. Can be
# http, file, etc.
#
class PodspecSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
title = "Fetching podspec for `#{name}` #{description}"
UI.titled_section(title, { :verbose_prefix => "-> " }) do
is_json = podspec_uri.split('.').last == 'json'
require 'open-uri'
open(podspec_uri) { |io| store_podspec(sandbox, io.read, is_json) }
end
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:podspec]}`"
end
private
# @!group Helpers
# @return [String] The uri of the podspec appending the name of the file
# and expanding it if necessary.
#
# @note If the declared path is expanded only if the represents a path
# relative to the file system.
#
def podspec_uri
declared_path = params[:podspec].to_s
if declared_path.match(%r{^.+://})
declared_path
else
normalized_podspec_path(declared_path)
end
end
end
end
end
module Pod module Pod
# The version of the cocoapods command line tool. # The version of the cocoapods command line tool.
# #
VERSION = '0.29.0' unless defined? Pod::VERSION VERSION = '0.33.1' unless defined? Pod::VERSION
end end
...@@ -40,9 +40,12 @@ module Pod ...@@ -40,9 +40,12 @@ module Pod
# added to the top of the prefix header. For OS X `Cocoa/Cocoa.h` # added to the top of the prefix header. For OS X `Cocoa/Cocoa.h`
# is imported. # is imported.
# #
# @note Only unique prefix_header_contents are added to the prefix header.
#
# @return [String] # @return [String]
# #
# @todo Subspecs can specify prefix header information too. # @todo Subspecs can specify prefix header information too.
# @todo Check to see if we have a similar duplication issue with file_accessor.prefix_header.
# #
def generate def generate
result = "#ifdef __OBJC__\n" result = "#ifdef __OBJC__\n"
...@@ -53,12 +56,18 @@ module Pod ...@@ -53,12 +56,18 @@ module Pod
result << %|\n#import "#{import}"| result << %|\n#import "#{import}"|
end end
file_accessors.each do |file_accessor| unique_prefix_header_contents = file_accessors.collect do |file_accessor|
file_accessor.spec_consumer.prefix_header_contents
end.compact.uniq
result << "\n"
unique_prefix_header_contents.each do |prefix_header_contents|
result << prefix_header_contents
result << "\n" result << "\n"
if prefix_header_contents = file_accessor.spec_consumer.prefix_header_contents end
result << prefix_header_contents
result << "\n" file_accessors.each do |file_accessor|
end
if prefix_header = file_accessor.prefix_header if prefix_header = file_accessor.prefix_header
result << Pathname(prefix_header).read result << Pathname(prefix_header).read
end end
......
...@@ -64,11 +64,12 @@ module Pod ...@@ -64,11 +64,12 @@ module Pod
@lockfile = lockfile @lockfile = lockfile
end end
# @return [Bool] Whether the installer is in update mode. In update mode # @return [Hash, Boolean, nil] Pods that have been requested to be
# the contents of the Lockfile are not taken into account for # updated or true if all Pods should be updated.
# deciding what Pods to install. # If all Pods should been updated the contents of the Lockfile are
# not taken into account for deciding what Pods to install.
# #
attr_accessor :update_mode attr_accessor :update
# Installs the Pods. # Installs the Pods.
# #
...@@ -89,6 +90,7 @@ module Pod ...@@ -89,6 +90,7 @@ module Pod
download_dependencies download_dependencies
generate_pods_project generate_pods_project
integrate_user_project if config.integrate_targets? integrate_user_project if config.integrate_targets?
perform_post_install_actions
end end
def resolve_dependencies def resolve_dependencies
...@@ -164,13 +166,14 @@ module Pod ...@@ -164,13 +166,14 @@ module Pod
# #
def analyze def analyze
if lockfile && lockfile.cocoapods_version > Version.new(VERSION) if lockfile && lockfile.cocoapods_version > Version.new(VERSION)
STDERR.puts '[!] The version of CocoaPods used to generate the lockfile is '\ STDERR.puts '[!] The version of CocoaPods used to generate ' \
'higher than the version of the current executable. Incompatibility ' \ "the lockfile (#{lockfile.cocoapods_version}) is "\
'issues may arise.'.yellow "higher than the version of the current executable (#{VERSION}). " \
'Incompatibility issues may arise.'.yellow
end end
analyzer = Analyzer.new(sandbox, podfile, lockfile) analyzer = Analyzer.new(sandbox, podfile, lockfile)
analyzer.update_mode = update_mode analyzer.update = update
@analysis_result = analyzer.analyze @analysis_result = analyzer.analyze
@aggregate_targets = analyzer.result.targets @aggregate_targets = analyzer.result.targets
end end
...@@ -249,7 +252,13 @@ module Pod ...@@ -249,7 +252,13 @@ module Pod
title_options = { :verbose_prefix => "-> ".green } title_options = { :verbose_prefix => "-> ".green }
root_specs.sort_by(&:name).each do |spec| root_specs.sort_by(&:name).each do |spec|
if pods_to_install.include?(spec.name) if pods_to_install.include?(spec.name)
UI.titled_section("Installing #{spec}".green, title_options) do if sandbox_state.changed.include?(spec.name) && sandbox.manifest
previous = sandbox.manifest.version(spec.name)
title = "Installing #{spec.name} #{spec.version} (was #{previous})"
else
title = "Installing #{spec}"
end
UI.titled_section(title.green, title_options) do
install_source_of_pod(spec.name) install_source_of_pod(spec.name)
end end
else else
...@@ -293,6 +302,32 @@ module Pod ...@@ -293,6 +302,32 @@ module Pod
end end
end end
# Performs any post-installation actions
#
# @return [void]
#
def perform_post_install_actions
warn_for_deprecations
end
# Prints a warning for any pods that are deprecated
#
# @return [void]
#
def warn_for_deprecations
deprecated_pods = root_specs.select do |spec|
spec.deprecated || spec.deprecated_in_favor_of
end
deprecated_pods.each do |spec|
if spec.deprecated_in_favor_of
UI.warn "#{spec.name} has been deprecated in " \
"favor of #{spec.deprecated_in_favor_of}"
else
UI.warn "#{spec.name} has been deprecated"
end
end
end
# Creates the Pods project from scratch if it doesn't exists. # Creates the Pods project from scratch if it doesn't exists.
# #
# @return [void] # @return [void]
...@@ -309,9 +344,10 @@ module Pod ...@@ -309,9 +344,10 @@ module Pod
pod_names = pod_targets.map(&:pod_name).uniq pod_names = pod_targets.map(&:pod_name).uniq
pod_names.each do |pod_name| pod_names.each do |pod_name|
path = sandbox.pod_dir(pod_name)
local = sandbox.local?(pod_name) local = sandbox.local?(pod_name)
@pods_project.add_pod_group(pod_name, path, local) path = sandbox.pod_dir(pod_name)
was_absolute = sandbox.local_path_was_absolute?(pod_name)
@pods_project.add_pod_group(pod_name, path, local, was_absolute)
end end
if config.podfile_path if config.podfile_path
...@@ -458,42 +494,11 @@ module Pod ...@@ -458,42 +494,11 @@ module Pod
# #
def run_pre_install_hooks def run_pre_install_hooks
UI.message "- Running pre install hooks" do UI.message "- Running pre install hooks" do
analysis_result.specifications.each do |spec|
executed = false
libraries_using_spec(spec).each do |lib|
lib_representation = library_rep(lib)
executed ||= run_spec_pre_install_hook(spec, lib_representation)
end
UI.message "- #{spec.name}" if executed
end
executed = run_podfile_pre_install_hook executed = run_podfile_pre_install_hook
UI.message "- Podfile" if executed UI.message "- Podfile" if executed
end end
end end
# Runs the pre install hook of the given specification with the given
# library representation.
#
# @param [Specification] spec
# The spec for which the pre install hook should be run.
#
# @param [Hooks::LibraryRepresentation] lib_representation
# The library representation to be passed as an argument to the
# hook.
#
# @raise Raises an informative if the hooks raises.
#
# @return [Bool] Whether the hook was run.
#
def run_spec_pre_install_hook(spec, lib_representation)
spec.pre_install!(pod_rep(spec.root.name), lib_representation)
rescue => e
raise Informative, "An error occurred while processing the pre-install " \
"hook of #{spec}." \
"\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end
# Runs the pre install hook of the Podfile # Runs the pre install hook of the Podfile
# #
# @raise Raises an informative if the hooks raises. # @raise Raises an informative if the hooks raises.
...@@ -517,42 +522,11 @@ module Pod ...@@ -517,42 +522,11 @@ module Pod
# #
def run_post_install_hooks def run_post_install_hooks
UI.message "- Running post install hooks" do UI.message "- Running post install hooks" do
analysis_result.specifications.each do |spec|
executed = false
libraries_using_spec(spec).each do |lib|
lib_representation = library_rep(lib)
executed ||= run_spec_post_install_hook(spec, lib_representation)
end
UI.message "- #{spec.name}" if executed
end
executed = run_podfile_post_install_hook executed = run_podfile_post_install_hook
UI.message "- Podfile" if executed UI.message "- Podfile" if executed
end end
end end
# Runs the post install hook of the given specification with the given
# library representation.
#
# @param [Specification] spec
# The spec for which the post install hook should be run.
#
# @param [Hooks::LibraryRepresentation] lib_representation
# The library representation to be passed as an argument to the
# hook.
#
# @raise Raises an informative if the hooks raises.
#
# @return [Bool] Whether the hook was run.
#
def run_spec_post_install_hook(spec, lib_representation)
spec.post_install!(lib_representation)
rescue => e
raise Informative, "An error occurred while processing the post-install " \
"hook of #{spec}." \
"\n\n#{e.message}\n\n#{e.backtrace * "\n"}"
end
# Runs the post install hook of the Podfile # Runs the post install hook of the Podfile
# #
# @raise Raises an informative if the hooks raises. # @raise Raises an informative if the hooks raises.
......
...@@ -33,7 +33,7 @@ module Pod ...@@ -33,7 +33,7 @@ module Pod
@podfile = podfile @podfile = podfile
@lockfile = lockfile @lockfile = lockfile
@update_mode = false @update = false
@allow_pre_downloads = true @allow_pre_downloads = true
@archs_by_target_def = {} @archs_by_target_def = {}
end end
...@@ -91,11 +91,30 @@ module Pod ...@@ -91,11 +91,30 @@ module Pod
# @!group Configuration # @!group Configuration
# @return [Hash, Boolean, nil] Pods that have been requested to be
# updated or true if all Pods should be updated
#
attr_accessor :update
# @return [Bool] Whether the version of the dependencies which did non # @return [Bool] Whether the version of the dependencies which did non
# change in the Podfile should be locked. # change in the Podfile should be locked.
# #
attr_accessor :update_mode def update_mode?
alias_method :update_mode?, :update_mode !!update
end
# @return [Symbol] Whether and how the dependencies in the Podfile
# should be updated.
#
def update_mode
if !update
:none
elsif update == true
:all
elsif update[:pods] != nil
:selected
end
end
# @return [Bool] Whether the analysis allows pre-downloads and thus # @return [Bool] Whether the analysis allows pre-downloads and thus
# modifications to the sandbox. # modifications to the sandbox.
...@@ -219,10 +238,15 @@ module Pod ...@@ -219,10 +238,15 @@ module Pod
# that prevent the resolver to update a Pod. # that prevent the resolver to update a Pod.
# #
def generate_version_locking_dependencies def generate_version_locking_dependencies
if update_mode? if update_mode == :all
[] []
else else
result.podfile_state.unchanged.map do |pod| locking_pods = result.podfile_state.unchanged
if update_mode == :selected
# If selected Pods should been updated, filter them out of the list
locking_pods = locking_pods.select { |pod| !update[:pods].include?(pod) }
end
locking_pods.map do |pod|
lockfile.dependency_to_lock_pod_named(pod) lockfile.dependency_to_lock_pod_named(pod)
end end
end end
...@@ -252,10 +276,14 @@ module Pod ...@@ -252,10 +276,14 @@ module Pod
deps_to_fetch = [] deps_to_fetch = []
deps_to_fetch_if_needed = [] deps_to_fetch_if_needed = []
deps_with_external_source = podfile.dependencies.select { |dep| dep.external_source } deps_with_external_source = podfile.dependencies.select { |dep| dep.external_source }
if update_mode?
if update_mode == :all
deps_to_fetch = deps_with_external_source deps_to_fetch = deps_with_external_source
else else
pods_to_fetch = result.podfile_state.added + result.podfile_state.changed pods_to_fetch = result.podfile_state.added + result.podfile_state.changed
if update_mode == :selected
pods_to_fetch += update[:pods]
end
deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) } deps_to_fetch = deps_with_external_source.select { |dep| pods_to_fetch.include?(dep.root_name) }
deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) } deps_to_fetch_if_needed = deps_with_external_source.select { |dep| result.podfile_state.unchanged.include?(dep.root_name) }
deps_to_fetch += deps_to_fetch_if_needed.select { |dep| sandbox.specification(dep.root_name).nil? || !dep.external_source[:local].nil? || !dep.external_source[:path].nil? } deps_to_fetch += deps_to_fetch_if_needed.select { |dep| sandbox.specification(dep.root_name).nil? || !dep.external_source[:local].nil? || !dep.external_source[:path].nil? }
...@@ -316,7 +344,7 @@ module Pod ...@@ -316,7 +344,7 @@ module Pod
def generate_sandbox_state def generate_sandbox_state
sandbox_state = nil sandbox_state = nil
UI.section "Comparing resolved specification to the sandbox manifest" do UI.section "Comparing resolved specification to the sandbox manifest" do
sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode, lockfile) sandbox_analyzer = SandboxAnalyzer.new(sandbox, result.specifications, update_mode?, lockfile)
sandbox_state = sandbox_analyzer.analyze sandbox_state = sandbox_analyzer.analyze
sandbox_state.print sandbox_state.print
end end
......
...@@ -63,6 +63,12 @@ module Pod ...@@ -63,6 +63,12 @@ module Pod
def install! def install!
download_source unless predownloaded? || local? download_source unless predownloaded? || local?
run_prepare_command run_prepare_command
rescue Informative
raise
rescue Object => e
UI.notice("Error installing #{root_spec.name}")
clean!
raise
end end
# Cleans the installations if appropriate. # Cleans the installations if appropriate.
...@@ -95,8 +101,18 @@ module Pod ...@@ -95,8 +101,18 @@ module Pod
def download_source def download_source
root.rmtree if root.exist? root.rmtree if root.exist?
if head_pod? if head_pod?
downloader.download_head begin
@specific_source = downloader.checkout_options downloader.download_head
@specific_source = downloader.checkout_options
rescue RuntimeError => e
if e.message == 'Abstract method'
raise Informative, "The pod '" + root_spec.name + "' does not " +
"support the :head option, as it uses a " + downloader.name +
" source. Remove that option to use this pod."
else
raise
end
end
else else
downloader.download downloader.download
unless downloader.options_specific? unless downloader.options_specific?
...@@ -114,12 +130,17 @@ module Pod ...@@ -114,12 +130,17 @@ module Pod
# Runs the prepare command bash script of the spec. # Runs the prepare command bash script of the spec.
# #
# @note Unsets the `CDPATH` env variable before running the
# shell script to avoid issues with relative paths
# (issue #1694).
#
# @return [void] # @return [void]
# #
def run_prepare_command def run_prepare_command
return unless root_spec.prepare_command return unless root_spec.prepare_command
UI.section(" > Running prepare command", '', 1) do UI.section(" > Running prepare command", '', 1) do
Dir.chdir(root) do Dir.chdir(root) do
ENV.delete('CDPATH')
prepare_command = root_spec.prepare_command.strip_heredoc.chomp prepare_command = root_spec.prepare_command.strip_heredoc.chomp
full_command = "\nset -e\n" + prepare_command full_command = "\nset -e\n" + prepare_command
bash!(full_command) bash!(full_command)
......
...@@ -15,7 +15,6 @@ module Pod ...@@ -15,7 +15,6 @@ module Pod
add_target add_target
add_files_to_build_phases add_files_to_build_phases
add_resources_bundle_targets add_resources_bundle_targets
# create_suport_files_group
create_xcconfig_file create_xcconfig_file
create_prefix_header create_prefix_header
create_dummy_source create_dummy_source
......
...@@ -81,21 +81,22 @@ module Pod ...@@ -81,21 +81,22 @@ module Pod
# #
def create_workspace def create_workspace
all_projects = user_project_paths.sort.push(sandbox.project_path).uniq all_projects = user_project_paths.sort.push(sandbox.project_path).uniq
projpaths = all_projects.map do |path| file_references = all_projects.map do |path|
path.relative_path_from(workspace_path.dirname).to_s relative_path = path.relative_path_from(workspace_path.dirname).to_s
Xcodeproj::Workspace::FileReference.new(relative_path, 'group')
end end
if workspace_path.exist? if workspace_path.exist?
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
new_projpaths = projpaths - workspace.projpaths new_file_references = file_references - workspace.file_references
unless new_projpaths.empty? unless new_file_references.empty?
workspace.projpaths.concat(new_projpaths) workspace.file_references.concat(new_file_references)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
end end
else else
UI.notice "From now on use `#{workspace_path.basename}`." UI.notice "From now on use `#{workspace_path.basename}`."
workspace = Xcodeproj::Workspace.new(*projpaths) workspace = Xcodeproj::Workspace.new(*file_references)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
end end
end end
......
...@@ -69,6 +69,7 @@ module Pod ...@@ -69,6 +69,7 @@ module Pod
@head_pods = [] @head_pods = []
@checkout_sources = {} @checkout_sources = {}
@development_pods = {} @development_pods = {}
@pods_with_absolute_path = []
end end
# @return [Lockfile] the manifest which contains the information about the # @return [Lockfile] the manifest which contains the information about the
...@@ -159,6 +160,16 @@ module Pod ...@@ -159,6 +160,16 @@ module Pod
end end
end end
# Returns true if the path as originally specified was absolute.
#
# @param [String] name
#
# @return [Bool] true if originally absolute
#
def local_path_was_absolute?(name)
@pods_with_absolute_path.include? name
end
# @return [Pathname] the directory where to store the documentation. # @return [Pathname] the directory where to store the documentation.
# #
def documentation_dir def documentation_dir
...@@ -180,7 +191,8 @@ module Pod ...@@ -180,7 +191,8 @@ module Pod
# #
def specification(name) def specification(name)
if file = specification_path(name) if file = specification_path(name)
Specification.from_file(file) original_path = development_pods[name]
Dir.chdir(original_path || Dir.pwd) { Specification.from_file(file) }
end end
end end
...@@ -206,7 +218,16 @@ module Pod ...@@ -206,7 +218,16 @@ module Pod
# #
def specification_path(name) def specification_path(name)
path = specifications_dir + "#{name}.podspec" path = specifications_dir + "#{name}.podspec"
path.exist? ? path : nil if path.exist?
path
else
path = specifications_dir + "#{name}.podspec.json"
if path.exist?
path
else
nil
end
end
end end
# Stores a specification in the `Local Podspecs` folder. # Stores a specification in the `Local Podspecs` folder.
...@@ -221,8 +242,9 @@ module Pod ...@@ -221,8 +242,9 @@ module Pod
# @todo Store all the specifications (including those not originating # @todo Store all the specifications (including those not originating
# from external sources) so users can check them. # from external sources) so users can check them.
# #
def store_podspec(name, podspec, external_source = false) def store_podspec(name, podspec, external_source = false, json = false)
output_path = specifications_dir(external_source) + "#{name}.podspec" file_name = json ? "#{name}.podspec.json" : "#{name}.podspec"
output_path = specifications_dir(external_source) + file_name
output_path.dirname.mkpath output_path.dirname.mkpath
if podspec.is_a?(String) if podspec.is_a?(String)
output_path.open('w') { |f| f.puts(podspec) } output_path.open('w') { |f| f.puts(podspec) }
...@@ -232,9 +254,13 @@ module Pod ...@@ -232,9 +254,13 @@ module Pod
end end
FileUtils.copy(podspec, output_path) FileUtils.copy(podspec, output_path)
end end
spec = Specification.from_file(output_path)
unless spec.name == name Dir.chdir(podspec.is_a?(Pathname) ? File.dirname(podspec) : Dir.pwd) do
raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`" spec = Specification.from_file(output_path)
unless spec.name == name
raise Informative, "The name of the given podspec `#{spec.name}` doesn't match the expected one `#{name}`"
end
end end
end end
...@@ -338,11 +364,15 @@ module Pod ...@@ -338,11 +364,15 @@ module Pod
# @param [#to_s] path # @param [#to_s] path
# The local path where the Pod is stored. # The local path where the Pod is stored.
# #
# @param [Bool] was_absolute
# True if the specified local path was absolute.
#
# @return [void] # @return [void]
# #
def store_local_path(name, path) def store_local_path(name, path, was_absolute = false)
root_name = Specification.root_name(name) root_name = Specification.root_name(name)
development_pods[root_name] = path.to_s development_pods[root_name] = path.to_s
@pods_with_absolute_path << root_name if was_absolute
end end
# @return [Hash{String=>String}] The path of the Pods with a local source # @return [Hash{String=>String}] The path of the Pods with a local source
......
...@@ -152,8 +152,13 @@ module Pod ...@@ -152,8 +152,13 @@ module Pod
sources.each do |source| sources.each do |source|
UI.section "Updating spec repo `#{source.name}`" do UI.section "Updating spec repo `#{source.name}`" do
Dir.chdir(source.data_provider.repo) do Dir.chdir(source.data_provider.repo) do
output = git!("pull") begin
UI.puts output if show_output && !config.verbose? output = git!("pull --ff-only")
UI.puts output if show_output && !config.verbose?
rescue Informative => e
raise Informative, 'An error occurred while performing ' \
"`git pull` on repo `#{source.name}`.\n" + e.message
end
end end
check_version_information(source.data_provider.repo) check_version_information(source.data_provider.repo)
end end
...@@ -201,12 +206,16 @@ module Pod ...@@ -201,12 +206,16 @@ module Pod
min, max = versions['min'], versions['max'] min, max = versions['min'], versions['max']
version_msg = ( min == max ) ? min : "#{min} - #{max}" version_msg = ( min == max ) ? min : "#{min} - #{max}"
raise Informative, "The `#{dir.basename}` repo requires " \ raise Informative, "The `#{dir.basename}` repo requires " \
"CocoaPods #{version_msg}\n".red + "CocoaPods #{version_msg} (currently using #{Pod::VERSION})\n".red +
"Update CocoaPods, or checkout the appropriate tag in the repo." "Update CocoaPods, or checkout the appropriate tag in the repo."
end end
needs_sudo = path_writable?(__FILE__)
if config.new_version_message? && cocoapods_update?(versions) if config.new_version_message? && cocoapods_update?(versions)
UI.puts "\nCocoaPods #{versions['last']} is available.\n".green UI.puts "\nCocoaPods #{versions['last']} is available.\n" \
"To update use: #{needs_sudo ? 'sudo ' : ''}" \
'gem install cocoapods\n'.green
end end
end end
...@@ -258,7 +267,16 @@ module Pod ...@@ -258,7 +267,16 @@ module Pod
def version_information(dir) def version_information(dir)
require 'yaml' require 'yaml'
yaml_file = dir + 'CocoaPods-version.yml' yaml_file = dir + 'CocoaPods-version.yml'
yaml_file.exist? ? YAML.load_file(yaml_file) : {} return {} unless yaml_file.exist?
begin
yaml = Pathname.new(yaml_file).read
YAMLHelper.load(yaml)
rescue Informative => e
raise Informative, "There was an error reading '#{yaml_file}'.\n" \
'Please consult http://blog.cocoapods.org/' \
'Repairing-Our-Broken-Specs-Repository/ ' \
'for more information.'
end
end end
public public
...@@ -283,6 +301,12 @@ module Pod ...@@ -283,6 +301,12 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
private
def path_writable?(path)
Pathname(path).dirname.writable?
end
end end
end end
end end
......
...@@ -158,8 +158,8 @@ module Pod ...@@ -158,8 +158,8 @@ module Pod
# Prints the textual representation of a given set. # Prints the textual representation of a given set.
# #
def pod(set, mode = :normal, statistics_provider = nil) def pod(set, mode = :normal, statistics_provider = nil)
if mode == :name if mode == :name_and_version
puts_indented set.name puts_indented "#{set.name} #{set.versions.first.version}"
else else
pod = Specification::Set::Presenter.new(set, statistics_provider) pod = Specification::Set::Presenter.new(set, statistics_provider)
title("\n-> #{pod.name} (#{pod.version})".green, '', 1) do title("\n-> #{pod.name} (#{pod.version})".green, '', 1) do
...@@ -184,10 +184,10 @@ module Pod ...@@ -184,10 +184,10 @@ module Pod
# Prints a message with a label. # Prints a message with a label.
# #
def labeled(label, value) def labeled(label, value, justification = 16)
if value if value
''.tap do |t| ''.tap do |t|
t << " - #{label}:".ljust(16) t << " - #{label}:".ljust(justification)
if value.is_a?(Array) if value.is_a?(Array)
separator = "\n - " separator = "\n - "
puts_indented t << separator << value.join(separator) puts_indented t << separator << value.join(separator)
......
...@@ -45,7 +45,7 @@ Repositories : #{repo_information.join("\n ")} ...@@ -45,7 +45,7 @@ Repositories : #{repo_information.join("\n ")}
#{'[!] Oh no, an error occurred.'.red} #{'[!] Oh no, an error occurred.'.red}
#{error_from_podfile(exception)} #{error_from_podfile(exception)}
#{'Search for existing github issues similar to yours:'.yellow} #{'Search for existing github issues similar to yours:'.yellow}
#{"https://github.com/CocoaPods/CocoaPods/search?q=#{CGI.escape(exception.message)}&type=Issues"} #{issues_url(exception)}
#{'If none exists, create a ticket, with the template displayed above, on:'.yellow} #{'If none exists, create a ticket, with the template displayed above, on:'.yellow}
https://github.com/CocoaPods/CocoaPods/issues/new https://github.com/CocoaPods/CocoaPods/issues/new
...@@ -57,6 +57,10 @@ EOS ...@@ -57,6 +57,10 @@ EOS
private private
def pathless_exception_message(message)
message.gsub(/- \(.*\):/, '-')
end
def markdown_podfile def markdown_podfile
return '' unless Config.instance.podfile_path && Config.instance.podfile_path.exist? return '' unless Config.instance.podfile_path && Config.instance.podfile_path.exist?
<<-EOS <<-EOS
...@@ -75,6 +79,16 @@ EOS ...@@ -75,6 +79,16 @@ EOS
end end
end end
def remove_color(string)
string.gsub(/\e\[(\d+)m/, '')
end
def issues_url(exception)
message = remove_color(pathless_exception_message(exception.message))
'https://github.com/CocoaPods/CocoaPods/search?q=' \
"#{CGI.escape(message)}&type=Issues"
end
def host_information def host_information
product, version, build =`sw_vers`.strip.split("\n").map { |line| line.split(":").last.strip } product, version, build =`sw_vers`.strip.split("\n").map { |line| line.split(":").last.strip }
"#{product} #{version} (#{build})" "#{product} #{version} (#{build})"
......
...@@ -60,8 +60,8 @@ module Pod ...@@ -60,8 +60,8 @@ module Pod
# Replace default spec with a subspec if asked for # Replace default spec with a subspec if asked for
a_spec = spec a_spec = spec
if spec && @only_subspec if spec && @only_subspec
a_spec = spec.subspec_by_name(@only_subspec) a_spec = spec.subspec_by_name(@only_subspec)
@subspec_name = a_spec.name @subspec_name = a_spec.name
end end
UI.print " -> #{a_spec ? a_spec.name : file.basename}\r" unless config.silent? UI.print " -> #{a_spec ? a_spec.name : file.basename}\r" unless config.silent?
...@@ -196,6 +196,12 @@ module Pod ...@@ -196,6 +196,12 @@ module Pod
# Perform analysis for a given spec (or subspec) # Perform analysis for a given spec (or subspec)
# #
def perform_extensive_analysis(spec) def perform_extensive_analysis(spec)
validate_homepage(spec)
validate_screenshots(spec)
validate_social_media_url(spec)
validate_documentation_url(spec)
validate_docset_url(spec)
spec.available_platforms.each do |platform| spec.available_platforms.each do |platform|
UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
@consumer = spec.consumer(platform) @consumer = spec.consumer(platform)
...@@ -208,18 +214,69 @@ module Pod ...@@ -208,18 +214,69 @@ module Pod
perform_extensive_subspec_analysis(spec) unless @no_subspecs perform_extensive_subspec_analysis(spec) unless @no_subspecs
end end
# Recurively perform the extensive analysis on all subspecs # Recursively perform the extensive analysis on all subspecs
# #
def perform_extensive_subspec_analysis(spec) def perform_extensive_subspec_analysis(spec)
spec.subspecs.each do |subspec| spec.subspecs.each do |subspec|
@subspec_name = subspec.name @subspec_name = subspec.name
perform_extensive_analysis(subspec) perform_extensive_analysis(subspec)
end end
end end
attr_accessor :consumer attr_accessor :consumer
attr_accessor :subspec_name attr_accessor :subspec_name
# Performs validation of a URL
#
def validate_url(url)
resp = Pod::HTTP::validate_url(url)
if !resp
warning "There was a problem validating the URL #{url}."
elsif !resp.success?
warning "The URL (#{url}) is not reachable."
end
resp
end
# Performs validations related to the `homepage` attribute.
#
def validate_homepage(spec)
if spec.homepage
validate_url(spec.homepage)
end
end
# Performs validation related to the `screenshots` attribute.
#
def validate_screenshots(spec)
spec.screenshots.compact.each do |screenshot|
request = validate_url(screenshot)
if request && !(request.headers['content-type'] && request.headers['content-type'].first =~ /image\/.*/i)
warning "The screenshot #{screenshot} is not a valid image."
end
end
end
# Performs validations related to the `social_media_url` attribute.
#
def validate_social_media_url(spec)
validate_url(spec.social_media_url) if spec.social_media_url
end
# Performs validations related to the `documentation_url` attribute.
#
def validate_documentation_url(spec)
validate_url(spec.documentation_url) if spec.documentation_url
end
# Performs validations related to the `docset_url` attribute.
#
def validate_docset_url(spec)
validate_url(spec.docset_url) if spec.docset_url
end
def setup_validation_environment def setup_validation_environment
validation_dir.rmtree if validation_dir.exist? validation_dir.rmtree if validation_dir.exist?
validation_dir.mkpath validation_dir.mkpath
...@@ -294,8 +351,10 @@ module Pod ...@@ -294,8 +351,10 @@ module Pod
end end
end end
unless file_accessor.license || spec.license && ( spec.license[:type] == 'Public Domain' || spec.license[:text] ) if consumer.spec.root?
warning "Unable to find a license file" unless file_accessor.license || spec.license && ( spec.license[:type] == 'Public Domain' || spec.license[:text] )
warning "Unable to find a license file"
end
end end
end end
...@@ -392,9 +451,10 @@ module Pod ...@@ -392,9 +451,10 @@ module Pod
end end
# @return [String] Executes xcodebuild in the current working directory and # @return [String] Executes xcodebuild in the current working directory and
# returns its output (bot STDOUT and STDERR). # returns its output (both STDOUT and STDERR).
# #
def xcodebuild def xcodebuild
UI.puts 'xcodebuild clean build -target Pods' if config.verbose?
`xcodebuild clean build -target Pods 2>&1` `xcodebuild clean build -target Pods 2>&1`
end end
......
Subproject commit 05902614470a36022b0eb7854641191fd3971254 Subproject commit 9ff0ddd87c25f7357a70e8863cef47b0e2557eca
This is a Bazaar control directory.
Do not change any files in this directory.
See http://bazaar.canonical.com/ for more information about Bazaar.
Bazaar-NG meta directory, format 1
Bazaar Branch Format 7 (needs bzr 1.6)
2 fred@sharpnoodles.com-20131030202140-gg5dfrrtaotfxlrh
Bazaar Working Tree Format 6 (bzr 1.14)
Bazaar repository format 2a (needs bzr 1.16 or later)
B+Tree Graph Index 2
node_ref_lists=1
key_elements=1
len=1
row_lengths=1
xQ
;0޺tK-R4n?'oCwK;l-W.6l
"ǰ^c:BMF@,B
\ No newline at end of file
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=0
row_lengths=
B+Tree Graph Index 2
node_ref_lists=1
key_elements=2
len=3
row_lengths=1
xM0@a֜ Lg ԅ71P,ȏ-+M W'ܦ5CH>xi& ("ükA boax{oļ#PB][а^IR`2
4i,FE;;t
"tJ57sL :*7}v e
\ No newline at end of file
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=1
row_lengths=1
x PLZ
8'@8x0ы&V|6Hcr7eyhZCbr"&s?-
\ No newline at end of file
B+Tree Graph Index 2
node_ref_lists=0
key_elements=1
len=0
row_lengths=
Pod::Spec.new do |s|
s.name = "BazaarSource"
s.version = "0.0.1"
s.summary = "A short description of BazaarSource."
s.homepage = "http://EXAMPLE/BazaarSource"
s.license = 'MIT (example)'
s.author = { "Fred McCann" => "fred@sharpnoodles.com" }
s.source = { :git => "http://EXAMPLE/BazaarSource.git", :tag => "0.0.1" }
s.source_files = 'Classes', 'Classes/**/*.{h,m}'
end
Subproject commit 90e5fbce17d66e5341f105c1eb26133a01686838
Subproject commit 65a8282c0b5a6f84bc6266d73bbe7475ef75659d
Subproject commit 287a78804972c1c4ce41d9e2771e4beb63764a16
[ui]
username = Eloy Duran <eloy.de.enige@gmail.com>
Removed comments.
\ No newline at end of file
data/MercurialSource.podspec.i
data/README.i
1 3d2759856083e6dbb5b5d0b702aa625b5b21a10a
Pod::Spec.new do |s|
s.name = "MercurialSource"
s.version = "0.0.1"
s.summary = "A short description of MercurialSource."
s.homepage = "http://EXAMPLE/MercurialSource"
s.license = 'MIT (example)'
s.author = { "Dan Cutting" => "dcutting@gmail.com" }
s.source = { :git => "http://EXAMPLE/MercurialSource.git", :tag => "0.0.1" }
s.source_files = 'Classes', 'Classes/**/*.{h,m}'
end
Subproject commit ee564d9da8878957e7b77cac987d9601eb04eca5 Subproject commit b0f4e85738f1f911e32e2914b39e9acdce7c7ed9
...@@ -18,11 +18,4 @@ Pod::Spec.new do |s| ...@@ -18,11 +18,4 @@ Pod::Spec.new do |s|
:file => 'LICENSE', :file => 'LICENSE',
:text => 'Permission is hereby granted ...' :text => 'Permission is hereby granted ...'
} }
s.documentation = {
:html => 'http://banana-corp.local/banana-lib/docs.html',
:appledoc => [
'--project-company', 'Banana Corp',
'--company-id', 'com.banana',
]
}
end end
This is a Subversion repository; use the 'svnadmin' tool to examine
it. Do not add, delete, or modify files here unless you know how
to avoid corrupting the repository.
Visit http://subversion.tigris.org/ for more information.
### This file is an example authorization file for svnserve.
### Its format is identical to that of mod_authz_svn authorization
### files.
### As shown below each section defines authorizations for the path and
### (optional) repository specified by the section name.
### The authorizations follow. An authorization line can refer to:
### - a single user,
### - a group of users defined in a special [groups] section,
### - an alias defined in a special [aliases] section,
### - all authenticated users, using the '$authenticated' token,
### - only anonymous users, using the '$anonymous' token,
### - anyone, using the '*' wildcard.
###
### A match can be inverted by prefixing the rule with '~'. Rules can
### grant read ('r') access, read-write ('rw') access, or no access
### ('').
[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average
[groups]
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,&joe
# [/foo/bar]
# harry = rw
# &joe = r
# * =
# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r
### This file is an example password file for svnserve.
### Its format is similar to that of svnserve.conf. As shown in the
### example below it contains one section labelled [users].
### The name and password for each user follow, one account per line.
[users]
# harry = harryssecret
# sally = sallyssecret
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.
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.
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