Rake main application object. When invoking rake from the command line, a Rake::Application object is created and run.
Methods
Public Reader
Public Class
Public Instance
- run
- init
- load_rakefile
- top_level
- add_loader
- options
- invoke_task
- parse_task_string
- standard_exception_handling
- display_error_message
- deprecate
- have_rakefile
- tty_output?
- tty_output=
- truncate_output?
- display_tasks_and_comments
- terminal_width
- dynamic_width
- dynamic_width_stty
- dynamic_width_tput
- unix?
- windows?
- truncate
- display_prerequisites
- standard_rake_options
- handle_options
- rake_require
- find_rakefile_location
- print_rakefile_directory
- system_dir
- collect_tasks
- add_import
- load_imports
- const_warning
- rakefile_location
Private Instance
Included modules
- TaskManager
Classes and Modules
- Options
Constants
DEFAULT_RAKEFILES | = | ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze |
Attributes
name | [R] |
The name of the application (typically ‘rake’) |
original_dir | [R] |
The original directory where rake was invoked. |
rakefile | [R] |
Name of the actual rakefile used. |
top_level_tasks | [R] |
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 31 31: def initialize 32: super 33: @name = 'rake' 34: @rakefiles = DEFAULT_RAKEFILES.dup 35: @rakefile = nil 36: @pending_imports = [] 37: @imported = [] 38: @loaders = {} 39: @default_loader = Rake::DefaultLoader.new 40: @original_dir = Dir.pwd 41: @top_level_tasks = [] 42: add_loader('rb', DefaultLoader.new) 43: add_loader('rf', DefaultLoader.new) 44: add_loader('rake', DefaultLoader.new) 45: @tty_output = STDOUT.tty? 46: end
Public Instance methods
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 (run_tasks).
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 58 58: def run 59: standard_exception_handling do 60: init 61: load_rakefile 62: top_level 63: end 64: end
Initialize the command line parameters and app name.
# File lib/rake/application.rb, line 67 67: def init(app_name='rake') 68: standard_exception_handling do 69: @name = app_name 70: handle_options 71: collect_tasks 72: end 73: end
Find the rakefile and then load it and any pending imports.
# File lib/rake/application.rb, line 76 76: def load_rakefile 77: standard_exception_handling do 78: raw_load_rakefile 79: end 80: end
Run the top level tasks of a Rake application.
# File lib/rake/application.rb, line 83 83: def top_level 84: standard_exception_handling do 85: if options.show_tasks 86: display_tasks_and_comments 87: elsif options.show_prereqs 88: display_prerequisites 89: else 90: top_level_tasks.each { |task_name| invoke_task(task_name) } 91: end 92: end 93: end
Add a loader to handle imported files ending in the extension ext.
# File lib/rake/application.rb, line 97 97: def add_loader(ext, loader) 98: ext = ".#{ext}" unless ext =~ /^\./ 99: @loaders[ext] = loader 100: end
Application options from the command line
# File lib/rake/application.rb, line 103 103: def options 104: @options ||= Options.new 105: end
private —————————————————————-
# File lib/rake/application.rb, line 109 109: def invoke_task(task_string) 110: name, args = parse_task_string(task_string) 111: t = self[name] 112: t.invoke(*args) 113: end
# File lib/rake/application.rb, line 115 115: def parse_task_string(string) 116: if string =~ /^([^\[]+)(\[(.*)\])$/ 117: name = $1 118: args = $3.split(/\s*,\s*/) 119: else 120: name = string 121: args = [] 122: end 123: [name, args] 124: end
Provide standard exception handling for the given block.
# File lib/rake/application.rb, line 127 127: def standard_exception_handling 128: begin 129: yield 130: rescue SystemExit => ex 131: # Exit silently with current status 132: raise 133: rescue OptionParser::InvalidOption => ex 134: $stderr.puts ex.message 135: exit(false) 136: rescue Exception => ex 137: # Exit with error message 138: display_error_message(ex) 139: exit(false) 140: end 141: end
Display the error message that caused the exception.
# File lib/rake/application.rb, line 144 144: def display_error_message(ex) 145: $stderr.puts "#{name} aborted!" 146: $stderr.puts ex.message 147: if options.trace 148: $stderr.puts ex.backtrace.join("\n") 149: else 150: $stderr.puts rakefile_location(ex.backtrace) 151: end 152: $stderr.puts "Tasks: #{ex.chain}" if has_chain?(ex) 153: $stderr.puts "(See full trace by running task with --trace)" unless options.trace 154: end
Warn about deprecated usage.
Example:
Rake.application.deprecate("import", "Rake.import", caller.first)
# File lib/rake/application.rb, line 161 161: def deprecate(old_usage, new_usage, call_site) 162: return if options.ignore_deprecate 163: $stderr.puts "WARNING: '#{old_usage}' is deprecated. " + 164: "Please use '#{new_usage}' instead.\n" + 165: " at #{call_site}" 166: 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 176 176: def have_rakefile 177: @rakefiles.each do |fn| 178: if File.exist?(fn) 179: others = Dir.glob(fn, File::FNM_CASEFOLD) 180: return others.size == 1 ? others.first : fn 181: elsif fn == '' 182: return fn 183: end 184: end 185: return nil 186: end
True if we are outputting to TTY, false otherwise
# File lib/rake/application.rb, line 189 189: def tty_output? 190: @tty_output 191: end
Override the detected TTY output state (mostly for testing)
# File lib/rake/application.rb, line 194 194: def tty_output=( tty_output_state ) 195: @tty_output = tty_output_state 196: 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 200 200: def truncate_output? 201: tty_output? || ENV['RAKE_COLUMNS'] 202: end
Display the tasks and comments.
# File lib/rake/application.rb, line 205 205: def display_tasks_and_comments 206: displayable_tasks = tasks.select { |t| 207: t.comment && t.name =~ options.show_task_pattern 208: } 209: case options.show_tasks 210: when :tasks 211: width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10 212: max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil 213: displayable_tasks.each do |t| 214: printf "#{name} %-#{width}s # %s\n", 215: t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment 216: end 217: when :describe 218: displayable_tasks.each do |t| 219: puts "#{name} #{t.name_with_args}" 220: t.full_comment.split("\n").each do |line| 221: puts " #{line}" 222: end 223: puts 224: end 225: when :lines 226: displayable_tasks.each do |t| 227: t.locations.each do |loc| 228: printf "#{name} %-30s %s\n",t.name_with_args, loc 229: end 230: end 231: else 232: fail "Unknown show task mode: '#{options.show_tasks}'" 233: end 234: end
# File lib/rake/application.rb, line 236 236: def terminal_width 237: if ENV['RAKE_COLUMNS'] 238: result = ENV['RAKE_COLUMNS'].to_i 239: else 240: result = unix? ? dynamic_width : 80 241: end 242: (result < 10) ? 80 : result 243: rescue 244: 80 245: end
Calculate the dynamic width of the
# File lib/rake/application.rb, line 248 248: def dynamic_width 249: @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput) 250: end
# File lib/rake/application.rb, line 252 252: def dynamic_width_stty 253: %{stty size 2>/dev/null}.split[1].to_i 254: end
# File lib/rake/application.rb, line 256 256: def dynamic_width_tput 257: %{tput cols 2>/dev/null}.to_i 258: end
# File lib/rake/application.rb, line 260 260: def unix? 261: RbConfig::CONFIG['host_os'] =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/ 262: end
# File lib/rake/application.rb, line 264 264: def windows? 265: Win32.windows? 266: end
# File lib/rake/application.rb, line 268 268: def truncate(string, width) 269: if string.length <= width 270: string 271: else 272: ( string[0, width-3] || "" ) + "..." 273: end 274: end
Display the tasks and prerequisites
# File lib/rake/application.rb, line 277 277: def display_prerequisites 278: tasks.each do |t| 279: puts "#{name} #{t.name}" 280: t.prerequisites.each { |pre| puts " #{pre}" } 281: end 282: end
A list of all the standard options used in rake, suitable for passing to OptionParser.
# File lib/rake/application.rb, line 286 286: def standard_rake_options 287: [ 288: ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace", 289: lambda { |value| 290: require 'rake/classic_namespace' 291: options.classic_namespace = true 292: } 293: ], 294: ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", 295: lambda { |value| 296: options.show_tasks = :describe 297: options.show_task_pattern = Regexp.new(value || '') 298: TaskManager.record_task_metadata = true 299: } 300: ], 301: ['--dry-run', '-n', "Do a dry run without executing actions.", 302: lambda { |value| 303: Rake.verbose(true) 304: Rake.nowrite(true) 305: options.dryrun = true 306: options.trace = true 307: } 308: ], 309: ['--execute', '-e CODE', "Execute some Ruby code and exit.", 310: lambda { |value| 311: eval(value) 312: exit 313: } 314: ], 315: ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.", 316: lambda { |value| 317: puts eval(value) 318: exit 319: } 320: ], 321: ['--execute-continue', '-E CODE', 322: "Execute some Ruby code, then continue with normal task processing.", 323: lambda { |value| eval(value) } 324: ], 325: ['--threads', '-j [N]', Integer, "Run up to N tasks simultaneously; without N (or N=0), no limit.", 326: lambda { |value| 327: # nil.to_i == 0, which means unlimited threads 328: options.threads = value.to_i 329: } 330: ], 331: ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.", 332: lambda { |value| $:.push(value) } 333: ], 334: ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.", 335: lambda { |value| options.nosearch = true } 336: ], 337: ['--prereqs', '-P', "Display the tasks and dependencies, then exit.", 338: lambda { |value| options.show_prereqs = true } 339: ], 340: ['--quiet', '-q', "Do not log messages to standard output.", 341: lambda { |value| Rake.verbose(false) } 342: ], 343: ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.", 344: lambda { |value| 345: value ||= '' 346: @rakefiles.clear 347: @rakefiles << value 348: } 349: ], 350: ['--rakelibdir', '--rakelib', '-R RAKELIBDIR', 351: "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')", 352: lambda { |value| options.rakelib = value.split(':') } 353: ], 354: ['--randomize[=SEED]', Integer, "Randomize the order of sibling prerequisites.", 355: lambda { |value| 356: MultiTask.class_eval { remove_method(:invoke_prerequisites) } 357: options.randomize = value || (srand ; srand % 10_000) 358: srand options.randomize 359: at_exit do 360: $stderr.puts "Run options: --randomize=#{options.randomize}" 361: end 362: } 363: ], 364: ['--require', '-r MODULE', "Require MODULE before executing rakefile.", 365: lambda { |value| 366: begin 367: require value 368: rescue LoadError => ex 369: begin 370: rake_require value 371: rescue LoadError 372: raise ex 373: end 374: end 375: } 376: ], 377: ['--rules', "Trace the rules resolution.", 378: lambda { |value| options.trace_rules = true } 379: ], 380: ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.", 381: lambda { |value| 382: Rake.verbose(false) 383: options.silent = true 384: } 385: ], 386: ['--system', '-g', 387: "Using system wide (global) rakefiles (usually '~/.rake/*.rake').", 388: lambda { |value| options.load_system = true } 389: ], 390: ['--no-system', '--nosystem', '-G', 391: "Use standard project Rakefile search paths, ignore system wide rakefiles.", 392: lambda { |value| options.ignore_system = true } 393: ], 394: ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.", 395: lambda { |value| 396: options.show_tasks = :tasks 397: options.show_task_pattern = Regexp.new(value || '') 398: Rake::TaskManager.record_task_metadata = true 399: } 400: ], 401: ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.", 402: lambda { |value| 403: options.trace = true 404: Rake.verbose(true) 405: } 406: ], 407: ['--verbose', '-v', "Log message to standard output.", 408: lambda { |value| Rake.verbose(true) } 409: ], 410: ['--version', '-V', "Display the program version.", 411: lambda { |value| 412: puts "drake, version #{RAKEVERSION}" 413: exit 414: } 415: ], 416: ['--where', '-W [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.", 417: lambda { |value| 418: options.show_tasks = :lines 419: options.show_task_pattern = Regexp.new(value || '') 420: Rake::TaskManager.record_task_metadata = true 421: } 422: ], 423: ['--no-deprecation-warnings', '-X', "Disable the deprecation warnings.", 424: lambda { |value| 425: options.ignore_deprecate = true 426: } 427: ], 428: ] 429: end
Read and handle the command line options.
# File lib/rake/application.rb, line 432 432: def handle_options 433: options.rakelib = ['rakelib'] 434: 435: OptionParser.new do |opts| 436: opts.banner = "drake [-f rakefile] {options} targets..." 437: opts.separator "" 438: opts.separator "Options are ..." 439: 440: opts.on_tail("-h", "--help", "-H", "Display this help message.") do 441: puts opts 442: exit 443: end 444: 445: standard_rake_options.each { |args| opts.on(*args) } 446: opts.environment('RAKEOPT') 447: end.parse! 448: 449: # If class namespaces are requested, set the global options 450: # according to the values in the options structure. 451: if options.classic_namespace 452: $show_tasks = options.show_tasks 453: $show_prereqs = options.show_prereqs 454: $trace = options.trace 455: $dryrun = options.dryrun 456: $silent = options.silent 457: end 458: 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 462 462: def rake_require(file_name, paths=$LOAD_PATH, loaded=$") 463: fn = file_name + ".rake" 464: return false if loaded.include?(fn) 465: paths.each do |path| 466: full_path = File.join(path, fn) 467: if File.exist?(full_path) 468: Rake.load_rakefile(full_path) 469: loaded << fn 470: return true 471: end 472: end 473: fail LoadError, "Can't find #{file_name}" 474: end
# File lib/rake/application.rb, line 476 476: def find_rakefile_location 477: here = Dir.pwd 478: while ! (fn = have_rakefile) 479: Dir.chdir("..") 480: if Dir.pwd == here || options.nosearch 481: return nil 482: end 483: here = Dir.pwd 484: end 485: [fn, here] 486: ensure 487: Dir.chdir(Rake.original_dir) 488: end
# File lib/rake/application.rb, line 490 490: def print_rakefile_directory(location) 491: $stderr.puts "(in #{Dir.pwd})" unless 492: options.silent or original_dir == location 493: end
The directory path containing the system wide rakefiles.
# File lib/rake/application.rb, line 527 527: def system_dir 528: @system_dir ||= 529: begin 530: if ENV['RAKE_SYSTEM'] 531: ENV['RAKE_SYSTEM'] 532: else 533: standard_system_dir 534: end 535: end 536: 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 553 553: def collect_tasks 554: @top_level_tasks = [] 555: ARGV.each do |arg| 556: if arg =~ /^(\w+)=(.*)$/ 557: ENV[$1] = $2 558: else 559: @top_level_tasks << arg unless arg =~ /^-/ 560: end 561: end 562: @top_level_tasks.push("default") if @top_level_tasks.size == 0 563: end
Add a file to the list of files to be imported.
# File lib/rake/application.rb, line 566 566: def add_import(fn) 567: @pending_imports << fn 568: end
Load the pending list of imported files.
# File lib/rake/application.rb, line 571 571: def load_imports 572: while fn = @pending_imports.shift 573: next if @imported.member?(fn) 574: if fn_task = lookup(fn) 575: fn_task.invoke 576: end 577: ext = File.extname(fn) 578: loader = @loaders[ext] || @default_loader 579: loader.load(fn) 580: @imported << fn 581: end 582: end
Warn about deprecated use of top level constant names.
# File lib/rake/application.rb, line 585 585: def const_warning(const_name) 586: @const_warning ||= false 587: if ! @const_warning 588: $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } + 589: %{found at: #{rakefile_location}} # ' 590: $stderr.puts %{ Use --classic-namespace on rake command} 591: $stderr.puts %{ or 'require "rake/classic_namespace"' in Rakefile} 592: end 593: @const_warning = true 594: end
# File lib/rake/application.rb, line 596 596: def rakefile_location backtrace = caller 597: backtrace.map { |t| t[/([^:]+):/,1] } 598: 599: re = /^#{@rakefile}$/ 600: re = /#{re.source}/ if windows? 601: 602: backtrace.find { |str| str =~ re } || '' 603: end
Private Instance methods
Does the exception have a task invocation chain?
# File lib/rake/application.rb, line 169 169: def has_chain?(exception) 170: exception.respond_to?(:chain) && exception.chain 171: end
# File lib/rake/application.rb, line 521 521: def glob(path, &block) 522: Dir[path.gsub("\\", '/')].each(&block) 523: end