Imported File#ftype spec from rubyspecs.
[rbx.git] / lib / rubygems / config_file.rb
blobc657bf7f01e4752f8a1543c9ae38ce6a985db05a
1 #--
2 # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3 # All rights reserved.
4 # See LICENSE.txt for permissions.
5 #++
7 require 'yaml'
8 require 'rubygems'
10 # Store the gem command options specified in the configuration file.  The
11 # config file object acts much like a hash.
13 class Gem::ConfigFile
15   DEFAULT_BACKTRACE = false
16   DEFAULT_BENCHMARK = false
17   DEFAULT_BULK_THRESHOLD = 1000
18   DEFAULT_VERBOSITY = true
19   DEFAULT_UPDATE_SOURCES = true
21   system_config_path = 
22     begin
23       require 'Win32API'
25       CSIDL_COMMON_APPDATA = 0x0023
26       path = 0.chr * 260
27       SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP', 'L'
28       SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path
30       path.strip
31     rescue LoadError
32       '/etc'
33     end
35   SYSTEM_WIDE_CONFIG_FILE = File.join system_config_path, 'gemrc'
36   
37   # List of arguments supplied to the config file object.
38   attr_reader :args
40   # True if we print backtraces on errors.
41   attr_writer :backtrace
43   # True if we are benchmarking this run.
44   attr_accessor :benchmark
46   # Bulk threshold value.  If the number of missing gems are above
47   # this threshold value, then a bulk download technique is used.
48   attr_accessor :bulk_threshold
50   # Verbose level of output:
51   # * false -- No output
52   # * true -- Normal output
53   # * :loud -- Extra output
54   attr_accessor :verbose
56   # True if we want to update the SourceInfoCache every time, false otherwise
57   attr_accessor :update_sources
59   # Create the config file object.  +args+ is the list of arguments
60   # from the command line.
61   #
62   # The following command line options are handled early here rather
63   # than later at the time most command options are processed.
64   #
65   # * --config-file and --config-file==NAME -- Obviously these need
66   #   to be handled by the ConfigFile object to ensure we get the
67   #   right config file.
68   #
69   # * --backtrace -- Backtrace needs to be turned on early so that
70   #   errors before normal option parsing can be properly handled.
71   #
72   # * --debug -- Enable Ruby level debug messages.  Handled early
73   #   for the same reason as --backtrace.
74   #
75   def initialize(arg_list)
76     @config_file_name = nil
77     need_config_file_name = false
79     arg_list = arg_list.map do |arg|
80       if need_config_file_name then
81         @config_file_name = arg
82         nil
83       elsif arg =~ /^--config-file=(.*)/ then
84         @config_file_name = $1
85         nil
86       elsif arg =~ /^--config-file$/ then
87         need_config_file_name = true
88         nil
89       else
90         arg
91       end
92     end.compact
94     @backtrace = DEFAULT_BACKTRACE
95     @benchmark = DEFAULT_BENCHMARK
96     @bulk_threshold = DEFAULT_BULK_THRESHOLD
97     @verbose = DEFAULT_VERBOSITY
98     @update_sources = DEFAULT_UPDATE_SOURCES
100     @hash = load_file(SYSTEM_WIDE_CONFIG_FILE)
101     @hash.merge!(load_file(config_file_name.dup.untaint))
103     # HACK these override command-line args, which is bad
104     @backtrace = @hash[:backtrace] if @hash.key? :backtrace
105     @benchmark = @hash[:benchmark] if @hash.key? :benchmark
106     @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold
107     Gem.sources.replace @hash[:sources] if @hash.key? :sources
108     @verbose = @hash[:verbose] if @hash.key? :verbose
109     @update_sources = @hash[:update_sources] if @hash.key? :update_sources
111     handle_arguments arg_list
112   end
114   def load_file(filename)
115     begin
116       YAML.load(File.read(filename)) if filename and File.exist?(filename)
117     rescue ArgumentError
118       warn "Failed to load #{config_file_name}"
119     rescue Errno::EACCES
120       warn "Failed to load #{config_file_name} due to permissions problem."
121     end or {}
122   end
124   # True if the backtrace option has been specified, or debug is on.
125   def backtrace
126     @backtrace or $DEBUG
127   end
129   # The name of the configuration file.
130   def config_file_name
131     @config_file_name || Gem.config_file
132   end
134   # Delegates to @hash
135   def each(&block)
136     hash = @hash.dup
137     hash.delete :update_sources
138     hash.delete :verbose
139     hash.delete :benchmark
140     hash.delete :backtrace
141     hash.delete :bulk_threshold
143     yield :update_sources, @update_sources
144     yield :verbose, @verbose
145     yield :benchmark, @benchmark
146     yield :backtrace, @backtrace
147     yield :bulk_threshold, @bulk_threshold
149     yield 'config_file_name', @config_file_name if @config_file_name
151     hash.each(&block)
152   end
154   # Handle the command arguments.
155   def handle_arguments(arg_list)
156     @args = []
158     arg_list.each do |arg|
159       case arg
160       when /^--(backtrace|traceback)$/ then
161         @backtrace = true
162       when /^--bench(mark)?$/ then
163         @benchmark = true
164       when /^--debug$/ then
165         $DEBUG = true
166       else
167         @args << arg
168       end
169     end
170   end
172   # Really verbose mode gives you extra output.
173   def really_verbose
174     case verbose
175     when true, false, nil then false
176     else true
177     end
178   end
180   # to_yaml only overwrites things you can't override on the command line.
181   def to_yaml # :nodoc:
182     yaml_hash = {}
183     yaml_hash[:backtrace] = @hash.key?(:backtrace) ? @hash[:backtrace] :
184       DEFAULT_BACKTRACE
185     yaml_hash[:benchmark] = @hash.key?(:benchmark) ? @hash[:benchmark] :
186       DEFAULT_BENCHMARK
187     yaml_hash[:bulk_threshold] = @hash.key?(:bulk_threshold) ?
188       @hash[:bulk_threshold] : DEFAULT_BULK_THRESHOLD
189     yaml_hash[:sources] = Gem.sources
190     yaml_hash[:update_sources] = @hash.key?(:update_sources) ?
191       @hash[:update_sources] : DEFAULT_UPDATE_SOURCES
192     yaml_hash[:verbose] = @hash.key?(:verbose) ? @hash[:verbose] :
193       DEFAULT_VERBOSITY
195     keys = yaml_hash.keys.map { |key| key.to_s }
196     keys << 'debug'
197     re = Regexp.union(*keys)
199     @hash.each do |key, value|
200       key = key.to_s
201       next if key =~ re
202       yaml_hash[key.to_s] = value
203     end
205     yaml_hash.to_yaml
206   end
208   # Writes out this config file, replacing its source.
209   def write
210     File.open config_file_name, 'w' do |fp|
211       fp.write self.to_yaml
212     end
213   end
215   # Return the configuration information for +key+.
216   def [](key)
217     @hash[key.to_s]
218   end
220   # Set configuration option +key+ to +value+.
221   def []=(key, value)
222     @hash[key.to_s] = value
223   end
225   def ==(other) # :nodoc:
226     self.class === other and
227     @backtrace == other.backtrace and
228     @benchmark == other.benchmark and
229     @bulk_threshold == other.bulk_threshold and
230     @verbose == other.verbose and
231     @update_sources == other.update_sources and
232     @hash == other.hash
233   end
235   protected
237   attr_reader :hash