Created
October 26, 2010 16:05
-
-
Save anonymous/647185 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems/user_interaction' | |
module Gem::RubyGemPlus | |
RUBYGEMPLUS_CACHE = File.join((File.writable?(Gem.dir) ? Gem.dir : Gem.user_dir), 'cache') | |
RUBYGEMPLUS_USER_AGENT ="rubygem" | |
class GemPlusRemoteFetcher < Gem::RemoteFetcher | |
def download(spec, source_uri, install_dir = Gem.dir) | |
return super unless scheme_supported?(source_uri) | |
CurlUnsafeDownloadStrategy.new(source_uri + "gems/#{spec.file_name}", spec.file_name).fetch | |
end | |
def fetch_path(uri, mtime = nil, head = false) | |
return super unless scheme_supported?(uri) | |
path = CurlUnsafeDownloadStrategy.new(uri,nil).fetch | |
data = IO.read(path) | |
data = Gem.gunzip data if data and not head and uri.to_s =~ /gz$/ | |
data | |
end | |
def fetch_size(url) | |
puts "fetch size : #{url}" | |
super | |
end | |
private | |
def scheme_supported?(uri) | |
uri && uri.to_s.strip =~ %r[^https?://] | |
end | |
def ensure_tmp_dir(install_dir) | |
gem_file_name = spec.file_name | |
local_gem_path = File.join RUBYGEMPLUS_CACHE, gem_file_name | |
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir | |
end | |
end | |
module Util | |
include Gem::UserInteraction | |
def detect_download_strategy url | |
CurlDownloadStrategy | |
end | |
def curl *args | |
safe_system 'curl', '-f#LA', RUBYGEMPLUS_USER_AGENT, *args unless args.empty? | |
end | |
def safe_system cmd, *args | |
raise ExecutionError.new(cmd, args, $?) unless system(cmd, *args) | |
end | |
def system cmd, *args | |
#puts "#{cmd} #{args*' '}" | |
fork do | |
yield if block_given? | |
args.collect!{|arg| arg.to_s} | |
exec(cmd, *args) rescue nil | |
exit! 1 # never gets here unless exec failed | |
end | |
Process.wait | |
$?.success? | |
end | |
class ExecutionError <RuntimeError | |
attr :exit_status | |
attr :command | |
def initialize cmd, args = [], es = nil | |
@command = cmd | |
super "Failure while executing: #{cmd} #{pretty(args)*' '}" | |
@exit_status = es.exitstatus rescue 1 | |
end | |
def was_running_configure? | |
@command == './configure' | |
end | |
private | |
def pretty args | |
args.collect do |arg| | |
if arg.to_s.include? ' ' | |
"'#{ arg.gsub "'", "\\'" }'" | |
else | |
arg | |
end | |
end | |
end | |
end | |
class BuildError <ExecutionError | |
attr :env | |
def initialize cmd, args = [], es = nil | |
super | |
@env = ENV.to_hash | |
end | |
end | |
end | |
class AbstractDownloadStrategy | |
include Gem::RubyGemPlus::Util | |
def initialize url, name=nil | |
@url=url | |
@unique_token="#{name}" unless name.to_s.empty? or name == '__UNKNOWN__' | |
end | |
def expand_safe_system_args args | |
args.each_with_index do |arg, ii| | |
if arg.is_a? Hash | |
unless ARGV.verbose? | |
args[ii] = arg[:quiet_flag] | |
else | |
args.delete_at ii | |
end | |
return args | |
end | |
end | |
# 2 as default because commands are eg. svn up, git pull | |
args.insert(2, '-q') unless ARGV.verbose? | |
return args | |
end | |
def quiet_safe_system *args | |
safe_system *expand_safe_system_args(args) | |
end | |
end | |
class CurlDownloadStrategy <AbstractDownloadStrategy | |
attr_reader :tarball_path | |
def initialize url, name | |
super | |
if @unique_token | |
@tarball_path=File.join(RUBYGEMPLUS_CACHE,@unique_token) | |
else | |
@tarball_path=File.join(RUBYGEMPLUS_CACHE,File.basename(@url.to_s)) | |
end | |
end | |
def cached_location | |
@tarball_path | |
end | |
# Private method, can be overridden if needed. | |
def _fetch | |
curl @url, '-o', @tarball_path | |
end | |
def fetch | |
say "Downloading #{@url}" | |
unless File.exist?(@tarball_path) | |
begin | |
_fetch | |
rescue Exception | |
# ignore_interrupts { @tarball_path.unlink if @tarball_path.exist? } | |
raise | |
end | |
else | |
puts "File already downloaded and cached to #{RUBYGEMPLUS_CACHE}" | |
end | |
return @tarball_path # thus performs checksum verification | |
end | |
private | |
def chdir | |
entries=Dir['*'] | |
case entries.length | |
when 0 then raise "Empty archive" | |
when 1 then Dir.chdir entries.first rescue nil | |
end | |
end | |
end | |
# Download via an HTTP POST. | |
# Query parameters on the URL are converted into POST parameters | |
class CurlPostDownloadStrategy <CurlDownloadStrategy | |
def _fetch | |
base_url,data = @url.split('?') | |
curl base_url, '-d', data, '-o', @tarball_path | |
end | |
end | |
# Use this strategy to download but not unzip a file. | |
# Useful for installing jars. | |
class NoUnzipCurlDownloadStrategy <CurlDownloadStrategy | |
def stage | |
FileUtils.cp @tarball_path, File.basename(@url) | |
end | |
end | |
# This Download Strategy is provided for use with sites that | |
# only provide HTTPS and also have a broken cert. | |
# Try not to need this, as we probably won't accept the forulae | |
# into trunk. | |
class CurlUnsafeDownloadStrategy <CurlDownloadStrategy | |
def _fetch | |
curl @url, '--insecure', '-o', @tarball_path | |
end | |
end | |
Gem::RemoteFetcher.instance_variable_set "@fetcher", GemPlusRemoteFetcher.new(Gem.configuration[:http_proxy]) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment