Skip to content

Instantly share code, notes, and snippets.

Created October 26, 2010 16:05
Show Gist options
  • Save anonymous/647185 to your computer and use it in GitHub Desktop.
Save anonymous/647185 to your computer and use it in GitHub Desktop.
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