* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / rubygems.rb
blobfde91bfd4b34f6ba92e199276c848876a0a5a90e
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.
212   def self.available?(gem, *requirements)
213     requirements = Gem::Requirement.default if requirements.empty?
215     unless gem.respond_to?(:name) and
216            gem.respond_to?(:version_requirements) then
217       gem = Gem::Dependency.new gem, requirements
218     end
220     !Gem.source_index.search(gem).empty?
221   end
223   ##
224   # The mode needed to read a file as straight binary.
226   def self.binary_mode
227     @binary_mode ||= RUBY_VERSION > '1.9' ? 'rb:ascii-8bit' : 'rb'
228   end
230   ##
231   # The path where gem executables are to be installed.
233   def self.bindir(install_dir=Gem.dir)
234     return File.join(install_dir, 'bin') unless
235       install_dir.to_s == Gem.default_dir
236     Gem.default_bindir
237   end
239   ##
240   # Reset the +dir+ and +path+ values.  The next time +dir+ or +path+
241   # is requested, the values will be calculated from scratch.  This is
242   # mainly used by the unit tests to provide test isolation.
244   def self.clear_paths
245     @gem_home = nil
246     @gem_path = nil
247     @@source_index = nil
248     MUTEX.synchronize do
249       @searcher = nil
250     end
251   end
253   ##
254   # The path to standard location of the user's .gemrc file.
256   def self.config_file
257     File.join Gem.user_home, '.gemrc'
258   end
260   ##
261   # The standard configuration object for gems.
263   def self.configuration
264     return @configuration if @configuration
265     require 'rubygems/config_file'
266     @configuration = Gem::ConfigFile.new []
267   end
269   ##
270   # Use the given configuration object (which implements the ConfigFile
271   # protocol) as the standard configuration object.
273   def self.configuration=(config)
274     @configuration = config
275   end
277   ##
278   # The path the the data directory specified by the gem name.  If the
279   # package is not available as a gem, return nil.
281   def self.datadir(gem_name)
282     spec = @loaded_specs[gem_name]
283     return nil if spec.nil?
284     File.join(spec.full_gem_path, 'data', gem_name)
285   end
287   ##
288   # A Zlib::Deflate.deflate wrapper
290   def self.deflate(data)
291     Zlib::Deflate.deflate data
292   end
294   ##
295   # The path where gems are to be installed.
297   def self.dir
298     @gem_home ||= nil
299     set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
300     @gem_home
301   end
303   ##
304   # Expand each partial gem path with each of the required paths specified
305   # in the Gem spec.  Each expanded path is yielded.
307   def self.each_load_path(partials)
308     partials.each do |gp|
309       base = File.basename(gp)
310       specfn = File.join(dir, "specifications", base + ".gemspec")
311       if File.exist?(specfn)
312         spec = eval(File.read(specfn))
313         spec.require_paths.each do |rp|
314           yield(File.join(gp, rp))
315         end
316       else
317         filename = File.join(gp, 'lib')
318         yield(filename) if File.exist?(filename)
319       end
320     end
321   end
323   private_class_method :each_load_path
325   ##
326   # Quietly ensure the named Gem directory contains all the proper
327   # subdirectories.  If we can't create a directory due to a permission
328   # problem, then we will silently continue.
330   def self.ensure_gem_subdirectories(gemdir)
331     require 'fileutils'
333     Gem::DIRECTORIES.each do |filename|
334       fn = File.join gemdir, filename
335       FileUtils.mkdir_p fn rescue nil unless File.exist? fn
336     end
337   end
339   ##
340   # Finds the user's home directory.
341   #--
342   # Some comments from the ruby-talk list regarding finding the home
343   # directory:
344   #
345   #   I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
346   #   to be depending on HOME in those code samples. I propose that
347   #   it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
348   #   least on Win32).
350   def self.find_home
351     ['HOME', 'USERPROFILE'].each do |homekey|
352       return ENV[homekey] if ENV[homekey]
353     end
355     if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
356       return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
357     end
359     begin
360       File.expand_path("~")
361     rescue
362       if File::ALT_SEPARATOR then
363           "C:/"
364       else
365           "/"
366       end
367     end
368   end
370   private_class_method :find_home
372   ##
373   # Zlib::GzipReader wrapper that unzips +data+.
375   def self.gunzip(data)
376     data = StringIO.new data
378     Zlib::GzipReader.new(data).read
379   end
381   ##
382   # Zlib::GzipWriter wrapper that zips +data+.
384   def self.gzip(data)
385     zipped = StringIO.new
387     Zlib::GzipWriter.wrap zipped do |io| io.write data end
389     zipped.string
390   end
392   ##
393   # A Zlib::Inflate#inflate wrapper
395   def self.inflate(data)
396     Zlib::Inflate.inflate data
397   end
399   ##
400   # Return a list of all possible load paths for the latest version for all
401   # gems in the Gem installation.
403   def self.latest_load_paths
404     result = []
406     Gem.path.each do |gemdir|
407       each_load_path(latest_partials(gemdir)) do |load_path|
408         result << load_path
409       end
410     end
412     result
413   end
415   ##
416   # Return only the latest partial paths in the given +gemdir+.
418   def self.latest_partials(gemdir)
419     latest = {}
420     all_partials(gemdir).each do |gp|
421       base = File.basename(gp)
422       if base =~ /(.*)-((\d+\.)*\d+)/ then
423         name, version = $1, $2
424         ver = Gem::Version.new(version)
425         if latest[name].nil? || ver > latest[name][0]
426           latest[name] = [ver, gp]
427         end
428       end
429     end
430     latest.collect { |k,v| v[1] }
431   end
433   private_class_method :latest_partials
435   ##
436   # The index to insert activated gem paths into the $LOAD_PATH.
437   #
438   # Defaults to the site lib directory unless gem_prelude.rb has loaded paths,
439   # then it inserts the activated gem's paths before the gem_prelude.rb paths
440   # so you can override the gem_prelude.rb default $LOAD_PATH paths.
442   def self.load_path_insert_index
443     index = $LOAD_PATH.index ConfigMap[:sitelibdir]
445     $LOAD_PATH.each_with_index do |path, i|
446       if path.instance_variables.include?(:@gem_prelude_index) or
447         path.instance_variables.include?('@gem_prelude_index') then
448         index = i
449         break
450       end
451     end
453     index
454   end
456   ##
457   # The file name and line number of the caller of the caller of this method.
459   def self.location_of_caller
460     file, lineno = caller[1].split(':')
461     lineno = lineno.to_i
462     [file, lineno]
463   end
465   private_class_method :location_of_caller
467   ##
468   # manage_gems is useless and deprecated.  Don't call it anymore.
469   #--
470   # TODO warn w/ RubyGems 1.2.x release.
472   def self.manage_gems
473     #file, lineno = location_of_caller
475     #warn "#{file}:#{lineno}:Warning: Gem#manage_gems is deprecated and will be removed on or after September 2008."
476   end
478   ##
479   # The version of the Marshal format for your Ruby.
481   def self.marshal_version
482     "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
483   end
485   ##
486   # Array of paths to search for Gems.
488   def self.path
489     @gem_path ||= nil
491     unless @gem_path then
492       paths = if ENV['GEM_PATH'] then
493                 [ENV['GEM_PATH']]
494               else
495                 [default_path]
496               end
498       if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
499         paths << APPLE_GEM_HOME
500       end
502       set_paths paths.compact.join(File::PATH_SEPARATOR)
503     end
505     @gem_path
506   end
508   ##
509   # Set array of platforms this RubyGems supports (primarily for testing).
511   def self.platforms=(platforms)
512     @platforms = platforms
513   end
515   ##
516   # Array of platforms this RubyGems supports.
518   def self.platforms
519     @platforms ||= []
520     if @platforms.empty?
521       @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
522     end
523     @platforms
524   end
526   ##
527   # The directory prefix this RubyGems was installed at.
529   def self.prefix
530     prefix = File.dirname File.expand_path(__FILE__)
532     if File.dirname(prefix) == File.expand_path(ConfigMap[:sitelibdir]) or
533        File.dirname(prefix) == File.expand_path(ConfigMap[:libdir]) or
534        'lib' != File.basename(prefix) then
535       nil
536     else
537       File.dirname prefix
538     end
539   end
541   ##
542   # Refresh source_index from disk and clear searcher.
544   def self.refresh
545     source_index.refresh!
547     MUTEX.synchronize do
548       @searcher = nil
549     end
550   end
552   ##
553   # Safely read a file in binary mode on all platforms.
555   def self.read_binary(path)
556     File.open path, binary_mode do |f| f.read end
557   end
559   ##
560   # Report a load error during activation.  The message of load error
561   # depends on whether it was a version mismatch or if there are not gems of
562   # any version by the requested name.
564   def self.report_activate_error(gem)
565     matches = Gem.source_index.find_name(gem.name)
567     if matches.empty? then
568       error = Gem::LoadError.new(
569           "Could not find RubyGem #{gem.name} (#{gem.version_requirements})\n")
570     else
571       error = Gem::LoadError.new(
572           "RubyGem version error: " +
573           "#{gem.name}(#{matches.first.version} not #{gem.version_requirements})\n")
574     end
576     error.name = gem.name
577     error.version_requirement = gem.version_requirements
578     raise error
579   end
581   private_class_method :report_activate_error
583   def self.required_location(gemname, libfile, *version_constraints)
584     version_constraints = Gem::Requirement.default if version_constraints.empty?
585     matches = Gem.source_index.find_name(gemname, version_constraints)
586     return nil if matches.empty?
587     spec = matches.last
588     spec.require_paths.each do |path|
589       result = File.join(spec.full_gem_path, path, libfile)
590       return result if File.exist?(result)
591     end
592     nil
593   end
595   ##
596   # The path to the running Ruby interpreter.
598   def self.ruby
599     if @ruby.nil? then
600       @ruby = File.join(ConfigMap[:bindir],
601                         ConfigMap[:ruby_install_name])
602       @ruby << ConfigMap[:EXEEXT]
603     end
605     @ruby
606   end
608   ##
609   # A Gem::Version for the currently running ruby.
611   def self.ruby_version
612     return @ruby_version if defined? @ruby_version
613     version = RUBY_VERSION.dup
614     version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
615     @ruby_version = Gem::Version.new version
616   end
618   ##
619   # The GemPathSearcher object used to search for matching installed gems.
621   def self.searcher
622     MUTEX.synchronize do
623       @searcher ||= Gem::GemPathSearcher.new
624     end
625   end
627   ##
628   # Set the Gem home directory (as reported by Gem.dir).
630   def self.set_home(home)
631     home = home.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
632     @gem_home = home
633     ensure_gem_subdirectories(@gem_home)
634   end
636   private_class_method :set_home
638   ##
639   # Set the Gem search path (as reported by Gem.path).
641   def self.set_paths(gpaths)
642     if gpaths
643       @gem_path = gpaths.split(File::PATH_SEPARATOR)
645       if File::ALT_SEPARATOR then
646         @gem_path.map! do |path|
647           path.gsub File::ALT_SEPARATOR, File::SEPARATOR
648         end
649       end
651       @gem_path << Gem.dir
652     else
653       # TODO: should this be Gem.default_path instead?
654       @gem_path = [Gem.dir]
655     end
657     @gem_path.uniq!
658     @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
659   end
661   private_class_method :set_paths
663   ##
664   # Returns the Gem::SourceIndex of specifications that are in the Gem.path
666   def self.source_index
667     @@source_index ||= SourceIndex.from_installed_gems
668   end
670   ##
671   # Returns an Array of sources to fetch remote gems from.  If the sources
672   # list is empty, attempts to load the "sources" gem, then uses
673   # default_sources if it is not installed.
675   def self.sources
676     if @sources.empty? then
677       begin
678         gem 'sources', '> 0.0.1'
679         require 'sources'
680       rescue LoadError
681         @sources = default_sources
682       end
683     end
685     @sources
686   end
688   ##
689   # Glob pattern for require-able path suffixes.
691   def self.suffix_pattern
692     @suffix_pattern ||= "{#{suffixes.join(',')}}"
693   end
695   ##
696   # Suffixes for require-able paths.
698   def self.suffixes
699     ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
700   end
702   ##
703   # Use the +home+ and +paths+ values for Gem.dir and Gem.path.  Used mainly
704   # by the unit tests to provide environment isolation.
706   def self.use_paths(home, paths=[])
707     clear_paths
708     set_home(home) if home
709     set_paths(paths.join(File::PATH_SEPARATOR)) if paths
710   end
712   ##
713   # The home directory for the user.
715   def self.user_home
716     @user_home ||= find_home
717   end
719   ##
720   # Is this a windows platform?
722   def self.win_platform?
723     if @@win_platform.nil? then
724       @@win_platform = !!WIN_PATTERNS.find { |r| RUBY_PLATFORM =~ r }
725     end
727     @@win_platform
728   end
730   class << self
732     attr_reader :loaded_specs
734     # :stopdoc:
736     alias cache source_index # an alias for the old name
738     # :startdoc:
740   end
742   MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
744   YAML_SPEC_DIR = 'quick/'
748 module Config
749   # :stopdoc:
750   class << self
751     # Return the path to the data directory associated with the named
752     # package.  If the package is loaded as a gem, return the gem
753     # specific data directory.  Otherwise return a path to the share
754     # area as define by "#{ConfigMap[:datadir]}/#{package_name}".
755     def datadir(package_name)
756       Gem.datadir(package_name) ||
757         File.join(Gem::ConfigMap[:datadir], package_name)
758     end
759   end
760   # :startdoc:
763 require 'rubygems/exceptions'
764 require 'rubygems/version'
765 require 'rubygems/requirement'
766 require 'rubygems/dependency'
767 require 'rubygems/gem_path_searcher'    # Needed for Kernel#gem
768 require 'rubygems/source_index'         # Needed for Kernel#gem
769 require 'rubygems/platform'
770 require 'rubygems/builder'              # HACK: Needed for rake's package task.
772 begin
773   require 'rubygems/defaults/operating_system'
774 rescue LoadError
777 if defined?(RUBY_ENGINE) then
778   begin
779     require "rubygems/defaults/#{RUBY_ENGINE}"
780   rescue LoadError
781   end
784 if RUBY_VERSION < '1.9' then
785   require 'rubygems/custom_require'