Class: Rake::Application

Inherits:
Object
  • Object
show all
Includes:
TaskManager
Defined in:
lib/rake.rb

Overview

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

Constant Summary collapse

DEFAULT_RAKEFILES =
['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze

Instance Attribute Summary collapse

Attributes included from TaskManager

#last_description

Instance Method Summary collapse

Methods included from TaskManager

#[], #clear, #create_rule, #current_scope, #define_task, #enhance_with_matching_rule, #in_namespace, #intern, #lookup, #resolve_args, #synthesize_file_task, #tasks

Constructor Details

#initializeApplication

Initialize a Rake::Application object.



1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
# File 'lib/rake.rb', line 1940

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?
end

Instance Attribute Details

#nameObject (readonly)

The name of the application (typically ‘rake’)



1926
1927
1928
# File 'lib/rake.rb', line 1926

def name
  @name
end

#original_dirObject (readonly)

The original directory where rake was invoked.



1929
1930
1931
# File 'lib/rake.rb', line 1929

def original_dir
  @original_dir
end

#rakefileObject (readonly)

Name of the actual rakefile used.



1932
1933
1934
# File 'lib/rake.rb', line 1932

def rakefile
  @rakefile
end

#top_level_tasksObject (readonly)

List of the top level task names (task names from the command line).



1935
1936
1937
# File 'lib/rake.rb', line 1935

def top_level_tasks
  @top_level_tasks
end

Instance Method Details

#add_import(fn) ⇒ Object

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



2400
2401
2402
# File 'lib/rake.rb', line 2400

def add_import(fn)
  @pending_imports << fn
end

#add_loader(ext, loader) ⇒ Object

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



2004
2005
2006
2007
# File 'lib/rake.rb', line 2004

def add_loader(ext, loader)
  ext = ".#{ext}" unless ext =~ /^\./
  @loaders[ext] = loader
end

#collect_tasks(argv) ⇒ Object

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.



2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
# File 'lib/rake.rb', line 2387

def collect_tasks(argv)
  @top_level_tasks = []
  argv.each do |arg|
    if arg =~ /^(\w+)=(.*)$/
      ENV[$1] = $2
    else
      @top_level_tasks << arg unless arg =~ /^-/
    end
  end
  @top_level_tasks.push("default") if @top_level_tasks.size == 0
end

#const_warning(const_name) ⇒ Object

Warn about deprecated use of top level constant names.



2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
# File 'lib/rake.rb', line 2419

def const_warning(const_name)
  @const_warning ||= false
  if ! @const_warning
    $stderr.puts %{WARNING: Deprecated reference to top-level constant '#{const_name}' } +
      %{found at: #{rakefile_location}} # '
    $stderr.puts %{    Use --classic-namespace on rake command}
    $stderr.puts %{    or 'require "rake/classic_namespace"' in Rakefile}
  end
  @const_warning = true
end

#display_prerequisitesObject

Display the tasks and prerequisites



2148
2149
2150
2151
2152
2153
# File 'lib/rake.rb', line 2148

def display_prerequisites
  tasks.each do |t|
    puts "rake #{t.name}"
    t.prerequisites.each { |pre| puts "    #{pre}" }
  end
end

#display_tasks_and_commentsObject

Display the tasks and dependencies.



2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
# File 'lib/rake.rb', line 2085

def display_tasks_and_comments
  displayable_tasks = tasks.select { |t|
    t.comment && t.name =~ options.show_task_pattern
  }
  if options.full_description
    displayable_tasks.each do |t|
      puts "rake #{t.name_with_args}"
      t.full_comment.split("\n").each do |line|
        puts "    #{line}"
      end
      puts
    end
  else
    width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
    max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
    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
  end
end

#dynamic_widthObject

Calculate the dynamic width of the



2119
2120
2121
# File 'lib/rake.rb', line 2119

def dynamic_width
  @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
end

#dynamic_width_sttyObject



2123
2124
2125
# File 'lib/rake.rb', line 2123

def dynamic_width_stty
  %x{stty size 2>/dev/null}.split[1].to_i
end

#dynamic_width_tputObject



2127
2128
2129
# File 'lib/rake.rb', line 2127

def dynamic_width_tput
  %x{tput cols 2>/dev/null}.to_i
end

#find_rakefile_locationObject



2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
# File 'lib/rake.rb', line 2319

def find_rakefile_location
  here = Dir.pwd
  while ! (fn = have_rakefile)
    Dir.chdir("..")
    if Dir.pwd == here || options.nosearch
      return nil
    end
    here = Dir.pwd
  end
  [fn, here]
ensure
  Dir.chdir(Rake.original_dir)
end

#handle_optionsObject

Read and handle the command line options.



2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
# File 'lib/rake.rb', line 2275

def handle_options
  options.rakelib = ['rakelib']

  opts = OptionParser.new
  opts.banner = "rake [-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) }
  parsed_argv = opts.parse(ARGV)

  # If class namespaces are requested, set the global options
  # according to the values in the options structure.
  if options.classic_namespace
    $show_tasks = options.show_tasks
    $show_prereqs = options.show_prereqs
    $trace = options.trace
    $dryrun = options.dryrun
    $silent = options.silent
  end
  parsed_argv
end

#have_rakefileObject

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



2059
2060
2061
2062
2063
2064
2065
2066
# File 'lib/rake.rb', line 2059

def have_rakefile
  @rakefiles.each do |fn|
    if File.exist?(fn) || fn == ''
      return fn
    end
  end
  return nil
end

#init(app_name = 'rake') ⇒ Object

Initialize the command line parameters and app name.



1975
1976
1977
1978
1979
1980
# File 'lib/rake.rb', line 1975

def init(app_name='rake')
  standard_exception_handling do
    @name = app_name
    collect_tasks handle_options
  end
end

#invoke_task(task_string) ⇒ Object

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



2016
2017
2018
2019
2020
# File 'lib/rake.rb', line 2016

def invoke_task(task_string)
  name, args = parse_task_string(task_string)
  t = self[name]
  t.invoke(*args)
end

#load_importsObject

Load the pending list of imported files.



2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
# File 'lib/rake.rb', line 2405

def load_imports
  while fn = @pending_imports.shift
    next if @imported.member?(fn)
    if fn_task = lookup(fn)
      fn_task.invoke
    end
    ext = File.extname(fn)
    loader = @loaders[ext] || @default_loader
    loader.load(fn)
    @imported << fn
  end
end

#load_rakefileObject

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



1983
1984
1985
1986
1987
# File 'lib/rake.rb', line 1983

def load_rakefile
  standard_exception_handling do
    raw_load_rakefile
  end
end

#optionsObject

Application options from the command line



2010
2011
2012
# File 'lib/rake.rb', line 2010

def options
  @options ||= OpenStruct.new
end

#parse_task_string(string) ⇒ Object



2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
# File 'lib/rake.rb', line 2022

def parse_task_string(string)
  if string =~ /^([^\[]+)(\[(.*)\])$/
    name = $1
    args = $3.split(/\s*,\s*/)
  else
    name = string
    args = []
  end
  [name, args]
end

#rake_require(file_name, paths = $LOAD_PATH, loaded = $") ⇒ Object

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



2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
# File 'lib/rake.rb', line 2305

def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
  return false if loaded.include?(file_name)
  paths.each do |path|
    fn = file_name + ".rake"
    full_path = File.join(path, fn)
    if File.exist?(full_path)
      load full_path
      loaded << fn
      return true
    end
  end
  fail LoadError, "Can't find #{file_name}"
end

#rakefile_locationObject



2430
2431
2432
2433
2434
2435
2436
# File 'lib/rake.rb', line 2430

def rakefile_location
  begin
    fail
  rescue RuntimeError => ex
    ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
  end
end

#raw_load_rakefileObject

:nodoc:



2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
# File 'lib/rake.rb', line 2333

def raw_load_rakefile # :nodoc:
  rakefile, location = find_rakefile_location
  if (! options.ignore_system) &&
      (options.load_system || rakefile.nil?) &&
      system_dir && File.directory?(system_dir)
    puts "(in #{Dir.pwd})" unless options.silent
    glob("#{system_dir}/*.rake") do |name|
      add_import name
    end
  else
    fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if
      rakefile.nil?
    @rakefile = rakefile
    Dir.chdir(location)
    puts "(in #{Dir.pwd})" unless options.silent
    $rakefile = @rakefile if options.classic_namespace
    load File.expand_path(@rakefile) if @rakefile && @rakefile != ''
    options.rakelib.each do |rlib|
      glob("#{rlib}/*.rake") do |name|
        add_import name
      end
    end
  end
  load_imports
end

#runObject

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.



1966
1967
1968
1969
1970
1971
1972
# File 'lib/rake.rb', line 1966

def run
  standard_exception_handling do
    init
    load_rakefile
    top_level
  end
end

#standard_exception_handlingObject

Provide standard execption handling for the given block.



2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
# File 'lib/rake.rb', line 2034

def standard_exception_handling
  begin
    yield
  rescue SystemExit => ex
    # Exit silently with current status
    exit(ex.status)
  rescue SystemExit, OptionParser::InvalidOption => ex
    # Exit silently
    exit(1)
  rescue Exception => ex
    # Exit with error message
    $stderr.puts "rake aborted!"
    $stderr.puts ex.message
    if options.trace
      $stderr.puts ex.backtrace.join("\n")
    else
      $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
      $stderr.puts "(See full trace by running task with --trace)"
    end
    exit(1)
  end
end

#standard_rake_optionsObject

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



2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
# File 'lib/rake.rb', line 2157

def standard_rake_options
  [
    ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
      lambda { |value|
        require 'rake/classic_namespace'
        options.classic_namespace = true
      }
    ],
    ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
      lambda { |value|
        options.show_tasks = true
        options.full_description = true
        options.show_task_pattern = Regexp.new(value || '')
      }
    ],
    ['--dry-run', '-n', "Do a dry run without executing actions.",
      lambda { |value|
        verbose(true)
        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) }            
    ],
    ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
      lambda { |value| $:.push(value) }
    ],
    ['--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| 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(':') }
    ],
    ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
      lambda { |value|
        begin
          require value
        rescue LoadError => ex
          begin
            rake_require value
          rescue LoadError => ex2
            raise ex
          end
        end
      }
    ],
    ['--rules', "Trace the rules resolution.",
      lambda { |value| options.trace_rules = true }
    ],
    ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
      lambda { |value| options.nosearch = true }
    ],
    ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
      lambda { |value|
        verbose(false)
        options.silent = true
      }
    ],
    ['--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|
        options.show_tasks = true
        options.show_task_pattern = Regexp.new(value || '')
        options.full_description = false
      }
    ],
    ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
      lambda { |value|
        options.trace = true
        verbose(true)
      }
    ],
    ['--verbose', '-v', "Log message to standard output (default).",
      lambda { |value| verbose(true) }
    ],
    ['--version', '-V', "Display the program version.",
      lambda { |value|
        puts "rake, version #{RAKEVERSION}"
        exit
      }
    ]
  ]
end

#system_dirObject

The directory path containing the system wide rakefiles.



2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
# File 'lib/rake.rb', line 2365

def system_dir
  @system_dir ||=
    begin
      if ENV['RAKE_SYSTEM']
        ENV['RAKE_SYSTEM']
      elsif Win32.windows?
        Win32.win32_system_dir
      else
        standard_system_dir
      end
    end
end

#terminal_widthObject



2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
# File 'lib/rake.rb', line 2107

def terminal_width
  if ENV['RAKE_COLUMNS']
    result = ENV['RAKE_COLUMNS'].to_i
  else
    result = unix? ? dynamic_width : 80
  end
  (result < 10) ? 80 : result
rescue
  80
end

#top_levelObject

Run the top level tasks of a Rake application.



1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
# File 'lib/rake.rb', line 1990

def top_level
  standard_exception_handling 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

#truncate(string, width) ⇒ Object



2139
2140
2141
2142
2143
2144
2145
# File 'lib/rake.rb', line 2139

def truncate(string, width)
  if string.length <= width
    string
  else
    ( string[0, width-3] || "" ) + "..."
  end
end

#truncate_output?Boolean

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

Returns:

  • (Boolean)


2080
2081
2082
# File 'lib/rake.rb', line 2080

def truncate_output?
  tty_output? || ENV['RAKE_COLUMNS']
end

#tty_output=(tty_output_state) ⇒ Object

Override the detected TTY output state (mostly for testing)



2074
2075
2076
# File 'lib/rake.rb', line 2074

def tty_output=( tty_output_state )
  @tty_output = tty_output_state
end

#tty_output?Boolean

True if we are outputting to TTY, false otherwise

Returns:

  • (Boolean)


2069
2070
2071
# File 'lib/rake.rb', line 2069

def tty_output?
  @tty_output
end

#unix?Boolean

Returns:

  • (Boolean)


2131
2132
2133
# File 'lib/rake.rb', line 2131

def unix?
  RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
end

#windows?Boolean

Returns:

  • (Boolean)


2135
2136
2137
# File 'lib/rake.rb', line 2135

def windows?
  Win32.windows?
end