[Nitro] [OT] Roll n' Rain

TRANS transfire at gmail.com
Wed Jun 28 00:35:10 EDT 2006


On 6/27/06, James Britt <james.britt at gmail.com> wrote:

> Pretty much.  An "app" could be a single line of code that just
> bootstraps itself by fetching code across the wire.  Zero installation.

> A few people cooked up assorted versions of this (I called mine
> HyperActive Require).
>
> http://www.oreillynet.com/ruby/blog/2006/01/the_year_of_living_dangerously.html

>
> Yeah, there were interesting ideas kicked around on this.

I've expiremented with this too. Would it really be so great? I think
I'd rather add signed .drp (like .jar) support to require then let
require take url to a .drp file.  In any case here's my original stab
at it w/ example at bottom:

require 'open-uri'
require 'digest/md5'
require 'fileutils'

REMOTE_CACHE = File.expand_path( '~/.config/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]  # TODD 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


# Example

remote_source 'fruitapp',
'http://roll.rubyforge.org/source/fruitapp/lib/fruitapp/1.0.0/'
remote_dependency '9de3cd6daece5f07aa3ddb0319a21415', 'tryme.rb'

require 'fruitapp/tryme.rb'


More information about the Nitro-general mailing list