class Rake::Application

  1. lib/rake/application.rb
Parent: Rake

                

Rake main application object. When invoking rake from the command line, a Rake::Application object is created and run.

Included modules

  1. TaskManager

Classes and Modules

  1. 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

new ()

Initialize a Rake::Application object.

[show source]
    # 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 ()

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.

[show source]
    # 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
init (app_name='rake')

Initialize the command line parameters and app name.

[show source]
    # 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
load_rakefile ()

Find the rakefile and then load it and any pending imports.

[show source]
    # File lib/rake/application.rb, line 76
76:     def load_rakefile
77:       standard_exception_handling do
78:         raw_load_rakefile
79:       end
80:     end
top_level ()

Run the top level tasks of a Rake application.

[show source]
    # 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_loader (ext, loader)

Add a loader to handle imported files ending in the extension ext.

[show source]
     # File lib/rake/application.rb, line 97
 97:     def add_loader(ext, loader)
 98:       ext = ".#{ext}" unless ext =~ /^\./
 99:       @loaders[ext] = loader
100:     end
options ()

Application options from the command line

[show source]
     # File lib/rake/application.rb, line 103
103:     def options
104:       @options ||= Options.new
105:     end
invoke_task (task_string)

private —————————————————————-

[show source]
     # 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
parse_task_string (string)
[show source]
     # 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
standard_exception_handling ()

Provide standard exception handling for the given block.

[show source]
     # 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_error_message (ex)

Display the error message that caused the exception.

[show source]
     # 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
deprecate (old_usage, new_usage, call_site)

Warn about deprecated usage.

Example:

Rake.application.deprecate("import", "Rake.import", caller.first)
[show source]
     # 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
have_rakefile ()

True if one of the files in RAKEFILES is in the current directory. If a match is found, it is copied into @rakefile.

[show source]
     # 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
tty_output? ()

True if we are outputting to TTY, false otherwise

[show source]
     # File lib/rake/application.rb, line 189
189:     def tty_output?
190:       @tty_output
191:     end
tty_output= ( tty_output_state )

Override the detected TTY output state (mostly for testing)

[show source]
     # File lib/rake/application.rb, line 194
194:     def tty_output=( tty_output_state )
195:       @tty_output = tty_output_state
196:     end
truncate_output? ()

We will truncate output if we are outputting to a TTY or if we’ve been given an explicit column width to honor

[show source]
     # File lib/rake/application.rb, line 200
200:     def truncate_output?
201:       tty_output? || ENV['RAKE_COLUMNS']
202:     end
display_tasks_and_comments ()

Display the tasks and comments.

[show source]
     # 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
terminal_width ()
[show source]
     # 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
dynamic_width ()

Calculate the dynamic width of the

[show source]
     # File lib/rake/application.rb, line 248
248:     def dynamic_width
249:       @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
250:     end
dynamic_width_stty ()
[show source]
     # File lib/rake/application.rb, line 252
252:     def dynamic_width_stty
253:       %{stty size 2>/dev/null}.split[1].to_i
254:     end
dynamic_width_tput ()
[show source]
     # File lib/rake/application.rb, line 256
256:     def dynamic_width_tput
257:       %{tput cols 2>/dev/null}.to_i
258:     end
unix? ()
[show source]
     # 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
windows? ()
[show source]
     # File lib/rake/application.rb, line 264
264:     def windows?
265:       Win32.windows?
266:     end
truncate (string, width)
[show source]
     # 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_prerequisites ()

Display the tasks and prerequisites

[show source]
     # 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
standard_rake_options ()

A list of all the standard options used in rake, suitable for passing to OptionParser.

[show source]
     # 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
handle_options ()

Read and handle the command line options.

[show source]
     # 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
rake_require (file_name, paths=$LOAD_PATH, loaded=$")

Similar to the regular Ruby require command, but will check for *.rake files in addition to *.rb files.

[show source]
     # 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
find_rakefile_location ()
[show source]
     # 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
print_rakefile_directory (location)
[show source]
     # 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
system_dir ()

The directory path containing the system wide rakefiles.

[show source]
     # 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_tasks ()

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.

[show source]
     # 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_import (fn)

Add a file to the list of files to be imported.

[show source]
     # File lib/rake/application.rb, line 566
566:     def add_import(fn)
567:       @pending_imports << fn
568:     end
load_imports ()

Load the pending list of imported files.

[show source]
     # 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
const_warning (const_name)

Warn about deprecated use of top level constant names.

[show source]
     # 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
rakefile_location (backtrace = caller)
[show source]
     # 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

has_chain? (exception)

Does the exception have a task invocation chain?

[show source]
     # File lib/rake/application.rb, line 169
169:     def has_chain?(exception)
170:       exception.respond_to?(:chain) && exception.chain
171:     end
glob (path, &block)
[show source]
     # File lib/rake/application.rb, line 521
521:     def glob(path, &block)
522:       Dir[path.gsub("\\", '/')].each(&block)
523:     end