Class Rake::Application
In: lib/rake.rb
Parent: Object

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

Methods

Included Modules

TaskManager

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.

[Source]

      # File lib/rake.rb, line 1948
1948:     def initialize
1949:       super
1950:       @name = 'rake'
1951:       @rakefiles = DEFAULT_RAKEFILES.dup
1952:       @rakefile = nil
1953:       @pending_imports = []
1954:       @imported = []
1955:       @loaders = {}
1956:       @default_loader = Rake::DefaultLoader.new
1957:       @original_dir = Dir.pwd
1958:       @top_level_tasks = []
1959:       add_loader('rb', DefaultLoader.new)
1960:       add_loader('rf', DefaultLoader.new)
1961:       add_loader('rake', DefaultLoader.new)
1962:       @tty_output = STDOUT.tty?
1963:     end

Public Instance methods

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

[Source]

      # File lib/rake.rb, line 2411
2411:     def add_import(fn)
2412:       @pending_imports << fn
2413:     end

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

[Source]

      # File lib/rake.rb, line 2013
2013:     def add_loader(ext, loader)
2014:       ext = ".#{ext}" unless ext =~ /^\./
2015:       @loaders[ext] = loader
2016:     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.

[Source]

      # File lib/rake.rb, line 2398
2398:     def collect_tasks
2399:       @top_level_tasks = []
2400:       ARGV.each do |arg|
2401:         if arg =~ /^(\w+)=(.*)$/
2402:           ENV[$1] = $2
2403:         else
2404:           @top_level_tasks << arg unless arg =~ /^-/
2405:         end
2406:       end
2407:       @top_level_tasks.push("default") if @top_level_tasks.size == 0
2408:     end

Warn about deprecated use of top level constant names.

[Source]

      # File lib/rake.rb, line 2430
2430:     def const_warning(const_name)
2431:       @const_warning ||= false
2432:       if ! @const_warning
2433:         $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } +
2434:           %{found at: #{rakefile_location}} # '
2435:         $stderr.puts %{    Use --classic-namespace on rake command}
2436:         $stderr.puts %{    or 'require "rake/classic_namespace"' in Rakefile}
2437:       end
2438:       @const_warning = true
2439:     end

Display the tasks and prerequisites

[Source]

      # File lib/rake.rb, line 2160
2160:     def display_prerequisites
2161:       tasks.each do |t|
2162:         puts "#{name} #{t.name}"
2163:         t.prerequisites.each { |pre| puts "    #{pre}" }
2164:       end
2165:     end

Display the tasks and comments.

[Source]

      # File lib/rake.rb, line 2097
2097:     def display_tasks_and_comments
2098:       displayable_tasks = tasks.select { |t|
2099:         t.comment && t.name =~ options.show_task_pattern
2100:       }
2101:       if options.full_description
2102:         displayable_tasks.each do |t|
2103:           puts "#{name} #{t.name_with_args}"
2104:           t.full_comment.split("\n").each do |line|
2105:             puts "    #{line}"
2106:           end
2107:           puts
2108:         end
2109:       else
2110:         width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
2111:         max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
2112:         displayable_tasks.each do |t|
2113:           printf "#{name} %-#{width}s  # %s\n",
2114:             t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
2115:         end
2116:       end
2117:     end

Calculate the dynamic width of the

[Source]

      # File lib/rake.rb, line 2131
2131:     def dynamic_width
2132:       @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
2133:     end

[Source]

      # File lib/rake.rb, line 2135
2135:     def dynamic_width_stty
2136:       %x{stty size 2>/dev/null}.split[1].to_i
2137:     end

[Source]

      # File lib/rake.rb, line 2139
2139:     def dynamic_width_tput
2140:       %x{tput cols 2>/dev/null}.to_i
2141:     end

[Source]

      # File lib/rake.rb, line 2330
2330:     def find_rakefile_location
2331:       here = Dir.pwd
2332:       while ! (fn = have_rakefile)
2333:         Dir.chdir("..")
2334:         if Dir.pwd == here || options.nosearch
2335:           return nil
2336:         end
2337:         here = Dir.pwd
2338:       end
2339:       [fn, here]
2340:     ensure
2341:       Dir.chdir(Rake.original_dir)
2342:     end

Read and handle the command line options.

[Source]

      # File lib/rake.rb, line 2287
2287:     def handle_options
2288:       options.rakelib = ['rakelib']
2289: 
2290:       OptionParser.new do |opts|
2291:         opts.banner = "rake [-f rakefile] {options} targets..."
2292:         opts.separator ""
2293:         opts.separator "Options are ..."
2294: 
2295:         opts.on_tail("-h", "--help", "-H", "Display this help message.") do
2296:           puts opts
2297:           exit
2298:         end
2299: 
2300:         standard_rake_options.each { |args| opts.on(*args) }
2301:       end.parse!
2302: 
2303:       # If class namespaces are requested, set the global options
2304:       # according to the values in the options structure.
2305:       if options.classic_namespace
2306:         $show_tasks = options.show_tasks
2307:         $show_prereqs = options.show_prereqs
2308:         $trace = options.trace
2309:         $dryrun = options.dryrun
2310:         $silent = options.silent
2311:       end
2312:     end

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

[Source]

      # File lib/rake.rb, line 2068
2068:     def have_rakefile
2069:       @rakefiles.each do |fn|
2070:         if File.exist?(fn)
2071:           others = Dir.glob(fn, File::FNM_CASEFOLD)
2072:           return others.size == 1 ? others.first : fn
2073:         elsif fn == ''
2074:           return fn
2075:         end
2076:       end
2077:       return nil
2078:     end

Initialize the command line parameters and app name.

[Source]

      # File lib/rake.rb, line 1983
1983:     def init(app_name='rake')
1984:       standard_exception_handling do
1985:         @name = app_name
1986:         handle_options
1987:         collect_tasks
1988:       end
1989:     end

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

[Source]

      # File lib/rake.rb, line 2025
2025:     def invoke_task(task_string)
2026:       name, args = parse_task_string(task_string)
2027:       t = self[name]
2028:       t.invoke(*args)
2029:     end

Load the pending list of imported files.

[Source]

      # File lib/rake.rb, line 2416
2416:     def load_imports
2417:       while fn = @pending_imports.shift
2418:         next if @imported.member?(fn)
2419:         if fn_task = lookup(fn)
2420:           fn_task.invoke
2421:         end
2422:         ext = File.extname(fn)
2423:         loader = @loaders[ext] || @default_loader
2424:         loader.load(fn)
2425:         @imported << fn
2426:       end
2427:     end

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

[Source]

      # File lib/rake.rb, line 1992
1992:     def load_rakefile
1993:       standard_exception_handling do
1994:         raw_load_rakefile
1995:       end
1996:     end

Application options from the command line

[Source]

      # File lib/rake.rb, line 2019
2019:     def options
2020:       @options ||= OpenStruct.new
2021:     end

[Source]

      # File lib/rake.rb, line 2031
2031:     def parse_task_string(string)
2032:       if string =~ /^([^\[]+)(\[(.*)\])$/
2033:         name = $1
2034:         args = $3.split(/\s*,\s*/)
2035:       else
2036:         name = string
2037:         args = []
2038:       end
2039:       [name, args]
2040:     end

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

[Source]

      # File lib/rake.rb, line 2316
2316:     def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
2317:       return false if loaded.include?(file_name)
2318:       paths.each do |path|
2319:         fn = file_name + ".rake"
2320:         full_path = File.join(path, fn)
2321:         if File.exist?(full_path)
2322:           load full_path
2323:           loaded << fn
2324:           return true
2325:         end
2326:       end
2327:       fail LoadError, "Can't find #{file_name}"
2328:     end

[Source]

      # File lib/rake.rb, line 2441
2441:     def rakefile_location
2442:       begin
2443:         fail
2444:       rescue RuntimeError => ex
2445:         ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2446:       end
2447:     end

Run the Rake application. The run method performs the following three steps:

If you wish to build a custom rake command, you should call init on your application. The define any tasks. Finally, call top_level to run your top level tasks.

[Source]

      # File lib/rake.rb, line 1974
1974:     def run
1975:       standard_exception_handling do
1976:         init
1977:         load_rakefile
1978:         top_level
1979:       end
1980:     end

Provide standard execption handling for the given block.

[Source]

      # File lib/rake.rb, line 2043
2043:     def standard_exception_handling
2044:       begin
2045:         yield
2046:       rescue SystemExit => ex
2047:         # Exit silently with current status
2048:         exit(ex.status)
2049:       rescue SystemExit, OptionParser::InvalidOption => ex
2050:         # Exit silently
2051:         exit(1)
2052:       rescue Exception => ex
2053:         # Exit with error message
2054:         $stderr.puts "#{name} aborted!"
2055:         $stderr.puts ex.message
2056:         if options.trace
2057:           $stderr.puts ex.backtrace.join("\n")
2058:         else
2059:           $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
2060:           $stderr.puts "(See full trace by running task with --trace)"
2061:         end
2062:         exit(1)
2063:       end
2064:     end

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

[Source]

      # File lib/rake.rb, line 2169
2169:     def standard_rake_options
2170:       [
2171:         ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
2172:           lambda { |value|
2173:             require 'rake/classic_namespace'
2174:             options.classic_namespace = true
2175:           }
2176:         ],
2177:         ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
2178:           lambda { |value|
2179:             options.show_tasks = true
2180:             options.full_description = true
2181:             options.show_task_pattern = Regexp.new(value || '')
2182:           }
2183:         ],
2184:         ['--dry-run', '-n', "Do a dry run without executing actions.",
2185:           lambda { |value|
2186:             verbose(true)
2187:             nowrite(true)
2188:             options.dryrun = true
2189:             options.trace = true
2190:           }
2191:         ],
2192:         ['--execute',  '-e CODE', "Execute some Ruby code and exit.",
2193:           lambda { |value|
2194:             eval(value)
2195:             exit
2196:           }
2197:         ],
2198:         ['--execute-print',  '-p CODE', "Execute some Ruby code, print the result, then exit.",
2199:           lambda { |value|
2200:             puts eval(value)
2201:             exit
2202:           }
2203:         ],
2204:         ['--execute-continue',  '-E CODE',
2205:           "Execute some Ruby code, then continue with normal task processing.",
2206:           lambda { |value| eval(value) }            
2207:         ],
2208:         ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
2209:           lambda { |value| $:.push(value) }
2210:         ],
2211:         ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
2212:           lambda { |value| options.show_prereqs = true }
2213:         ],
2214:         ['--quiet', '-q', "Do not log messages to standard output.",
2215:           lambda { |value| verbose(false) }
2216:         ],
2217:         ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
2218:           lambda { |value| 
2219:             value ||= ''
2220:             @rakefiles.clear 
2221:             @rakefiles << value
2222:           }
2223:         ],
2224:         ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
2225:           "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
2226:           lambda { |value| options.rakelib = value.split(':') }
2227:         ],
2228:         ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
2229:           lambda { |value|
2230:             begin
2231:               require value
2232:             rescue LoadError => ex
2233:               begin
2234:                 rake_require value
2235:               rescue LoadError => ex2
2236:                 raise ex
2237:               end
2238:             end
2239:           }
2240:         ],
2241:         ['--rules', "Trace the rules resolution.",
2242:           lambda { |value| options.trace_rules = true }
2243:         ],
2244:         ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
2245:           lambda { |value| options.nosearch = true }
2246:         ],
2247:         ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
2248:           lambda { |value|
2249:             verbose(false)
2250:             options.silent = true
2251:           }
2252:         ],
2253:         ['--system',  '-g',
2254:           "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
2255:           lambda { |value| options.load_system = true }
2256:         ],
2257:         ['--no-system', '--nosystem', '-G',
2258:           "Use standard project Rakefile search paths, ignore system wide rakefiles.",
2259:           lambda { |value| options.ignore_system = true }
2260:         ],
2261:         ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
2262:           lambda { |value|
2263:             options.show_tasks = true
2264:             options.show_task_pattern = Regexp.new(value || '')
2265:             options.full_description = false
2266:           }
2267:         ],
2268:         ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
2269:           lambda { |value|
2270:             options.trace = true
2271:             verbose(true)
2272:           }
2273:         ],
2274:         ['--verbose', '-v', "Log message to standard output.",
2275:           lambda { |value| verbose(true) }
2276:         ],
2277:         ['--version', '-V', "Display the program version.",
2278:           lambda { |value|
2279:             puts "rake, version #{RAKEVERSION}"
2280:             exit
2281:           }
2282:         ]
2283:       ]
2284:     end

The directory path containing the system wide rakefiles.

[Source]

      # File lib/rake.rb, line 2376
2376:     def system_dir
2377:       @system_dir ||=
2378:         begin
2379:           if ENV['RAKE_SYSTEM']
2380:             ENV['RAKE_SYSTEM']
2381:           elsif Win32.windows?
2382:             Win32.win32_system_dir
2383:           else
2384:             standard_system_dir
2385:           end
2386:         end
2387:     end

[Source]

      # File lib/rake.rb, line 2119
2119:     def terminal_width
2120:       if ENV['RAKE_COLUMNS']
2121:         result = ENV['RAKE_COLUMNS'].to_i
2122:       else
2123:         result = unix? ? dynamic_width : 80
2124:       end
2125:       (result < 10) ? 80 : result
2126:     rescue
2127:       80
2128:     end

Run the top level tasks of a Rake application.

[Source]

      # File lib/rake.rb, line 1999
1999:     def top_level
2000:       standard_exception_handling do
2001:         if options.show_tasks
2002:           display_tasks_and_comments
2003:         elsif options.show_prereqs
2004:           display_prerequisites
2005:         else
2006:           top_level_tasks.each { |task_name| invoke_task(task_name) }
2007:         end
2008:       end
2009:     end

[Source]

      # File lib/rake.rb, line 2151
2151:     def truncate(string, width)
2152:       if string.length <= width
2153:         string
2154:       else
2155:         ( string[0, width-3] || "" ) + "..."
2156:       end
2157:     end

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

[Source]

      # File lib/rake.rb, line 2092
2092:     def truncate_output?
2093:       tty_output? || ENV['RAKE_COLUMNS']
2094:     end

Override the detected TTY output state (mostly for testing)

[Source]

      # File lib/rake.rb, line 2086
2086:     def tty_output=( tty_output_state )
2087:       @tty_output = tty_output_state
2088:     end

True if we are outputting to TTY, false otherwise

[Source]

      # File lib/rake.rb, line 2081
2081:     def tty_output?
2082:       @tty_output
2083:     end

[Source]

      # File lib/rake.rb, line 2143
2143:     def unix?
2144:       RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
2145:     end

[Source]

      # File lib/rake.rb, line 2147
2147:     def windows?
2148:       Win32.windows?
2149:     end

[Validate]