PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/Ruby/StdLib/ruby/1.9.1/rake.rb

http://github.com/IronLanguages/main
Ruby | 2485 lines | 1641 code | 236 blank | 608 comment | 121 complexity | 6c9b2532d6f122f3d2b9b672ba4940d9 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. #--
  2. # Copyright 2003, 2004, 2005, 2006, 2007, 2008 by Jim Weirich (jim@weirichhouse.org)
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to
  6. # deal in the Software without restriction, including without limitation the
  7. # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. # sell copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. # IN THE SOFTWARE.
  21. #++
  22. #
  23. # = Rake -- Ruby Make
  24. #
  25. # This is the main file for the Rake application. Normally it is referenced
  26. # as a library via a require statement, but it can be distributed
  27. # independently as an application.
  28. RAKEVERSION = '0.8.7'
  29. require 'rbconfig'
  30. require 'fileutils'
  31. require 'singleton'
  32. require 'monitor'
  33. require 'optparse'
  34. require 'ostruct'
  35. require 'rake/win32'
  36. $trace = false
  37. ######################################################################
  38. # Rake extensions to Module.
  39. #
  40. class Module
  41. # Check for an existing method in the current class before extending. IF
  42. # the method already exists, then a warning is printed and the extension is
  43. # not added. Otherwise the block is yielded and any definitions in the
  44. # block will take effect.
  45. #
  46. # Usage:
  47. #
  48. # class String
  49. # rake_extension("xyz") do
  50. # def xyz
  51. # ...
  52. # end
  53. # end
  54. # end
  55. #
  56. def rake_extension(method)
  57. if method_defined?(method)
  58. $stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
  59. else
  60. yield
  61. end
  62. end
  63. end # module Module
  64. ######################################################################
  65. # User defined methods to be added to String.
  66. #
  67. class String
  68. rake_extension("ext") do
  69. # Replace the file extension with +newext+. If there is no extension on
  70. # the string, append the new extension to the end. If the new extension
  71. # is not given, or is the empty string, remove any existing extension.
  72. #
  73. # +ext+ is a user added method for the String class.
  74. def ext(newext='')
  75. return self.dup if ['.', '..'].include? self
  76. if newext != ''
  77. newext = (newext =~ /^\./) ? newext : ("." + newext)
  78. end
  79. self.chomp(File.extname(self)) << newext
  80. end
  81. end
  82. rake_extension("pathmap") do
  83. # Explode a path into individual components. Used by +pathmap+.
  84. def pathmap_explode
  85. head, tail = File.split(self)
  86. return [self] if head == self
  87. return [tail] if head == '.' || tail == '/'
  88. return [head, tail] if head == '/'
  89. return head.pathmap_explode + [tail]
  90. end
  91. protected :pathmap_explode
  92. # Extract a partial path from the path. Include +n+ directories from the
  93. # front end (left hand side) if +n+ is positive. Include |+n+|
  94. # directories from the back end (right hand side) if +n+ is negative.
  95. def pathmap_partial(n)
  96. dirs = File.dirname(self).pathmap_explode
  97. partial_dirs =
  98. if n > 0
  99. dirs[0...n]
  100. elsif n < 0
  101. dirs.reverse[0...-n].reverse
  102. else
  103. "."
  104. end
  105. File.join(partial_dirs)
  106. end
  107. protected :pathmap_partial
  108. # Preform the pathmap replacement operations on the given path. The
  109. # patterns take the form 'pat1,rep1;pat2,rep2...'.
  110. def pathmap_replace(patterns, &block)
  111. result = self
  112. patterns.split(';').each do |pair|
  113. pattern, replacement = pair.split(',')
  114. pattern = Regexp.new(pattern)
  115. if replacement == '*' && block_given?
  116. result = result.sub(pattern, &block)
  117. elsif replacement
  118. result = result.sub(pattern, replacement)
  119. else
  120. result = result.sub(pattern, '')
  121. end
  122. end
  123. result
  124. end
  125. protected :pathmap_replace
  126. # Map the path according to the given specification. The specification
  127. # controls the details of the mapping. The following special patterns are
  128. # recognized:
  129. #
  130. # * <b>%p</b> -- The complete path.
  131. # * <b>%f</b> -- The base file name of the path, with its file extension,
  132. # but without any directories.
  133. # * <b>%n</b> -- The file name of the path without its file extension.
  134. # * <b>%d</b> -- The directory list of the path.
  135. # * <b>%x</b> -- The file extension of the path. An empty string if there
  136. # is no extension.
  137. # * <b>%X</b> -- Everything *but* the file extension.
  138. # * <b>%s</b> -- The alternate file separater if defined, otherwise use
  139. # the standard file separator.
  140. # * <b>%%</b> -- A percent sign.
  141. #
  142. # The %d specifier can also have a numeric prefix (e.g. '%2d'). If the
  143. # number is positive, only return (up to) +n+ directories in the path,
  144. # starting from the left hand side. If +n+ is negative, return (up to)
  145. # |+n+| directories from the right hand side of the path.
  146. #
  147. # Examples:
  148. #
  149. # 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
  150. # 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
  151. #
  152. # Also the %d, %p, %f, %n, %x, and %X operators can take a
  153. # pattern/replacement argument to perform simple string substititions on a
  154. # particular part of the path. The pattern and replacement are speparated
  155. # by a comma and are enclosed by curly braces. The replacement spec comes
  156. # after the % character but before the operator letter. (e.g.
  157. # "%{old,new}d"). Muliple replacement specs should be separated by
  158. # semi-colons (e.g. "%{old,new;src,bin}d").
  159. #
  160. # Regular expressions may be used for the pattern, and back refs may be
  161. # used in the replacement text. Curly braces, commas and semi-colons are
  162. # excluded from both the pattern and replacement text (let's keep parsing
  163. # reasonable).
  164. #
  165. # For example:
  166. #
  167. # "src/org/onestepback/proj/A.java".pathmap("%{^src,bin}X.class")
  168. #
  169. # returns:
  170. #
  171. # "bin/org/onestepback/proj/A.class"
  172. #
  173. # If the replacement text is '*', then a block may be provided to perform
  174. # some arbitrary calculation for the replacement.
  175. #
  176. # For example:
  177. #
  178. # "/path/to/file.TXT".pathmap("%X%{.*,*}x") { |ext|
  179. # ext.downcase
  180. # }
  181. #
  182. # Returns:
  183. #
  184. # "/path/to/file.txt"
  185. #
  186. def pathmap(spec=nil, &block)
  187. return self if spec.nil?
  188. result = ''
  189. spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
  190. case frag
  191. when '%f'
  192. result << File.basename(self)
  193. when '%n'
  194. result << File.basename(self).ext
  195. when '%d'
  196. result << File.dirname(self)
  197. when '%x'
  198. result << File.extname(self)
  199. when '%X'
  200. result << self.ext
  201. when '%p'
  202. result << self
  203. when '%s'
  204. result << (File::ALT_SEPARATOR || File::SEPARATOR)
  205. when '%-'
  206. # do nothing
  207. when '%%'
  208. result << "%"
  209. when /%(-?\d+)d/
  210. result << pathmap_partial($1.to_i)
  211. when /^%\{([^}]*)\}(\d*[dpfnxX])/
  212. patterns, operator = $1, $2
  213. result << pathmap('%' + operator).pathmap_replace(patterns, &block)
  214. when /^%/
  215. fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
  216. else
  217. result << frag
  218. end
  219. end
  220. result
  221. end
  222. end
  223. end # class String
  224. ##############################################################################
  225. module Rake
  226. # Errors -----------------------------------------------------------
  227. # Error indicating an ill-formed task declaration.
  228. class TaskArgumentError < ArgumentError
  229. end
  230. # Error indicating a recursion overflow error in task selection.
  231. class RuleRecursionOverflowError < StandardError
  232. def initialize(*args)
  233. super
  234. @targets = []
  235. end
  236. def add_target(target)
  237. @targets << target
  238. end
  239. def message
  240. super + ": [" + @targets.reverse.join(' => ') + "]"
  241. end
  242. end
  243. # --------------------------------------------------------------------------
  244. # Rake module singleton methods.
  245. #
  246. class << self
  247. # Current Rake Application
  248. def application
  249. @application ||= Rake::Application.new
  250. end
  251. # Set the current Rake application object.
  252. def application=(app)
  253. @application = app
  254. end
  255. # Return the original directory where the Rake application was started.
  256. def original_dir
  257. application.original_dir
  258. end
  259. end
  260. ####################################################################
  261. # Mixin for creating easily cloned objects.
  262. #
  263. module Cloneable
  264. # Clone an object by making a new object and setting all the instance
  265. # variables to the same values.
  266. def dup
  267. sibling = self.class.new
  268. instance_variables.each do |ivar|
  269. value = self.instance_variable_get(ivar)
  270. new_value = value.clone rescue value
  271. sibling.instance_variable_set(ivar, new_value)
  272. end
  273. sibling.taint if tainted?
  274. sibling
  275. end
  276. def clone
  277. sibling = dup
  278. sibling.freeze if frozen?
  279. sibling
  280. end
  281. end
  282. ####################################################################
  283. # Exit status class for times the system just gives us a nil.
  284. class PseudoStatus
  285. attr_reader :exitstatus
  286. def initialize(code=0)
  287. @exitstatus = code
  288. end
  289. def to_i
  290. @exitstatus << 8
  291. end
  292. def >>(n)
  293. to_i >> n
  294. end
  295. def stopped?
  296. false
  297. end
  298. def exited?
  299. true
  300. end
  301. end
  302. ####################################################################
  303. # TaskAguments manage the arguments passed to a task.
  304. #
  305. class TaskArguments
  306. include Enumerable
  307. attr_reader :names
  308. # Create a TaskArgument object with a list of named arguments
  309. # (given by :names) and a set of associated values (given by
  310. # :values). :parent is the parent argument object.
  311. def initialize(names, values, parent=nil)
  312. @names = names
  313. @parent = parent
  314. @hash = {}
  315. names.each_with_index { |name, i|
  316. @hash[name.to_sym] = values[i] unless values[i].nil?
  317. }
  318. end
  319. # Create a new argument scope using the prerequisite argument
  320. # names.
  321. def new_scope(names)
  322. values = names.collect { |n| self[n] }
  323. self.class.new(names, values, self)
  324. end
  325. # Find an argument value by name or index.
  326. def [](index)
  327. lookup(index.to_sym)
  328. end
  329. # Specify a hash of default values for task arguments. Use the
  330. # defaults only if there is no specific value for the given
  331. # argument.
  332. def with_defaults(defaults)
  333. @hash = defaults.merge(@hash)
  334. end
  335. def each(&block)
  336. @hash.each(&block)
  337. end
  338. def method_missing(sym, *args, &block)
  339. lookup(sym.to_sym)
  340. end
  341. def to_hash
  342. @hash
  343. end
  344. def to_s
  345. @hash.inspect
  346. end
  347. def inspect
  348. to_s
  349. end
  350. protected
  351. def lookup(name)
  352. if @hash.has_key?(name)
  353. @hash[name]
  354. elsif ENV.has_key?(name.to_s)
  355. ENV[name.to_s]
  356. elsif ENV.has_key?(name.to_s.upcase)
  357. ENV[name.to_s.upcase]
  358. elsif @parent
  359. @parent.lookup(name)
  360. end
  361. end
  362. end
  363. EMPTY_TASK_ARGS = TaskArguments.new([], [])
  364. ####################################################################
  365. # InvocationChain tracks the chain of task invocations to detect
  366. # circular dependencies.
  367. class InvocationChain
  368. def initialize(value, tail)
  369. @value = value
  370. @tail = tail
  371. end
  372. def member?(obj)
  373. @value == obj || @tail.member?(obj)
  374. end
  375. def append(value)
  376. if member?(value)
  377. fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
  378. end
  379. self.class.new(value, self)
  380. end
  381. def to_s
  382. "#{prefix}#{@value}"
  383. end
  384. def self.append(value, chain)
  385. chain.append(value)
  386. end
  387. private
  388. def prefix
  389. "#{@tail.to_s} => "
  390. end
  391. class EmptyInvocationChain
  392. def member?(obj)
  393. false
  394. end
  395. def append(value)
  396. InvocationChain.new(value, self)
  397. end
  398. def to_s
  399. "TOP"
  400. end
  401. end
  402. EMPTY = EmptyInvocationChain.new
  403. end # class InvocationChain
  404. end # module Rake
  405. module Rake
  406. ###########################################################################
  407. # A Task is the basic unit of work in a Rakefile. Tasks have associated
  408. # actions (possibly more than one) and a list of prerequisites. When
  409. # invoked, a task will first ensure that all of its prerequisites have an
  410. # opportunity to run and then it will execute its own actions.
  411. #
  412. # Tasks are not usually created directly using the new method, but rather
  413. # use the +file+ and +task+ convenience methods.
  414. #
  415. class Task
  416. # List of prerequisites for a task.
  417. attr_reader :prerequisites
  418. # List of actions attached to a task.
  419. attr_reader :actions
  420. # Application owning this task.
  421. attr_accessor :application
  422. # Comment for this task. Restricted to a single line of no more than 50
  423. # characters.
  424. attr_reader :comment
  425. # Full text of the (possibly multi-line) comment.
  426. attr_reader :full_comment
  427. # Array of nested namespaces names used for task lookup by this task.
  428. attr_reader :scope
  429. # Return task name
  430. def to_s
  431. name
  432. end
  433. def inspect
  434. "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
  435. end
  436. # List of sources for task.
  437. attr_writer :sources
  438. def sources
  439. @sources ||= []
  440. end
  441. # First source from a rule (nil if no sources)
  442. def source
  443. @sources.first if defined?(@sources)
  444. end
  445. # Create a task named +task_name+ with no actions or prerequisites. Use
  446. # +enhance+ to add actions and prerequisites.
  447. def initialize(task_name, app)
  448. @name = task_name.to_s
  449. @prerequisites = []
  450. @actions = []
  451. @already_invoked = false
  452. @full_comment = nil
  453. @comment = nil
  454. @lock = Monitor.new
  455. @application = app
  456. @scope = app.current_scope
  457. @arg_names = nil
  458. end
  459. # Enhance a task with prerequisites or actions. Returns self.
  460. def enhance(deps=nil, &block)
  461. @prerequisites |= deps if deps
  462. @actions << block if block_given?
  463. self
  464. end
  465. # Name of the task, including any namespace qualifiers.
  466. def name
  467. @name.to_s
  468. end
  469. # Name of task with argument list description.
  470. def name_with_args # :nodoc:
  471. if arg_description
  472. "#{name}#{arg_description}"
  473. else
  474. name
  475. end
  476. end
  477. # Argument description (nil if none).
  478. def arg_description # :nodoc:
  479. @arg_names ? "[#{(arg_names || []).join(',')}]" : nil
  480. end
  481. # Name of arguments for this task.
  482. def arg_names
  483. @arg_names || []
  484. end
  485. # Reenable the task, allowing its tasks to be executed if the task
  486. # is invoked again.
  487. def reenable
  488. @already_invoked = false
  489. end
  490. # Clear the existing prerequisites and actions of a rake task.
  491. def clear
  492. clear_prerequisites
  493. clear_actions
  494. self
  495. end
  496. # Clear the existing prerequisites of a rake task.
  497. def clear_prerequisites
  498. prerequisites.clear
  499. self
  500. end
  501. # Clear the existing actions on a rake task.
  502. def clear_actions
  503. actions.clear
  504. self
  505. end
  506. # Invoke the task if it is needed. Prerequites are invoked first.
  507. def invoke(*args)
  508. task_args = TaskArguments.new(arg_names, args)
  509. invoke_with_call_chain(task_args, InvocationChain::EMPTY)
  510. end
  511. # Same as invoke, but explicitly pass a call chain to detect
  512. # circular dependencies.
  513. def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
  514. new_chain = InvocationChain.append(self, invocation_chain)
  515. @lock.synchronize do
  516. if application.options.trace
  517. puts "** Invoke #{name} #{format_trace_flags}"
  518. end
  519. return if @already_invoked
  520. @already_invoked = true
  521. invoke_prerequisites(task_args, new_chain)
  522. execute(task_args) if needed?
  523. end
  524. end
  525. protected :invoke_with_call_chain
  526. # Invoke all the prerequisites of a task.
  527. def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
  528. @prerequisites.each { |n|
  529. prereq = application[n, @scope]
  530. prereq_args = task_args.new_scope(prereq.arg_names)
  531. prereq.invoke_with_call_chain(prereq_args, invocation_chain)
  532. }
  533. end
  534. # Format the trace flags for display.
  535. def format_trace_flags
  536. flags = []
  537. flags << "first_time" unless @already_invoked
  538. flags << "not_needed" unless needed?
  539. flags.empty? ? "" : "(" + flags.join(", ") + ")"
  540. end
  541. private :format_trace_flags
  542. # Execute the actions associated with this task.
  543. def execute(args=nil)
  544. args ||= EMPTY_TASK_ARGS
  545. if application.options.dryrun
  546. puts "** Execute (dry run) #{name}"
  547. return
  548. end
  549. if application.options.trace
  550. puts "** Execute #{name}"
  551. end
  552. application.enhance_with_matching_rule(name) if @actions.empty?
  553. @actions.each do |act|
  554. case act.arity
  555. when 1
  556. act.call(self)
  557. else
  558. act.call(self, args)
  559. end
  560. end
  561. end
  562. # Is this task needed?
  563. def needed?
  564. true
  565. end
  566. # Timestamp for this task. Basic tasks return the current time for their
  567. # time stamp. Other tasks can be more sophisticated.
  568. def timestamp
  569. @prerequisites.collect { |p| application[p].timestamp }.max || Time.now
  570. end
  571. # Add a description to the task. The description can consist of an option
  572. # argument list (enclosed brackets) and an optional comment.
  573. def add_description(description)
  574. return if ! description
  575. comment = description.strip
  576. add_comment(comment) if comment && ! comment.empty?
  577. end
  578. # Writing to the comment attribute is the same as adding a description.
  579. def comment=(description)
  580. add_description(description)
  581. end
  582. # Add a comment to the task. If a comment alread exists, separate
  583. # the new comment with " / ".
  584. def add_comment(comment)
  585. if @full_comment
  586. @full_comment << " / "
  587. else
  588. @full_comment = ''
  589. end
  590. @full_comment << comment
  591. if @full_comment =~ /\A([^.]+?\.)( |$)/
  592. @comment = $1
  593. else
  594. @comment = @full_comment
  595. end
  596. end
  597. private :add_comment
  598. # Set the names of the arguments for this task. +args+ should be
  599. # an array of symbols, one for each argument name.
  600. def set_arg_names(args)
  601. @arg_names = args.map { |a| a.to_sym }
  602. end
  603. # Return a string describing the internal state of a task. Useful for
  604. # debugging.
  605. def investigation
  606. result = "------------------------------\n"
  607. result << "Investigating #{name}\n"
  608. result << "class: #{self.class}\n"
  609. result << "task needed: #{needed?}\n"
  610. result << "timestamp: #{timestamp}\n"
  611. result << "pre-requisites: \n"
  612. prereqs = @prerequisites.collect {|name| application[name]}
  613. prereqs.sort! {|a,b| a.timestamp <=> b.timestamp}
  614. prereqs.each do |p|
  615. result << "--#{p.name} (#{p.timestamp})\n"
  616. end
  617. latest_prereq = @prerequisites.collect{|n| application[n].timestamp}.max
  618. result << "latest-prerequisite time: #{latest_prereq}\n"
  619. result << "................................\n\n"
  620. return result
  621. end
  622. # ----------------------------------------------------------------
  623. # Rake Module Methods
  624. #
  625. class << self
  626. # Clear the task list. This cause rake to immediately forget all the
  627. # tasks that have been assigned. (Normally used in the unit tests.)
  628. def clear
  629. Rake.application.clear
  630. end
  631. # List of all defined tasks.
  632. def tasks
  633. Rake.application.tasks
  634. end
  635. # Return a task with the given name. If the task is not currently
  636. # known, try to synthesize one from the defined rules. If no rules are
  637. # found, but an existing file matches the task name, assume it is a file
  638. # task with no dependencies or actions.
  639. def [](task_name)
  640. Rake.application[task_name]
  641. end
  642. # TRUE if the task name is already defined.
  643. def task_defined?(task_name)
  644. Rake.application.lookup(task_name) != nil
  645. end
  646. # Define a task given +args+ and an option block. If a rule with the
  647. # given name already exists, the prerequisites and actions are added to
  648. # the existing task. Returns the defined task.
  649. def define_task(*args, &block)
  650. Rake.application.define_task(self, *args, &block)
  651. end
  652. # Define a rule for synthesizing tasks.
  653. def create_rule(*args, &block)
  654. Rake.application.create_rule(*args, &block)
  655. end
  656. # Apply the scope to the task name according to the rules for
  657. # this kind of task. Generic tasks will accept the scope as
  658. # part of the name.
  659. def scope_name(scope, task_name)
  660. (scope + [task_name]).join(':')
  661. end
  662. end # class << Rake::Task
  663. end # class Rake::Task
  664. ###########################################################################
  665. # A FileTask is a task that includes time based dependencies. If any of a
  666. # FileTask's prerequisites have a timestamp that is later than the file
  667. # represented by this task, then the file must be rebuilt (using the
  668. # supplied actions).
  669. #
  670. class FileTask < Task
  671. # Is this file task needed? Yes if it doesn't exist, or if its time stamp
  672. # is out of date.
  673. def needed?
  674. ! File.exist?(name) || out_of_date?(timestamp)
  675. end
  676. # Time stamp for file task.
  677. def timestamp
  678. if File.exist?(name)
  679. File.mtime(name.to_s)
  680. else
  681. Rake::EARLY
  682. end
  683. end
  684. private
  685. # Are there any prerequisites with a later time than the given time stamp?
  686. def out_of_date?(stamp)
  687. @prerequisites.any? { |n| application[n].timestamp > stamp}
  688. end
  689. # ----------------------------------------------------------------
  690. # Task class methods.
  691. #
  692. class << self
  693. # Apply the scope to the task name according to the rules for this kind
  694. # of task. File based tasks ignore the scope when creating the name.
  695. def scope_name(scope, task_name)
  696. task_name
  697. end
  698. end
  699. end # class Rake::FileTask
  700. ###########################################################################
  701. # A FileCreationTask is a file task that when used as a dependency will be
  702. # needed if and only if the file has not been created. Once created, it is
  703. # not re-triggered if any of its dependencies are newer, nor does trigger
  704. # any rebuilds of tasks that depend on it whenever it is updated.
  705. #
  706. class FileCreationTask < FileTask
  707. # Is this file task needed? Yes if it doesn't exist.
  708. def needed?
  709. ! File.exist?(name)
  710. end
  711. # Time stamp for file creation task. This time stamp is earlier
  712. # than any other time stamp.
  713. def timestamp
  714. Rake::EARLY
  715. end
  716. end
  717. ###########################################################################
  718. # Same as a regular task, but the immediate prerequisites are done in
  719. # parallel using Ruby threads.
  720. #
  721. class MultiTask < Task
  722. private
  723. def invoke_prerequisites(args, invocation_chain)
  724. threads = @prerequisites.collect { |p|
  725. Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
  726. }
  727. threads.each { |t| t.join }
  728. end
  729. end
  730. end # module Rake
  731. ## ###########################################################################
  732. # Task Definition Functions ...
  733. # Declare a basic task.
  734. #
  735. # Example:
  736. # task :clobber => [:clean] do
  737. # rm_rf "html"
  738. # end
  739. #
  740. def task(*args, &block)
  741. Rake::Task.define_task(*args, &block)
  742. end
  743. # Declare a file task.
  744. #
  745. # Example:
  746. # file "config.cfg" => ["config.template"] do
  747. # open("config.cfg", "w") do |outfile|
  748. # open("config.template") do |infile|
  749. # while line = infile.gets
  750. # outfile.puts line
  751. # end
  752. # end
  753. # end
  754. # end
  755. #
  756. def file(*args, &block)
  757. Rake::FileTask.define_task(*args, &block)
  758. end
  759. # Declare a file creation task.
  760. # (Mainly used for the directory command).
  761. def file_create(args, &block)
  762. Rake::FileCreationTask.define_task(args, &block)
  763. end
  764. # Declare a set of files tasks to create the given directories on demand.
  765. #
  766. # Example:
  767. # directory "testdata/doc"
  768. #
  769. def directory(dir)
  770. Rake.each_dir_parent(dir) do |d|
  771. file_create d do |t|
  772. mkdir_p t.name if ! File.exist?(t.name)
  773. end
  774. end
  775. end
  776. # Declare a task that performs its prerequisites in parallel. Multitasks does
  777. # *not* guarantee that its prerequisites will execute in any given order
  778. # (which is obvious when you think about it)
  779. #
  780. # Example:
  781. # multitask :deploy => [:deploy_gem, :deploy_rdoc]
  782. #
  783. def multitask(args, &block)
  784. Rake::MultiTask.define_task(args, &block)
  785. end
  786. # Create a new rake namespace and use it for evaluating the given block.
  787. # Returns a NameSpace object that can be used to lookup tasks defined in the
  788. # namespace.
  789. #
  790. # E.g.
  791. #
  792. # ns = namespace "nested" do
  793. # task :run
  794. # end
  795. # task_run = ns[:run] # find :run in the given namespace.
  796. #
  797. def namespace(name=nil, &block)
  798. Rake.application.in_namespace(name, &block)
  799. end
  800. # Declare a rule for auto-tasks.
  801. #
  802. # Example:
  803. # rule '.o' => '.c' do |t|
  804. # sh %{cc -o #{t.name} #{t.source}}
  805. # end
  806. #
  807. def rule(*args, &block)
  808. Rake::Task.create_rule(*args, &block)
  809. end
  810. # Describe the next rake task.
  811. #
  812. # Example:
  813. # desc "Run the Unit Tests"
  814. # task :test => [:build]
  815. # runtests
  816. # end
  817. #
  818. def desc(description)
  819. Rake.application.last_description = description
  820. end
  821. # Import the partial Rakefiles +fn+. Imported files are loaded _after_ the
  822. # current file is completely loaded. This allows the import statement to
  823. # appear anywhere in the importing file, and yet allowing the imported files
  824. # to depend on objects defined in the importing file.
  825. #
  826. # A common use of the import statement is to include files containing
  827. # dependency declarations.
  828. #
  829. # See also the --rakelibdir command line option.
  830. #
  831. # Example:
  832. # import ".depend", "my_rules"
  833. #
  834. def import(*fns)
  835. fns.each do |fn|
  836. Rake.application.add_import(fn)
  837. end
  838. end
  839. #############################################################################
  840. # This a FileUtils extension that defines several additional commands to be
  841. # added to the FileUtils utility functions.
  842. #
  843. module FileUtils
  844. RUBY_EXT = ((RbConfig::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ?
  845. "" :
  846. RbConfig::CONFIG['EXEEXT'])
  847. RUBY = File.join(
  848. RbConfig::CONFIG['bindir'],
  849. RbConfig::CONFIG['ruby_install_name'] + RUBY_EXT).
  850. sub(/.*\s.*/m, '"\&"')
  851. OPT_TABLE['sh'] = %w(noop verbose)
  852. OPT_TABLE['ruby'] = %w(noop verbose)
  853. # Run the system command +cmd+. If multiple arguments are given the command
  854. # is not run with the shell (same semantics as Kernel::exec and
  855. # Kernel::system).
  856. #
  857. # Example:
  858. # sh %{ls -ltr}
  859. #
  860. # sh 'ls', 'file with spaces'
  861. #
  862. # # check exit status after command runs
  863. # sh %{grep pattern file} do |ok, res|
  864. # if ! ok
  865. # puts "pattern not found (status = #{res.exitstatus})"
  866. # end
  867. # end
  868. #
  869. def sh(*cmd, &block)
  870. options = (Hash === cmd.last) ? cmd.pop : {}
  871. unless block_given?
  872. show_command = cmd.join(" ")
  873. show_command = show_command[0,42] + "..." unless $trace
  874. # TODO code application logic heref show_command.length > 45
  875. block = lambda { |ok, status|
  876. ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
  877. }
  878. end
  879. if RakeFileUtils.verbose_flag == :default
  880. options[:verbose] = true
  881. else
  882. options[:verbose] ||= RakeFileUtils.verbose_flag
  883. end
  884. options[:noop] ||= RakeFileUtils.nowrite_flag
  885. rake_check_options options, :noop, :verbose
  886. rake_output_message cmd.join(" ") if options[:verbose]
  887. unless options[:noop]
  888. res = rake_system(*cmd)
  889. status = $?
  890. status = PseudoStatus.new(1) if !res && status.nil?
  891. block.call(res, status)
  892. end
  893. end
  894. def rake_system(*cmd)
  895. system(*cmd)
  896. end
  897. private :rake_system
  898. # Run a Ruby interpreter with the given arguments.
  899. #
  900. # Example:
  901. # ruby %{-pe '$_.upcase!' <README}
  902. #
  903. def ruby(*args,&block)
  904. options = (Hash === args.last) ? args.pop : {}
  905. if args.length > 1 then
  906. sh(*([RUBY] + args + [options]), &block)
  907. else
  908. sh("#{RUBY} #{args.first}", options, &block)
  909. end
  910. end
  911. LN_SUPPORTED = [true]
  912. # Attempt to do a normal file link, but fall back to a copy if the link
  913. # fails.
  914. def safe_ln(*args)
  915. unless LN_SUPPORTED[0]
  916. cp(*args)
  917. else
  918. begin
  919. ln(*args)
  920. rescue StandardError, NotImplementedError => ex
  921. LN_SUPPORTED[0] = false
  922. cp(*args)
  923. end
  924. end
  925. end
  926. # Split a file path into individual directory names.
  927. #
  928. # Example:
  929. # split_all("a/b/c") => ['a', 'b', 'c']
  930. #
  931. def split_all(path)
  932. head, tail = File.split(path)
  933. return [tail] if head == '.' || tail == '/'
  934. return [head, tail] if head == '/'
  935. return split_all(head) + [tail]
  936. end
  937. end
  938. #############################################################################
  939. # RakeFileUtils provides a custom version of the FileUtils methods that
  940. # respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
  941. #
  942. module RakeFileUtils
  943. include FileUtils
  944. class << self
  945. attr_accessor :verbose_flag, :nowrite_flag
  946. end
  947. RakeFileUtils.verbose_flag = :default
  948. RakeFileUtils.nowrite_flag = false
  949. $fileutils_verbose = true
  950. $fileutils_nowrite = false
  951. FileUtils::OPT_TABLE.each do |name, opts|
  952. default_options = []
  953. if opts.include?(:verbose) || opts.include?("verbose")
  954. default_options << ':verbose => RakeFileUtils.verbose_flag'
  955. end
  956. if opts.include?(:noop) || opts.include?("noop")
  957. default_options << ':noop => RakeFileUtils.nowrite_flag'
  958. end
  959. next if default_options.empty?
  960. module_eval(<<-EOS, __FILE__, __LINE__ + 1)
  961. def #{name}( *args, &block )
  962. super(
  963. *rake_merge_option(args,
  964. #{default_options.join(', ')}
  965. ), &block)
  966. end
  967. EOS
  968. end
  969. # Get/set the verbose flag controlling output from the FileUtils utilities.
  970. # If verbose is true, then the utility method is echoed to standard output.
  971. #
  972. # Examples:
  973. # verbose # return the current value of the verbose flag
  974. # verbose(v) # set the verbose flag to _v_.
  975. # verbose(v) { code } # Execute code with the verbose flag set temporarily to _v_.
  976. # # Return to the original value when code is done.
  977. def verbose(value=nil)
  978. oldvalue = RakeFileUtils.verbose_flag
  979. RakeFileUtils.verbose_flag = value unless value.nil?
  980. if block_given?
  981. begin
  982. yield
  983. ensure
  984. RakeFileUtils.verbose_flag = oldvalue
  985. end
  986. end
  987. RakeFileUtils.verbose_flag
  988. end
  989. # Get/set the nowrite flag controlling output from the FileUtils utilities.
  990. # If verbose is true, then the utility method is echoed to standard output.
  991. #
  992. # Examples:
  993. # nowrite # return the current value of the nowrite flag
  994. # nowrite(v) # set the nowrite flag to _v_.
  995. # nowrite(v) { code } # Execute code with the nowrite flag set temporarily to _v_.
  996. # # Return to the original value when code is done.
  997. def nowrite(value=nil)
  998. oldvalue = RakeFileUtils.nowrite_flag
  999. RakeFileUtils.nowrite_flag = value unless value.nil?
  1000. if block_given?
  1001. begin
  1002. yield
  1003. ensure
  1004. RakeFileUtils.nowrite_flag = oldvalue
  1005. end
  1006. end
  1007. oldvalue
  1008. end
  1009. # Use this function to prevent protentially destructive ruby code from
  1010. # running when the :nowrite flag is set.
  1011. #
  1012. # Example:
  1013. #
  1014. # when_writing("Building Project") do
  1015. # project.build
  1016. # end
  1017. #
  1018. # The following code will build the project under normal conditions. If the
  1019. # nowrite(true) flag is set, then the example will print:
  1020. # DRYRUN: Building Project
  1021. # instead of actually building the project.
  1022. #
  1023. def when_writing(msg=nil)
  1024. if RakeFileUtils.nowrite_flag
  1025. puts "DRYRUN: #{msg}" if msg
  1026. else
  1027. yield
  1028. end
  1029. end
  1030. # Merge the given options with the default values.
  1031. def rake_merge_option(args, defaults)
  1032. if Hash === args.last
  1033. defaults.update(args.last)
  1034. args.pop
  1035. end
  1036. args.push defaults
  1037. args
  1038. end
  1039. private :rake_merge_option
  1040. # Send the message to the default rake output (which is $stderr).
  1041. def rake_output_message(message)
  1042. $stderr.puts(message)
  1043. end
  1044. private :rake_output_message
  1045. # Check that the options do not contain options not listed in +optdecl+. An
  1046. # ArgumentError exception is thrown if non-declared options are found.
  1047. def rake_check_options(options, *optdecl)
  1048. h = options.dup
  1049. optdecl.each do |name|
  1050. h.delete name
  1051. end
  1052. raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
  1053. end
  1054. private :rake_check_options
  1055. extend self
  1056. end
  1057. #############################################################################
  1058. # Include the FileUtils file manipulation functions in the top level module,
  1059. # but mark them private so that they don't unintentionally define methods on
  1060. # other objects.
  1061. include RakeFileUtils
  1062. private(*FileUtils.instance_methods(false))
  1063. private(*RakeFileUtils.instance_methods(false))
  1064. ######################################################################
  1065. module Rake
  1066. ###########################################################################
  1067. # A FileList is essentially an array with a few helper methods defined to
  1068. # make file manipulation a bit easier.
  1069. #
  1070. # FileLists are lazy. When given a list of glob patterns for possible files
  1071. # to be included in the file list, instead of searching the file structures
  1072. # to find the files, a FileList holds the pattern for latter use.
  1073. #
  1074. # This allows us to define a number of FileList to match any number of
  1075. # files, but only search out the actual files when then FileList itself is
  1076. # actually used. The key is that the first time an element of the
  1077. # FileList/Array is requested, the pending patterns are resolved into a real
  1078. # list of file names.
  1079. #
  1080. class FileList
  1081. include Cloneable
  1082. # == Method Delegation
  1083. #
  1084. # The lazy evaluation magic of FileLists happens by implementing all the
  1085. # array specific methods to call +resolve+ before delegating the heavy
  1086. # lifting to an embedded array object (@items).
  1087. #
  1088. # In addition, there are two kinds of delegation calls. The regular kind
  1089. # delegates to the @items array and returns the result directly. Well,
  1090. # almost directly. It checks if the returned value is the @items object
  1091. # itself, and if so will return the FileList object instead.
  1092. #
  1093. # The second kind of delegation call is used in methods that normally
  1094. # return a new Array object. We want to capture the return value of these
  1095. # methods and wrap them in a new FileList object. We enumerate these
  1096. # methods in the +SPECIAL_RETURN+ list below.
  1097. # List of array methods (that are not in +Object+) that need to be
  1098. # delegated.
  1099. ARRAY_METHODS = (Array.instance_methods - (Object.instance_methods - [:<=>])).map { |n| n.to_s }
  1100. # List of additional methods that must be delegated.
  1101. MUST_DEFINE = %w[to_a inspect]
  1102. # List of methods that should not be delegated here (we define special
  1103. # versions of them explicitly below).
  1104. MUST_NOT_DEFINE = %w[to_a to_ary partition *]
  1105. # List of delegated methods that return new array values which need
  1106. # wrapping.
  1107. SPECIAL_RETURN = %w[
  1108. map collect sort sort_by select find_all reject grep
  1109. compact flatten uniq values_at
  1110. + - & |
  1111. ]
  1112. DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
  1113. # Now do the delegation.
  1114. DELEGATING_METHODS.each_with_index do |sym, i|
  1115. if SPECIAL_RETURN.include?(sym)
  1116. define_method(sym) do |*args, &block|
  1117. resolve
  1118. result = @items.send(sym, *args, &block)
  1119. FileList.new.import(result)
  1120. end
  1121. else
  1122. define_method(sym) do |*args, &block|
  1123. resolve
  1124. result = @items.send(sym, *args, &block)
  1125. result.object_id == @items.object_id ? self : result
  1126. end
  1127. end
  1128. end
  1129. # Create a file list from the globbable patterns given. If you wish to
  1130. # perform multiple includes or excludes at object build time, use the
  1131. # "yield self" pattern.
  1132. #
  1133. # Example:
  1134. # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
  1135. #
  1136. # pkg_files = FileList.new('lib/**/*') do |fl|
  1137. # fl.exclude(/\bCVS\b/)
  1138. # end
  1139. #
  1140. def initialize(*patterns)
  1141. @pending_add = []
  1142. @pending = false
  1143. @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
  1144. @exclude_procs = DEFAULT_IGNORE_PROCS.dup
  1145. @exclude_re = nil
  1146. @items = []
  1147. patterns.each { |pattern| include(pattern) }
  1148. yield self if block_given?
  1149. end
  1150. # Add file names defined by glob patterns to the file list. If an array
  1151. # is given, add each element of the array.
  1152. #
  1153. # Example:
  1154. # file_list.include("*.java", "*.cfg")
  1155. # file_list.include %w( math.c lib.h *.o )
  1156. #
  1157. def include(*filenames)
  1158. # TODO: check for pending
  1159. filenames.each do |fn|
  1160. if fn.respond_to? :to_ary
  1161. include(*fn.to_ary)
  1162. else
  1163. @pending_add << fn
  1164. end
  1165. end
  1166. @pending = true
  1167. self
  1168. end
  1169. alias :add :include
  1170. # Register a list of file name patterns that should be excluded from the
  1171. # list. Patterns may be regular expressions, glob patterns or regular
  1172. # strings. In addition, a block given to exclude will remove entries that
  1173. # return true when given to the block.
  1174. #
  1175. # Note that glob patterns are expanded against the file system. If a file
  1176. # is explicitly added to a file list, but does not exist in the file
  1177. # system, then an glob pattern in the exclude list will not exclude the
  1178. # file.
  1179. #
  1180. # Examples:
  1181. # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
  1182. # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
  1183. #
  1184. # If "a.c" is a file, then ...
  1185. # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
  1186. #
  1187. # If "a.c" is not a file, then ...
  1188. # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
  1189. #
  1190. def exclude(*patterns, &block)
  1191. patterns.each do |pat|
  1192. @exclude_patterns << pat
  1193. end
  1194. if block_given?
  1195. @exclude_procs << block
  1196. end
  1197. resolve_exclude if ! @pending
  1198. self
  1199. end
  1200. # Clear all the exclude patterns so that we exclude nothing.
  1201. def clear_exclude
  1202. @exclude_patterns = []
  1203. @exclude_procs = []
  1204. calculate_exclude_regexp if ! @pending
  1205. self
  1206. end
  1207. # Define equality.
  1208. def ==(array)
  1209. to_ary == array
  1210. end
  1211. # Return the internal array object.
  1212. def to_a
  1213. resolve
  1214. @items
  1215. end
  1216. # Return the internal array object.
  1217. def to_ary
  1218. to_a
  1219. end
  1220. # Lie about our class.
  1221. def is_a?(klass)
  1222. klass == Array || super(klass)
  1223. end
  1224. alias kind_of? is_a?
  1225. # Redefine * to return either a string or a new file list.
  1226. def *(other)
  1227. result = @items * other
  1228. case result
  1229. when Array
  1230. FileList.new.import(result)
  1231. else
  1232. result
  1233. end
  1234. end
  1235. # Resolve all the pending adds now.
  1236. def resolve
  1237. if @pending
  1238. @pending = false
  1239. @pending_add.each do |fn| resolve_add(fn) end
  1240. @pending_add = []
  1241. resolve_exclude
  1242. end
  1243. self
  1244. end
  1245. def calculate_exclude_regexp
  1246. ignores = []
  1247. @exclude_patterns.each do |pat|
  1248. case pat
  1249. when Regexp
  1250. ignores << pat
  1251. when /[*?]/
  1252. Dir[pat].each do |p| ignores << p end
  1253. else
  1254. ignores << Regexp.quote(pat)
  1255. end
  1256. end
  1257. if ignores.empty?
  1258. @exclude_re = /^$/
  1259. else
  1260. re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
  1261. @exclude_re = Regexp.new(re_str)
  1262. end
  1263. end
  1264. def resolve_add(fn)
  1265. case fn
  1266. when %r{[*?\[\{]}
  1267. add_matching(fn)
  1268. else
  1269. self << fn
  1270. end
  1271. end
  1272. private :resolve_add
  1273. def resolve_exclude
  1274. calculate_exclude_regexp
  1275. reject! { |fn| exclude?(fn) }
  1276. self
  1277. end
  1278. private :resolve_exclude
  1279. # Return a new FileList with the results of running +sub+ against each
  1280. # element of the oringal list.
  1281. #
  1282. # Example:
  1283. # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
  1284. #
  1285. def sub(pat, rep)
  1286. inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
  1287. end
  1288. # Return a new FileList with the results of running +gsub+ against each
  1289. # element of the original list.
  1290. #
  1291. # Example:
  1292. # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
  1293. # => ['lib\\test\\file', 'x\\y']
  1294. #
  1295. def gsub(pat, rep)
  1296. inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
  1297. end
  1298. # Same as +sub+ except that the oringal file list is modified.
  1299. def sub!(pat, rep)
  1300. each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
  1301. self
  1302. end
  1303. # Same as +gsub+ except that the original file list is modified.
  1304. def gsub!(pat, rep)
  1305. each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
  1306. self
  1307. end
  1308. # Apply the pathmap spec to each of the included file names, returning a
  1309. # new file list with the modified paths. (See String#pathmap for
  1310. # details.)
  1311. def pathmap(spec=nil)
  1312. collect { |fn| fn.pathmap(spec) }
  1313. end
  1314. # Return a new FileList with <tt>String#ext</tt> method applied
  1315. # to each member of the array.
  1316. #
  1317. # This method is a shortcut for:
  1318. #
  1319. # array.collect { |item| item.ext(newext) }
  1320. #
  1321. # +ext+ is a user added method for the Array class.
  1322. def ext(newext='')
  1323. collect { |fn| fn.ext(newext) }
  1324. end
  1325. # Grep each of the files in the filelist using the given pattern. If a
  1326. # block is given, call the block on each matching line, passing the file
  1327. # name, line number, and the matching line of text. If no block is given,
  1328. # a standard emac style file:linenumber:line message will be printed to
  1329. # standard out.
  1330. def egrep(pattern, *options)
  1331. each do |fn|
  1332. open(fn, "rb", *options) do |inf|
  1333. count = 0
  1334. inf.each do |line|
  1335. count += 1
  1336. if pattern.match(line)
  1337. if block_given?
  1338. yield fn, count, line
  1339. else
  1340. puts "#{fn}:#{count}:#{line}"
  1341. end
  1342. end
  1343. end
  1344. end
  1345. end
  1346. end
  1347. # Return a new file list that only contains file names from the current
  1348. # file list that exist on the file system.
  1349. def existing
  1350. select { |fn| File.exist?(fn) }
  1351. end
  1352. # Modify the current file list so that it contains only file name that
  1353. # exist on the file system.
  1354. def existing!
  1355. resolve
  1356. @items = @items.select { |fn| File.exist?(fn) }
  1357. self
  1358. end
  1359. # FileList version of partition. Needed because the nested arrays should
  1360. # be FileLists in this version.
  1361. def partition(&block) # :nodoc:
  1362. resolve
  1363. result = @items.partition(&block)
  1364. [
  1365. FileList.new.import(result[0]),
  1366. FileList.new.import(result[1]),
  1367. ]
  1368. end
  1369. # Convert a FileList to a string by joining all elements with a space.
  1370. def to_s
  1371. resolve
  1372. self.join(' ')
  1373. end
  1374. # Add matching glob patterns.
  1375. def add_matching(pattern)
  1376. Dir[pattern].each do |fn|
  1377. self << fn unless exclude?(fn)
  1378. end
  1379. end
  1380. private :add_matching
  1381. # Should the given file name be excluded?
  1382. def exclude?(fn)
  1383. calculate_exclude_regexp unless @exclude_re
  1384. fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
  1385. end
  1386. DEFAULT_IGNORE_PATTERNS = [
  1387. /(^|[\/\\])CVS([\/\\]|$)/,
  1388. /(^|[\/\\])\.svn([\/\\]|$)/,
  1389. /\.bak$/,
  1390. /~$/
  1391. ]
  1392. DEFAULT_IGNORE_PROCS = [
  1393. proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
  1394. ]
  1395. # @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
  1396. def import(array)
  1397. @items = array
  1398. self
  1399. end
  1400. class << self
  1401. # Create a new file list including the files listed. Similar to:
  1402. #
  1403. # FileList.new(*args)
  1404. def [](*args)
  1405. new(*args)
  1406. end
  1407. end
  1408. end # FileList
  1409. end
  1410. module Rake
  1411. class << self
  1412. # Yield each file or directory component.
  1413. def each_dir_parent(dir) # :nodoc:
  1414. old_length = nil
  1415. while dir != '.' && dir.length != old_length
  1416. yield(dir)
  1417. old_length = dir.length
  1418. dir = File.dirname(dir)
  1419. end
  1420. end
  1421. end
  1422. end # module Rake
  1423. # Alias FileList to be available at the top level.
  1424. FileList = Rake::FileList
  1425. #############################################################################
  1426. module Rake
  1427. # Default Rakefile loader used by +import+.
  1428. class DefaultLoader
  1429. def load(fn)
  1430. Kernel.load(File.expand_path(fn))
  1431. end
  1432. end
  1433. # EarlyTime is a fake timestamp that occurs _before_ any other time value.
  1434. class EarlyTime
  1435. include Comparable
  1436. include Singleton
  1437. def <=>(other)
  1438. -1
  1439. end
  1440. def to_s
  1441. "<EARLY TIME>"
  1442. end
  1443. end
  1444. EARLY = EarlyTime.instance
  1445. end # module Rake
  1446. #############################################################################
  1447. # Extensions to time to allow comparisons with an early time class.
  1448. #
  1449. class Time
  1450. alias rake_original_time_compare :<=>
  1451. def <=>(other)
  1452. if Rake::EarlyTime === other
  1453. - other.<=>(self)
  1454. else
  1455. rake_original_time_compare(other)
  1456. end
  1457. end
  1458. end # class Time
  1459. module Rake
  1460. ####################################################################
  1461. # The NameSpace class will lookup task names in the the scope
  1462. # defined by a +namespace+ command.
  1463. #
  1464. class NameSpace
  1465. # Create a namespace lookup object using the given task manager
  1466. # and the list of scopes.
  1467. def initialize(task_manager, scope_list)
  1468. @task_manager = task_manager
  1469. @scope = scope_list.dup
  1470. end
  1471. # Lookup a task named +name+ in the namespace.
  1472. def [](name)
  1473. @task_manager.lookup(name, @scope)
  1474. end
  1475. # Return the list of tasks defined in this and nested namespaces.
  1476. def tasks
  1477. @task_manager.tasks_in_scope(@scope)
  1478. end
  1479. end # NameSpace
  1480. ####################################################################
  1481. # The TaskManager module is a mixin for managing tasks.
  1482. module TaskManager
  1483. # Track the last comment made in the Rakefile.
  1484. attr_accessor :last_description
  1485. alias :last_comment :last_description # Backwards compatibility
  1486. def initialize
  1487. super
  1488. @tasks = Hash.new
  1489. @rules = Array.new
  1490. @scope = Array.new
  1491. @last_description = nil
  1492. end
  1493. def create_rule(*args, &block)
  1494. pattern, arg_names, deps = resolve_args(args)
  1495. pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
  1496. @rules << [pattern, deps, block]
  1497. end
  1498. def define_task(task_class, *args, &block)
  1499. task_name, arg_names, deps = resolve_args(args)
  1500. task_name = task_class.scope_name(@scope, task_name)
  1501. deps = [deps] unless deps.respond_to?(:to_ary)
  1502. deps = deps.collect {|d| d.to_s }
  1503. task = intern(task_class, task_name)
  1504. task.set_arg_names(arg_names) unless arg_names.empty?
  1505. task.add_description(@last_description)
  1506. @last_description = nil
  1507. task.enhance(deps, &block)
  1508. task
  1509. end
  1510. # Lookup a task. Return an existing task if found, otherwise
  1511. # create a task of the current type.
  1512. def intern(task_class, task_name)
  1513. @tasks[task_name.to_s] ||= task_class.new(task_name, self)
  1514. end
  1515. # Find a matching task for +task_name+.
  1516. def [](task_name, scopes=nil)
  1517. task_name = task_name.to_s
  1518. self.lookup(task_name, scopes) or
  1519. enhance_with_matching_rule(task_name) or
  1520. synthesize_file_task(task_name) or
  1521. fail "Don't know how to build task '#{task_name}'"
  1522. end
  1523. def synthesize_file_task(task_name)
  1524. return nil unless File.exist?(task_name)
  1525. define_task(Rake::FileTask, task_name)
  1526. end
  1527. # Resolve the arguments for a task/rule. Returns a triplet of
  1528. # [task_name, arg_name_list, prerequisites].
  1529. def resolve_args(args)
  1530. if args.last.is_a?(Hash)
  1531. deps = args.pop
  1532. resolve_args_with_dependencies(args, deps)
  1533. else
  1534. resolve_args_without_dependencies(args)
  1535. end
  1536. end
  1537. # Resolve task arguments for a task or rule when there are no
  1538. # dependencies declared.
  1539. #
  1540. # The patterns recognized by this argument resolving function are:
  1541. #
  1542. # task :t
  1543. # task :t, [:a]
  1544. # task :t, :a (deprecated)
  1545. #
  1546. def resolve_args_without_dependencies(args)
  1547. task_name = args.shift
  1548. if args.size == 1 && args.first.respond_to?(:to_ary)
  1549. arg_names = args.first.to_ary
  1550. else
  1551. arg_names = args
  1552. end
  1553. [task_name, arg_names, []]
  1554. end
  1555. private :

Large files files are truncated, but you can click here to view the full file