Commit f8dfe1a8 authored by Fabio Pelosin's avatar Fabio Pelosin

Extracted downloader.

parent 504bfd33
......@@ -8,12 +8,12 @@ gemspec
group :development do
gem "cocoapods-core", :git => "git://github.com/CocoaPods/Core.git"
gem "xcodeproj", :git => "git://github.com/CocoaPods/Xcodeproj.git"
gem "cocoapods-downloader", :path => '../cocoapods-downloader'
gem "mocha", "~> 0.11.4"
gem "bacon"
gem "mocha-on-bacon"
gem "rake"
gem "vcr"
gem "webmock", '>= 1.8.0', '< 1.9'
end
group :debugging do
......
......@@ -40,6 +40,11 @@ PATH
rake (~> 0.9.4)
xcodeproj (~> 0.4.0)
PATH
remote: ../cocoapods-downloader
specs:
cocoapods-downloader (0.1.0)
GEM
remote: http://rubygems.org/
specs:
......@@ -52,7 +57,6 @@ GEM
claide (0.2.0)
coderay (1.0.8)
colored (1.2)
crack (0.3.1)
escape (0.0.4)
faraday (0.8.4)
multipart-post (~> 1.1)
......@@ -91,10 +95,6 @@ GEM
redcarpet (2.2.2)
slop (3.3.3)
terminal-notifier (1.4.2)
vcr (2.3.0)
webmock (1.8.11)
addressable (>= 2.2.7)
crack (>= 0.1.7)
yajl-ruby (1.1.0)
yard (0.8.3)
......@@ -106,6 +106,7 @@ DEPENDENCIES
bacon
cocoapods!
cocoapods-core!
cocoapods-downloader!
github-markup
kicker!
mocha (~> 0.11.4)
......@@ -115,7 +116,5 @@ DEPENDENCIES
rake
rb-fsevent
redcarpet
vcr
webmock (>= 1.8.0, < 1.9)
xcodeproj!
yard
......@@ -23,7 +23,6 @@ module Pod
end
autoload :Command, 'cocoapods/command'
autoload :Downloader, 'cocoapods/downloader'
autoload :Executable, 'cocoapods/executable'
autoload :ExternalSources, 'cocoapods/external_sources'
autoload :Installer, 'cocoapods/installer'
......@@ -49,8 +48,10 @@ module Pod
autoload :XCConfig, 'cocoapods/generator/xcconfig'
end
require 'cocoapods/file_list'
require 'cocoapods-core'
require 'cocoapods/downloader'
require 'cocoapods/file_list'
require 'cocoapods/config'
require 'cocoapods/source'
end
......
......@@ -87,7 +87,11 @@ module Pod
UI.puts "\nValidating #{'spec'.pluralize(count)}".yellow
podspec_files.each do |podspec|
validator = Validator.new(podspec)
begin
validator.validate
rescue Exception => e
raise Informative, "The `#{podspec}` specification does not validate."
end
raise Informative, "The `#{podspec}` specification does not validate." unless validator.validated?
end
end
......
require 'uri'
require 'cocoapods-downloader'
module Pod
class Downloader
autoload :Git, 'cocoapods/downloader/git'
autoload :GitHub, 'cocoapods/downloader/git'
autoload :Mercurial, 'cocoapods/downloader/mercurial'
autoload :Subversion, 'cocoapods/downloader/subversion'
autoload :Http, 'cocoapods/downloader/http'
module Downloader
class Base
extend Executable
def self.for_pod(pod)
spec = pod.top_specification
for_target(pod.root, spec.source.dup)
override_api do
def execute_command(executable, command, raise_on_failure = false)
Executable.execute_command(executable, command, raise_on_failure = false)
end
attr_reader :target_path, :url, :options
def initialize(target_path, url, options)
@target_path, @url, @options = target_path, url, options
@target_path.mkpath
def download_action(ui_message)
UI.section(" > #{ui_message}", '', 1) do
yield
end
private
def self.for_target(target_path, options)
options = options.dup
if url = options.delete(:git)
if url.to_s =~ /github.com/
GitHub.new(target_path, url, options)
else
Git.new(target_path, url, options)
end
elsif url = options.delete(:hg)
Mercurial.new(target_path, url, options)
elsif url = options.delete(:svn)
Subversion.new(target_path, url, options)
elsif url = options.delete(:http)
Http.new(target_path, url, options)
else
raise "Unsupported download strategy `#{options.inspect}`."
end
end
end
end
require 'open-uri'
# require 'tempfile'
require 'zlib'
require 'digest/sha1'
module Pod
class Downloader
# Concreted Downloader class that provides support for specifications with
# git sources.
#
class Git < Downloader
include Config::Mixin
executable :git
def download
create_cache unless cache_exist?
UI.section(' > Cloning git repo', '', 1) do
if options[:tag]
download_tag
elsif options[:branch]
download_branch
elsif options[:commit]
download_commit
else
download_head
end
Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules]
end
prune_cache
end
# @!group Download implementations
# @return [Pathname] The clone URL, which resolves to the cache path.
#
def clone_url
cache_path
end
# @return [void] Convenience method to perform clones operations.
#
def clone(from, to)
UI.section(" > Cloning to Pods folder",'',1) do
git! %Q|clone "#{from}" "#{to}"|
end
end
# @return [void] Checkouts the HEAD of the git source in the destination
# path.
#
def download_head
if cache_exist?
update_cache
else
create_cache
end
clone(clone_url, target_path)
Dir.chdir(target_path) { git! "submodule update --init" } if options[:submodules]
end
# @return [void] Checkouts a specific tag of the git source in the
# destination path.
#
def download_tag
ensure_ref_exists(options[:tag])
Dir.chdir(target_path) do
git! "init"
git! "remote add origin '#{clone_url}'"
git! "fetch origin tags/#{options[:tag]}"
git! "reset --hard FETCH_HEAD"
git! "checkout -b activated-pod-commit"
end
end
# @return [void] Checkouts a specific commit of the git source in the
# destination path.
#
def download_commit
ensure_ref_exists(options[:commit])
clone(clone_url, target_path)
Dir.chdir(target_path) do
git! "checkout -b activated-pod-commit #{options[:commit]}"
end
end
# @return [void] Checkouts the HEAD of a specific branch of the git
# source in the destination path.
#
def download_branch
ensure_remote_branch_exists(options[:branch])
clone(clone_url, target_path)
Dir.chdir(target_path) do
git! "remote add upstream '#{@url}'" # we need to add the original url, not the cache url
git! "fetch -q upstream" # refresh the branches
git! "checkout --track -b activated-pod-commit upstream/#{options[:branch]}" # create a new tracking branch
UI.message("Just downloaded and checked out branch: #{options[:branch]} from upstream #{clone_url}")
end
end
# @!group Checking references
# @return [Bool] Wether a reference (commit SHA or tag)
#
def ref_exists?(ref)
Dir.chdir(cache_path) { git "rev-list --max-count=1 #{ref}" }
$? == 0
end
# @return [void] Checks if a reference exists in the cache and updates
# only if necessary.
#
# @raise If after the update the reference can't be found.
#
def ensure_ref_exists(ref)
return if ref_exists?(ref)
update_cache
raise Informative, "[!] Cache unable to find git reference `#{ref}' for `#{url}'.".red unless ref_exists?(ref)
end
# @return [Bool] Wether a branch exists in the cache.
#
def branch_exists?(branch)
Dir.chdir(cache_path) { git "branch --all | grep #{branch}$" } # check for remote branch and do suffix matching ($ anchor)
$? == 0
end
# @return [void] Checks if a branch exists in the cache and updates
# only if necessary.
#
# @raise If after the update the branch can't be found.
#
def ensure_remote_branch_exists(branch)
return if branch_exists?(branch)
update_cache
raise Informative, "[!] Cache unable to find git reference `#{branch}' for `#{url}' (#{$?}).".red unless branch_exists?(branch)
end
# @!group Cache
# The maximum allowed size for the cache expressed in Mb.
#
MAX_CACHE_SIZE = 500
# @return [Pathname] The directory where the cache for the current git
# repo is stored.
#
# @note The name of the directory is the SHA1 hash value of the URL of
# the git repo.
#
def cache_path
@cache_path ||= caches_root + "#{Digest::SHA1.hexdigest(url.to_s)}"
end
# @return [Pathname] The directory where the git caches are stored.
#
def caches_root
Pathname.new(File.expand_path("~/Library/Caches/CocoaPods/Git"))
end
# @return [Integer] The global size of the git cache expressed in Mb.
#
def caches_size
`du -cm`.split("\n").last.to_i
end
# @return [Bool] Wether the cache exits.
#
# @note The previous implementation of the cache didn't use a barebone
# git repo. This method takes into account this fact and checks
# that the cache is actually a barebone repo. If the cache was not
# barebone it will be deleted and recreated.
#
def cache_exist?
cache_path.exist? &&
cache_origin_url(cache_path).to_s == url.to_s &&
Dir.chdir(cache_path) { git("config core.bare").chomp == "true" }
end
# @return [String] The origin URL of the cache with the given directory.
#
# @param [String] dir The directory of the cache.
#
def cache_origin_url(dir)
Dir.chdir(dir) { `git config remote.origin.url`.chomp }
end
# @return [void] Creates the barebone repo that will serve as the cache
# for the current repo.
#
def create_cache
UI.section(" > Creating cache git repo (#{cache_path})",'',1) do
cache_path.rmtree if cache_path.exist?
cache_path.mkpath
git! %Q|clone --mirror "#{url}" "#{cache_path}"|
end
end
# @return [void] Updates the barebone repo used as a cache against its
# remote.
#
def update_cache
UI.section(" > Updating cache git repo (#{cache_path})",'',1) do
Dir.chdir(cache_path) { git! "remote update" }
end
end
# @return [void] Deletes the oldest caches until they the global size is
# below the maximum allowed.
#
def prune_cache
return unless caches_root.exist?
Dir.chdir(caches_root) do
repos = Pathname.new(caches_root).children.select { |c| c.directory? }.sort_by(&:ctime)
while caches_size >= MAX_CACHE_SIZE && !repos.empty?
dir = repos.shift
UI.message "#{'->'.yellow} Removing git cache for `#{cache_origin_url(dir)}'"
dir.rmtree
end
end
end
end
# This class allows to download tarballs from GitHub and is not currently
# being used by CocoaPods as the git cache is preferable.
#
class GitHub < Git
def download_head
download_only? ? download_and_extract_tarball('master') : super
end
def download_tag
download_only? ? download_and_extract_tarball(options[:tag]) : super
end
def download_commit
download_only? ? download_and_extract_tarball(options[:commit]) : super
end
def download_branch
download_only? ? download_and_extract_tarball(options[:branch]) : super
end
def tarball_url_for(id)
original_url, username, reponame = *(url.match(/[:\/]([\w\-]+)\/([\w\-]+)\.git/))
"https://github.com/#{username}/#{reponame}/tarball/#{id}"
end
def tmp_path
target_path + "tarball.tar.gz"
end
private
def download_only?
@options[:download_only]
end
def download_and_extract_tarball(id)
File.open(tmp_path, "w+") do |tmpfile|
open tarball_url_for(id) do |archive|
tmpfile.write Zlib::GzipReader.new(archive).read
end
system "tar xf #{tmpfile.path} -C #{target_path} --strip-components 1"
end
end
end
end
end
require 'open-uri'
require 'tempfile'
require 'zlib'
require 'yaml'
module Pod
class Downloader
class Http < Downloader
class UnsupportedFileTypeError < StandardError; end
executable :curl
executable :unzip
executable :tar
attr_accessor :filename, :download_path
def download
@filename = filename_with_type type
@download_path = target_path + @filename
UI.section(' > Downloading from HTTP', '', 3) do
download_file @download_path
extract_with_type @download_path, type
end
end
def type
options[:type] || type_with_url(url)
end
private
def type_with_url(url)
if url =~ /.zip$/
:zip
elsif url =~ /.(tgz|tar\.gz)$/
:tgz
elsif url =~ /.tar$/
:tar
elsif url =~ /.(tbz|tar\.bz2)$/
:tbz
else
nil
end
end
def filename_with_type(type=:zip)
case type
when :zip
"file.zip"
when :tgz
"file.tgz"
when :tar
"file.tar"
when :tbz
"file.tbz"
else
raise UnsupportedFileTypeError.new "Unsupported file type: #{type}"
end
end
def download_file(full_filename)
curl! "-L -o '#{full_filename}' '#{url}'"
end
def extract_with_type(full_filename, type=:zip)
case type
when :zip
unzip! "'#{full_filename}' -d '#{target_path}'"
when :tgz
tar! "xfz '#{full_filename}' -C '#{target_path}'"
when :tar
tar! "xf '#{full_filename}' -C '#{target_path}'"
when :tbz
tar! "xfj '#{full_filename}' -C '#{target_path}'"
else
raise UnsupportedFileTypeError.new "Unsupported file type: #{type}"
end
end
end
end
end
module Pod
class Downloader
class Mercurial < Downloader
executable :hg
def download
UI.section(' > Cloning mercurial repo', '', 3) do
if options[:revision]
download_revision
else
download_head
end
end
end
def download_head
hg! "clone \"#{url}\" \"#{target_path}\""
end
def download_revision
hg! "clone \"#{url}\" --rev '#{options[:revision]}' \"#{target_path}\""
end
end
end
end
module Pod
class Downloader
class Subversion < Downloader
executable :svn
def initialize(target_path, url, options)
@target_path, @url, @options = target_path, url, options
end
def download
UI.section(' > Exporting subversion repo', '', 3) do
svn! %|#{export_subcommand} "#{reference_url}" "#{target_path}"|
end
end
def download_head
UI.section(' > Exporting subversion repo', '', 3) do
svn! %|#{export_subcommand} "#{trunk_url}" "#{target_path}"|
end
end
def export_subcommand
result = 'export --non-interactive --trust-server-cert'
end
def reference_url
result = url.dup
result << '/' << options[:folder] if options[:folder]
result << '/tags/' << options[:tag] if options[:tag]
result << '" -r "' << options[:revision] if options[:revision]
result
end
def trunk_url
result = url.dup
result << '/' << options[:folder] if options[:folder]
result << '/trunk'
result
end
end
end
end
......@@ -20,6 +20,35 @@ module Pod
end
end
# TODO
#
def self.execute_command(bin, command, raise_on_failure = false)
bin = `which #{bin}`.strip
if bin.empty?
raise Informative, "Unable to locate the executable `#{name}'"
end
full_command = "#{bin} #{command}"
if Config.instance.verbose?
UI.message("$ #{full_command}")
stdout, stderr = Indenter.new(STDOUT), Indenter.new(STDERR)
else
stdout, stderr = Indenter.new, Indenter.new
end
status = Open4.spawn(full_command, :stdout => stdout, :stderr => stderr, :status => true)
output = stdout.join("\n") + stderr.join("\n") # TODO will this suffice?
unless status.success?
if raise_on_failure
raise Informative, "#{name} #{command}\n\n#{output}"
else
UI.message("[!] Failed: #{full_command}".red)
end
end
output
end
def executable(name)
bin = `which #{name}`.strip
base_method = "base_" << name.to_s
......
......@@ -613,15 +613,11 @@ module Pod
# @return [void]
#
def download_pod(pod)
downloader = Downloader.for_pod(pod)
downloader = Downloader.for_target(pod.root, pod.top_specification.source.dup)
downloader.cache_root = "~/Library/Caches/CocoaPods"
downloader.max_cache_size = 500
if pod.top_specification.version.head?
if downloader.respond_to?(:download_head)
downloader.download_head
else
raise Informative,
"The downloader of class `#{downloader.class.name}' does not" \
"support the `:head' option."
end
else
downloader.download
end
......
[ui]
username = Eloy Duran <eloy.de.enige@gmail.com>
Second commit
\ No newline at end of file
......@@ -109,7 +109,8 @@ module Pod
end
end
it "lints a remote podspec" do
#TODO
xit "lints a remote podspec" do
Dir.chdir(fixture('spec-repos') + 'master/JSONKit/1.4/') do
cmd = command('spec', 'lint', '--quick', '--only-errors', '--silent', 'https://github.com/CocoaPods/Specs/raw/master/A2DynamicDelegate/2.0.1/A2DynamicDelegate.podspec')
VCR.use_cassette('linter', :record => :new_episodes) { lambda { cmd.run }.should.not.raise }
......
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe Downloader::Git do
extend SpecHelper::TemporaryDirectory
before do
@pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
end
it "check's out a specific commit" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'first commit'
end
it "check's out a specific branch" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :branch => 'topicbranch'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'topicbranch'
end
it "check's out a specific tag" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :tag => 'v1.0'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'v1.0'
end
it "doesn't updates submodules by default" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => '6cc9afc'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'post v1.0'
(@pod.root + 'libPusher/README.md').should.not.exist?
end
it "initializes submodules when checking out a specific commit" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => '6cc9afc', :submodules => true
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'post v1.0'
(@pod.root + 'libPusher/README.md').read.strip.should.match /^libPusher/
end
it "initializes submodules when checking out a specific tag" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :tag => 'v1.1', :submodules => true
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'post v1.0'
(@pod.root + 'libPusher/README.md').read.strip.should.match /^libPusher/
end
it "prepares the cache if it does not exist" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
downloader.cache_path.rmtree if downloader.cache_path.exist?
downloader.expects(:create_cache).once
downloader.stubs(:download_commit)
downloader.download
end
it "prepares the cache if it does not exist when the HEAD is requested explicitly" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib')
)
downloader = Downloader.for_pod(@pod)
downloader.cache_path.rmtree if downloader.cache_path.exist?
downloader.expects(:create_cache).once
downloader.stubs(:clone)
downloader.download_head
end
it "removes the oldest repo if the caches is too big" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
original_chace_size = Downloader::Git::MAX_CACHE_SIZE
Downloader::Git.__send__(:remove_const,'MAX_CACHE_SIZE')
Downloader::Git::MAX_CACHE_SIZE = 0
downloader = Downloader.for_pod(@pod)
downloader.stubs(:cache_dir).returns(temporary_directory)
downloader.download
downloader.cache_path.should.not.exist?
Downloader::Git.__send__(:remove_const,'MAX_CACHE_SIZE')
Downloader::Git::MAX_CACHE_SIZE = original_chace_size
end
it "raises if it can't find the url" do
@pod.top_specification.stubs(:source).returns(
:git => 'find_me_if_you_can'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
it "raises if it can't find a commit" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'aaaaaa'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
it "raises if it can't find a tag" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :tag => 'aaaaaa'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
it "does not raise if it can find the reference" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.not.raise
end
it "returns the cache directory as the clone url" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
downloader.clone_url.to_s.should.match /Library\/Caches\/CocoaPods\/Git/
end
it "updates the cache if the HEAD is requested" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib')
)
downloader = Downloader.for_pod(@pod)
downloader.expects(:update_cache).once
downloader.download
end
it "updates the cache if the ref is not available" do
# create the origin repo and the cache
tmp_repo_path = temporary_directory + 'banana-lib-source'
`git clone #{fixture('banana-lib')} #{tmp_repo_path}`
@pod.top_specification.stubs(:source).returns(
:git => tmp_repo_path, :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
downloader.download
# make a new commit in the origin
commit = ''
Dir.chdir(tmp_repo_path) do
`touch test.txt`
`git add test.txt`
`git commit -m 'test'`
commit = `git rev-parse HEAD`.chomp
end
# require the new commit
pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
pod.top_specification.stubs(:source).returns(
:git => tmp_repo_path, :commit => commit
)
downloader = Downloader.for_pod(pod)
downloader.download
(pod.root + 'test.txt').should.exist?
end
it "doesn't update the cache if the ref is available" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :commit => 'fd56054'
)
downloader = Downloader.for_pod(@pod)
downloader.download
@pod.root.rmtree
downloader.expects(:update_cache).never
downloader.download
end
it "updates the cache if the branch is not available" do
# create the origin repo and the cache
tmp_repo_path = temporary_directory + 'banana-lib-source'
`git clone #{fixture('banana-lib')} #{tmp_repo_path}`
@pod.top_specification.stubs(:source).returns(
:git => tmp_repo_path, :branch => 'master'
)
downloader = Downloader.for_pod(@pod)
downloader.download
# make a new branch in the origin
branch = 'test'
Dir.chdir(tmp_repo_path) do
`touch test.txt`
`git checkout -b #{branch} >/dev/null 2>&1`
`git add test.txt`
`git commit -m 'test'`
end
# require the new branch
pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
pod.top_specification.stubs(:source).returns(
:git => tmp_repo_path, :branch => branch
)
downloader = Downloader.for_pod(pod)
downloader.download
(pod.root + 'test.txt').should.exist?
end
it "doesn't update the cache if the branch is available" do
@pod.top_specification.stubs(:source).returns(
:git => fixture('banana-lib'), :branch => 'master'
)
downloader = Downloader.for_pod(@pod)
downloader.download
@pod.root.rmtree
downloader.expects(:update_cache).never
downloader.download
end
end
describe "for GitHub repositories, with :download_only set to true" do
extend SpecHelper::TemporaryDirectory
before do
@pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
end
it "downloads HEAD with no other options specified" do
@pod.top_specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :download_only => true
)
downloader = Downloader.for_pod(@pod)
VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download }
# deliberately keep this assertion as loose as possible for now
(@pod.root + 'README.md').readlines[0].should =~ /libPusher/
end
it "downloads a specific tag when specified" do
@pod.top_specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :tag => 'v1.1', :download_only => true
)
downloader = Downloader.for_pod(@pod)
VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download }
# deliberately keep this assertion as loose as possible for now
(@pod.root + 'libPusher.podspec').readlines.grep(/1.1/).should.not.be.empty
end
it "downloads a specific branch when specified" do
@pod.top_specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :branch => 'gh-pages', :download_only => true
)
downloader = Downloader.for_pod(@pod)
VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download }
# deliberately keep this assertion as loose as possible for now
(@pod.root + 'index.html').readlines.grep(/libPusher Documentation/).should.not.be.empty
end
it "downloads a specific commit when specified" do
@pod.top_specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :commit => 'eca89998d5', :download_only => true
)
downloader = Downloader.for_pod(@pod)
VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download }
# deliberately keep this assertion as loose as possible for now
(@pod.root + 'README.md').readlines[0].should =~ /PusherTouch/
end
end
end
require File.expand_path('../../spec_helper', __FILE__)
module Pod
describe "Downloader" do
before do
@pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
end
describe "for Mercurial" do
it "check's out a specific revision" do
@pod.top_specification.stubs(:source).returns(
:hg => fixture('mercurial-repo'), :revision => '46198bb3af96'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'first commit'
end
it "raises if it fails to download" do
@pod.top_specification.stubs(:source).returns(
:hg => "find me if you can", :revision => '46198bb3af96'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
end
describe "for Subversion" do
it "check's out a specific revision" do
@pod.top_specification.stubs(:source).returns(
:svn => "file://#{fixture('subversion-repo')}", :revision => '1'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'first commit'
end
it "check's out a specific tag" do
@pod.top_specification.stubs(:source).returns(
:svn => "file://#{fixture('subversion-repo')}", :tag => 'tag-1'
)
downloader = Downloader.for_pod(@pod)
downloader.download
(@pod.root + 'README').read.strip.should == 'tag 1'
end
it "check's out the head version" do
@pod.top_specification.stubs(:source).returns(
:svn => "file://#{fixture('subversion-repo')}", :revision => '1'
)
downloader = Downloader.for_pod(@pod)
downloader.download_head
(@pod.root + 'README').read.strip.should == 'unintersting'
end
it "raises if it fails to download" do
@pod.top_specification.stubs(:source).returns(
:svn => "find me if you can", :revision => '1'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
end
describe "for HTTP" do
extend SpecHelper::TemporaryDirectory
it "download file and unzip it" do
@pod.top_specification.stubs(:source).returns(
:http => 'http://dl.google.com/googleadmobadssdk/googleadmobsearchadssdkios.zip'
)
downloader = Downloader.for_pod(@pod)
VCR.use_cassette('tarballs', :record => :new_episodes) { downloader.download }
(@pod.root + 'GoogleAdMobSearchAdsSDK/GADSearchRequest.h').should.exist
(@pod.root + 'GoogleAdMobSearchAdsSDK/GADSearchRequest.h').read.strip.should =~ /Google Search Ads iOS SDK/
end
it "raises if it fails to download" do
@pod.top_specification.stubs(:source).returns(
:http => 'find me if you can.zip'
)
downloader = Downloader.for_pod(@pod)
lambda { downloader.download }.should.raise Informative
end
end
end
end
......@@ -66,15 +66,4 @@ end
SpecHelper::Fixture.fixture('banana-lib') # ensure it exists
require 'vcr'
require 'webmock'
VCR.configure do |c|
# Namespace the fixture by the Ruby version, because different Ruby versions
# can lead to different ways the data is interpreted.
c.cassette_library_dir = (ROOT + "spec/fixtures/vcr/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}").to_s
c.hook_into :webmock # or :fakeweb
c.allow_http_connections_when_no_cassette = true
end
require "active_support/core_ext/string/strip"
require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(:source => source_options)
stub('pod') do
stubs(:root).returns(temporary_sandbox.root)
stubs(:top_specification).returns(specification)
end
end
module Pod
describe Downloader do
it "returns a git downloader with parsed options" do
pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
downloader = Downloader.for_pod(pod)
downloader.should.be.instance_of Downloader::Git
downloader.url.should == 'http://banana-corp.local/banana-lib.git'
downloader.options.should == { :tag => 'v1.0' }
end
it 'returns a github downloader when the :git URL is on github' do
pod = LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox, Platform.ios)
pod.top_specification.stubs(:source).returns(:git => "git://github.com/CocoaPods/CocoaPods")
downloader = Downloader.for_pod(pod)
downloader.should.be.instance_of Downloader::GitHub
end
end
describe Downloader::GitHub do
it 'can convert public HTTP repository URLs to the tarball URL' do
downloader = Downloader.for_pod(stub_pod_with_source(
:git => "https://github.com/CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert private HTTP repository URLs to the tarball URL' do
downloader = Downloader.for_pod(stub_pod_with_source(
:git => "https://lukeredpath@github.com/CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert private SSH repository URLs to the tarball URL' do
downloader = Downloader.for_pod(stub_pod_with_source(
:git => "git@github.com:CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
it 'can convert public git protocol repository URLs to the tarball URL' do
downloader = Downloader.for_pod(stub_pod_with_source(
:git => "git://github.com/CocoaPods/CocoaPods.git"
))
downloader.tarball_url_for('master').should == "https://github.com/CocoaPods/CocoaPods/tarball/master"
end
end
end
require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(
:source => source_options
)
stub('pod') do
stubs(:root).returns(temporary_sandbox.root)
stubs(:top_specification).returns(specification)
end
end
describe Pod::Downloader::Http do
it 'should find download file type' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.zip'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :zip
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tar'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :tar
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tgz'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :tgz
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'http://www.kernel.org/pub/linux/kernel/v1.0/linux-1.0.tar.bz2'
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :tbz
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0',
:type => :zip
))
downloader.should.be.instance_of Pod::Downloader::Http
downloader.type.should == :zip
end
it 'should download file and extract it with proper type' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.zip'
))
downloader.expects(:download_file).with(anything())
downloader.expects(:extract_with_type).with(anything(), :zip).at_least_once
downloader.download
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.tgz'
))
downloader.expects(:download_file).with(anything())
downloader.expects(:extract_with_type).with(anything(), :tgz).at_least_once
downloader.download
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'http://www.kernel.org/pub/linux/kernel/v1.0/linux-1.0.tar.bz2'
))
downloader.expects(:download_file).with(anything())
downloader.expects(:extract_with_type).with(anything(), :tbz).at_least_once
downloader.download
end
it 'should raise error when unsupported filetype is pass' do
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0.rar'
))
downloader.expects(:download).raises(Pod::Downloader::Http::UnsupportedFileTypeError)
downloader.download rescue nil
downloader = Pod::Downloader.for_pod(stub_pod_with_source(
:http => 'https://testflightapp.com/media/sdk-downloads/TestFlightSDK1.0',
:type => :rar
))
downloader.expects(:download).raises(Pod::Downloader::Http::UnsupportedFileTypeError)
downloader.download rescue nil
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