PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/External.LCA_RESTRICTED/Languages/Ruby/ruby19/lib/ruby/gems/1.9.1/gems/rake-0.8.7/lib/rake.rb

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

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