module QED # Settings ecapsulates setup code for running QED. # # By convention, configuration for QED is placed in `task/qed.rb`. # Configuration may also be placed at project root level in `qed.rb`, # or if you're old-school, a `.qed` hidden file can still be used. If you # don't like any of these choices, QED supports configuration file mapping # via the `.map` file. Just add a `qed: path/to/qed/config/file` entry. # # In this file special configuration setups can be placed to automatically # effect QED execution, in particular optional profiles can be defined. # # if ENV['cover'] # require 'simplecov' # SimpleCov.start do # coverage_dir 'log/coverage' # add_group "Shared" do |src_file| # /lib\/dotruby\/v(\d+)(.*?)$/ !~ src_file.filename # end # add_group "Revision 0", "lib/dotruby/v0" # end # end # class Settings # # Because QED usese the Confection library, but Confection also # uses QED for testing, a special configuration exception needed # be sliced out so Confection's test could run without QED using # it. We handle this via a environment variable `config`. Set # it to 'none' to deactivate the use of Confection. # def self.configless? ENV['config'] == 'none' end require 'tmpdir' require 'fileutils' require 'confection' unless configless? # If files are not specified than these directories # will be searched. DEFAULT_FILES = ['qed', 'demo', 'spec'] # QED support configuration file mapping. #MAP_FILE = '.map' # Glob pattern used to search for project's root directory. ROOT_PATTERN = '{.map,.ruby,.git/,.hg/,_darcs/}' # Glob pattern used to find QED configuration file relative to root directory. CONFIG_PATTERN = '{.,,task/}qed,qedfile{,.rb}' # Home directory. HOME = File.expand_path('~') # Directory names to omit from automatic selection. OMIT_PATHS = %w{applique helpers support sample samples fixture fixtures} # # # def initialize(files, options={}) @files = [files].flatten.compact @files = [DEFAULT_FILES.find{ |d| File.directory?(d) }] if @files.empty? @files = @files.compact @format = options[:format] || :dot @trace = options[:trace] || false @mode = options[:mode] || nil @profile = options[:profile] || :default @loadpath = options[:loadpath] || ['lib'] @requires = options[:requires] || [] @omit = OMIT_PATHS # TODO: eventually make configurable @rootless = options[:rootless] #@profiles = {} @root = @rootless ? system_tmpdir : find_root # Set global. TODO: find away to not need this ? $ROOT = @root initialize_configuration #profile = options[:profile] #confection(:qed, profile) end # # Because QED uses the Confection library, but Confection also # uses QED for testing, a special configuration exception needed # be sliced out so Confection's demos could run without QED using # it. We handle this via a `.qed` config file. Add this file # to a project and it will deactivate the use of Confection, # and load the contents of the file instead. # def initialize_configuration require 'confection' unless configless? end # Demonstration files (or globs). attr_reader :files # File patterns to omit. attr_accessor :omit # Output format. attr_accessor :format # Trace execution? attr_accessor :trace # Parse mode. attr_accessor :mode # Paths to be added to $LOAD_PATH. attr_reader :loadpath # Libraries to be required. attr_reader :requires # Operate from project root? attr_accessor :rooted # Selected profile. attr_accessor :profile # # If Environment varible is set to 'none' then COnfection will not be # used for configuration. # def configless? self.class.configless? end # # Operate relative to project root directory, or use system's location. # def rootless? @rootless end # # Project's root directory. # def root_directory @root end # # Shorthand for `#root_directory`. # alias_method :root, :root_directory # # Temporary directory. If `#rootless?` return true then this will be # a system's temporary directory (e.g. `/tmp/qed/foo/20111117242323/`). # Otherwise, it will local to the project's root int `tmp/qed/`. # def temporary_directory @temporary_directory ||= ( if rootless? system_tmpdir else File.join(root_directory, 'tmp', 'qed') end #FileUtils.mkdir_p(dir) unless File.directory?(dir) ) end # # Shorthand for `#temporary_directory`. # alias_method :tmpdir, :temporary_directory # # Remove and recreate temporary working directory. # def clear_directory FileUtils.rm_r(tmpdir) if File.exist?(tmpdir) FileUtils.mkdir_p(tmpdir) end # # Define a profile. # # @deprecated Confection library is used instead. # # @param [#to_s] name # Name of profile. # # @yield Procedure to run for profile. # # @return [Proc] The procedure. # #def profile(name, &block) # raise "The #profile method is deprecated." # #@profiles[name.to_s] = block #end # # Profiles are collected from the Confection library, unless # confection is deactivated via the override file. # def profiles return [] if configless? Confection.profiles(:qed) end =begin # # Keeps a list of defined profiles. # attr_accessor :profiles # Profile configurations. #def profiles # @profiles ||= ( # files = Dir["#{settings_directory}/*.rb"] # files.map do |file| # File.basename(file).chomp('.rb') # end # ) #end # # Load QED profile (from -e option). # def load_profile(name) if profile = profiles[name.to_s] instance_eval(&profile) #eval('self', TOPLEVEL_BINDING).instance_eval(&prof) end #return unless settings_directory #if file = Dir["#{settings_directory}/#{profile}.rb"].first # require(file) #end end =end # # Load QED configuration profile. QED configurations are defined # via standards of the Confection library, unless otherwise # deativated via the `.qed` file. # def load_profile(profile) return if configless? config = confection(:qed, profile.to_sym) config.exec end # # Locate project's root directory. This is done by searching upward # in the file heirarchy for the existence of one of the following: # # .map # .ruby # .git/ # .hg/ # _darcs/ # .qed # .qed.rb # qed.rb # # Failing to find any of these locations, resort to the fallback: # # lib/ # # If that isn't found, then returns a temporary system location. # and sets `rootless` to true. # def find_root(path=nil) path = File.expand_path(path || Dir.pwd) path = File.dirname(path) unless File.directory?(path) root = lookup(ROOT_PATTERN, path) || lookup(CONFIG_PATTERN, path) return root if root #root = lookup(path, '{qed,demo,spec}/') #return root if root root = lookup('lib/', path) if !root warn "QED is running rootless." root = system_tmpdir @rootless = true end return root #abort "QED failed to resolve project's root location.\n" + # "QED looks for following entries to identify the root:\n" + # ROOT_PATTERN + # "Please add one of them to your project to proceed." end # TODO: Use Dir.ascend from Ruby Facets. # # Lookup path +glob+, searching each higher directory # in turn until just before the users home directory # is reached or just before the system's root directory. # def lookup(glob, path=Dir.pwd) until path == HOME or path == '/' # until home or root mark = Dir.glob(File.join(path,glob), File::FNM_CASEFOLD).first return path if mark path = File.dirname(path) end end # # System-wide temporary directory for QED executation. # def system_tmpdir @system_tmpdir ||= ( File.join(Dir.tmpdir, 'qed', File.basename(Dir.pwd), Time.new.strftime("%Y%m%d%H%M%S")) ) end # # Lookup, cache and return QED config file. # def config_override @config_override ||= ( Dir.glob(File.join(root_directory, '.qed')).first ) end ## ## Return cached file map from a project's `.map` file, if it exists. ## #def file_map # @file_map ||= ( # if File.exist?(map_file) # YAML.load_file(map_file) # else # {} # end # ) #end ## ## Lookup, cache and return `.map` map file. ## #def map_file # @_map_file ||= File.join(root_directory,MAP_FILE) #end end end