Commit 83da2fba authored by Luke Redpath's avatar Luke Redpath

Added a new Github-specific downloader that can download repositories as a gzipped tarball.

Generally speaking, this should be much faster than cloning a repository (even a shallow one)
and we can take take advantage of Github's tarball support. I've made this opt-in (using the
:download_only option) in case this breaks any existing functionality people expect (e.g. 
using submodules).
parent 550ab66d
require 'uri'
module Pod
class Downloader
autoload :Git, 'cocoapods/downloader/git'
......@@ -28,7 +30,11 @@ module Pod
def self.for_target(target_path, options)
options = options.dup
if url = options.delete(:git)
Git.new(target_path, url, options)
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)
......
require 'open-uri'
require 'tempfile'
require 'zlib'
module Pod
class Downloader
class Git < Downloader
......@@ -39,5 +43,46 @@ module Pod
(target_path + '.git').rmtree
end
end
class GitHub < Git
def download_head
download_only? ? download_and_extract_tarball('master') : super
end
def download_tag
super unless download_only?
download_only? ? download_and_extract_tarball(options[:tag]) : super
end
def download_commit
super unless download_only?
download_only? ? download_and_extract_tarball(options[:commit]) : super
end
def clean
# no-op
end
def tarball_url_for(id)
original_url, username, reponame = *(url.match(/[:\/](\w+)\/(\w+).git/).to_a)
"https://github.com/#{username}/#{reponame}/tarball/#{id}"
end
private
def download_only?
@options[:download_only]
end
def download_and_extract_tarball(id)
Tempfile.open('tarball') do |tmpfile|
open tarball_url_for(id) do |archive|
tmpfile.write Zlib::GzipReader.new(archive).read
end
system "tar zxf #{tmpfile.path} -C #{target_path} --strip-components 1"
end
end
end
end
end
......@@ -38,6 +38,44 @@ describe "Pod::Downloader" do
end
end
describe "for Github repositories, with :download_only set to true" do
extend SpecHelper::TemporaryDirectory
it "downloads HEAD with no other options specified" do
@pod.specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :download_only => true
)
downloader = Pod::Downloader.for_pod(@pod)
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.specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :tag => 'v1.1', :download_only => true
)
downloader = Pod::Downloader.for_pod(@pod)
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 commit when specified" do
@pod.specification.stubs(:source).returns(
:git => "git://github.com/lukeredpath/libPusher.git", :commit => 'eca89998d5', :download_only => true
)
downloader = Pod::Downloader.for_pod(@pod)
downloader.download
# deliberately keep this assertion as loose as possible for now
(@pod.root + 'README.md').readlines[0].should =~ /PusherTouch/
end
end
describe "for Mercurial" do
it "check's out a specific revision" do
@pod.specification.stubs(:source).returns(
......
require File.expand_path('../../spec_helper', __FILE__)
def stub_pod_with_source(source_options)
specification = stub(
:part_of_other_pod? => false,
:source => source_options
)
stub('pod') do
stubs(:root).returns(temporary_sandbox.root)
stubs(:specification).returns(specification)
end
end
describe "Pod::Downloader" do
it "returns a git downloader with parsed options" do
pod = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox)
......@@ -8,4 +19,43 @@ describe "Pod::Downloader" do
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 = Pod::LocalPod.new(fixture_spec('banana-lib/BananaLib.podspec'), temporary_sandbox)
pod.specification.stubs(:source).returns(:git => "git://github.com/CocoaPods/CocoaPods")
downloader = Pod::Downloader.for_pod(pod)
downloader.should.be.instance_of Pod::Downloader::GitHub
end
end
describe Pod::Downloader::GitHub do
it 'can convert public HTTP repository URLs to the tarball URL' do
downloader = Pod::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 = Pod::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 = Pod::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 = Pod::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
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