I know there are other solutions to this out there. Just wanted to
share my work/play at it. I was trying to make it reletvely secure
without being too much a pain to use. This is was I arrived at.
Usage looks like this:
remote_source ‘fruitapp’,
‘http://roll.rubyforge.org/source/fruitapp/lib/fruitapp/1.0.0/’
remote_dependency ‘9de3cd6daece5f07aa3ddb0319a21415’, ‘tryme.rb’
require ‘fruitapp/tryme.rb’
The MD5 checksum of course is there to help ensure you get what you
expect. Of course that’s the most time consuming part becasue you have
to keep those upto date with new versions.
Anyway, just thought I’d share it just in case it interested anyone.
Here’s the code:
— remote_require.rb
require ‘open-uri’
require ‘digest/md5’
require ‘fileutils’
REMOTE_CACHE = File.expand_path( ‘~/.lib/site_ruby/1.8/’ )
FileUtils.mkdir_p REMOTE_CACHE unless File.directory? REMOTE_CACHE
$:.unshift REMOTE_CACHE
$current_source = nil
$current_source_stack = []
$remote_source = nil
$remote_dependency = {}
module Kernel
class ChecksumError < LoadError ; end
def remote_source( ref, uri )
$remote_source = { :ref=>ref.chomp(‘/’), :uri=>uri.chomp(‘/’) }
end
def remote_dependency( md5sum, file )
raise “dependency without source” unless $remote_source
$remote_dependency[ File.join( $remote_source[:ref], file ) ] = {
:ref => $remote_source[:ref],
:file => file,
:uri => $remote_source[:uri],
:md5 => md5sum
}
end
req = method(:require)
define_method :require do |fname|
if r = $remote_dependency[fname]
$current_source_stack << $current_source
$current_source = r
end
begin
req.call fname
rescue LoadError => e
# Bit of a shortcoming here since it’s not very efficient to
# be searching an remote location for multiple matches.
# .so suffix must be specified explicity on the remote end.
fname = fname + ‘.rb’ unless fname =~ /.rb$/ or fname =~ /.so$/
raise e unless $current_source
s = $current_source
url = fname.sub( /^#{s[:ref]}/, s[:uri] )
$stderr << "remote require – " + url if $DEBUG
rf = URI.parse( url ).read
if r
unless Digest::MD5.new( rf ).hexdigest == s[:md5] # TODO
checksum
raise ChecksumError.new(e)
end
end
newfile = File.join( REMOTE_CACHE, fname )
newdir = File.dirname( newfile )
FileUtils.mkdir_p newdir
File.open( newfile, ‘w+’ ) do |f|
f << rf
end
retry
ensure
$current_source = $current_source_stack.pop if r
end
end
end