require'erb'require'shellwords'moduleRSpecmoduleCore# Responsible for utilizing externally provided configuration options,# whether via the command line, `.rspec`, `~/.rspec`,# `$XDG_CONFIG_HOME/rspec/options`, `.rspec-local` or a custom options# file.classConfigurationOptions# @param args [Array<String>] command line argumentsdefinitialize(args)@args=args.duporganize_optionsend# Updates the provided {Configuration} instance based on the provided# external configuration options.## @param config [Configuration] the configuration instance to updatedefconfigure(config)process_options_intoconfigconfigure_filter_managerconfig.filter_managerload_formatters_intoconfigend# @api private# Updates the provided {FilterManager} based on the filter options.# @param filter_manager [FilterManager] instance to updatedefconfigure_filter_manager(filter_manager)@filter_manager_options.eachdo|command,value|filter_manager.__send__command,valueendend# @return [Hash] the final merged options, drawn from all external sourcesattr_reader:options# @return [Array<String>] the original command-line argumentsattr_reader:argsprivatedeforganize_options@filter_manager_options=[]@options=(file_options<<command_line_options<<env_options).eachdo|opts|@filter_manager_options<<[:include,opts.delete(:inclusion_filter)]ifopts.key?(:inclusion_filter)@filter_manager_options<<[:exclude,opts.delete(:exclusion_filter)]ifopts.key?(:exclusion_filter)end@options=@options.inject(:libs=>[],:requires=>[])do|hash,opts|hash.merge(opts)do|key,oldval,newval|[:libs,:requires].include?(key)?oldval+newval:newvalendendendUNFORCED_OPTIONS=Set.new([:requires,:profile,:drb,:libs,:files_or_directories_to_run,:full_description,:full_backtrace,:tty])UNPROCESSABLE_OPTIONS=Set.new([:formatters])defforce?(key)!UNFORCED_OPTIONS.include?(key)enddeforder(keys)OPTIONS_ORDER.reverse_eachdo|key|keys.unshift(key)ifkeys.delete(key)endkeysendOPTIONS_ORDER=[# It's important to set this before anything that might issue a# deprecation (or otherwise access the reporter).:deprecation_stream,# load paths depend on nothing, but must be set before `requires`# to support load-path-relative requires.:libs,# `files_or_directories_to_run` uses `default_path` so it must be# set before it.:default_path,:only_failures,# These must be set before `requires` to support checking# `config.files_to_run` from within `spec_helper.rb` when a# `-rspec_helper` option is used.:files_or_directories_to_run,:pattern,:exclude_pattern,# Necessary so that the `--seed` option is applied before requires,# in case required files do something with the provided seed.# (such as seed global randomization with it).:order,# In general, we want to require the specified files as early as# possible. The `--require` option is specifically intended to allow# early requires. For later requires, they can just put the require in# their spec files, but `--require` provides a unique opportunity for# users to instruct RSpec to load an extension file early for maximum# flexibility.:requires]defprocess_options_into(config)opts=options.reject{|k,_|UNPROCESSABLE_OPTIONS.include?k}order(opts.keys).eachdo|key|force?(key)?config.force(key=>opts[key]):config.__send__("#{key}=",opts[key])endenddefload_formatters_into(config)options[:formatters].each{|pair|config.add_formatter(*pair)}ifoptions[:formatters]enddeffile_optionsifcustom_options_file[custom_options]else[global_options,project_options,local_options]endenddefenv_optionsreturn{}unlessENV['SPEC_OPTS']parse_args_ignoring_files_or_dirs_to_run(Shellwords.split(ENV["SPEC_OPTS"]),"ENV['SPEC_OPTS']")enddefcommand_line_options@command_line_options||=Parser.parse(@args)enddefcustom_optionsoptions_from(custom_options_file)enddeflocal_options@local_options||=options_from(local_options_file)enddefproject_options@project_options||=options_from(project_options_file)enddefglobal_options@global_options||=options_from(global_options_file)enddefoptions_from(path)args=args_from_options_file(path)parse_args_ignoring_files_or_dirs_to_run(args,path)enddefparse_args_ignoring_files_or_dirs_to_run(args,source)options=Parser.parse(args,source)options.delete(:files_or_directories_to_run)optionsenddefargs_from_options_file(path)return[]unlesspath&&File.exist?(path)config_string=options_file_as_erb_string(path)FlatMap.flat_map(config_string.split(/\n+/),&:shellsplit)enddefoptions_file_as_erb_string(path)ifRUBY_VERSION>='2.6'ERB.new(File.read(path),:trim_mode=>'-').result(binding)elseERB.new(File.read(path),nil,'-').result(binding)endenddefcustom_options_filecommand_line_options[:custom_options_file]enddefproject_options_file"./.rspec"enddeflocal_options_file"./.rspec-local"enddefglobal_options_filexdg_options_file_if_exists||home_options_file_pathenddefxdg_options_file_if_existspath=xdg_options_file_pathifpath&&File.exist?(path)pathendenddefhome_options_file_pathFile.join(File.expand_path("~"),".rspec")rescueArgumentError# :nocov:RSpec.warning"Unable to find ~/.rspec because the HOME environment variable is not set"nil# :nocov:enddefxdg_options_file_pathxdg_config_home=resolve_xdg_config_homeifxdg_config_homeFile.join(xdg_config_home,"rspec","options")endenddefresolve_xdg_config_homeFile.expand_path(ENV.fetch("XDG_CONFIG_HOME","~/.config"))rescueArgumentError# :nocov:# On Ruby 2.4, `File.expand("~")` works even if `ENV['HOME']` is not set.# But on earlier versions, it fails.nil# :nocov:endendendend