diff options
Diffstat (limited to 'trunk/lib/rubygems/config_file.rb')
-rw-r--r-- | trunk/lib/rubygems/config_file.rb | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/trunk/lib/rubygems/config_file.rb b/trunk/lib/rubygems/config_file.rb new file mode 100644 index 0000000000..c093c31a1b --- /dev/null +++ b/trunk/lib/rubygems/config_file.rb @@ -0,0 +1,259 @@ +#-- +# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. +# All rights reserved. +# See LICENSE.txt for permissions. +#++ + +require 'yaml' +require 'rubygems' + +# Store the gem command options specified in the configuration file. The +# config file object acts much like a hash. + +class Gem::ConfigFile + + DEFAULT_BACKTRACE = false + DEFAULT_BENCHMARK = false + DEFAULT_BULK_THRESHOLD = 1000 + DEFAULT_VERBOSITY = true + DEFAULT_UPDATE_SOURCES = true + + ## + # For Ruby packagers to set configuration defaults. Set in + # rubygems/defaults/operating_system.rb + + OPERATING_SYSTEM_DEFAULTS = {} + + ## + # For Ruby implementers to set configuration defaults. Set in + # rubygems/defaults/#{RUBY_ENGINE}.rb + + PLATFORM_DEFAULTS = {} + + system_config_path = + begin + require 'Win32API' + + CSIDL_COMMON_APPDATA = 0x0023 + path = 0.chr * 260 + SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP', 'L' + SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path + + path.strip + rescue LoadError + '/etc' + end + + SYSTEM_WIDE_CONFIG_FILE = File.join system_config_path, 'gemrc' + + # List of arguments supplied to the config file object. + attr_reader :args + + # True if we print backtraces on errors. + attr_writer :backtrace + + # True if we are benchmarking this run. + attr_accessor :benchmark + + # Bulk threshold value. If the number of missing gems are above + # this threshold value, then a bulk download technique is used. + attr_accessor :bulk_threshold + + # Verbose level of output: + # * false -- No output + # * true -- Normal output + # * :loud -- Extra output + attr_accessor :verbose + + # True if we want to update the SourceInfoCache every time, false otherwise + attr_accessor :update_sources + + # Create the config file object. +args+ is the list of arguments + # from the command line. + # + # The following command line options are handled early here rather + # than later at the time most command options are processed. + # + # * --config-file and --config-file==NAME -- Obviously these need + # to be handled by the ConfigFile object to ensure we get the + # right config file. + # + # * --backtrace -- Backtrace needs to be turned on early so that + # errors before normal option parsing can be properly handled. + # + # * --debug -- Enable Ruby level debug messages. Handled early + # for the same reason as --backtrace. + # + def initialize(arg_list) + @config_file_name = nil + need_config_file_name = false + + arg_list = arg_list.map do |arg| + if need_config_file_name then + @config_file_name = arg + need_config_file_name = false + nil + elsif arg =~ /^--config-file=(.*)/ then + @config_file_name = $1 + nil + elsif arg =~ /^--config-file$/ then + need_config_file_name = true + nil + else + arg + end + end.compact + + @backtrace = DEFAULT_BACKTRACE + @benchmark = DEFAULT_BENCHMARK + @bulk_threshold = DEFAULT_BULK_THRESHOLD + @verbose = DEFAULT_VERBOSITY + @update_sources = DEFAULT_UPDATE_SOURCES + + operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS) + platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS) + system_config = load_file SYSTEM_WIDE_CONFIG_FILE + user_config = load_file config_file_name.dup.untaint + + @hash = operating_system_config.merge platform_config + @hash = @hash.merge system_config + @hash = @hash.merge user_config + + # HACK these override command-line args, which is bad + @backtrace = @hash[:backtrace] if @hash.key? :backtrace + @benchmark = @hash[:benchmark] if @hash.key? :benchmark + @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold + Gem.sources.replace @hash[:sources] if @hash.key? :sources + @verbose = @hash[:verbose] if @hash.key? :verbose + @update_sources = @hash[:update_sources] if @hash.key? :update_sources + + handle_arguments arg_list + end + + def load_file(filename) + begin + YAML.load(File.read(filename)) if filename and File.exist?(filename) + rescue ArgumentError + warn "Failed to load #{config_file_name}" + rescue Errno::EACCES + warn "Failed to load #{config_file_name} due to permissions problem." + end or {} + end + + # True if the backtrace option has been specified, or debug is on. + def backtrace + @backtrace or $DEBUG + end + + # The name of the configuration file. + def config_file_name + @config_file_name || Gem.config_file + end + + # Delegates to @hash + def each(&block) + hash = @hash.dup + hash.delete :update_sources + hash.delete :verbose + hash.delete :benchmark + hash.delete :backtrace + hash.delete :bulk_threshold + + yield :update_sources, @update_sources + yield :verbose, @verbose + yield :benchmark, @benchmark + yield :backtrace, @backtrace + yield :bulk_threshold, @bulk_threshold + + yield 'config_file_name', @config_file_name if @config_file_name + + hash.each(&block) + end + + # Handle the command arguments. + def handle_arguments(arg_list) + @args = [] + + arg_list.each do |arg| + case arg + when /^--(backtrace|traceback)$/ then + @backtrace = true + when /^--bench(mark)?$/ then + @benchmark = true + when /^--debug$/ then + $DEBUG = true + else + @args << arg + end + end + end + + # Really verbose mode gives you extra output. + def really_verbose + case verbose + when true, false, nil then false + else true + end + end + + # to_yaml only overwrites things you can't override on the command line. + def to_yaml # :nodoc: + yaml_hash = {} + yaml_hash[:backtrace] = @hash.key?(:backtrace) ? @hash[:backtrace] : + DEFAULT_BACKTRACE + yaml_hash[:benchmark] = @hash.key?(:benchmark) ? @hash[:benchmark] : + DEFAULT_BENCHMARK + yaml_hash[:bulk_threshold] = @hash.key?(:bulk_threshold) ? + @hash[:bulk_threshold] : DEFAULT_BULK_THRESHOLD + yaml_hash[:sources] = Gem.sources + yaml_hash[:update_sources] = @hash.key?(:update_sources) ? + @hash[:update_sources] : DEFAULT_UPDATE_SOURCES + yaml_hash[:verbose] = @hash.key?(:verbose) ? @hash[:verbose] : + DEFAULT_VERBOSITY + + keys = yaml_hash.keys.map { |key| key.to_s } + keys << 'debug' + re = Regexp.union(*keys) + + @hash.each do |key, value| + key = key.to_s + next if key =~ re + yaml_hash[key.to_s] = value + end + + yaml_hash.to_yaml + end + + # Writes out this config file, replacing its source. + def write + File.open config_file_name, 'w' do |fp| + fp.write self.to_yaml + end + end + + # Return the configuration information for +key+. + def [](key) + @hash[key.to_s] + end + + # Set configuration option +key+ to +value+. + def []=(key, value) + @hash[key.to_s] = value + end + + def ==(other) # :nodoc: + self.class === other and + @backtrace == other.backtrace and + @benchmark == other.benchmark and + @bulk_threshold == other.bulk_threshold and + @verbose == other.verbose and + @update_sources == other.update_sources and + @hash == other.hash + end + + protected + + attr_reader :hash + +end + |