[R] |
name |
The name of the application (typically ‘rake’)
|
[R] |
original_dir |
The original directory where rake was invoked.
|
[R] |
rakefile |
Name of the actual rakefile used.
|
[R] |
top_level_tasks |
List of the top level task names (task names from the command line).
|
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
Add a file to the list of files to be imported.
2411: def add_import(fn)
2412: @pending_imports << fn
2413: end
Add a loader to handle imported files ending in the extension ext.
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.
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.
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
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.
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
2131: def dynamic_width
2132: @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
2133: end
2135: def dynamic_width_stty
2136: %x{stty size 2>/dev/null}.split[1].to_i
2137: end
2139: def dynamic_width_tput
2140: %x{tput cols 2>/dev/null}.to_i
2141: end
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.
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:
2304:
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.
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.
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
—————————————————————-
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.
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.
1992: def load_rakefile
1993: standard_exception_handling do
1994: raw_load_rakefile
1995: end
1996: end
2019: def options
2020: @options ||= OpenStruct.new
2021: end
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.
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
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:
- 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. The define any tasks. Finally, call top_level to run your top level
tasks.
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.
2043: def standard_exception_handling
2044: begin
2045: yield
2046: rescue SystemExit => ex
2047:
2048: exit(ex.status)
2049: rescue SystemExit, OptionParser::InvalidOption => ex
2050:
2051: exit(1)
2052: rescue Exception => ex
2053:
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.
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.
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
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.
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
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
2092: def truncate_output?
2093: tty_output? || ENV['RAKE_COLUMNS']
2094: end
Override the detected TTY output state (mostly for testing)
2086: def tty_output=( tty_output_state )
2087: @tty_output = tty_output_state
2088: end
True if we are outputting to TTY, false otherwise
2081: def tty_output?
2082: @tty_output
2083: end
2143: def unix?
2144: RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
2145: end
2147: def windows?
2148: Win32.windows?
2149: end