class Rake::Application
Rake main application object. When invoking rake
from the
command line, a Rake::Application object is
created and run.
Constants
- DEFAULT_RAKEFILES
Attributes
The name of the application (typically 'rake')
The original directory where rake was invoked.
Name of the actual rakefile used.
Number of columns on the terminal
List of the top level task names (task names from the command line).
Public Class Methods
Initialize a Rake::Application object.
# File lib/rake/application.rb, line 46 def initialize super @name = 'rake' @rakefiles = DEFAULT_RAKEFILES.dup @rakefile = nil @pending_imports = [] @imported = [] @loaders = {} @default_loader = Rake::DefaultLoader.new @original_dir = Dir.pwd @top_level_tasks = [] add_loader('rb', DefaultLoader.new) add_loader('rf', DefaultLoader.new) add_loader('rake', DefaultLoader.new) @tty_output = STDOUT.tty? @terminal_columns = ENV['RAKE_COLUMNS'].to_i end
Public Instance Methods
Add a file to the list of files to be imported.
# File lib/rake/application.rb, line 699 def add_import(fn) @pending_imports << fn end
Add a loader to handle imported files ending in the extension
ext
.
# File lib/rake/application.rb, line 129 def add_loader(ext, loader) ext = ".#{ext}" unless ext =~ /^\./ @loaders[ext] = loader end
Collect the list of tasks on the command line. If no tasks are given, return a list containing only the default task. Environmental assignments are processed at this time as well.
# File lib/rake/application.rb, line 680 def collect_tasks @top_level_tasks = [] ARGV.each do |arg| if arg =~ /^(\w+)=(.*)$/m ENV[$1] = $2 else @top_level_tasks << arg unless arg =~ /^-/ end end @top_level_tasks.push(default_task_name) if @top_level_tasks.empty? end
Default task name (“default”). (May be overridden by subclasses)
# File lib/rake/application.rb, line 694 def default_task_name "default" end
Warn about deprecated usage.
Example:
Rake.application.deprecate("import", "Rake.import", caller.first)
# File lib/rake/application.rb, line 203 def deprecate(old_usage, new_usage, call_site) unless options.ignore_deprecate $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + "Please use '#{new_usage}' instead.\n" + " at #{call_site}" end end
Display the error message that caused the exception.
# File lib/rake/application.rb, line 185 def display_error_message(ex) trace "#{name} aborted!" trace ex.message if options.backtrace trace ex.backtrace.join("\n") else trace Backtrace.collapse(ex.backtrace).join("\n") end trace "Tasks: #{ex.chain}" if has_chain?(ex) trace "(See full trace by running task with --trace)" unless options.backtrace end
Display the tasks and prerequisites
# File lib/rake/application.rb, line 331 def display_prerequisites tasks.each do |t| puts "#{name} #{t.name}" t.prerequisites.each { |pre| puts " #{pre}" } end end
Display the tasks and comments.
# File lib/rake/application.rb, line 248 def display_tasks_and_comments displayable_tasks = tasks.select { |t| (options.show_all_tasks || t.comment) && t.name =~ options.show_task_pattern } case options.show_tasks when :tasks width = displayable_tasks.map { |t| t.name_with_args.length }.max || 10 if truncate_output? max_column = terminal_width - name.size - width - 7 else max_column = nil end displayable_tasks.each do |t| printf("#{name} %-#{width}s # %s\n", t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment) end when :describe displayable_tasks.each do |t| puts "#{name} #{t.name_with_args}" comment = t.full_comment || "" comment.split("\n").each do |line| puts " #{line}" end puts end when :lines displayable_tasks.each do |t| t.locations.each do |loc| printf "#{name} %-30s %s\n", t.name_with_args, loc end end else fail "Unknown show task mode: '#{options.show_tasks}'" end end
Calculate the dynamic width of the
# File lib/rake/application.rb, line 299 def dynamic_width @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) end
# File lib/rake/application.rb, line 303 def dynamic_width_stty %x{stty size 2>/dev/null}.split[1].to_i end
# File lib/rake/application.rb, line 307 def dynamic_width_tput %x{tput cols 2>/dev/null}.to_i end
Exit the program because of an unhandle exception. (may be overridden by subclasses)
# File lib/rake/application.rb, line 180 def exit_because_of_exception(ex) exit(false) end
# File lib/rake/application.rb, line 605 def find_rakefile_location here = Dir.pwd until (fn = have_rakefile) Dir.chdir("..") return nil if Dir.pwd == here || options.nosearch here = Dir.pwd end [fn, here] ensure Dir.chdir(Rake.original_dir) end
Read and handle the command line options.
# File lib/rake/application.rb, line 570 def handle_options options.rakelib = ['rakelib'] options.trace_output = $stderr OptionParser.new do |opts| opts.banner = "#{Rake.application.name} [-f rakefile] {options} targets..." opts.separator "" opts.separator "Options are ..." opts.on_tail("-h", "--help", "-H", "Display this help message.") do puts opts exit end standard_rake_options.each { |args| opts.on(*args) } opts.environment('RAKEOPT') end.parse! end
True if one of the files in RAKEFILES is in the current directory. If a match is found, it is copied into @rakefile.
# File lib/rake/application.rb, line 219 def have_rakefile @rakefiles.each do |fn| if File.exist?(fn) others = FileList.glob(fn, File::FNM_CASEFOLD) return others.size == 1 ? others.first : fn elsif fn == '' return fn end end return nil end
Initialize the command line parameters and app name.
# File lib/rake/application.rb, line 83 def init(app_name='rake') standard_exception_handling do @name = app_name handle_options collect_tasks end end
private —————————————————————-
# File lib/rake/application.rb, line 146 def invoke_task(task_string) name, args = parse_task_string(task_string) t = self[name] t.invoke(*args) end
Load the pending list of imported files.
# File lib/rake/application.rb, line 704 def load_imports while fn = @pending_imports.shift next if @imported.member?(fn) fn_task = lookup(fn) and fn_task.invoke ext = File.extname(fn) loader = @loaders[ext] || @default_loader loader.load(fn) @imported << fn end end
Find the rakefile and then load it and any pending imports.
# File lib/rake/application.rb, line 92 def load_rakefile standard_exception_handling do raw_load_rakefile end end
Application options from the command line
# File lib/rake/application.rb, line 135 def options @options ||= OpenStruct.new end
# File lib/rake/application.rb, line 152 def parse_task_string(string) if string =~ /^([^\[]+)(\[(.*)\])$/ name = $1 args = $3.split(/\s*,\s*/) else name = string args = [] end [name, args] end
# File lib/rake/application.rb, line 617 def print_rakefile_directory(location) $stderr.puts "(in #{Dir.pwd})" unless options.silent or original_dir == location end
Similar to the regular Ruby require
command, but will check
for *.rake files in addition to *.rb files.
# File lib/rake/application.rb, line 591 def rake_require(file_name, paths=$LOAD_PATH, loaded=$") fn = file_name + ".rake" return false if loaded.include?(fn) paths.each do |path| full_path = File.join(path, fn) if File.exist?(full_path) Rake.load_rakefile(full_path) loaded << fn return true end end fail LoadError, "Can't find #{file_name}" end
# File lib/rake/application.rb, line 715 def rakefile_location(backtrace=caller) backtrace.map { |t| t[/([^:]+):/, 1] } re = /^#{@rakefile}$/ re = /#{re.source}/i if windows? backtrace.find { |str| str =~ re } || '' end
Run the Rake application. The run method performs the following three steps:
-
Initialize the command line options (
init
). -
Define the tasks (
load_rakefile
). -
Run the top level tasks (
top_level
).
If you wish to build a custom rake command, you should call
init
on your application. Then define any tasks. Finally,
call top_level
to run your top level tasks.
# File lib/rake/application.rb, line 74 def run standard_exception_handling do init load_rakefile top_level end end
Run the given block with the thread startup and shutdown.
# File lib/rake/application.rb, line 112 def run_with_threads thread_pool.gather_history if options.job_stats == :history yield thread_pool.join if options.job_stats stats = thread_pool.statistics puts "Maximum active threads: #{stats[:max_active_threads]}" puts "Total threads in play: #{stats[:total_threads_in_play]}" end ThreadHistoryDisplay.new(thread_pool.history).show if options.job_stats == :history end
Provide standard exception handling for the given block.
# File lib/rake/application.rb, line 164 def standard_exception_handling yield rescue SystemExit # Exit silently with current status raise rescue OptionParser::InvalidOption => ex $stderr.puts ex.message exit(false) rescue Exception => ex # Exit with error message display_error_message(ex) exit_because_of_exception(ex) end
A list of all the standard options used in rake, suitable for passing to OptionParser.
# File lib/rake/application.rb, line 352 def standard_rake_options sort_options( [ ['--all', '-A', "Show all tasks, even uncommented ones", lambda { |value| options.show_all_tasks = value } ], ['--backtrace=[OUT]', "Enable full backtrace. OUT can be stderr (default) or stdout.", lambda { |value| options.backtrace = true select_trace_output(options, 'backtrace', value) } ], ['--comments', "Show commented tasks only", lambda { |value| options.show_all_tasks = !value } ], ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :describe, value) } ], ['--dry-run', '-n', "Do a dry run without executing actions.", lambda { |value| Rake.verbose(true) Rake.nowrite(true) options.dryrun = true options.trace = true } ], ['--execute', '-e CODE', "Execute some Ruby code and exit.", lambda { |value| eval(value) exit } ], ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.", lambda { |value| puts eval(value) exit } ], ['--execute-continue', '-E CODE', "Execute some Ruby code, " + "then continue with normal task processing.", lambda { |value| eval(value) } ], ['--jobs', '-j [NUMBER]', "Specifies the maximum number of tasks to execute in parallel. " + "(default is 2)", lambda { |value| options.thread_pool_size = [(value || 2).to_i, 2].max } ], ['--job-stats [LEVEL]', "Display job statistics. " + "LEVEL=history displays a complete job list", lambda { |value| if value =~ /^history/i options.job_stats = :history else options.job_stats = true end } ], ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.", lambda { |value| $:.push(value) } ], ['--multitask', '-m', "Treat all tasks as multitasks.", lambda { |value| options.always_multitask = true } ], ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.", lambda { |value| options.nosearch = true } ], ['--prereqs', '-P', "Display the tasks and dependencies, then exit.", lambda { |value| options.show_prereqs = true } ], ['--quiet', '-q', "Do not log messages to standard output.", lambda { |value| Rake.verbose(false) } ], ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.", lambda { |value| value ||= '' @rakefiles.clear @rakefiles << value } ], ['--rakelibdir', '--rakelib', '-R RAKELIBDIR', "Auto-import any .rake files in RAKELIBDIR. " + "(default is 'rakelib')", lambda { |value| options.rakelib = value.split(File::PATH_SEPARATOR) } ], ['--require', '-r MODULE', "Require MODULE before executing rakefile.", lambda { |value| begin require value rescue LoadError => ex begin rake_require value rescue LoadError raise ex end end } ], ['--rules', "Trace the rules resolution.", lambda { |value| options.trace_rules = true } ], ['--silent', '-s', "Like --quiet, but also suppresses the " + "'in directory' announcement.", lambda { |value| Rake.verbose(false) options.silent = true } ], ['--suppress-backtrace PATTERN', "Suppress backtrace lines matching regexp PATTERN. " + "Ignored if --trace is on.", lambda { |value| options.suppress_backtrace_pattern = Regexp.new(value) } ], ['--system', '-g', "Using system wide (global) rakefiles " + "(usually '~/.rake/*.rake').", lambda { |value| options.load_system = true } ], ['--no-system', '--nosystem', '-G', "Use standard project Rakefile search paths, " + "ignore system wide rakefiles.", lambda { |value| options.ignore_system = true } ], ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) " + "with descriptions, then exit.", lambda { |value| select_tasks_to_show(options, :tasks, value) } ], ['--trace=[OUT]', '-t', "Turn on invoke/execute tracing, enable full backtrace. " + "OUT can be stderr (default) or stdout.", lambda { |value| options.trace = true options.backtrace = true select_trace_output(options, 'trace', value) Rake.verbose(true) } ], ['--verbose', '-v', "Log message to standard output.", lambda { |value| Rake.verbose(true) } ], ['--version', '-V', "Display the program version.", lambda { |value| puts "rake, version #{RAKEVERSION}" exit } ], ['--where', '-W [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", lambda { |value| select_tasks_to_show(options, :lines, value) options.show_all_tasks = true } ], ['--no-deprecation-warnings', '-X', "Disable the deprecation warnings.", lambda { |value| options.ignore_deprecate = true } ], ]) end
The directory path containing the system wide rakefiles.
# File lib/rake/application.rb, line 654 def system_dir @system_dir ||= begin if ENV['RAKE_SYSTEM'] ENV['RAKE_SYSTEM'] else standard_system_dir end end end
# File lib/rake/application.rb, line 287 def terminal_width if @terminal_columns.nonzero? result = @terminal_columns else result = unix? ? dynamic_width : 80 end (result < 10) ? 80 : result rescue 80 end
Run the top level tasks of a Rake application.
# File lib/rake/application.rb, line 99 def top_level run_with_threads do if options.show_tasks display_tasks_and_comments elsif options.show_prereqs display_prerequisites else top_level_tasks.each { |task_name| invoke_task(task_name) } end end end
# File lib/rake/application.rb, line 338 def trace(*strings) options.trace_output ||= $stderr trace_on(options.trace_output, *strings) end
# File lib/rake/application.rb, line 320 def truncate(string, width) if string.nil? "" elsif string.length <= width string else (string[0, width - 3] || "") + "..." end end
We will truncate output if we are outputting to a TTY or if we've been given an explicit column width to honor
# File lib/rake/application.rb, line 243 def truncate_output? tty_output? || @terminal_columns.nonzero? end
Override the detected TTY output state (mostly for testing)
# File lib/rake/application.rb, line 237 def tty_output=(tty_output_state) @tty_output = tty_output_state end
True if we are outputting to TTY, false otherwise
# File lib/rake/application.rb, line 232 def tty_output? @tty_output end
# File lib/rake/application.rb, line 311 def unix? RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i end
# File lib/rake/application.rb, line 316 def windows? Win32.windows? end
Private Instance Methods
# File lib/rake/application.rb, line 648 def glob(path, &block) FileList.glob(path.gsub("\\", '/')).each(&block) end
Does the exception have a task invocation chain?
# File lib/rake/application.rb, line 212 def has_chain?(exception) exception.respond_to?(:chain) && exception.chain end
# File lib/rake/application.rb, line 548 def select_tasks_to_show(options, show_tasks, value) options.show_tasks = show_tasks options.show_task_pattern = Regexp.new(value || '') Rake::TaskManager.record_task_metadata = true end
# File lib/rake/application.rb, line 555 def select_trace_output(options, trace_option, value) value = value.strip unless value.nil? case value when 'stdout' options.trace_output = $stdout when 'stderr', nil options.trace_output = $stderr else fail CommandLineOptionError, "Unrecognized --#{trace_option} option '#{value}'" end end
# File lib/rake/application.rb, line 343 def sort_options(options) options.sort_by { |opt| opt.select { |o| o =~ /^-/ }.map { |o| o.downcase }.sort.reverse } end