* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / gem_prelude.rb
blob28bbd8372fb8c2590d1dfce659cad53a7d3a794d
1 # depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
3 if defined?(Gem) then
5   module Kernel
7     def gem(gem_name, *version_requirements)
8       Gem.push_gem_version_on_load_path(gem_name, *version_requirements)
9     end
11   end
13   module Gem
15     ConfigMap = {
16       :sitedir => RbConfig::CONFIG["sitedir"],
17       :ruby_version => RbConfig::CONFIG["ruby_version"],
18       :libdir => RbConfig::CONFIG["libdir"],
19       :sitelibdir => RbConfig::CONFIG["sitelibdir"],
20       :arch => RbConfig::CONFIG["arch"],
21       :bindir => RbConfig::CONFIG["bindir"],
22       :EXEEXT => RbConfig::CONFIG["EXEEXT"],
23       :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
24       :ruby_install_name => RbConfig::CONFIG["ruby_install_name"]
25     }
27     def self.default_dir
28       if defined? RUBY_FRAMEWORK_VERSION
29         return File.join(File.dirname(ConfigMap[:sitedir]), "Gems")
30       else
31         File.join(ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version])
32       end
33     end
35     def self.dir
36       @gem_home ||= nil
37       set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
38       @gem_home
39     end
41     def self.path
42       @gem_path ||= nil
43       unless @gem_path
44         paths = [ENV['GEM_PATH']]
45         paths << APPLE_GEM_HOME if defined? APPLE_GEM_HOME
46         set_paths(paths.compact.join(File::PATH_SEPARATOR))
47       end
48       @gem_path
49     end
51     # Set the Gem home directory (as reported by +dir+).
52     def self.set_home(home)
53       @gem_home = home
54       ensure_gem_subdirectories(@gem_home)
55     end
57     def self.set_paths(gpaths)
58       if gpaths
59         @gem_path = gpaths.split(File::PATH_SEPARATOR)
60         @gem_path << Gem.dir
61       else
62         @gem_path = [Gem.dir]
63       end
64       @gem_path.uniq!
65       @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
66     end
68     def self.ensure_gem_subdirectories(path)
69     end
71     GEM_PRELUDE_METHODS = Gem.methods(false)
73     module QuickLoader
75       def self.load_full_rubygems_library
76         class << Gem
77           Gem::GEM_PRELUDE_METHODS.each do |method_name|
78             undef_method method_name
79           end
80         end
82         Kernel.module_eval do
83           undef_method :gem if method_defined? :gem
84         end
86         $".delete File.join(Gem::ConfigMap[:libdir], 'ruby',
87                             Gem::ConfigMap[:ruby_version], 'rubygems.rb')
89         require 'rubygems'
90       end
92       GemPaths = {}
93       GemVersions = {}
95       def push_gem_version_on_load_path(gem_name, *version_requirements)
96         if version_requirements.empty?
97           unless GemPaths.has_key?(gem_name)
98             raise LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n") 
99           end
101           # highest version gems already active
102           return false
103         else
104           if version_requirements.length > 1
105             QuickLoader.load_full_rubygems_library
106             return gem(gem_name, *version_requirements)
107           end
109           requirement, version = version_requirements[0].split
110           requirement.strip!
112           if requirement == ">" || requirement == ">="
113             if (GemVersions[gem_name] <=> Gem.calculate_integers_for_gem_version(version)) >= 0
114               return false 
115             end
116           elsif requirement == "~>"
117             loaded_version = GemVersions[gem_name]
118             required_version = Gem.calculate_integers_for_gem_version(version)
119             if loaded_version && (loaded_version[0] == required_version[0])
120               return false
121             end
122           end
124           QuickLoader.load_full_rubygems_library
125           gem(gem_name, *version_requirements)
126         end
127       end
129       def calculate_integers_for_gem_version(gem_version)
130         numbers = gem_version.split(".").collect {|n| n.to_i}
131         numbers.pop while numbers.last == 0
132         numbers << 0 if numbers.empty?
133         numbers
134       end
136       def push_all_highest_version_gems_on_load_path
137         Gem.path.each do |path|
138           gems_directory = File.join(path, "gems")
139           if File.exist?(gems_directory)
140             Dir.entries(gems_directory).each do |gem_directory_name|
141               next if gem_directory_name == "." || gem_directory_name == ".."
142               dash = gem_directory_name.rindex("-")
143               next if dash.nil?
144               gem_name = gem_directory_name[0...dash]
145               current_version = GemVersions[gem_name]
146               new_version = calculate_integers_for_gem_version(gem_directory_name[dash+1..-1])
147               if current_version
148                 if (current_version <=> new_version) == -1
149                   GemVersions[gem_name] = new_version
150                   GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
151                 end
152               else
153                 GemVersions[gem_name] = new_version
154                 GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
155               end
156             end
157           end
158         end
160         require_paths = []
162         GemPaths.values.each do |path|
163           if File.exist?(File.join(path, ".require_paths"))
164             require_paths.concat(File.read(File.join(path, ".require_paths")).split.map {|require_path| File.join(path, require_path)})
165           else
166             require_paths << File.join(path, "bin") if File.exist?(File.join(path, "bin"))
167             require_paths << File.join(path, "lib") if File.exist?(File.join(path, "lib"))
168           end
169         end
171         # "tag" the first require_path inserted into the $LOAD_PATH to enable
172         # indexing correctly with rubygems proper when it inserts an explicitly
173         # gem version
174         unless require_paths.empty?
175           require_paths.first.instance_variable_set(:@gem_prelude_index, true)
176         end
177         # gem directories must come after -I and ENV['RUBYLIB']
178         $:[$:.index(ConfigMap[:sitelibdir]),0] = require_paths
179       end
181       def const_missing(constant)
182         QuickLoader.load_full_rubygems_library
183         if Gem.const_defined?(constant)
184           Gem.const_get(constant)
185         else
186           super
187         end
188       end
190       def method_missing(method, *args, &block)
191         QuickLoader.load_full_rubygems_library
192         super unless Gem.respond_to?(method)
193         Gem.send(method, *args, &block)
194       end
195     end
197     extend QuickLoader
199   end
201   begin
202     Gem.push_all_highest_version_gems_on_load_path
203     $" << File.join(Gem::ConfigMap[:libdir], "ruby",
204                     Gem::ConfigMap[:ruby_version], "rubygems.rb")
205   rescue Exception => e
206     puts "Error loading gem paths on load path in gem_prelude"
207     puts e
208     puts e.backtrace.join("\n")
209   end