Commit d6dd337b authored by Luis de la Rosa's avatar Luis de la Rosa

Merge remote-tracking branch 'upstream/master'

parents 8d077cd5 cbf504ca
...@@ -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
# CocoaPods/CocoaPods specific
- ./bin/pod repo update --silent
install:
- bundle install --without=debugging documentation --path ./travis_bundle_dir
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="
...@@ -3,17 +3,230 @@ ...@@ -3,17 +3,230 @@
To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides/installing_cocoapods.html). To install or update CocoaPods see this [guide](http://docs.cocoapods.org/guides/installing_cocoapods.html).
## Master ## Master
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.30.0...master)
[CocoaPods-Core](https://github.com/CocoaPods/Core/compare/0.30.0...master) ##### Bug Fixes
* Fixed support for file references in the workspace generated by CocoaPods.
[Kyle Fuller][kylef]
[Fabio Pelosin][irrationalfab]
[Xcodeproj#105](https://github.com/CocoaPods/Xcodeproj/pull/150)
## 0.32.1
##### Bug Fixes
* Fixed the Podfile `default_subspec` attribute in nested subspecs.
[Fabio Pelosin][irrationalfab]
[#2050](https://github.com/CocoaPods/CocoaPods/issues/2050)
## 0.32.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/master...0.31.1)
[CocoaPods-Core](https://github.com/CocoaPods/Core/compare/master...0.31.1)
##### Enhancements ##### Enhancements
* Allow to update only a list of given pods with `pod update [POD_NAMES...]`.
[Marius Rackwitz](https://github.com/mrackwitz)
[CocoaPods#760](https://github.com/CocoaPods/CocoaPods/issues/760)
* `pod update` prints the previous version of the updated pods.
[Andrea Mazzini](https://github.com/andreamazz)
[#2008](https://github.com/CocoaPods/CocoaPods/issues/2008)
* `pod update` falls back to `pod install` if no Lockfile is present.
[Marius Rackwitz](https://github.com/mrackwitz)
* File references in the Pods project for development Pods now are absolute if
the dependency is specified with an absolute paths.
[Samuel Ford](https://github.com/samuelwford)
[#1042](https://github.com/CocoaPods/CocoaPods/issues/1042)
* Added `deprecated` and `deprecated_in_favor_of` attributes to Specification
DSL.
[Paul Young](https://github.com/paulyoung)
[Core#87](https://github.com/CocoaPods/Core/pull/87)
* Numerous improvements to the validator and to the linter.
* Validate the reachability of screenshot URLs in podspecs while linting a
specification.
[Kyle Fuller](https://github.com/kylef)
[#2010](https://github.com/CocoaPods/CocoaPods/issues/2010)
* Support HTTP redirects when linting homepage and screenshots.
[Boris Bügling](https://github.com/neonichu)
[#2027](https://github.com/CocoaPods/CocoaPods/pull/2027)
* The linter now checks `framework` and `library` attributes for invalid
strings.
[Paul Williamson](https://github.com/squarefrog)
[Fabio Pelosin](irrationalfab)
[Core#66](https://github.com/CocoaPods/Core/issues/66)
[Core#96](https://github.com/CocoaPods/Core/pull/96)
[Core#105](https://github.com/CocoaPods/Core/issues/105)
* The Linter will not check for comments anymore.
[Fabio Pelosin][irrationalfab]
[Core#108](https://github.com/CocoaPods/Core/issues/108)
* Removed legacy checks from the linter.
[Fabio Pelosin][irrationalfab]
[Core#108](https://github.com/CocoaPods/Core/issues/108)
* Added logic to handle subspecs and platform scopes to linter check of
the `requries_arc` attribute.
[Fabio Pelosin][irrationalfab]
[CocoaPods#2005](https://github.com/CocoaPods/CocoaPods/issues/2005)
* The linter no longer considers empty a Specification if it only specifies the
`resource_bundle` attribute.
[Joshua Kalpin][Kapin]
[#63](https://github.com/CocoaPods/Core/issues/63)
[#95](https://github.com/CocoaPods/Core/pull/95)
* `pod lib create` is now using the `configure` file instead of the
`_CONFIGURE.rb` file.
[Piet Brauer](https://github.com/pietbrauer)
[Orta Therox](https://github.com/orta)
* `pod lib create` now disallows any pod name that begins with a `.`
[Dustin Clark](https://github.com/clarkda)
[#2026](https://github.com/CocoaPods/CocoaPods/pull/2026)
[Core#97](https://github.com/CocoaPods/Core/pull/97)
[Core#98](https://github.com/CocoaPods/Core/issues/98)
* Prevent the user from using `pod` commands as root.
[Kyle Fuller](https://github.com/kylef)
[#1815](https://github.com/CocoaPods/CocoaPods/issues/1815)
* Dependencies declared with external sources now support HTTP downloads and
have improved support for all the options supported by the downloader.
[Fabio Pelosin][irrationalfab]
* An informative error message is presented when merge conflict is detected in
a YAML file.
[Luis de la Rosa](https://github.com/luisdelarosa)
[#69](https://github.com/CocoaPods/Core/issues/69)
[#100](https://github.com/CocoaPods/Core/pull/100)
##### Bug Fixes ##### Bug Fixes
* Fix for when using s.version as the :tag for a git repository in a Podspec
* Fixed the Podfile `default_subspec` attribute in nested subspecs.
[Fabio Pelosin][irrationalfab]
[#1021](https://github.com/CocoaPods/CocoaPods/issues/1021)
## 0.31.1
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.31.1...0.31.0)
[CocoaPods-Core](https://github.com/CocoaPods/Core/compare/0.31.1...0.31.0)
##### Minor Enhancements
* The specification now strips the indentation of the `prefix_header` and
`prepare_command` to aide their declaration as a here document (similarly to
what it already does with the description).
[Fabio Pelosin][irrationalfab]
[Core#51](https://github.com/CocoaPods/Core/issues/51)
##### Bug Fixes
* Fix linting for Pods which declare a private repo as the source.
[Boris Bügling](https://github.com/neonichu)
[Core#82](https://github.com/CocoaPods/Core/issues/82)
## 0.31.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.30.0...0.31.0)
[CocoaPods-Core](https://github.com/CocoaPods/Core/compare/0.30.0...0.31.0)
##### Enhancements
* Warnings are not promoted to errors anymore to maximise compatibility with
existing libraries.
[Fabio Pelosin](https://github.com/irrationalfab)
[#1629](https://github.com/CocoaPods/CocoaPods/issues/1629)
* Include the versions of the Pods to the output of `pod list`.
[Stefan Damm](https://github.com/StefanDamm)
[Robert Zuber](https://github.com/z00b)
[#1617](https://github.com/CocoaPods/CocoaPods/issues/1617)
* Generated prefix header file will now have unique prefix_header_contents for
Pods with subspecs.
[Luis de la Rosa](https://github.com/luisdelarosa)
[#1449](https://github.com/CocoaPods/CocoaPods/issues/1449)
* The linter will now check the reachability of the homepage of Podspecs during
a full lint.
[Richard Lee](https://github.com/dlackty)
[Fabio Pelosin](https://github.com/irrationalfab)
[#1704](https://github.com/CocoaPods/CocoaPods/issues/1704)
[Core#70](https://github.com/CocoaPods/Core/pull/70)
* Improved detection of the last version of a specification in `pod spec`
subcommands.
[Laurent Sansonetti](https://github.com/lrz)
[#1953](https://github.com/CocoaPods/CocoaPods/pull/1953)
* Display advised settings for Travis CI in the warning related presented when
the terminal encoding is not set to UTF-8.
[Richard Lee](https://github.com/dlackty)
[#1933](https://github.com/CocoaPods/CocoaPods/issues/1933)
[#1941](https://github.com/CocoaPods/CocoaPods/pull/1941)
* Unset the `CDPATH` env variable before shelling-out to `prepare_command`.
[Marc Boquet](https://github.com/apalancat)
[#1943](https://github.com/CocoaPods/CocoaPods/pull/1943)
##### Bug Fixes
* Resolve crash related to the I18n deprecation warning.
[Eloy Durán](https://github.com/alloy)
[#1950](https://github.com/CocoaPods/CocoaPods/issues/1950)
* Fix compilation issues related to the native Extension of Xcodeproj.
[Eloy Durán](https://github.com/alloy)
* Robustness against user Git configuration and against merge commits in `pod
repo` subcommands.
[Boris Bügling](https://github.com/neonichu)
[#1949](https://github.com/CocoaPods/CocoaPods/issues/1949)
[#1978](https://github.com/CocoaPods/CocoaPods/pull/1978)
* Gracefully inform the user if the `:head` option is not supported for a given
download strategy.
[Boris Bügling](https://github.com/neonichu)
[#1947](https://github.com/CocoaPods/CocoaPods/issues/1947)
[#1958](https://github.com/CocoaPods/CocoaPods/pull/1958)
* Cleanup a pod directory if error occurs while downloading.
[Alex Rothenberg](https://github.com/alexrothenberg)
[#1842](https://github.com/CocoaPods/CocoaPods/issues/1842)
[#1960](https://github.com/CocoaPods/CocoaPods/pull/1960)
* No longer warn for Github repositories with OAuth authentication.
[Boris Bügling](https://github.com/neonichu)
[#1928](https://github.com/CocoaPods/CocoaPods/issues/1928)
[Core#77](https://github.com/CocoaPods/Core/pull/77)
* Fix for when using `s.version` as the `:tag` for a git repository in a
Podspec.
[Joel Parsons](https://github.com/joelparsons) [Joel Parsons](https://github.com/joelparsons)
[#1721](https://github.com/CocoaPods/CocoaPods/issues/1721) [#1721](https://github.com/CocoaPods/CocoaPods/issues/1721)
[Core#72](https://github.com/CocoaPods/Core/pull/72) [Core#72](https://github.com/CocoaPods/Core/pull/72)
* Improved escaping of paths in Git downloader.
[Vladimir Burdukov](https://github.com/chipp)
[cocoapods-downloader#14](https://github.com/CocoaPods/cocoapods-downloader/pull/14)
* Podspec without explicitly set `requires_arc` attribute no longer passes the
lint.
[Richard Lee](https://github.com/dlackty)
[#1840](https://github.com/CocoaPods/CocoaPods/issues/1840)
[Core#71](https://github.com/CocoaPods/Core/pull/71)
* Properly quote headers in the `-isystem` compiler flag of the aggregate
targets.
[Eloy Durán](https://github.com/alloy)
[#1862](https://github.com/CocoaPods/CocoaPods/issues/1862)
[#1894](https://github.com/CocoaPods/CocoaPods/pull/1894)
## 0.30.0 ## 0.30.0
[CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.29.0...0.30.0) [CocoaPods](https://github.com/CocoaPods/CocoaPods/compare/0.29.0...0.30.0)
...@@ -2108,3 +2321,6 @@ allowing you to automate Xcode related tasks. ...@@ -2108,3 +2321,6 @@ allowing you to automate Xcode related tasks.
[5]: https://github.com/tomaz/appledoc [5]: https://github.com/tomaz/appledoc
[6]: https://github.com/CocoaPods/CocoaPods/compare/0.5.1...0.6.0 [6]: https://github.com/CocoaPods/CocoaPods/compare/0.5.1...0.6.0
[7]: https://github.com/CocoaPods/CocoaPods/compare/0.3.10...0.5.0 [7]: https://github.com/CocoaPods/CocoaPods/compare/0.3.10...0.5.0
[irrationalfab]: https://github.com/irrationalfab
[kylef]: (https://github.com/kylef)
...@@ -14,15 +14,20 @@ group :development do ...@@ -14,15 +14,20 @@ group :development do
gem 'claide', :git => 'https://github.com/CocoaPods/CLAide.git', :branch => 'master' gem 'claide', :git => 'https://github.com/CocoaPods/CLAide.git', :branch => 'master'
gem 'cocoapods-try', :git => 'https://github.com/CocoaPods/cocoapods-try.git', :branch => 'master' gem 'cocoapods-try', :git => 'https://github.com/CocoaPods/cocoapods-try.git', :branch => 'master'
gem 'rake', '~> 10.1.0' # Ruby 1.8.7
gem "mocha" gem "mocha"
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', '~> 10.1.0' # Ruby 1.8.7 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:
...@@ -31,11 +36,8 @@ group :development do ...@@ -31,11 +36,8 @@ group :development do
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.
......
...@@ -7,10 +7,10 @@ GIT ...@@ -7,10 +7,10 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Core.git remote: https://github.com/CocoaPods/Core.git
revision: 76c726cb88ec60dc64c62e2a87b1845319e84569 revision: e8216e010d9d1141a234da4d9d01cbd8416785b1
branch: master branch: master
specs: specs:
cocoapods-core (0.30.0) cocoapods-core (0.32.1)
activesupport (>= 3.2.15, < 4) activesupport (>= 3.2.15, < 4)
fuzzy_match (~> 2.0.4) fuzzy_match (~> 2.0.4)
json_pure (~> 1.8) json_pure (~> 1.8)
...@@ -18,19 +18,19 @@ GIT ...@@ -18,19 +18,19 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Xcodeproj.git remote: https://github.com/CocoaPods/Xcodeproj.git
revision: 4cc95f412d47fe8b31c5619c6705070b7849663f revision: 60c297e6dd8b04ba055b1350d72a7ef0f1092879
branch: master branch: master
specs: specs:
xcodeproj (0.15.3) xcodeproj (0.16.1)
activesupport (~> 3.0) activesupport (~> 3.0)
colored (~> 1.2) colored (~> 1.2)
GIT GIT
remote: https://github.com/CocoaPods/cocoapods-downloader.git remote: https://github.com/CocoaPods/cocoapods-downloader.git
revision: d064235f1ddc2823cb5f5f1d32f51f36e719051a revision: 224c8a191ef6b98d538d6228b0549d05194944ee
branch: master branch: master
specs: specs:
cocoapods-downloader (0.4.0) cocoapods-downloader (0.5.0)
GIT GIT
remote: https://github.com/CocoaPods/cocoapods-try.git remote: https://github.com/CocoaPods/cocoapods-try.git
...@@ -39,32 +39,6 @@ GIT ...@@ -39,32 +39,6 @@ GIT
specs: specs:
cocoapods-try (0.2.0) cocoapods-try (0.2.0)
GIT
remote: https://github.com/alloy/cocoapods-trunk.git
revision: febc522b4e462bacd013a48adb704c769586bd7e
specs:
cocoapods-trunk (0.0.1)
json (~> 1.8)
nap (>= 0.6)
netrc
GIT
remote: https://github.com/alloy/kicker.git
revision: 87b0047202c0320d4ef62e1f1a4b2cbdefadf008
branch: master
specs:
kicker (3.0.0)
listen (~> 1.3.0)
notify (~> 0.5.2)
GIT
remote: https://github.com/irrationalfab/PrettyBacon.git
revision: eaf7e6c786fd5ccc6fb88e943bf7c5e6c27569a3
branch: master
specs:
prettybacon (0.0.1)
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: b56c1268ba001f5eb55f940ca1c83bc6b83a9752
...@@ -74,18 +48,18 @@ GIT ...@@ -74,18 +48,18 @@ GIT
PATH PATH
remote: . remote: .
specs: specs:
cocoapods (0.30.0) cocoapods (0.32.1)
activesupport (>= 3.2.15, < 4) activesupport (>= 3.2.15, < 4)
claide (~> 0.5.0) claide (~> 0.5.0)
cocoapods-core (= 0.30.0) cocoapods-core (= 0.32.1)
cocoapods-downloader (~> 0.4.0) cocoapods-downloader (~> 0.5.0)
cocoapods-try (~> 0.2.0) cocoapods-try (~> 0.2.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.7)
open4 (~> 1.3) open4 (~> 1.3)
xcodeproj (~> 0.15.0) xcodeproj (~> 0.16.1)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
...@@ -93,6 +67,7 @@ GEM ...@@ -93,6 +67,7 @@ GEM
activesupport (3.2.17) activesupport (3.2.17)
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)
coderay (1.1.0) coderay (1.1.0)
...@@ -103,15 +78,20 @@ GEM ...@@ -103,15 +78,20 @@ GEM
simplecov (>= 0.7) simplecov (>= 0.7)
term-ansicolor term-ansicolor
thor thor
diffy (3.0.3) crack (0.4.2)
safe_yaml (~> 1.0.0)
diffy (3.0.4)
docile (1.1.3) docile (1.1.3)
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.1.0) github-markup (1.1.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)
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)
...@@ -124,11 +104,12 @@ GEM ...@@ -124,11 +104,12 @@ GEM
mocha-on-bacon (0.2.2) mocha-on-bacon (0.2.2)
mocha (>= 0.13.0) mocha (>= 0.13.0)
multi_json (1.9.2) multi_json (1.9.2)
nap (0.6.0) nap (0.7.0)
netrc (0.7.7)
notify (0.5.2) notify (0.5.2)
open4 (1.3.3) open4 (1.3.3)
posix-spawn (0.3.8) posix-spawn (0.3.8)
prettybacon (0.0.2)
bacon (~> 1.2)
pry (0.9.12.6) pry (0.9.12.6)
coderay (~> 1.0) coderay (~> 1.0)
method_source (~> 0.8) method_source (~> 0.8)
...@@ -145,6 +126,7 @@ GEM ...@@ -145,6 +126,7 @@ GEM
redcarpet (2.3.0) redcarpet (2.3.0)
rest-client (1.6.7) rest-client (1.6.7)
mime-types (>= 1.16) mime-types (>= 1.16)
safe_yaml (1.0.2)
simplecov (0.8.2) simplecov (0.8.2)
docile (~> 1.1.0) docile (~> 1.1.0)
multi_json multi_json
...@@ -154,7 +136,10 @@ GEM ...@@ -154,7 +136,10 @@ GEM
term-ansicolor (1.3.0) term-ansicolor (1.3.0)
tins (~> 1.0) tins (~> 1.0)
thor (0.19.1) thor (0.19.1)
tins (1.0.1) tins (1.1.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.4) yard (0.8.7.4)
...@@ -168,16 +153,16 @@ DEPENDENCIES ...@@ -168,16 +153,16 @@ DEPENDENCIES
cocoapods! cocoapods!
cocoapods-core! cocoapods-core!
cocoapods-downloader! cocoapods-downloader!
cocoapods-trunk!
cocoapods-try! cocoapods-try!
coveralls coveralls
diffy diffy
github-markup github-markup
kicker! i18n (= 0.6.4)
kicker
mime-types (< 2) mime-types (< 2)
mocha mocha
mocha-on-bacon mocha-on-bacon
prettybacon! prettybacon
pry pry
pygments.rb pygments.rb
rake (~> 10.1.0) rake (~> 10.1.0)
...@@ -185,5 +170,6 @@ DEPENDENCIES ...@@ -185,5 +170,6 @@ DEPENDENCIES
redcarpet (< 3.0.0) redcarpet (< 3.0.0)
ruby-prof! ruby-prof!
simplecov simplecov
webmock (< 1.16)
xcodeproj! xcodeproj!
yard yard
...@@ -31,15 +31,6 @@ task :bootstrap, :use_bundle_dir? do |t, args| ...@@ -31,15 +31,6 @@ task :bootstrap, :use_bundle_dir? do |t, args|
else else
execute_command "env XCODEPROJ_BUILD=1 bundle install" execute_command "env XCODEPROJ_BUILD=1 bundle install"
end end
puts "Checking for hg and bzr..."
if `which hg`.strip.empty?
puts "Please install Mercurial: `brew install hg`"
end
if `which bzr`.strip.empty?
puts "Please install Bazaar: `brew install bzr`"
end
end end
# Post release # Post release
...@@ -77,7 +68,7 @@ end ...@@ -77,7 +68,7 @@ end
namespace :spec do namespace :spec do
def specs(dir) def specs(dir)
FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ') FileList["spec/#{dir}_spec.rb"].shuffle.join(' ')
end end
#--------------------------------------# #--------------------------------------#
...@@ -89,7 +80,7 @@ namespace :spec do ...@@ -89,7 +80,7 @@ namespace :spec do
#--------------------------------------# #--------------------------------------#
unit_specs_command = "bundle exec bacon #{specs('unit/**')}" unit_specs_command = "bundle exec bacon #{specs('unit/**/*')}"
desc "Run the unit specs" desc "Run the unit specs"
task :unit => :unpack_fixture_tarballs do task :unit => :unpack_fixture_tarballs do
...@@ -104,8 +95,9 @@ namespace :spec do ...@@ -104,8 +95,9 @@ namespace :spec do
#--------------------------------------# #--------------------------------------#
desc "Run the functional specs" desc "Run the functional specs"
task :functional => :unpack_fixture_tarballs do task :functional, [:spec] => :unpack_fixture_tarballs do |t, args|
sh "bundle exec bacon #{specs('functional/**')}" args.with_defaults(:spec => '**/*')
sh "bundle exec bacon #{specs("functional/#{args[:spec]}")}"
end end
#--------------------------------------# #--------------------------------------#
...@@ -128,29 +120,10 @@ namespace :spec do ...@@ -128,29 +120,10 @@ namespace :spec do
# #
task :all => :unpack_fixture_tarballs do task :all => :unpack_fixture_tarballs do
ENV['GENERATE_COVERAGE'] = 'true' ENV['GENERATE_COVERAGE'] = 'true'
puts "\033[0;32mUsing #{`ruby --version`}\033[0m"
title 'Running the specs' title 'Running the specs'
sh "bundle exec bacon #{specs('**')}" sh "bundle exec bacon #{specs('**/*')}"
title 'Running Integration tests'
sh "bundle exec bacon spec/integration.rb"
title 'Running examples'
Rake::Task['examples:build'].invoke
end
# The integration 2 tests and the examples use the normal CocoaPods setup.
#
desc "Run all specs and build all examples"
task :ci => :unpack_fixture_tarballs do
title 'Running the specs'
sh "bundle exec bacon #{specs('**')}"
require 'pathname'
unless Pathname.new(ENV['HOME']+'/.cocoapods/repos/master').exist?
title 'Ensuring specs repo is up to date'
sh "./bin/pod setup"
end
title 'Running Integration tests' title 'Running Integration tests'
sh "bundle exec bacon spec/integration.rb" sh "bundle exec bacon spec/integration.rb"
...@@ -187,7 +160,8 @@ namespace :spec do ...@@ -187,7 +160,8 @@ namespace :spec do
desc "Rebuilds integration fixtures" desc "Rebuilds integration fixtures"
task :rebuild_integration_fixtures do task :rebuild_integration_fixtures do
title 'Running Integration tests' title 'Running Integration tests'
`bundle exec bacon spec/integration.rb` sh 'rm -rf spec/cocoapods-integration-specs/tmp'
Rake::Task['spec:integration'].invoke
title 'Storing fixtures' title 'Storing fixtures'
# Copy the files to the files produced by the specs to the after folders # Copy the files to the files produced by the specs to the after folders
......
...@@ -29,8 +29,8 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA ...@@ -29,8 +29,8 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA
# 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.5.0' s.add_runtime_dependency 'claide', '~> 0.5.0'
s.add_runtime_dependency 'cocoapods-downloader', '~> 0.4.0' s.add_runtime_dependency 'cocoapods-downloader', '~> 0.5.0'
s.add_runtime_dependency 'xcodeproj', '~> 0.15.0' s.add_runtime_dependency 'xcodeproj', '~> 0.16.1'
s.add_runtime_dependency 'cocoapods-try', '~> 0.2.0' s.add_runtime_dependency 'cocoapods-try', '~> 0.2.0'
s.add_runtime_dependency 'colored', '~> 1.2' s.add_runtime_dependency 'colored', '~> 1.2'
...@@ -38,7 +38,7 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA ...@@ -38,7 +38,7 @@ s.files = Dir["lib/**/*.rb"] + %w{ bin/pod bin/sandbox-pod README.md LICENSE CHA
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.7'
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
...@@ -65,24 +72,3 @@ if ENV['COCOA_PODS_ENV'] == 'development' ...@@ -65,24 +72,3 @@ if ENV['COCOA_PODS_ENV'] == 'development'
# require 'awesome_print' # require 'awesome_print'
# require 'pry' # require 'pry'
end end
# TODO remove for CocoaPods 0.31
#
module Pod
class Specification
def pre_install(&block)
UI.warn "[#{self}] The pre install hook of the specification " \
"DSL has been deprecated, use the `resource_bundles` or the " \
"`prepare_command` attributes."
UI.puts "[#{self}] The pre_install hook will be removed in the next release".red
@pre_install_callback = block
end
def post_install(&block)
UI.warn "[#{self}] The post install hook of the specification " \
"DSL has been deprecated, use the `resource_bundles` or the " \
"`prepare_command` attributes."
UI.puts "[#{self}] The post_install hook will be removed in the next release".red
@post_install_callback = block
end
end
end
...@@ -43,11 +43,14 @@ module Pod ...@@ -43,11 +43,14 @@ module Pod
end end
def self.run(argv) def self.run(argv)
help! "You cannot run CocoaPods as root." if Process.uid == 0
argv = CLAide::ARGV.new(argv) argv = CLAide::ARGV.new(argv)
if argv.flag?('version') if argv.flag?('version')
UI.puts VERSION UI.puts VERSION
exit 0 exit 0
end end
super(argv) super(argv)
UI.print_warnings UI.print_warnings
end end
......
...@@ -26,6 +26,7 @@ module Pod ...@@ -26,6 +26,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
...@@ -54,7 +55,7 @@ module Pod ...@@ -54,7 +55,7 @@ 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_url}' #{@name}" git!"clone '#{template_repo_url}' #{@name}"
end end
end end
...@@ -64,9 +65,13 @@ module Pod ...@@ -64,9 +65,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
......
...@@ -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
......
...@@ -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
...@@ -76,12 +78,42 @@ module Pod ...@@ -76,12 +78,42 @@ module Pod
self.summary = 'Update outdated project dependencies' self.summary = 'Update outdated project dependencies'
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 = '[POD_NAMES...]'
def initialize(argv)
@pods = argv.arguments! unless argv.arguments.empty?
super
end
def run def run
verify_podfile_exists! verify_podfile_exists!
if @pods
verify_lockfile_exists! 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) run_install_with_update(true)
end end
end end
end
end end
end end
......
...@@ -480,7 +480,7 @@ Pod::Spec.new do |s| ...@@ -480,7 +480,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 ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
......
require 'cocoapods/external_sources/abstract_external_source'
require 'cocoapods/external_sources/downloader_source'
require 'cocoapods/external_sources/path_source'
require 'cocoapods/external_sources/podspec_source'
module Pod module Pod
# Provides support for initializing the correct concrete class of an external # Provides support for initializing the correct concrete class of an external
...@@ -13,20 +18,7 @@ module Pod ...@@ -13,20 +18,7 @@ module Pod
name = dependency.root_name name = dependency.root_name
params = dependency.external_source params = dependency.external_source
klass = if params.key?(:git) then GitSource if klass = concrete_class_from_params(params)
elsif params.key?(:svn) then SvnSource
elsif params.key?(:hg) then MercurialSource
elsif params.key?(:bzr) then BazaarSource
elsif params.key?(:podspec) then PodspecSource
elsif params.key?(:path) then PathSource
end
if params.key?(:local)
klass = PathSource
UI.warn "The `:local` option of the Podfile has been renamed to `:path` and is deprecated." \
end
if klass
klass.new(name, params, podfile_path) klass.new(name, params, podfile_path)
else else
msg = "Unknown external source parameters for `#{name}`: `#{params}`" msg = "Unknown external source parameters for `#{name}`: `#{params}`"
...@@ -34,357 +26,20 @@ module Pod ...@@ -34,357 +26,20 @@ module Pod
end end
end end
#-------------------------------------------------------------------------# # @return [Class]
# 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 Fetching
# 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
#--------------------------------------#
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
#--------------------------------------#
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)
UI.titled_section("Pre-downloading: `#{name}` #{description}", { :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)
sandbox.store_podspec(name, spec, true)
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a Git remote.
#
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class GitSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
pre_download(sandbox)
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:git]}`".tap do |description|
description << ", commit `#{params[:commit]}`" if params[:commit]
description << ", branch `#{params[:branch]}`" if params[:branch]
description << ", tag `#{params[:tag]}`" if params[:tag]
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a SVN source
# remote.
#
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class SvnSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
pre_download(sandbox)
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:svn]}`".tap do |description|
description << ", folder `#{params[:folder]}`" if params[:folder]
description << ", tag `#{params[:tag]}`" if params[:tag]
description << ", revision `#{params[:revision]}`" if params[:revision]
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a Mercurial
# source remote.
#
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class MercurialSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
pre_download(sandbox)
end
# @see AbstractExternalSource#description
# #
def description def self.concrete_class_from_params(params)
"from `#{params[:hg]}`".tap do |description| if params.key?(:podspec)
description << ", revision `#{params[:revision]}`" if params[:revision] PodspecSource
elsif params.key?(:path)
PathSource
elsif params.key?(:local)
UI.warn "The `:local` option of the Podfile has been " \
"renamed to `:path` and it is deprecated."
PathSource
elsif Downloader.strategy_from_options(params)
DownloaderSource
end end
end end
end end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a Bazaar
# source remote.
#
# Supports all the options of the downloader (is similar to the git key of
# `source` attribute of a specification).
#
# @note The podspec must be in the root of the repository and should have a
# name matching the one of the dependency.
#
class BazaarSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
pre_download(sandbox)
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:bzr]}`".tap do |description|
description << ", tag `#{params[:tag]}`" if params[:tag]
description << ", revision `#{params[:revision]}`" if params[:revision]
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from an URL. Can be
# http, file, etc.
#
class PodspecSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
UI.titled_section("Fetching podspec for `#{name}` #{description}", { :verbose_prefix => "-> " }) do
require 'open-uri'
open(podspec_uri) { |io| store_podspec(sandbox, io.read) }
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
path_with_ext = File.extname(declared_path) == '.podspec' ? declared_path : "#{declared_path}/#{name}.podspec"
podfile_dir = File.dirname(podfile_path || '')
absolute_path = File.expand_path(path_with_ext, podfile_dir)
absolute_path
end
end
end
#-------------------------------------------------------------------------#
# Provides support for fetching a specification file from a path local to
# the machine running the installation.
#
# Works with the {LocalPod::LocalSourcedPod} class.
#
class PathSource < AbstractExternalSource
# @see AbstractExternalSource#fetch
#
def fetch(sandbox)
UI.titled_section("Fetching podspec for `#{name}` #{description}", { :verbose_prefix => "-> " }) do
podspec = podspec_path
store_podspec(sandbox, podspec)
sandbox.store_local_path(name, podspec.dirname)
end
end
# @see AbstractExternalSource#description
#
def description
"from `#{params[:path] || params[:local]}`"
end
#--------------------------------------#
private
# @!group Helpers
# @return [Pathname] the path of the podspec.
#
def podspec_path
declared_path = (params[:path] || params[:local]).to_s
path_with_ext = File.extname(declared_path) == '.podspec' ? declared_path : "#{declared_path}/#{name}.podspec"
podfile_dir = File.dirname(podfile_path || '')
absolute_path = File.expand_path(path_with_ext, podfile_dir)
pathname = Pathname.new(absolute_path)
unless pathname.exist?
raise Informative, "No podspec found for `#{name}` in `#{declared_path}`"
end
pathname
end
end
#-------------------------------------------------------------------------#
end
end end
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)
if File.extname(declared_path) == '.podspec'
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)
sandbox.store_podspec(name, spec, true)
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
require 'open-uri'
open(podspec_uri) { |io| store_podspec(sandbox, io.read) }
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.30.0' unless defined? Pod::VERSION VERSION = '0.32.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" result << "\n"
if prefix_header_contents = file_accessor.spec_consumer.prefix_header_contents
unique_prefix_header_contents.each do |prefix_header_contents|
result << prefix_header_contents result << prefix_header_contents
result << "\n" result << "\n"
end end
file_accessors.each do |file_accessor|
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
......
...@@ -44,13 +44,13 @@ module Pod ...@@ -44,13 +44,13 @@ module Pod
# @return [Xcodeproj::Config] # @return [Xcodeproj::Config]
# #
def generate def generate
header_search_path_flags = target.sandbox.public_headers.search_paths.map {|path| '-isystem'+path} header_search_path_flags = target.sandbox.public_headers.search_paths
@xcconfig = Xcodeproj::Config.new({ @xcconfig = Xcodeproj::Config.new({
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target), 'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(target.sandbox.public_headers.search_paths), 'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(target.sandbox.public_headers.search_paths),
'PODS_ROOT' => target.relative_pods_root, 'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_path_flags) 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_path_flags, '-isystem')
}) })
target.pod_targets.each do |pod_target| target.pod_targets.each do |pod_target|
......
...@@ -13,10 +13,13 @@ module Pod ...@@ -13,10 +13,13 @@ module Pod
# @param [Array<String>] strings # @param [Array<String>] strings
# a list of strings. # a list of strings.
# #
# @param [String] optional prefix, such as a flag or option.
#
# @return [String] the resulting string. # @return [String] the resulting string.
# #
def self.quote(strings) def self.quote(strings, prefix = nil)
strings.sort.map { |s| %W|"#{s}"| }.join(" ") prefix = "#{prefix} " if prefix
strings.sort.map { |s| %W|#{prefix}"#{s}"| }.join(" ")
end end
# @return [String] the default linker flags. `-ObjC` is always included # @return [String] the default linker flags. `-ObjC` is always included
......
...@@ -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.
# #
...@@ -169,7 +170,7 @@ module Pod ...@@ -169,7 +170,7 @@ module Pod
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
...@@ -235,7 +236,13 @@ module Pod ...@@ -235,7 +236,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
...@@ -295,9 +302,10 @@ module Pod ...@@ -295,9 +302,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
......
...@@ -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?
begin
downloader.download_head downloader.download_head
@specific_source = downloader.checkout_options @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)
......
...@@ -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
...@@ -338,11 +349,15 @@ module Pod ...@@ -338,11 +349,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,7 +152,7 @@ module Pod ...@@ -152,7 +152,7 @@ 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") output = git!("pull --no-rebase --no-commit")
UI.puts output if show_output && !config.verbose? UI.puts output if show_output && !config.verbose?
end end
check_version_information(source.data_provider.repo) check_version_information(source.data_provider.repo)
......
...@@ -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
......
...@@ -196,6 +196,9 @@ module Pod ...@@ -196,6 +196,9 @@ 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)
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,7 +211,7 @@ module Pod ...@@ -208,7 +211,7 @@ 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|
...@@ -220,6 +223,63 @@ module Pod ...@@ -220,6 +223,63 @@ module Pod
attr_accessor :consumer attr_accessor :consumer
attr_accessor :subspec_name attr_accessor :subspec_name
MAX_HTTP_REDIRECTS = 3
# Performs validation of a URL
#
def validate_url(url)
require 'rest'
begin
redirects = 0
resp = nil
loop do
resp = ::REST.head(url)
if resp.status_code >= 400
resp = ::REST.get(url)
end
if [301, 302, 303, 307, 308].include? resp.status_code
url = resp.headers['location'].first
redirects += 1
else
break
end
break unless redirects < MAX_HTTP_REDIRECTS
end
rescue
warning "There was a problem validating the URL #{url}."
resp = nil
end
if resp && !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
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
......
Subproject commit 27a44d7c15b58e8fa431ae774f13d348ad315721 Subproject commit 367aaee9111972a40d0569155f40cf6bb63e4634
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
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 file controls the configuration of the svnserve daemon, if you
### use it to allow access to this repository. (If you only allow
### access through http: and/or file: URLs, then this file is
### irrelevant.)
### Visit http://subversion.tigris.org/ for more information.
[general]
### These options control access to the repository for unauthenticated
### and authenticated users. Valid values are "write", "read",
### and "none". The sample settings below are the defaults.
# anon-access = read
# auth-access = write
### The password-db option controls the location of the password
### database file. Unless you specify a path starting with a /,
### the file's location is relative to the directory containing
### this configuration file.
### If SASL is enabled (see below), this file will NOT be used.
### Uncomment the line below to use the default password file.
# password-db = passwd
### The authz-db option controls the location of the authorization
### rules for path-based access control. Unless you specify a path
### starting with a /, the file's location is relative to the the
### directory containing this file. If you don't specify an
### authz-db, no path-based access control is done.
### Uncomment the line below to use the default authorization file.
# authz-db = authz
### This option specifies the authentication realm of the repository.
### If two repositories have the same authentication realm, they should
### have the same password database, and vice versa. The default realm
### is repository's uuid.
# realm = My First Repository
[sasl]
### This option specifies whether you want to use the Cyrus SASL
### library for authentication. Default is false.
### This section will be ignored if svnserve is not built with Cyrus
### SASL support; to check, run 'svnserve --version' and look for a line
### reading 'Cyrus SASL authentication is available.'
# use-sasl = true
### These options specify the desired strength of the security layer
### that you want SASL to provide. 0 means no encryption, 1 means
### integrity-checking only, values larger than 1 are correlated
### to the effective key length for encryption (e.g. 128 means 128-bit
### encryption). The values below are the defaults.
# min-encryption = 0
# max-encryption = 256
### This file controls the configuration of the FSFS filesystem.
[memcached-servers]
### These options name memcached servers used to cache internal FSFS
### data. See http://www.danga.com/memcached/ for more information on
### memcached. To use memcached with FSFS, run one or more memcached
### servers, and specify each of them as an option like so:
# first-server = 127.0.0.1:11211
# remote-memcached = mymemcached.corp.example.com:11212
### The option name is ignored; the value is of the form HOST:PORT.
### memcached servers can be shared between multiple repositories;
### however, if you do this, you *must* ensure that repositories have
### distinct UUIDs and paths, or else cached data from one repository
### might be used by another accidentally. Note also that memcached has
### no authentication for reads or writes, so you must ensure that your
### memcached servers are only accessible by trusted users.
[caches]
### When a cache-related error occurs, normally Subversion ignores it
### and continues, logging an error if the server is appropriately
### configured (and ignoring it with file:// access). To make
### Subversion never ignore cache errors, uncomment this line.
# fail-stop = true
[rep-sharing]
### To conserve space, the filesystem can optionally avoid storing
### duplicate representations. This comes at a slight cost in performace,
### as maintaining a database of shared representations can increase
### commit times. The space savings are dependent upon the size of the
### repository, the number of objects it contains and the amount of
### duplication between them, usually a function of the branching and
### merging process.
###
### The following parameter enables rep-sharing in the repository. It can
### be switched on and off at will, but for best space-saving results
### should be enabled consistently over the life of the repository.
# enable-rep-sharing = false
K 8
svn:date
V 27
2011-11-18T22:35:00.555031Z
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T22:36:39.964845Z
K 7
svn:log
V 14
Initial commit
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:25:58.501852Z
K 7
svn:log
V 5
tag 1
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:26:30.617415Z
K 7
svn:log
V 12
unintersting
END
K 10
svn:author
V 3
lbm
K 8
svn:date
V 27
2012-12-03T12:33:18.707618Z
K 7
svn:log
V 24
Added SvnSource podspec
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T22:36:55.378137Z
K 7
svn:log
V 13
Second commit
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T22:38:20.653871Z
K 7
svn:log
V 10
add subdir
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:14:35.265756Z
K 7
svn:log
V 25
Add proper svn structure.
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:15:57.343475Z
K 7
svn:log
V 13
tag a version
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:17:01.810456Z
K 7
svn:log
V 11
tag version
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:17:17.488194Z
K 7
svn:log
V 14
tagged version
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:17:45.822304Z
K 7
svn:log
V 17
different version
END
K 10
svn:author
V 4
eloy
K 8
svn:date
V 27
2011-11-18T23:25:31.320366Z
K 7
svn:log
V 5
tag 1
END
PLAIN
END
ENDREP
id: 0.0.r0/17
type: dir
count: 0
text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e
cpath: /
17 107
id: 2-4.0-10.r10/0
type: dir
pred: 2-4.0.r9/324
count: 4
text: 9 240 71 71 7db699d699fb8e3f5f5b75577f7337af
cpath: /tags/tag-1
copyfrom: 9 /trunk
PLAIN
K 5
tag-1
V 18
dir 2-4.0-10.r10/0
K 14
tagged-version
V 18
dir 2-4.0-5.r7/275
END
ENDREP
id: 1-4.0.r10/242
type: dir
pred: 1-4.0.r7/508
count: 3
text: 10 147 82 82 710e98498b49659cab7ca978f7367558
cpath: /tags
copyroot: 0 /
PLAIN
K 4
tags
V 17
dir 1-4.0.r10/242
K 5
trunk
V 16
dir 2-4.0.r9/324
END
ENDREP
id: 0.0.r10/459
type: dir
pred: 0.0.r9/539
count: 10
text: 10 378 68 68 1350231ca49d269ba334f78f5ff82de4
cpath: /
copyroot: 0 /
2-4._0.t9-9 add-dir false false /tags/tag-1
9 /trunk
459 588
id: 0-1.0-4.r4/0
type: file
pred: 0-1.0.r2/46
count: 2
text: 2 0 26 14 6d2fd4056babc68a3df3615c6361a522 667b7b6d0bf794ffbca8584b60497be5fea181d2 1-1/_1
cpath: /trunk/README
copyfrom: 2 /README
id: 0-3.1-4.r4/194
type: dir
pred: 0-3.0.r3/246
count: 1
text: 3 198 35 35 92805725a0ad7291b2bb1c985a3b096f
cpath: /trunk/dir
copyfrom: 3 /dir
PLAIN
K 6
README
V 17
file 0-1.0-4.r4/0
K 3
dir
V 18
dir 0-3.1-4.r4/194
END
ENDREP
id: 2-4.0.r4/421
type: dir
count: 0
text: 4 338 70 70 1302e144785b1f29a75c4371550ef7a5
cpath: /trunk
copyroot: 0 /
id: 1-4.0.r4/537
type: dir
count: 0
cpath: /tags
copyroot: 0 /
PLAIN
K 4
tags
V 16
dir 1-4.0.r4/537
K 5
trunk
V 16
dir 2-4.0.r4/421
END
ENDREP
id: 0.0.r4/681
type: dir
pred: 0.0.r3/440
count: 4
text: 4 601 67 67 a93953eb22a6cfcfd64d6f59a1ba8149
cpath: /
copyroot: 0 /
0-1._0.t3-3 add-file false false /trunk/README
2 /README
0-3._1.t3-3 add-dir false false /trunk/dir
3 /dir
_2.0.t3-3 add-dir false false /trunk
0-1.0.r2/46 delete-file false false /README
0-3.0.r3/246 delete-dir false false /dir
_1.0.t3-3 add-dir false false /tags
681 807
id: 2-4.0-5.r5/0
type: dir
pred: 2-4.0.r4/421
count: 1
text: 4 338 70 70 1302e144785b1f29a75c4371550ef7a5
cpath: /tags/tagged-version
copyfrom: 4 /trunk
PLAIN
K 14
tagged-version
V 16
dir 2-4.0-5.r5/0
END
ENDREP
id: 1-4.0.r5/213
type: dir
pred: 1-4.0.r4/537
count: 1
text: 5 154 46 46 d4a9b3df1f7b22adffe8c0d351c5f033
cpath: /tags
copyroot: 0 /
PLAIN
K 4
tags
V 16
dir 1-4.0.r5/213
K 5
trunk
V 16
dir 2-4.0.r4/421
END
ENDREP
id: 0.0.r5/427
type: dir
pred: 0.0.r4/681
count: 5
text: 5 347 67 67 2c669630127913bd14bbb09849d4532f
cpath: /
copyroot: 0 /
2-4._0.t4-4 add-dir false false /tags/tagged-version
4 /trunk
427 553
id: 2-4.0-7.r7/0
type: dir
pred: 2-4.0.r6/333
count: 2
text: 6 249 71 71 f0c7d69bd9f7850eb2b1bf893a2cff76
cpath: /tags/tagged-version/trunk
copyfrom: 6 /trunk
PLAIN
K 6
README
V 17
file 0-1.0-4.r4/0
K 3
dir
V 18
dir 0-3.1-4.r4/194
K 5
trunk
V 16
dir 2-4.0-7.r7/0
END
ENDREP
id: 2-4.0-5.r7/275
type: dir
pred: 2-4.0-5.r5/0
count: 2
text: 7 160 102 102 9e281f2563f4b0d13b52c88c3756d088
cpath: /tags/tagged-version
copyroot: 5 /tags/tagged-version
PLAIN
K 14
tagged-version
V 18
dir 2-4.0-5.r7/275
END
ENDREP
id: 1-4.0.r7/508
type: dir
pred: 1-4.0.r5/213
count: 2
text: 7 447 48 48 5754f08c0e6de74d12ccd64c552d9385
cpath: /tags
copyroot: 0 /
PLAIN
K 4
tags
V 16
dir 1-4.0.r7/508
K 5
trunk
V 16
dir 2-4.0.r6/333
END
ENDREP
id: 0.0.r7/722
type: dir
pred: 0.0.r6/548
count: 7
text: 7 642 67 67 a4a2261a005434283c7cf5295d77ca6e
cpath: /
copyroot: 0 /
2-4._0.t6-6 add-dir false false /tags/tagged-version/trunk
6 /trunk
722 848
a66ec713-344f-4902-9a97-2b60e25f44bb
This file is not used by Subversion 1.3.x or later.
However, its existence is required for compatibility with
Subversion 1.2.x or earlier.
This file is not used by Subversion 1.3.x or later.
However, its existence is required for compatibility with
Subversion 1.2.x or earlier.
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
module Pod module Pod
describe Command::Lib::Create do describe Command::Lib::Create do
before do
@sut = Command::Lib::Create
end
it "complains if wrong parameters" do it "complains if wrong parameters" do
lambda { run_command('lib', 'create') }.should.raise CLAide::Help lambda { run_command('lib', 'create') }.should.raise CLAide::Help
end end
...@@ -9,12 +15,55 @@ module Pod ...@@ -9,12 +15,55 @@ module Pod
it "complains if pod name contains spaces" do it "complains if pod name contains spaces" do
lambda { run_command('lib', 'create', 'Pod Name With Spaces') }.should.raise CLAide::Help lambda { run_command('lib', 'create', 'Pod Name With Spaces') }.should.raise CLAide::Help
end end
it "complains if pod name begins with a period" do
lambda { run_command('lib', 'create', '.HiddenPod') }.should.raise CLAide::Help
end
it "should create a new dir for the newly created pod" do
@sut.any_instance.stubs(:configure_template)
url = @sut::TEMPLATE_REPO
@sut.any_instance.expects(:git!).with("clone '#{url}' TestPod").once
run_command('lib', 'create', 'TestPod')
end
it "configures the template after cloning it passing the name of the Pod as the argument" do
@sut.any_instance.stubs(:clone_template)
dir = SpecHelper.temporary_directory + 'TestPod'
dir.mkpath
File.stubs(:exists?).with("configure").returns(true)
@sut.any_instance.expects(:system).with("./configure TestPod").once
run_command('lib', 'create', 'TestPod')
end
it "should show link to new pod guide after creation" do
@sut.any_instance.stubs(:clone_template)
@sut.any_instance.stubs(:configure_template)
output = run_command('lib', 'create', 'TestPod')
output.should.include? 'http://guides.cocoapods.org/making/making-a-cocoapod'
end
before do
@sut.any_instance.stubs(:configure_template)
end
it "should use the given template URL" do
template_url = 'https://github.com/custom/template.git'
@sut.any_instance.expects(:git!).with("clone '#{template_url}' TestPod").once
sut = run_command('lib', 'create', 'TestPod', template_url)
end
it "should use the default URL if no template URL is given" do
template_url = 'https://github.com/CocoaPods/pod-template.git'
@sut.any_instance.expects(:git!).with("clone '#{template_url}' TestPod").once
run_command('lib', 'create', 'TestPod')
end
end end
describe Command::Lib::Lint do describe Command::Lib::Lint do
it "lints the current working directory" do it "lints the current working directory" do
Dir.chdir(fixture('integration/Reachability')) do Dir.chdir(fixture('integration/Reachability')) do
cmd = command('lib', 'lint', '--only-errors') cmd = command('lib', 'lint', '--only-errors', '--quick')
cmd.run cmd.run
UI.output.should.include "passed validation" UI.output.should.include "passed validation"
end end
...@@ -35,14 +84,12 @@ module Pod ...@@ -35,14 +84,12 @@ module Pod
f << "spec.name = 'Broken'" f << "spec.name = 'Broken'"
f << 'end' f << 'end'
} }
tmp_validator = Validator.new('Broken.podspec') Validator.any_instance.expects(:no_clean=).with(false)
lint_path = tmp_validator.validation_dir Validator.any_instance.stubs(:perform_extensive_analysis)
should.raise Pod::Informative do
lambda { run_command('lib', 'lint', 'Broken.podspec') }.should.raise Pod::Informative run_command('lib', 'lint', 'Broken.podspec')
end
UI.output.should.include "Missing required attribute" UI.output.should.include "Missing required attribute"
lint_path.exist?.should == false
end end
end end
...@@ -53,46 +100,14 @@ module Pod ...@@ -53,46 +100,14 @@ module Pod
f << "spec.name = 'Broken'" f << "spec.name = 'Broken'"
f << 'end' f << 'end'
} }
lambda { run_command('lib', 'lint', 'Broken.podspec', '--no-clean') }.should.raise Pod::Informative Validator.any_instance.expects(:no_clean=).with(true)
Validator.any_instance.stubs(:perform_extensive_analysis)
UI.output.should.include "Pods project available at" should.raise Pod::Informative do
UI.output.should.include "Missing required attribute" run_command('lib', 'lint', 'Broken.podspec', '--no-clean')
lint_dir = UI.output[/.*Pods project available at `(.*)` for inspection./,1]
Pathname.new(lint_dir).exist?.should == true
end
end end
UI.output.should.include "Missing required attribute"
UI.output.should.include "Pods project available at"
end end
describe Command::Lib do
it "should create a new dir for the newly created pod" do
run_command('lib', 'create', 'TestPod')
Dir.chdir(temporary_directory) do
Pathname.new(temporary_directory + 'TestPod').exist?.should == true
end
end
it "should show link to new pod guide after creation" do
output = run_command('lib', 'create', 'TestPod')
output.should.include? 'http://guides.cocoapods.org/making/making-a-cocoapod'
end
before do
Command::Lib::Create.any_instance.stubs(:configure_template)
Command::Lib::Create.any_instance.stubs(:git!)
end
it "should use the given template URL" do
template_url = 'https://github.com/custom/template.git'
Command::Lib::Create.any_instance.expects(:git!).with("clone '#{template_url}' TestPod").once
sut = run_command('lib', 'create', 'TestPod', template_url)
end
it "should use the default URL if no template URL is given" do
template_url = 'https://github.com/CocoaPods/pod-template.git'
Command::Lib::Create.any_instance.expects(:git!).with("clone '#{template_url}' TestPod").once
run_command('lib', 'create', 'TestPod')
end end
end end
end end
...@@ -28,6 +28,16 @@ module Pod ...@@ -28,6 +28,16 @@ module Pod
out.should.include('BananaLib') out.should.include('BananaLib')
out.should.not.include('JSONKit') out.should.not.include('JSONKit')
end end
it "presents the known pods with versions" do
sets = SourcesManager.all_sets
jsonkit_set = sets.find { |s| s.name == 'JSONKit' }
out = run_command('list')
[ /BananaLib 1.0/,
/JSONKit #{jsonkit_set.versions.first}/,
/\d+ pods were found/
].each { |regex| out.should =~ regex }
end
end end
end end
...@@ -34,13 +34,54 @@ module Pod ...@@ -34,13 +34,54 @@ module Pod
it "tells the user that no Lockfile was found in the current working dir" do it "tells the user that no Lockfile was found in the current working dir" do
file = temporary_directory + 'Podfile' file = temporary_directory + 'Podfile'
File.open(file, 'w') {|f| f.write('platform :ios') } File.open(file, 'w') do |f|
f.puts('platform :ios')
f.puts('pod "Reachability"')
end
Dir.chdir(temporary_directory) do Dir.chdir(temporary_directory) do
exception = lambda { run_command('update','--no-repo-update') }.should.raise Informative exception = lambda { run_command('update', 'Reachability', '--no-repo-update') }.should.raise Informative
exception.message.should.include "No `Podfile.lock' found in the current working directory" exception.message.should.include "No `Podfile.lock' found in the current working directory"
end end
end end
describe "tells the user that the Pods cannot be updated unless they are installed" do
extend SpecHelper::TemporaryRepos
before do
file = temporary_directory + 'Podfile'
File.open(file, 'w') do |f|
f.puts('platform :ios')
f.puts('pod "BananaLib", "1.0"')
end
podfile = Podfile.new do
platform :ios
pod 'BananaLib', '1.0'
end
specs = [
Specification.new do |s|
s.name = 'BananaLib'
s.version = '1.0'
end
]
Lockfile.generate(podfile, specs).write_to_disk(temporary_directory + 'Podfile.lock')
end
it "for a single missing Pod" do
Dir.chdir(temporary_directory) do
exception = lambda { run_command('update', 'Reachability', '--no-repo-update') }.should.raise Informative
exception.message.should.include "Pod `Reachability' is not installed and cannot be updated"
end
end
it "for multiple missing Pods" do
Dir.chdir(temporary_directory) do
exception = lambda { run_command('update', 'Reachability', 'BananaLib2', '--no-repo-update') }.should.raise Informative
exception.message.should.include "Pods `Reachability', `BananaLib2' are not installed and cannot be updated"
end
end
end
end end
#---------------------------------------------------------------------------# #---------------------------------------------------------------------------#
......
...@@ -40,6 +40,8 @@ module Pod ...@@ -40,6 +40,8 @@ module Pod
before do before do
set_up_test_repo set_up_test_repo
config.repos_dir = SpecHelper.tmp_repos_path config.repos_dir = SpecHelper.tmp_repos_path
require 'rest'
::REST.stubs(:head => stub(:success? => true))
end end
it "lints a repository" do it "lints a repository" do
......
...@@ -14,5 +14,9 @@ module Pod ...@@ -14,5 +14,9 @@ module Pod
UI.output.should.include 'spec/fixtures/spec-repos/master/AFNetworking' UI.output.should.include 'spec/fixtures/spec-repos/master/AFNetworking'
end end
it "doesn't let you run as root" do
Process.stubs(:uid).returns(0)
lambda { Pod::Command.run(['--version']) }.should.raise CLAide::Help
end
end end
end end
...@@ -41,6 +41,12 @@ module Pod ...@@ -41,6 +41,12 @@ module Pod
output = UI.output output = UI.output
output.should.include? "RestKit/Network" output.should.include? "RestKit/Network"
end end
it "presents only name and version of a specification set in :name_and_version mode" do
@set = SourcesManager.search_by_name('RestKit').first
UI.pod(@set, :name_and_version)
output = UI.output
output.should.include? "RestKit #{@set.versions.first}"
end
end end
end end
...@@ -331,6 +331,10 @@ describe "Integration" do ...@@ -331,6 +331,10 @@ describe "Integration" do
check "install --no-repo-update", "install_subspecs" check "install --no-repo-update", "install_subspecs"
end end
describe "Installs a Pod with subspecs and does not duplicate the prefix header" do
check "install --no-repo-update", "install_subspecs_no_duplicate_prefix"
end
describe "Installs a Pod with a local source" do describe "Installs a Pod with a local source" do
check "install --no-repo-update", "install_local_source" check "install --no-repo-update", "install_local_source"
end end
...@@ -370,7 +374,11 @@ describe "Integration" do ...@@ -370,7 +374,11 @@ describe "Integration" do
describe "Pod update" do describe "Pod update" do
describe "Updates an existing installation" do describe "Updates an existing installation" do
check "update --no-repo-update", "update" check "update --no-repo-update", "update_all"
end
describe "Updates a selected Pod in an existing installation" do
check "update Reachability --no-repo-update", "update_selected"
end end
end end
......
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe ExternalSources::AbstractExternalSource do
before do
dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability'))
@subject = ExternalSources.from_dependency(dependency, nil)
end
#--------------------------------------#
describe "In general" do
it "compares to another" do
dependency_1 = Dependency.new("Reachability", :git => 'url')
dependency_2 = Dependency.new("Another_name", :git => 'url')
dependency_3 = Dependency.new("Reachability", :git => 'another_url')
dependency_1.should.be == dependency_1
dependency_1.should.not.be == dependency_2
dependency_1.should.not.be == dependency_3
end
it "fetches the specification from the remote stores it in the sandbox" do
config.sandbox.specification('Reachability').should == nil
@subject.fetch(config.sandbox)
config.sandbox.specification('Reachability').name.should == 'Reachability'
end
end
#--------------------------------------#
describe "Subclasses helpers" do
it "pre-downloads the Pod and stores the relevant information in the sandbox" do
sandbox = config.sandbox
@subject.send(:pre_download, sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
sandbox.predownloaded_pods.should == ["Reachability"]
sandbox.checkout_sources.should == {
"Reachability" => {
:git => fixture('integration/Reachability'),
:commit => "4ec575e4b074dcc87c44018cce656672a979b34a"
}
}
end
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe ExternalSources::DownloaderSource do
before do
params = {
:git => fixture('integration/Reachability'),
:branch => 'master'
}
dep = Dependency.new("Reachability", params)
@subject = ExternalSources.from_dependency(dep, nil)
end
it "creates a copy of the podspec" do
@subject.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "marks the Pod as pre-downloaded" do
@subject.fetch(config.sandbox)
config.sandbox.predownloaded_pods.should == ["Reachability"]
end
it "returns the description" do
expected = /from `.*Reachability`, branch `master`/
@subject.description.should.match(expected)
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe ExternalSources::PathSource do
before do
params = { :path => fixture('integration/Reachability') }
dependency = Dependency.new("Reachability", params)
podfile_path = fixture('integration/Podfile')
@subject = ExternalSources.from_dependency(dependency, podfile_path)
end
it "creates a copy of the podspec" do
@subject.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "supports the deprecated local key" do
params = { :local => fixture('integration/Reachability') }
dependency = Dependency.new("Reachability", params)
podfile_path = fixture('integration/Podfile')
@subject = ExternalSources.from_dependency(dependency, podfile_path)
@subject.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "returns the description" do
@subject.description.should.match %r|from `.*integration/Reachability`|
end
it "marks the Pod as local in the sandbox" do
@subject.fetch(config.sandbox)
config.sandbox.development_pods.should == {
"Reachability" => fixture('integration/Reachability').to_s
}
end
it "raises if the podspec cannot be found" do
@subject.stubs(:params).returns(:path => temporary_directory)
should.raise Informative do
@subject.fetch(config.sandbox)
end.message.should.match /No podspec found for `Reachability` in `#{temporary_directory}`/
it "marks a pod as relative" do
@subject.stubs(:params).returns(:path => './Reachability')
Pathname.any_instance.stubs(:exist?).returns(true)
config.sandbox.stubs(:store_podspec)
@subject.fetch(config.sandbox)
config.sandbox.local_path_was_absolute?('Reachability').should.be.false
end
it "marks a pod as absolute" do
@subject.stubs(:params).returns(:path => '/path/Reachability')
Pathname.any_instance.stubs(:exist?).returns(true)
config.sandbox.stubs(:store_podspec)
@subject.fetch(config.sandbox)
config.sandbox.local_path_was_absolute?('Reachability').should.be.true
end
end
describe "#podspec_path" do
it "handles absolute paths" do
@subject.stubs(:params).returns(:path => fixture('integration/Reachability'))
path = @subject.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "handles paths when there is no podfile path" do
@subject.stubs(:podfile_path).returns(nil)
@subject.stubs(:params).returns(:path => fixture('integration/Reachability'))
path = @subject.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "handles relative paths" do
@subject.stubs(:params).returns(:path => 'Reachability')
path = @subject.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "expands the tilde" do
File.stubs(:exist?).returns(true)
@subject.stubs(:params).returns(:path => '~/Reachability')
Pathname.any_instance.stubs(:exist?).returns(true)
path = @subject.send(:podspec_path)
path.should == Pathname(ENV['HOME']) + 'Reachability/Reachability.podspec'
end
end
describe '#absolute?' do
it 'returns that a path is relative' do
result = @subject.send(:absolute?, './ThirdPartyCode/UrbanAirship')
result.should.be.false
end
it "consider relative paths not explicitly set from the current dir" do
result = @subject.send(:absolute?, './ThirdPartyCode/UrbanAirship')
result.should.be.false
end
it 'returns that a path is absolute' do
result = @subject.send(:absolute?, '/path/to/UrbanAirship')
result.should.be.true
end
it 'considers absolute paths specified with the tilde' do
result = @subject.send(:absolute?, '~/path/to/UrbanAirship')
result.should.be.true
end
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe ExternalSources::PodspecSource do
before do
podspec_path = fixture('integration/Reachability/Reachability.podspec')
dependency = Dependency.new("Reachability", :podspec => podspec_path.to_s)
podfile_path = fixture('integration/Podfile')
@subject = ExternalSources.from_dependency(dependency, podfile_path)
end
it "creates a copy of the podspec" do
@subject.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "returns the description" do
@subject.description.should.match %r|from `.*Reachability/Reachability.podspec`|
end
describe "Helpers" do
it "handles absolute paths" do
@subject.stubs(:params).returns(:podspec => fixture('integration/Reachability'))
path = @subject.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "handles paths when there is no podfile path" do
@subject.stubs(:podfile_path).returns(nil)
@subject.stubs(:params).returns(:podspec => fixture('integration/Reachability'))
path = @subject.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "handles relative paths" do
@subject.stubs(:params).returns(:podspec => 'Reachability')
path = @subject.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "expands the tilde" do
File.stubs(:exist?).returns(true)
@subject.stubs(:params).returns(:podspec => '~/Reachability')
path = @subject.send(:podspec_uri)
path.should == ENV['HOME'] + '/Reachability/Reachability.podspec'
end
it "handles URLs" do
@subject.stubs(:params).returns(:podspec => "http://www.example.com/Reachability.podspec")
path = @subject.send(:podspec_uri)
path.should == "http://www.example.com/Reachability.podspec"
end
end
end
end
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
module Pod module Pod
describe ExternalSources do describe ExternalSources do
it "returns the instance of appropriate concrete class according to the parameters" do
git = Dependency.new("Reachability", :git => nil)
svn = Dependency.new("Reachability", :svn => nil)
podspec = Dependency.new("Reachability", :podspec => nil)
local = Dependency.new("Reachability", :local => nil)
path = Dependency.new("Reachability", :path => nil)
ExternalSources.from_dependency(git, nil).class.should == ExternalSources::GitSource
ExternalSources.from_dependency(svn, nil).class.should == ExternalSources::SvnSource
ExternalSources.from_dependency(podspec, nil).class.should == ExternalSources::PodspecSource
ExternalSources.from_dependency(local, nil).class.should == ExternalSources::PathSource
ExternalSources.from_dependency(path, nil).class.should == ExternalSources::PathSource
end
end
#---------------------------------------------------------------------------#
describe ExternalSources::AbstractExternalSource do
before do
dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability'))
@external_source = ExternalSources.from_dependency(dependency, nil)
end
#--------------------------------------#
describe "In general" do
it "compares to another" do
dependency_1 = Dependency.new("Reachability", :git => 'url')
dependency_2 = Dependency.new("Another_name", :git => 'url')
dependency_3 = Dependency.new("Reachability", :git => 'another_url')
dependency_1.should.be == dependency_1
dependency_1.should.not.be == dependency_2
dependency_1.should.not.be == dependency_3
end
it "fetches the specification from the remote stores it in the sandbox" do
config.sandbox.specification('Reachability').should == nil
@external_source.fetch(config.sandbox)
config.sandbox.specification('Reachability').name.should == 'Reachability'
end
end
#--------------------------------------#
describe "Subclasses helpers" do
it "pre-downloads the Pod and stores the relevant information in the sandbox" do
sandbox = config.sandbox
@external_source.send(:pre_download, sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
sandbox.predownloaded_pods.should == ["Reachability"]
sandbox.checkout_sources.should == {
"Reachability" => {
:git => fixture('integration/Reachability'),
:commit => "4ec575e4b074dcc87c44018cce656672a979b34a"
}
}
end
end
end
#---------------------------------------------------------------------------#
describe ExternalSources::GitSource do
before do
dependency = Dependency.new("Reachability", :git => fixture('integration/Reachability'))
@external_source = ExternalSources.from_dependency(dependency, nil)
end
it "creates a copy of the podspec" do
@external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "marks a LocalPod as downloaded" do
@external_source.fetch(config.sandbox)
config.sandbox.predownloaded_pods.should == ["Reachability"]
end
it "returns the description" do
@external_source.description.should.match %r|from `.*Reachability`|
end
end
#---------------------------------------------------------------------------#
describe ExternalSources::SvnSource do
before do before do
dependency = Dependency.new("SvnSource", :svn => "file://#{fixture('subversion-repo/trunk')}") @subject = ExternalSources
@external_source = ExternalSources.from_dependency(dependency, nil)
end
it "creates a copy of the podspec" do
@external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/SvnSource.podspec'
path.should.exist?
end
it "marks a LocalPod as downloaded" do
@external_source.fetch(config.sandbox)
config.sandbox.predownloaded_pods.should == ["SvnSource"]
end end
it "returns the description" do describe "from_dependency" do
@external_source.description.should.match %r|from `.*subversion-repo/trunk`| it "supports a podspec source" do
end dep = Dependency.new("Reachability", :podspec => nil)
end klass = @subject.from_dependency(dep, nil).class
klass.should == @subject::PodspecSource
#---------------------------------------------------------------------------#
describe ExternalSources::MercurialSource do
before do
dependency = Dependency.new("MercurialSource", :hg => fixture('mercurial-repo'))
@external_source = ExternalSources.from_dependency(dependency, nil)
end end
it "creates a copy of the podspec" do it "supports a path source" do
@external_source.fetch(config.sandbox) dep = Dependency.new("Reachability", :path => nil)
path = config.sandbox.root + 'Local Podspecs/MercurialSource.podspec' klass = @subject.from_dependency(dep, nil).class
path.should.exist? klass.should == @subject::PathSource
end end
it "marks a LocalPod as downloaded" do it "supports a path source specified with the legacy :local key" do
@external_source.fetch(config.sandbox) dep = Dependency.new("Reachability", :local => nil)
config.sandbox.predownloaded_pods.should == ["MercurialSource"] klass = @subject.from_dependency(dep, nil).class
klass.should == @subject::PathSource
end end
it "returns the description" do it "supports all the strategies implemented by the downloader" do
@external_source.description.should.match %r|from `.*/mercurial-repo`| [:git, :svn, :hg, :bzr, :http].each do |strategy|
dep = Dependency.new("Reachability", strategy => nil)
klass = @subject.from_dependency(dep, nil).class
klass.should == @subject::DownloaderSource
end end
end end
#---------------------------------------------------------------------------#
describe ExternalSources::BazaarSource do
before do
dependency = Dependency.new("BazaarSource", :bzr => fixture('bzr-repo'))
@external_source = ExternalSources.from_dependency(dependency, nil)
end end
it "creates a copy of the podspec" do
@external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/BazaarSource.podspec'
path.should.exist?
end end
it "marks a LocalPod as downloaded" do
@external_source.fetch(config.sandbox)
config.sandbox.predownloaded_pods.should == ["BazaarSource"]
end
it "returns the description" do
@external_source.description.should.match %r|from `.*/bzr-repo`|
end
end
#---------------------------------------------------------------------------#
describe ExternalSources::PodspecSource do
before do
podspec_path = fixture('integration/Reachability/Reachability.podspec')
dependency = Dependency.new("Reachability", :podspec => podspec_path.to_s)
podfile_path = fixture('integration/Podfile')
@external_source = ExternalSources.from_dependency(dependency, podfile_path)
end
it "creates a copy of the podspec" do
@external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "returns the description" do
@external_source.description.should.match %r|from `.*Reachability/Reachability.podspec`|
end
describe "Helpers" do
it "handles absolute paths" do
@external_source.stubs(:params).returns(:podspec => fixture('integration/Reachability'))
path = @external_source.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "handles paths when there is no podfile path" do
@external_source.stubs(:podfile_path).returns(nil)
@external_source.stubs(:params).returns(:podspec => fixture('integration/Reachability'))
path = @external_source.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "handles relative paths" do
@external_source.stubs(:params).returns(:podspec => 'Reachability')
path = @external_source.send(:podspec_uri)
path.should == fixture('integration/Reachability/Reachability.podspec').to_s
end
it "expands the tilde" do
@external_source.stubs(:params).returns(:podspec => '~/Reachability')
path = @external_source.send(:podspec_uri)
path.should == ENV['HOME'] + '/Reachability/Reachability.podspec'
end
it "handles urls" do
@external_source.stubs(:params).returns(:podspec => "http://www.example.com/Reachability.podspec")
path = @external_source.send(:podspec_uri)
path.should == "http://www.example.com/Reachability.podspec"
end
end
end
#---------------------------------------------------------------------------#
describe ExternalSources::PathSource do
before do
podspec_path = fixture('integration/Reachability/Reachability.podspec')
dependency = Dependency.new("Reachability", :path => fixture('integration/Reachability'))
podfile_path = fixture('integration/Podfile')
@external_source = ExternalSources.from_dependency(dependency, podfile_path)
end
it "creates a copy of the podspec" do
@external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "creates a copy of the podspec [Deprecated local option]" do
dependency = Dependency.new("Reachability", :local => fixture('integration/Reachability'))
podfile_path = fixture('integration/Podfile')
external_source = ExternalSources.from_dependency(dependency, podfile_path)
external_source.fetch(config.sandbox)
path = config.sandbox.root + 'Local Podspecs/Reachability.podspec'
path.should.exist?
end
it "returns the description" do
@external_source.description.should.match %r|from `.*integration/Reachability`|
end
it "marks the Pod as local in the sandbox" do
@external_source.fetch(config.sandbox)
config.sandbox.development_pods.should == {
"Reachability" => fixture('integration/Reachability').to_s
}
end
describe "Helpers" do
it "handles absolute paths" do
@external_source.stubs(:params).returns(:path => fixture('integration/Reachability'))
path = @external_source.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "handles paths when there is no podfile path" do
@external_source.stubs(:podfile_path).returns(nil)
@external_source.stubs(:params).returns(:path => fixture('integration/Reachability'))
path = @external_source.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "handles relative paths" do
@external_source.stubs(:params).returns(:path => 'Reachability')
path = @external_source.send(:podspec_path)
path.should == fixture('integration/Reachability/Reachability.podspec')
end
it "expands the tilde" do
@external_source.stubs(:params).returns(:path => '~/Reachability')
Pathname.any_instance.stubs(:exist?).returns(true)
path = @external_source.send(:podspec_path)
path.should == Pathname(ENV['HOME']) + 'Reachability/Reachability.podspec'
end
it "raises if the podspec cannot be found" do
@external_source.stubs(:params).returns(:path => temporary_directory)
e = lambda { @external_source.send(:podspec_path) }.should.raise Informative
e.message.should.match /No podspec found for `Reachability` in `#{temporary_directory}`/
end
end
end
#---------------------------------------------------------------------------#
end end
...@@ -21,6 +21,43 @@ module Pod ...@@ -21,6 +21,43 @@ module Pod
EOS EOS
end end
# @note Declaring a subspec was found in issue #1449 to generate duplicates of the prefix_header_contents
it "does not duplicate the contents of the specification's prefix header when a subspec is declared" do
@spec.prefix_header_contents = '#import "BlocksKit.h"'
@spec.prefix_header_file = nil
@spec.subspec 'UI' do |subspec|
subspec.source_files = 'Source/UI/*.{h,m}'
end
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
# @note Declaring a subspec was found in issue #1449 to generate duplicates of the prefix_header_contents
it "does not duplicate the contents of the specification's prefix header when a subspec is declared multiple times" do
@spec.prefix_header_contents = '#import "BlocksKit.h"'
@spec.prefix_header_file = nil
@spec.subspec 'UI' do |su|
su.source_files = 'Source/UI/*.{h,m}'
end
@spec.subspec 'Helpers' do |sh|
sh.source_files = 'Source/Helpers/*.{h,m}'
end
@gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "BlocksKit.h"
EOS
end
it "includes the contents of the specification's prefix header file" do it "includes the contents of the specification's prefix header file" do
@gen.generate.should == <<-EOS.strip_heredoc @gen.generate.should == <<-EOS.strip_heredoc
#ifdef __OBJC__ #ifdef __OBJC__
......
...@@ -61,7 +61,7 @@ module Pod ...@@ -61,7 +61,7 @@ module Pod
end end
it 'adds the sandbox public headers search paths to the xcconfig, with quotes, as system headers' do it 'adds the sandbox public headers search paths to the xcconfig, with quotes, as system headers' do
expected = "$(inherited) \"-isystem#{config.sandbox.public_headers.search_paths.join('" -isystem"')}\"" expected = "$(inherited) -isystem \"#{config.sandbox.public_headers.search_paths.join('" -isystem "')}\""
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
......
...@@ -37,6 +37,11 @@ module Pod ...@@ -37,6 +37,11 @@ module Pod
result = @sut.quote(['string1', 'string2']) result = @sut.quote(['string1', 'string2'])
result.should == '"string1" "string2"' result.should == '"string1" "string2"'
end end
it "inserts an optional string and then the normal quoted string" do
result = @sut.quote(['string1', 'string2'], '-isystem')
result.should == '-isystem "string1" -isystem "string2"'
end
end end
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
......
...@@ -95,14 +95,14 @@ module Pod ...@@ -95,14 +95,14 @@ module Pod
it "considers changed a Pod whose specification is in head mode if in update mode" do it "considers changed a Pod whose specification is in head mode if in update mode" do
@sandbox.stubs(:head_pod?).returns(true) @sandbox.stubs(:head_pod?).returns(true)
@analyzer.stubs(:update_mode).returns(true) @analyzer.stubs(:update_mode?).returns(true)
@analyzer.send(:pod_changed?, 'BananaLib').should == true @analyzer.send(:pod_changed?, 'BananaLib').should == true
end end
it "doesn't consider changed a Pod whose specification is in head mode if not in update mode" do it "doesn't consider changed a Pod whose specification is in head mode if not in update mode" do
@sandbox.stubs(:head_pod?).returns(true) @sandbox.stubs(:head_pod?).returns(true)
@analyzer.stubs(:sandbox_head_version?).returns(true) @analyzer.stubs(:sandbox_head_version?).returns(true)
@analyzer.stubs(:update_mode).returns(false) @analyzer.stubs(:update_mode?).returns(false)
@analyzer.send(:pod_changed?, 'BananaLib').should == false @analyzer.send(:pod_changed?, 'BananaLib').should == false
end end
......
...@@ -117,7 +117,7 @@ module Pod ...@@ -117,7 +117,7 @@ module Pod
end end
it "does not lock the dependencies in update mode" do it "does not lock the dependencies in update mode" do
@analyzer.update_mode = true @analyzer.update = true
@analyzer.analyze @analyzer.analyze
@analyzer.send(:locked_dependencies).map(&:to_s).should == [] @analyzer.send(:locked_dependencies).map(&:to_s).should == []
end end
...@@ -129,19 +129,19 @@ module Pod ...@@ -129,19 +129,19 @@ module Pod
podfile_state.added << "BananaLib" podfile_state.added << "BananaLib"
@analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state)) @analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state))
@podfile.stubs(:dependencies).returns([Dependency.new('BananaLib', :git => "example.com")]) @podfile.stubs(:dependencies).returns([Dependency.new('BananaLib', :git => "example.com")])
ExternalSources::GitSource.any_instance.expects(:fetch) ExternalSources::DownloaderSource.any_instance.expects(:fetch)
@analyzer.send(:fetch_external_sources) @analyzer.send(:fetch_external_sources)
end end
xit "it fetches the specification from either the sandbox or from the remote be default" do xit "it fetches the specification from either the sandbox or from the remote be default" do
dependency = Dependency.new('Name', :git => 'www.example.com') dependency = Dependency.new('Name', :git => 'www.example.com')
ExternalSources::GitSource.any_instance.expects(:specification_from_external).returns(Specification.new).once ExternalSources::DownloaderSource.any_instance.expects(:specification_from_external).returns(Specification.new).once
@resolver.send(:set_from_external_source, dependency) @resolver.send(:set_from_external_source, dependency)
end end
xit "it fetches the specification from the remote if in update mode" do xit "it fetches the specification from the remote if in update mode" do
dependency = Dependency.new('Name', :git => 'www.example.com') dependency = Dependency.new('Name', :git => 'www.example.com')
ExternalSources::GitSource.any_instance.expects(:specification).returns(Specification.new).once ExternalSources::DownloaderSource.any_instance.expects(:specification).returns(Specification.new).once
@resolver.update_external_specs = false @resolver.update_external_specs = false
@resolver.send(:set_from_external_source, dependency) @resolver.send(:set_from_external_source, dependency)
end end
......
...@@ -61,6 +61,36 @@ module Pod ...@@ -61,6 +61,36 @@ module Pod
} }
end end
it "cleans up directory when an error occurs during download" do
config.sandbox.store_head_pod('BananaLib')
pod_folder = config.sandbox.root + 'BananaLib'
partially_downloaded_file = pod_folder + 'partially_downloaded_file'
mock_downloader = Object.new
singleton_class = class << mock_downloader; self; end
singleton_class.send(:define_method, :download_head) do
FileUtils.mkdir_p(pod_folder)
FileUtils.touch(partially_downloaded_file)
raise("some network error")
end
@installer.stubs(:downloader).returns(mock_downloader)
lambda {
@installer.install!
}.should.raise(RuntimeError).message.should.equal('some network error')
partially_downloaded_file.should.not.exist
end
it "fails when using :head for Http source" do
config.sandbox.store_head_pod('BananaLib')
@spec.source = { :http => 'http://dl.google.com/googleadmobadssdk/googleadmobsearchadssdkios.zip' }
@spec.source_files = 'GoogleAdMobSearchAdsSDK/*.h'
Pod::Downloader::Http.any_instance.stubs(:download_head)
should.raise Informative do
@installer.install!
end.message.should.match /does not support the :head option, as it uses a Http source./
end
end end
#--------------------------------------# #--------------------------------------#
...@@ -83,6 +113,13 @@ module Pod ...@@ -83,6 +113,13 @@ module Pod
@installer.install! @installer.install!
end.message.should.match /command not found/ end.message.should.match /command not found/
end end
it "unsets $CDPATH environment variable" do
ENV['CDPATH'] = "BogusPath"
@spec.prepare_command = "cd Classes;ls Banana.h"
lambda { @installer.install! }.should.not.raise
end
end end
#--------------------------------------# #--------------------------------------#
......
...@@ -34,7 +34,10 @@ module Pod ...@@ -34,7 +34,10 @@ module Pod
@integrator.integrate! @integrator.integrate!
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
workspace.projpaths.find { |path| path =~ /Pods.xcodeproj/ }.should.not.be.nil pods_project_ref = workspace.file_references.find do |ref|
ref.path =~ /Pods.xcodeproj/
end
pods_project_ref.should.not.be.nil
end end
it "integrates the user targets" do it "integrates the user targets" do
...@@ -60,7 +63,7 @@ module Pod ...@@ -60,7 +63,7 @@ module Pod
@integrator.send(:create_workspace) @integrator.send(:create_workspace)
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
saved.projpaths.should == [ saved.file_references.map(&:path).should == [
"SampleProject/SampleProject.xcodeproj", "SampleProject/SampleProject.xcodeproj",
"Pods/Pods.xcodeproj" "Pods/Pods.xcodeproj"
] ]
...@@ -68,22 +71,24 @@ module Pod ...@@ -68,22 +71,24 @@ module Pod
it "updates an existing workspace if needed" do it "updates an existing workspace if needed" do
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
workspace = Xcodeproj::Workspace.new('SampleProject/SampleProject.xcodeproj') ref = Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group')
workspace = Xcodeproj::Workspace.new(ref)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
@integrator.send(:create_workspace) @integrator.send(:create_workspace)
saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
saved.projpaths.should == [ saved.file_references.map(&:path).should == [
"SampleProject/SampleProject.xcodeproj", "SampleProject/SampleProject.xcodeproj",
"Pods/Pods.xcodeproj" "Pods/Pods.xcodeproj"
] ]
end end
it "doesn't write the workspace if not needed" do it "doesn't write the workspace if not needed" do
projpaths = [ file_references = [
"SampleProject/SampleProject.xcodeproj", Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group'),
"Pods/Pods.xcodeproj" Xcodeproj::Workspace::FileReference.new('Pods/Pods.xcodeproj', 'group')
] ]
workspace = Xcodeproj::Workspace.new(projpaths)
workspace = Xcodeproj::Workspace.new(file_references)
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
Xcodeproj::Workspace.expects(:save_as).never Xcodeproj::Workspace.expects(:save_as).never
...@@ -91,12 +96,13 @@ module Pod ...@@ -91,12 +96,13 @@ module Pod
end end
it "only appends projects to the workspace and never deletes one" do it "only appends projects to the workspace and never deletes one" do
workspace = Xcodeproj::Workspace.new('user_added_project.xcodeproj') ref = Xcodeproj::Workspace::FileReference.new('user_added_project.xcodeproj', 'group')
workspace = Xcodeproj::Workspace.new(ref)
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
@integrator.send(:create_workspace) @integrator.send(:create_workspace)
saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
saved.projpaths.should == [ saved.file_references.map(&:path).should == [
'user_added_project.xcodeproj', 'user_added_project.xcodeproj',
"SampleProject/SampleProject.xcodeproj", "SampleProject/SampleProject.xcodeproj",
"Pods/Pods.xcodeproj" "Pods/Pods.xcodeproj"
...@@ -104,16 +110,17 @@ module Pod ...@@ -104,16 +110,17 @@ module Pod
end end
it "preserves the order of the projects in the workspace" do it "preserves the order of the projects in the workspace" do
projpaths = [ file_references = [
"Pods/Pods.xcodeproj", Xcodeproj::Workspace::FileReference.new('Pods/Pods.xcodeproj', 'group'),
"SampleProject/SampleProject.xcodeproj", Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group'),
] ]
workspace = Xcodeproj::Workspace.new(projpaths)
workspace = Xcodeproj::Workspace.new(file_references)
workspace_path = @integrator.send(:workspace_path) workspace_path = @integrator.send(:workspace_path)
workspace.save_as(workspace_path) workspace.save_as(workspace_path)
@integrator.send(:create_workspace) @integrator.send(:create_workspace)
saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
saved.projpaths.should == [ saved.file_references.map(&:path).should == [
"Pods/Pods.xcodeproj", "Pods/Pods.xcodeproj",
"SampleProject/SampleProject.xcodeproj", "SampleProject/SampleProject.xcodeproj",
] ]
......
...@@ -21,6 +21,16 @@ def generate_podfile(pods = ['JSONKit']) ...@@ -21,6 +21,16 @@ def generate_podfile(pods = ['JSONKit'])
end end
end end
# @return [Podfile]
#
def generate_local_podfile
podfile = Pod::Podfile.new do
platform :ios
xcodeproj SpecHelper.fixture('SampleProject/SampleProject'), 'Test' => :debug, 'App Store' => :release
pod 'Reachability', :path => SpecHelper.fixture('integration/Reachability')
end
end
#-----------------------------------------------------------------------------# #-----------------------------------------------------------------------------#
module Pod module Pod
...@@ -113,8 +123,8 @@ module Pod ...@@ -113,8 +123,8 @@ module Pod
end end
it "configures the analyzer to use update mode if appropriate" do it "configures the analyzer to use update mode if appropriate" do
@installer.update_mode = true @installer.update = true
Installer::Analyzer.any_instance.expects(:update_mode=).with(true) Installer::Analyzer.any_instance.expects(:update=).with(true)
@installer.send(:analyze) @installer.send(:analyze)
@installer.aggregate_targets.map(&:name).sort.should == ['Pods'] @installer.aggregate_targets.map(&:name).sort.should == ['Pods']
@installer.pod_targets.map(&:name).sort.should == ['Pods-JSONKit'] @installer.pod_targets.map(&:name).sort.should == ['Pods-JSONKit']
...@@ -194,6 +204,22 @@ module Pod ...@@ -194,6 +204,22 @@ module Pod
@installer.installed_specs.should == [spec] @installer.installed_specs.should == [spec]
end end
it "prints the previous version of a pod while updating the spec" do
spec = Spec.new
spec.name = 'RestKit'
spec.version = '2.0'
manifest = Lockfile.new({})
manifest.stubs(:version).with('RestKit').returns('1.0')
@installer.sandbox.stubs(:manifest).returns(manifest)
@installer.stubs(:root_specs).returns([spec])
sandbox_state = Installer::Analyzer::SpecsState.new
sandbox_state.changed << 'RestKit'
@installer.stubs(:sandbox_state).returns(sandbox_state)
@installer.expects(:install_source_of_pod).with('RestKit')
@installer.send(:install_pod_sources)
UI.output.should.include 'was 1.0'
end
#--------------------------------------# #--------------------------------------#
describe "#clean" do describe "#clean" do
...@@ -247,6 +273,15 @@ module Pod ...@@ -247,6 +273,15 @@ module Pod
@installer.pods_project.class.should == Pod::Project @installer.pods_project.class.should == Pod::Project
end end
it "preserves Pod paths specified as absolute or rooted to home" do
local_podfile = generate_local_podfile
local_installer = Installer.new(config.sandbox, local_podfile)
local_installer.send(:analyze)
local_installer.send(:prepare_pods_project)
group = local_installer.pods_project.group_for_spec('Reachability')
Pathname.new(group.path).should.be.absolute
end
it "adds the Podfile to the Pods project" do it "adds the Podfile to the Pods project" do
config.stubs(:podfile_path).returns(Pathname.new('/Podfile')) config.stubs(:podfile_path).returns(Pathname.new('/Podfile'))
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
......
require File.expand_path('../../spec_helper', __FILE__) require File.expand_path('../../spec_helper', __FILE__)
def set_up_test_repo_for_update
set_up_test_repo
upstream = SpecHelper.temporary_directory + 'upstream'
FileUtils.cp_r(test_repo_path, upstream)
Dir.chdir(test_repo_path) do
`git remote add origin #{upstream}`
`git remote -v`
`git fetch -q`
`git branch --set-upstream-to=origin/master master`
`git config branch.master.rebase true`
end
config.repos_dir = SpecHelper.tmp_repos_path
end
module Pod module Pod
describe SourcesManager do describe SourcesManager do
...@@ -87,21 +101,26 @@ module Pod ...@@ -87,21 +101,26 @@ module Pod
extend SpecHelper::TemporaryRepos extend SpecHelper::TemporaryRepos
it "update source backed by a git repository" do it "update source backed by a git repository" do
set_up_test_repo set_up_test_repo_for_update
upstream = SpecHelper.temporary_directory + 'upstream'
FileUtils.cp_r(test_repo_path, upstream)
Dir.chdir(test_repo_path) do
`git remote add origin #{upstream}`
`git remote -v`
`git fetch -q`
`git branch --set-upstream-to=origin/master master`
end
config.repos_dir = SpecHelper.tmp_repos_path
SourcesManager.update(test_repo_path.basename.to_s, true) SourcesManager.update(test_repo_path.basename.to_s, true)
UI.output.should.match /Already up-to-date/ UI.output.should.match /Already up-to-date/
end end
it "is robust against user settings for git repos" do
set_up_test_repo_for_update
SourcesManager.expects(:git!).with() { |options| options.should.match /--no-rebase/ }
SourcesManager.update(test_repo_path.basename.to_s, true)
end
it "doesn't allow merge commits" do
set_up_test_repo_for_update
SourcesManager.expects(:git!).with() { |options| options.should.match /--no-commit/ }
SourcesManager.update(test_repo_path.basename.to_s, true)
end
it 'returns whether a source has a reachable git remote' do it 'returns whether a source has a reachable git remote' do
SourcesManager.git_remote_reachable?(repo_make('a_new_repo_that_is_new')).should.be.false SourcesManager.git_remote_reachable?(repo_make('a_new_repo_that_is_new')).should.be.false
SourcesManager.git_remote_reachable?(SourcesManager.master_repo_dir).should.be.true SourcesManager.git_remote_reachable?(SourcesManager.master_repo_dir).should.be.true
......
...@@ -73,6 +73,9 @@ module Pod ...@@ -73,6 +73,9 @@ module Pod
it "handles symlinks" do it "handles symlinks" do
file = write_podspec(stub_podspec) file = write_podspec(stub_podspec)
validator = Validator.new(file) validator = Validator.new(file)
validator.quick = true
validator.stubs(:validate_homepage)
validator.stubs(:validate_screenshots)
validator.validate validator.validate
validator.validation_dir.should.be == Pathname.new("/private/tmp/CocoaPods/Lint") validator.validation_dir.should.be == Pathname.new("/private/tmp/CocoaPods/Lint")
end end
...@@ -81,9 +84,101 @@ module Pod ...@@ -81,9 +84,101 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
describe "Extensive analysis" do describe "Extensive analysis" do
describe "Homepage validation" do
require 'webmock'
before do
@sut = Validator.new(podspec_path)
@sut.stubs(:install_pod)
@sut.stubs(:build_pod)
@sut.stubs(:check_file_patterns)
@sut.stubs(:tear_down_validation_environment)
end
it "checks if the homepage is valid" do
WebMock::API.stub_request(:head, /not-found/).to_return(:status => 404)
WebMock::API.stub_request(:get, /not-found/).to_return(:status => 404)
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/not-found/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /The URL (.*) is not reachable/
end
it "indicates if it was not able to validate the homepage" do
WebMock::API.stub_request(:head, 'banana-corp.local').to_raise(SocketError)
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /There was a problem validating the URL/
end
it "does not fail if the homepage redirects" do
WebMock::API.stub_request(:head, /redirect/).to_return(
:status => 301, :headers => { 'Location' => 'http://banana-corp.local/found/' } )
WebMock::API.stub_request(:head, /found/).to_return( :status => 200 )
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/redirect/')
@sut.validate
@sut.results.length.should.equal 0
end
it "does not fail if the homepage does not support HEAD" do
WebMock::API.stub_request(:head, /page/).to_return( :status => 405 )
WebMock::API.stub_request(:get, /page/).to_return( :status => 200 )
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/page/')
@sut.validate
@sut.results.length.should.equal 0
end
it "does not fail if the homepage errors on HEAD" do
WebMock::API.stub_request(:head, /page/).to_return( :status => 500 )
WebMock::API.stub_request(:get, /page/).to_return( :status => 200 )
Specification.any_instance.stubs(:homepage).returns('http://banana-corp.local/page/')
@sut.validate
@sut.results.length.should.equal 0
end
it "does not follow redirects infinitely" do
WebMock::API.stub_request(:head, /redirect/).to_return(
:status => 301,
:headers => { 'Location' => 'http://banana-corp.local/redirect/' } )
Specification.any_instance.stubs(:homepage).returns(
'http://banana-corp.local/redirect/')
@sut.validate
@sut.results.map(&:to_s).first.should.match /The URL \(.*\) is not reachable/
end
end
describe "Screenshot validation" do
require 'webmock'
before do
@sut = Validator.new(podspec_path)
@sut.stubs(:install_pod)
@sut.stubs(:build_pod)
@sut.stubs(:check_file_patterns)
@sut.stubs(:tear_down_validation_environment)
@sut.stubs(:validate_homepage)
WebMock::API.stub_request(:head, 'banana-corp.local/valid-image.png').to_return(:status => 200, :headers => { 'Content-Type' => 'image/png' })
end
it "checks if the screenshots are valid" do
Specification.any_instance.stubs(:screenshots).returns(['http://banana-corp.local/valid-image.png'])
@sut.validate
@sut.results.should.be.empty?
end
it "should fail if any of the screenshots URLS do not return an image" do
WebMock::API.stub_request(:head, 'banana-corp.local/').to_return(:status => 200)
Specification.any_instance.stubs(:screenshots).returns(['http://banana-corp.local/valid-image.png', 'http://banana-corp.local/'])
@sut.validate
@sut.results.map(&:to_s).first.should.match /The screenshot .* is not a valid image/
end
end
it "respects the no clean option" do it "respects the no clean option" do
file = write_podspec(stub_podspec) file = write_podspec(stub_podspec)
sut = Validator.new(file) sut = Validator.new(file)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.no_clean = true sut.no_clean = true
sut.validate sut.validate
sut.validation_dir.should.exist sut.validation_dir.should.exist
...@@ -92,6 +187,8 @@ module Pod ...@@ -92,6 +187,8 @@ module Pod
it "builds the pod per platform" do it "builds the pod per platform" do
file = write_podspec(stub_podspec) file = write_podspec(stub_podspec)
sut = Validator.new(file) sut = Validator.new(file)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.expects(:install_pod).twice sut.expects(:install_pod).twice
sut.expects(:build_pod).twice sut.expects(:build_pod).twice
sut.expects(:check_file_patterns).twice sut.expects(:check_file_patterns).twice
...@@ -100,6 +197,8 @@ module Pod ...@@ -100,6 +197,8 @@ module Pod
it "uses the deployment target of the specification" do it "uses the deployment target of the specification" do
sut = Validator.new(podspec_path) sut = Validator.new(podspec_path)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
podfile = sut.send(:podfile_from_spec, :ios, '5.0') podfile = sut.send(:podfile_from_spec, :ios, '5.0')
dependency = podfile.target_definitions['Pods'].dependencies.first dependency = podfile.target_definitions['Pods'].dependencies.first
dependency.external_source.has_key?(:podspec).should.be.true dependency.external_source.has_key?(:podspec).should.be.true
...@@ -107,6 +206,8 @@ module Pod ...@@ -107,6 +206,8 @@ module Pod
it "respects the local option" do it "respects the local option" do
sut = Validator.new(podspec_path) sut = Validator.new(podspec_path)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
podfile = sut.send(:podfile_from_spec, :ios, '5.0') podfile = sut.send(:podfile_from_spec, :ios, '5.0')
deployment_target = podfile.target_definitions['Pods'].platform.deployment_target deployment_target = podfile.target_definitions['Pods'].platform.deployment_target
deployment_target.to_s.should == "5.0" deployment_target.to_s.should == "5.0"
...@@ -116,6 +217,8 @@ module Pod ...@@ -116,6 +217,8 @@ module Pod
sut = Validator.new(podspec_path) sut = Validator.new(podspec_path)
sut.stubs(:check_file_patterns) sut.stubs(:check_file_patterns)
sut.stubs(:xcodebuild).returns("file.m:1:1: warning: direct access to objective-c's isa is deprecated") sut.stubs(:xcodebuild).returns("file.m:1:1: warning: direct access to objective-c's isa is deprecated")
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.validate sut.validate
first = sut.results.map(&:to_s).first first = sut.results.map(&:to_s).first
first.should.include "[xcodebuild]" first.should.include "[xcodebuild]"
...@@ -126,6 +229,8 @@ module Pod ...@@ -126,6 +229,8 @@ module Pod
file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'wrong_paht.*'")) file = write_podspec(stub_podspec(/s\.source_files = 'JSONKit\.\*'/, "s.source_files = 'wrong_paht.*'"))
sut = Validator.new(file) sut = Validator.new(file)
sut.stubs(:build_pod) sut.stubs(:build_pod)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.validate sut.validate
sut.results.map(&:to_s).first.should.match /source_files.*did not match/ sut.results.map(&:to_s).first.should.match /source_files.*did not match/
sut.result_type.should == :error sut.result_type.should == :error
...@@ -139,6 +244,9 @@ module Pod ...@@ -139,6 +244,9 @@ module Pod
spec = Specification.from_file(file) spec = Specification.from_file(file)
sut = Validator.new(spec) sut = Validator.new(spec)
sut.stubs(:validate_homepage)
sut.stubs(:validate_screenshots)
sut.stubs(:build_pod)
sut.validate sut.validate
sut.validated?.should.be.true sut.validated?.should.be.true
end end
......
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