Created
March 16, 2009 20:46
-
-
Save dcparker/80061 to your computer and use it in GitHub Desktop.
Rubygems sandboxer for Merb.
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
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