Skip to content

Instantly share code, notes, and snippets.

@dcparker
Created March 16, 2009 20:46
Show Gist options
  • Save dcparker/80061 to your computer and use it in GitHub Desktop.
Save dcparker/80061 to your computer and use it in GitHub Desktop.
Rubygems sandboxer for Merb.
local_rubygems = !!($:[0] == '.')
$:.shift if local_rubygems # Takes off the extra '.' put on the beginning. Now the next line will require the real rubygems
# Now require the REAL rubygems.
# (we're going to FREEZE it next)
load 'rubygems.rb'
$:.unshift('.') if local_rubygems
module Gem
Sandbox = {
'merb-core' => '=0.9.7',
'dm-core' => '=0.9.8',
'merb_datamapper' => '=0.9.7',
'json' => '=1.1.2',
}
class SourceIndex
def load_gems_in(*spec_dirs)
@gems.clear
spec_dirs.reverse_each do |spec_dir|
spec_files = Dir.glob File.join(spec_dir, '*.gemspec')
spec_files.each do |spec_file|
if gemspec = self.class.load_specification(spec_file.untaint)
if Gem::Sandbox.include?(gemspec.name)
version_requirement = Gem::Requirement.create Gem::Sandbox[gemspec.name]
add_spec gemspec if version_requirement.satisfied_by? gemspec.version
else
add_spec gemspec
end
end
end
end
self
end
end
def self.activate(agem, *version_requirements)
$INDENT ||= ''
if version_requirements.empty? then
version_requirements = Gem::Requirement.default
end
unless agem.respond_to?(:name) and
agem.respond_to?(:version_requirements) then
agem = Gem::Dependency.new(agem, version_requirements)
end
# puts "#{$INDENT}Loading gem #{agem.name} #{agem.version_requirements}"
matches = Gem.source_index.find_name(agem.name, agem.version_requirements)
report_activate_error(agem) if matches.empty?
if @loaded_specs[agem.name] then
# This gem is already loaded. If the currently loaded gem is not in the
# list of candidate gems, then we have a version conflict.
existing_spec = @loaded_specs[agem.name]
unless matches.any? { |spec| spec.version == existing_spec.version } then
raise Gem::Exception,
"can't activate #{agem}, already activated #{existing_spec.full_name}"
end
return false
end
# new load
spec = matches.last
return false if spec.loaded?
# puts " '#{spec.name}' => '=#{spec.version}',"
spec.loaded = true
@loaded_specs[spec.name] = spec
# Load dependent gems first
spec.runtime_dependencies.each do |dep_gem|
$INDENT += "\t"
activate dep_gem
$INDENT.chop!
end
# bin directory must come before library directories
spec.require_paths.unshift spec.bindir if spec.bindir
require_paths = spec.require_paths.map do |path|
File.join spec.full_gem_path, path
end
sitelibdir = ConfigMap[:sitelibdir]
# gem directories must come after -I and ENV['RUBYLIB']
insert_index = load_path_insert_index
if insert_index then
# gem directories must come after -I and ENV['RUBYLIB']
$LOAD_PATH.insert(insert_index, *require_paths)
else
# we are probably testing in core, -I and RUBYLIB don't apply
$LOAD_PATH.unshift(*require_paths)
end
return true
end
end
if $0 == 'rubygems.rb'
def sandbox_merb
puts "Making merb freezable..."
merb_sh = `whereis merb`.chomp
merb_script = File.read(merb_sh)
new_merb_script = ''
# Put in the comments at the top
merb_script.each_line do |line|
break if line =~ /require\s+.rubygems./ || line =~ /\$:\.unshift\('\.'\)/
new_merb_script << line
end
# Put in the one new custom line
new_merb_script << "$:.unshift('.')\n"
# Put in the rest of the script
hit = false
merb_script.each_line do |line|
next if line =~ /\$:\.shift/
if line =~ /require\s+.rubygems./
line << "$:.shift\n"
hit = true
end
new_merb_script << line if hit
end
File.open(merb_sh, 'w') {|f| f.puts new_merb_script }
puts `cat #{merb_sh}`
puts "Done."
end
case ARGV[0]
when 'sandbox_merb'
sandbox_merb
when 'list_dependencies'
puts "Dependencies:"
Gem::Sandbox.each do |name,version|
version = version[/[\d\.]+/]
puts "#{name}-#{version}"
end
when 'install_dependencies'
puts "Installing Dependencies..."
Gem::Sandbox.each do |name,version|
version = version[/[\d\.]+/]
has = `gem list #{name}`
if has =~ /#{name} \(.*#{version}.*\)/
puts "Already have #{name} #{version}"
else
puts "gem install #{name} --version #{version}"
system("gem install #{name} --version #{version}")
end
end
sandbox_merb
else
puts "Usage: ./rubygems.rb (sandbox_merb | list_dependencies | install_dependencies)"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment