Grammar and stream of consciousness cleanup for Channel and Scheduler rdoc
[rbx.git] / lib / rubygems.rb
blob4f2cc94ae036a24873d243a0feba6db37109827c
1 # -*- ruby -*-
2 #--
3 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
4 # All rights reserved.
5 # See LICENSE.txt for permissions.
6 #++
8 require 'rubygems/rubygems_version'
9 require 'rubygems/defaults'
10 require 'thread'
12 module Gem
13   class LoadError < ::LoadError
14     attr_accessor :name, :version_requirement
15   end
16 end
18 module Kernel
20   ##
21   # Use Kernel#gem to activate a specific version of +gem_name+.
22   #
23   # +version_requirements+ is a list of version requirements that the
24   # specified gem must match, most commonly "= example.version.number".  See
25   # Gem::Requirement for how to specify a version requirement.
26   #
27   # If you will be activating the latest version of a gem, there is no need to
28   # call Kernel#gem, Kernel#require will do the right thing for you.
29   #
30   # Kernel#gem returns true if the gem was activated, otherwise false.  If the
31   # gem could not be found, didn't match the version requirements, or a
32   # different version was already activated, an exception will be raised.
33   #
34   # Kernel#gem should be called *before* any require statements (otherwise
35   # RubyGems may load a conflicting library version).
36   #
37   # In older RubyGems versions, the environment variable GEM_SKIP could be
38   # used to skip activation of specified gems, for example to test out changes
39   # that haven't been installed yet.  Now RubyGems defers to -I and the
40   # RUBYLIB environment variable to skip activation of a gem.
41   #
42   # Example:
43   #
44   #   GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
46   def gem(gem_name, *version_requirements)
47     skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
48     raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
49     Gem.activate(gem_name, *version_requirements)
50   end
52 end
55 # Main module to hold all RubyGem classes/modules.
57 module Gem
59   ConfigMap = {} unless defined?(ConfigMap)
60   require 'rbconfig'
61   RbConfig = Config unless defined? ::RbConfig
63   ConfigMap.merge!(
64     :BASERUBY => RbConfig::CONFIG["BASERUBY"],
65     :EXEEXT => RbConfig::CONFIG["EXEEXT"],
66     :RUBY_INSTALL_NAME => RbConfig::CONFIG["RUBY_INSTALL_NAME"],
67     :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
68     :arch => RbConfig::CONFIG["arch"],
69     :bindir => RbConfig::CONFIG["bindir"],
70     :datadir => RbConfig::CONFIG["datadir"],
71     :libdir => RbConfig::CONFIG["libdir"],
72     :ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
73     :ruby_version => RbConfig::CONFIG["ruby_version"],
74     :sitedir => RbConfig::CONFIG["sitedir"],
75     :sitelibdir => RbConfig::CONFIG["sitelibdir"],
76     :vendordir => RbConfig::CONFIG["vendordir"] ,
77     :vendorlibdir => RbConfig::CONFIG["vendorlibdir"]
78   )
80   DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES)
82   MUTEX = Mutex.new
84   RubyGemsPackageVersion = RubyGemsVersion
86   ##
87   # An Array of Regexps that match windows ruby platforms.
89   WIN_PATTERNS = [
90     /bccwin/i,
91     /cygwin/i,
92     /djgpp/i,
93     /mingw/i,
94     /mswin/i,
95     /wince/i,
96   ]
98   @@source_index = nil
99   @@win_platform = nil
101   @configuration = nil
102   @loaded_specs = {}
103   @platforms = []
104   @ruby = nil
105   @sources = []
107   ##
108   # Activates an installed gem matching +gem+.  The gem must satisfy
109   # +version_requirements+.
110   #
111   # Returns true if the gem is activated, false if it is already
112   # loaded, or an exception otherwise.
113   #
114   # Gem#activate adds the library paths in +gem+ to $LOAD_PATH.  Before a Gem
115   # is activated its required Gems are activated.  If the version information
116   # is omitted, the highest version Gem of the supplied name is loaded.  If a
117   # Gem is not found that meets the version requirements or a required Gem is
118   # not found, a Gem::LoadError is raised.
119   #
120   # More information on version requirements can be found in the
121   # Gem::Requirement and Gem::Version documentation.
123   def self.activate(gem, *version_requirements)
124     if version_requirements.empty? then
125       version_requirements = Gem::Requirement.default
126     end
128     unless gem.respond_to?(:name) and
129            gem.respond_to?(:version_requirements) then
130       gem = Gem::Dependency.new(gem, version_requirements)
131     end
133     matches = Gem.source_index.find_name(gem.name, gem.version_requirements)
134     report_activate_error(gem) if matches.empty?
136     if @loaded_specs[gem.name] then
137       # This gem is already loaded.  If the currently loaded gem is not in the
138       # list of candidate gems, then we have a version conflict.
139       existing_spec = @loaded_specs[gem.name]
141       unless matches.any? { |spec| spec.version == existing_spec.version } then
142         raise Gem::Exception,
143               "can't activate #{gem}, already activated #{existing_spec.full_name}"
144       end
146       return false
147     end
149     # new load
150     spec = matches.last
151     return false if spec.loaded?
153     spec.loaded = true
154     @loaded_specs[spec.name] = spec
156     # Load dependent gems first
157     spec.runtime_dependencies.each do |dep_gem|
158       activate dep_gem
159     end
161     # bin directory must come before library directories
162     spec.require_paths.unshift spec.bindir if spec.bindir
164     require_paths = spec.require_paths.map do |path|
165       File.join spec.full_gem_path, path
166     end
168     sitelibdir = ConfigMap[:sitelibdir]
170     # gem directories must come after -I and ENV['RUBYLIB']
171     insert_index = load_path_insert_index
173     if insert_index then
174       # gem directories must come after -I and ENV['RUBYLIB']
175       $LOAD_PATH.insert(insert_index, *require_paths)
176     else
177       # we are probably testing in core, -I and RUBYLIB don't apply
178       $LOAD_PATH.unshift(*require_paths)
179     end
181     return true
182   end
184   ##
185   # An Array of all possible load paths for all versions of all gems in the
186   # Gem installation.
188   def self.all_load_paths
189     result = []
191     Gem.path.each do |gemdir|
192       each_load_path all_partials(gemdir) do |load_path|
193         result << load_path
194       end
195     end
197     result
198   end
200   ##
201   # Return all the partial paths in +gemdir+.
203   def self.all_partials(gemdir)
204     Dir[File.join(gemdir, 'gems/*')]
205   end
207   private_class_method :all_partials
209   ##
210   # See if a given gem is available.
211   
212   def self.available?(gem, *requirements)
213     requirements = Gem::Requirement.default if requirements.empty?
214     
215     unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements) 
216       gem = Gem::Dependency.new(gem, requirements)
217     end
218     
219     !Gem.source_index.search(gem).empty?
220   end
221   
222   ##
223   # The mode needed to read a file as straight binary.
225   def self.binary_mode
226     @binary_mode ||= RUBY_VERSION > '1.9' ? 'rb:ascii-8bit' : 'rb'
227   end
229   ##
230   # The path where gem executables are to be installed.
232   def self.bindir(install_dir=Gem.dir)
233     return File.join(install_dir, 'bin') unless
234       install_dir.to_s == Gem.default_dir
235     Gem.default_bindir
236   end
238   ##
239   # Reset the +dir+ and +path+ values.  The next time +dir+ or +path+
240   # is requested, the values will be calculated from scratch.  This is
241   # mainly used by the unit tests to provide test isolation.
243   def self.clear_paths
244     @gem_home = nil
245     @gem_path = nil
246     @@source_index = nil
247     MUTEX.synchronize do
248       @searcher = nil
249     end
250   end
252   ##
253   # The path to standard location of the user's .gemrc file.
255   def self.config_file
256     File.join Gem.user_home, '.gemrc'
257   end
259   ##
260   # The standard configuration object for gems.
262   def self.configuration
263     return @configuration if @configuration
264     require 'rubygems/config_file'
265     @configuration = Gem::ConfigFile.new []
266   end
268   ##
269   # Use the given configuration object (which implements the ConfigFile
270   # protocol) as the standard configuration object.
272   def self.configuration=(config)
273     @configuration = config
274   end
276   ##
277   # The path the the data directory specified by the gem name.  If the
278   # package is not available as a gem, return nil.
280   def self.datadir(gem_name)
281     spec = @loaded_specs[gem_name]
282     return nil if spec.nil?
283     File.join(spec.full_gem_path, 'data', gem_name)
284   end
286   ##
287   # A Zlib::Deflate.deflate wrapper
289   def self.deflate(data)
290     Zlib::Deflate.deflate data
291   end
293   ##
294   # The path where gems are to be installed.
296   def self.dir
297     @gem_home ||= nil
298     set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
299     @gem_home
300   end
302   ##
303   # Expand each partial gem path with each of the required paths specified
304   # in the Gem spec.  Each expanded path is yielded.
306   def self.each_load_path(partials)
307     partials.each do |gp|
308       base = File.basename(gp)
309       specfn = File.join(dir, "specifications", base + ".gemspec")
310       if File.exist?(specfn)
311         spec = eval(File.read(specfn))
312         spec.require_paths.each do |rp|
313           yield(File.join(gp, rp))
314         end
315       else
316         filename = File.join(gp, 'lib')
317         yield(filename) if File.exist?(filename)
318       end
319     end
320   end
322   private_class_method :each_load_path
324   ##
325   # Quietly ensure the named Gem directory contains all the proper
326   # subdirectories.  If we can't create a directory due to a permission
327   # problem, then we will silently continue.
329   def self.ensure_gem_subdirectories(gemdir)
330     require 'fileutils'
332     Gem::DIRECTORIES.each do |filename|
333       fn = File.join gemdir, filename
334       FileUtils.mkdir_p fn rescue nil unless File.exist? fn
335     end
336   end
338   ##
339   # Finds the user's home directory.
340   #--
341   # Some comments from the ruby-talk list regarding finding the home
342   # directory:
343   #
344   #   I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
345   #   to be depending on HOME in those code samples. I propose that
346   #   it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
347   #   least on Win32).
349   def self.find_home
350     ['HOME', 'USERPROFILE'].each do |homekey|
351       return ENV[homekey] if ENV[homekey]
352     end
354     if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
355       return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
356     end
358     begin
359       File.expand_path("~")
360     rescue
361       if File::ALT_SEPARATOR then
362           "C:/"
363       else
364           "/"
365       end
366     end
367   end
369   private_class_method :find_home
371   ##
372   # Zlib::GzipReader wrapper that unzips +data+.
374   def self.gunzip(data)
375     data = StringIO.new data
377     Zlib::GzipReader.new(data).read
378   end
380   ##
381   # Zlib::GzipWriter wrapper that zips +data+.
383   def self.gzip(data)
384     zipped = StringIO.new
386     Zlib::GzipWriter.wrap zipped do |io| io.write data end
388     zipped.string
389   end
391   ##
392   # A Zlib::Inflate#inflate wrapper
394   def self.inflate(data)
395     Zlib::Inflate.inflate data
396   end
398   ##
399   # Return a list of all possible load paths for the latest version for all
400   # gems in the Gem installation.
402   def self.latest_load_paths
403     result = []
405     Gem.path.each do |gemdir|
406       each_load_path(latest_partials(gemdir)) do |load_path|
407         result << load_path
408       end
409     end
411     result
412   end
414   ##
415   # Return only the latest partial paths in the given +gemdir+.
417   def self.latest_partials(gemdir)
418     latest = {}
419     all_partials(gemdir).each do |gp|
420       base = File.basename(gp)
421       if base =~ /(.*)-((\d+\.)*\d+)/ then
422         name, version = $1, $2
423         ver = Gem::Version.new(version)
424         if latest[name].nil? || ver > latest[name][0]
425           latest[name] = [ver, gp]
426         end
427       end
428     end
429     latest.collect { |k,v| v[1] }
430   end
432   private_class_method :latest_partials
434   ##
435   # The index to insert activated gem paths into the $LOAD_PATH.
436   #
437   # Defaults to the site lib directory unless gem_prelude.rb has loaded paths,
438   # then it inserts the activated gem's paths before the gem_prelude.rb paths
439   # so you can override the gem_prelude.rb default $LOAD_PATH paths.
441   def self.load_path_insert_index
442     index = $LOAD_PATH.index ConfigMap[:sitelibdir]
444     $LOAD_PATH.each_with_index do |path, i|
445       if path.instance_variables.include?(:@gem_prelude_index) or
446         path.instance_variables.include?('@gem_prelude_index') then
447         index = i
448         break
449       end
450     end
452     index
453   end
455   ##
456   # The file name and line number of the caller of the caller of this method.
458   def self.location_of_caller
459     file, lineno = caller[1].split(':')
460     lineno = lineno.to_i
461     [file, lineno]
462   end
464   private_class_method :location_of_caller
466   ##
467   # manage_gems is useless and deprecated.  Don't call it anymore.
468   #--
469   # TODO warn w/ RubyGems 1.2.x release.
471   def self.manage_gems
472     #file, lineno = location_of_caller
474     #warn "#{file}:#{lineno}:Warning: Gem#manage_gems is deprecated and will be removed on or after September 2008."
475   end
477   ##
478   # The version of the Marshal format for your Ruby.
480   def self.marshal_version
481     "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
482   end
484   ##
485   # Array of paths to search for Gems.
487   def self.path
488     @gem_path ||= nil
490     unless @gem_path then
491       paths = if ENV['GEM_PATH'] then
492                 [ENV['GEM_PATH']]
493               else
494                 [default_path]
495               end
497       if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
498         paths << APPLE_GEM_HOME
499       end
501       set_paths paths.compact.join(File::PATH_SEPARATOR)
502     end
504     @gem_path
505   end
507   ##
508   # Set array of platforms this RubyGems supports (primarily for testing).
510   def self.platforms=(platforms)
511     @platforms = platforms
512   end
514   ##
515   # Array of platforms this RubyGems supports.
517   def self.platforms
518     @platforms ||= []
519     if @platforms.empty?
520       @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
521     end
522     @platforms
523   end
525   ##
526   # The directory prefix this RubyGems was installed at.
528   def self.prefix
529     prefix = File.dirname File.expand_path(__FILE__)
531     if File.dirname(prefix) == File.expand_path(ConfigMap[:sitelibdir]) or
532        File.dirname(prefix) == File.expand_path(ConfigMap[:libdir]) or
533        'lib' != File.basename(prefix) then
534       nil
535     else
536       File.dirname prefix
537     end
538   end
540   ##
541   # Refresh source_index from disk and clear searcher.
543   def self.refresh
544     source_index.refresh!
546     MUTEX.synchronize do
547       @searcher = nil
548     end
549   end
551   ##
552   # Safely read a file in binary mode on all platforms.
554   def self.read_binary(path)
555     File.open path, binary_mode do |f| f.read end
556   end
558   ##
559   # Report a load error during activation.  The message of load error
560   # depends on whether it was a version mismatch or if there are not gems of
561   # any version by the requested name.
563   def self.report_activate_error(gem)
564     matches = Gem.source_index.find_name(gem.name)
566     if matches.empty? then
567       error = Gem::LoadError.new(
568           "Could not find RubyGem #{gem.name} (#{gem.version_requirements})\n")
569     else
570       error = Gem::LoadError.new(
571           "RubyGem version error: " +
572           "#{gem.name}(#{matches.first.version} not #{gem.version_requirements})\n")
573     end
575     error.name = gem.name
576     error.version_requirement = gem.version_requirements
577     raise error
578   end
580   private_class_method :report_activate_error
582   def self.required_location(gemname, libfile, *version_constraints)
583     version_constraints = Gem::Requirement.default if version_constraints.empty?
584     matches = Gem.source_index.find_name(gemname, version_constraints)
585     return nil if matches.empty?
586     spec = matches.last
587     spec.require_paths.each do |path|
588       result = File.join(spec.full_gem_path, path, libfile)
589       return result if File.exist?(result)
590     end
591     nil
592   end
594   ##
595   # The path to the running Ruby interpreter.
597   def self.ruby
598     if @ruby.nil? then
599       @ruby = File.join(ConfigMap[:bindir],
600                         ConfigMap[:ruby_install_name])
601       @ruby << ConfigMap[:EXEEXT]
602     end
604     @ruby
605   end
607   ##
608   # A Gem::Version for the currently running ruby.
610   def self.ruby_version
611     return @ruby_version if defined? @ruby_version
612     version = RUBY_VERSION.dup
613     version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
614     @ruby_version = Gem::Version.new version
615   end
617   ##
618   # The GemPathSearcher object used to search for matching installed gems.
620   def self.searcher
621     MUTEX.synchronize do
622       @searcher ||= Gem::GemPathSearcher.new
623     end
624   end
626   ##
627   # Set the Gem home directory (as reported by Gem.dir).
629   def self.set_home(home)
630     home = home.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
631     @gem_home = home
632     ensure_gem_subdirectories(@gem_home)
633   end
635   private_class_method :set_home
637   ##
638   # Set the Gem search path (as reported by Gem.path).
640   def self.set_paths(gpaths)
641     if gpaths
642       @gem_path = gpaths.split(File::PATH_SEPARATOR)
644       if File::ALT_SEPARATOR then
645         @gem_path.map! do |path|
646           path.gsub File::ALT_SEPARATOR, File::SEPARATOR
647         end
648       end
650       @gem_path << Gem.dir
651     else
652       @gem_path = [Gem.dir]
653     end
655     @gem_path.uniq!
656     @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
657   end
659   private_class_method :set_paths
661   ##
662   # Returns the Gem::SourceIndex of specifications that are in the Gem.path
664   def self.source_index
665     @@source_index ||= SourceIndex.from_installed_gems
666   end
668   ##
669   # Returns an Array of sources to fetch remote gems from.  If the sources
670   # list is empty, attempts to load the "sources" gem, then uses
671   # default_sources if it is not installed.
673   def self.sources
674     if @sources.empty? then
675       begin
676         gem 'sources', '> 0.0.1'
677         require 'sources'
678       rescue LoadError
679         @sources = default_sources
680       end
681     end
683     @sources
684   end
686   ##
687   # Glob pattern for require-able path suffixes.
689   def self.suffix_pattern
690     @suffix_pattern ||= "{#{suffixes.join(',')}}"
691   end
693   ##
694   # Suffixes for require-able paths.
696   def self.suffixes
697     ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
698   end
700   ##
701   # Use the +home+ and +paths+ values for Gem.dir and Gem.path.  Used mainly
702   # by the unit tests to provide environment isolation.
704   def self.use_paths(home, paths=[])
705     clear_paths
706     set_home(home) if home
707     set_paths(paths.join(File::PATH_SEPARATOR)) if paths
708   end
710   ##
711   # The home directory for the user.
713   def self.user_home
714     @user_home ||= find_home
715   end
717   ##
718   # Is this a windows platform?
720   def self.win_platform?
721     if @@win_platform.nil? then
722       @@win_platform = !!WIN_PATTERNS.find { |r| RUBY_PLATFORM =~ r }
723     end
725     @@win_platform
726   end
728   class << self
730     attr_reader :loaded_specs
732     # :stopdoc:
734     alias cache source_index # an alias for the old name
736     # :startdoc:
738   end
740   MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
742   YAML_SPEC_DIR = 'quick/'
746 module Config
747   # :stopdoc:
748   class << self
749     # Return the path to the data directory associated with the named
750     # package.  If the package is loaded as a gem, return the gem
751     # specific data directory.  Otherwise return a path to the share
752     # area as define by "#{ConfigMap[:datadir]}/#{package_name}".
753     def datadir(package_name)
754       Gem.datadir(package_name) ||
755         File.join(Gem::ConfigMap[:datadir], package_name)
756     end
757   end
758   # :startdoc:
761 require 'rubygems/exceptions'
762 require 'rubygems/version'
763 require 'rubygems/requirement'
764 require 'rubygems/dependency'
765 require 'rubygems/gem_path_searcher'    # Needed for Kernel#gem
766 require 'rubygems/source_index'         # Needed for Kernel#gem
767 require 'rubygems/platform'
768 require 'rubygems/builder'              # HACK: Needed for rake's package task.
770 begin
771   require 'rubygems/defaults/operating_system'
772 rescue LoadError
775 if defined?(RUBY_ENGINE) then
776   begin
777     require "rubygems/defaults/#{RUBY_ENGINE}"
778   rescue LoadError
779   end
782 if RUBY_VERSION < '1.9' then
783   require 'rubygems/custom_require'