PageRenderTime 75ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/mkvtoolnix-5.5.0/rake.d/vendor/drake-0.8.7.0.2.4/lib/rake.rb

#
Ruby | 2563 lines | 1713 code | 241 blank | 609 comment | 127 complexity | fc1da04aaff5ec01d19fe5c0a89d3d35 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0, GPL-2.0

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.0.2.4'
  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. attr_reader :value # :nodoc:
  370. def initialize(value, tail)
  371. @value = value
  372. @tail = tail
  373. end
  374. def member?(obj)
  375. @value == obj || @tail.member?(obj)
  376. end
  377. def append(value)
  378. if member?(value)
  379. fail RuntimeError, "Circular dependency detected: #{to_s} => #{value}"
  380. end
  381. self.class.new(value, self)
  382. end
  383. def to_s
  384. "#{prefix}#{@value}"
  385. end
  386. def self.append(value, chain)
  387. chain.append(value)
  388. end
  389. private
  390. def prefix
  391. "#{@tail.to_s} => "
  392. end
  393. class EmptyInvocationChain
  394. def member?(obj)
  395. false
  396. end
  397. def append(value)
  398. InvocationChain.new(value, self)
  399. end
  400. def to_s
  401. "TOP"
  402. end
  403. end
  404. EMPTY = EmptyInvocationChain.new
  405. end # class InvocationChain
  406. end # module Rake
  407. module Rake
  408. ###########################################################################
  409. # A Task is the basic unit of work in a Rakefile. Tasks have associated
  410. # actions (possibly more than one) and a list of prerequisites. When
  411. # invoked, a task will first ensure that all of its prerequisites have an
  412. # opportunity to run and then it will execute its own actions.
  413. #
  414. # Tasks are not usually created directly using the new method, but rather
  415. # use the +file+ and +task+ convenience methods.
  416. #
  417. class Task
  418. # List of prerequisites for a task.
  419. attr_reader :prerequisites
  420. # List of actions attached to a task.
  421. attr_reader :actions
  422. # Application owning this task.
  423. attr_accessor :application
  424. # Comment for this task. Restricted to a single line of no more than 50
  425. # characters.
  426. attr_reader :comment
  427. # Full text of the (possibly multi-line) comment.
  428. attr_reader :full_comment
  429. # Array of nested namespaces names used for task lookup by this task.
  430. attr_reader :scope
  431. # Return task name
  432. def to_s
  433. name
  434. end
  435. def inspect
  436. "<#{self.class} #{name} => [#{prerequisites.join(', ')}]>"
  437. end
  438. # List of sources for task.
  439. attr_writer :sources
  440. def sources
  441. @sources ||= []
  442. end
  443. # First source from a rule (nil if no sources)
  444. def source
  445. @sources.first if defined?(@sources)
  446. end
  447. # Create a task named +task_name+ with no actions or prerequisites. Use
  448. # +enhance+ to add actions and prerequisites.
  449. def initialize(task_name, app)
  450. @name = task_name.to_s
  451. @prerequisites = []
  452. @actions = []
  453. @already_invoked = false
  454. @full_comment = nil
  455. @comment = nil
  456. @lock = Monitor.new
  457. @application = app
  458. @scope = app.current_scope
  459. @arg_names = nil
  460. end
  461. # Enhance a task with prerequisites or actions. Returns self.
  462. def enhance(deps=nil, &block)
  463. @prerequisites |= deps if deps
  464. @actions << block if block_given?
  465. self
  466. end
  467. # Name of the task, including any namespace qualifiers.
  468. def name
  469. @name.to_s
  470. end
  471. # Name of task with argument list description.
  472. def name_with_args # :nodoc:
  473. if arg_description
  474. "#{name}#{arg_description}"
  475. else
  476. name
  477. end
  478. end
  479. # Argument description (nil if none).
  480. def arg_description # :nodoc:
  481. @arg_names ? "[#{(arg_names || []).join(',')}]" : nil
  482. end
  483. # Name of arguments for this task.
  484. def arg_names
  485. @arg_names || []
  486. end
  487. # Reenable the task, allowing its tasks to be executed if the task
  488. # is invoked again.
  489. def reenable
  490. @already_invoked = false
  491. end
  492. # Clear the existing prerequisites and actions of a rake task.
  493. def clear
  494. clear_prerequisites
  495. clear_actions
  496. self
  497. end
  498. # Clear the existing prerequisites of a rake task.
  499. def clear_prerequisites
  500. prerequisites.clear
  501. self
  502. end
  503. # Clear the existing actions on a rake task.
  504. def clear_actions
  505. actions.clear
  506. self
  507. end
  508. def invoke_serial(*args) # :nodoc:
  509. task_args = TaskArguments.new(arg_names, args)
  510. invoke_with_call_chain(task_args, InvocationChain::EMPTY)
  511. end
  512. # Invoke the task if it is needed. Prerequites are invoked first.
  513. def invoke(*args)
  514. if application.options.threads == 1
  515. invoke_serial(*args)
  516. else
  517. invoke_parallel(*args)
  518. end
  519. end
  520. # Same as invoke, but explicitly pass a call chain to detect
  521. # circular dependencies.
  522. def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
  523. new_chain = InvocationChain.append(self, invocation_chain)
  524. if application.options.threads == 1
  525. @lock.synchronize do
  526. return unless prepare_invoke
  527. invoke_prerequisites(task_args, new_chain)
  528. execute(task_args) if needed?
  529. end
  530. else
  531. return unless prepare_invoke
  532. invoke_with_call_chain_collector(task_args, new_chain, invocation_chain)
  533. end
  534. end
  535. protected :invoke_with_call_chain
  536. def prepare_invoke # :nodoc:
  537. if application.options.randomize
  538. @prerequisites = @prerequisites.sort_by { rand }
  539. end
  540. if application.options.trace
  541. puts "** Invoke #{name} #{format_trace_flags}"
  542. end
  543. return if @already_invoked
  544. @already_invoked = true
  545. end
  546. # Invoke all the prerequisites of a task.
  547. def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
  548. @prerequisites.each { |n|
  549. invoke_prerequisite(n, task_args, invocation_chain)
  550. }
  551. end
  552. def invoke_prerequisite(prereq_name, task_args, invocation_chain) #:nodoc:
  553. prereq = application[prereq_name, @scope]
  554. prereq_args = task_args.new_scope(prereq.arg_names)
  555. prereq.invoke_with_call_chain(prereq_args, invocation_chain)
  556. prereq
  557. end
  558. # Format the trace flags for display.
  559. def format_trace_flags
  560. flags = []
  561. flags << "first_time" unless @already_invoked
  562. flags << "not_needed" unless needed?
  563. flags.empty? ? "" : "(" + flags.join(", ") + ")"
  564. end
  565. private :format_trace_flags
  566. # Execute the actions associated with this task.
  567. def execute(args=nil)
  568. args ||= EMPTY_TASK_ARGS
  569. if application.options.dryrun
  570. puts "** Execute (dry run) #{name}"
  571. return
  572. end
  573. if application.options.trace
  574. puts "** Execute #{name}"
  575. end
  576. application.enhance_with_matching_rule(name) if @actions.empty?
  577. @actions.each do |act|
  578. case act.arity
  579. when 1
  580. act.call(self)
  581. else
  582. act.call(self, args)
  583. end
  584. end
  585. end
  586. # Is this task needed?
  587. def needed?
  588. true
  589. end
  590. # Timestamp for this task. Basic tasks return the current time for their
  591. # time stamp. Other tasks can be more sophisticated.
  592. def timestamp
  593. @prerequisites.collect { |p| application[p].timestamp }.max || Time.now
  594. end
  595. # Add a description to the task. The description can consist of an option
  596. # argument list (enclosed brackets) and an optional comment.
  597. def add_description(description)
  598. return if ! description
  599. comment = description.strip
  600. add_comment(comment) if comment && ! comment.empty?
  601. end
  602. # Writing to the comment attribute is the same as adding a description.
  603. def comment=(description)
  604. add_description(description)
  605. end
  606. # Add a comment to the task. If a comment alread exists, separate
  607. # the new comment with " / ".
  608. def add_comment(comment)
  609. if @full_comment
  610. @full_comment << " / "
  611. else
  612. @full_comment = ''
  613. end
  614. @full_comment << comment
  615. if @full_comment =~ /\A([^.]+?\.)( |$)/
  616. @comment = $1
  617. else
  618. @comment = @full_comment
  619. end
  620. end
  621. private :add_comment
  622. # Set the names of the arguments for this task. +args+ should be
  623. # an array of symbols, one for each argument name.
  624. def set_arg_names(args)
  625. @arg_names = args.map { |a| a.to_sym }
  626. end
  627. # Return a string describing the internal state of a task. Useful for
  628. # debugging.
  629. def investigation
  630. result = "------------------------------\n"
  631. result << "Investigating #{name}\n"
  632. result << "class: #{self.class}\n"
  633. result << "task needed: #{needed?}\n"
  634. result << "timestamp: #{timestamp}\n"
  635. result << "pre-requisites: \n"
  636. prereqs = @prerequisites.collect {|name| application[name]}
  637. prereqs.sort! {|a,b| a.timestamp <=> b.timestamp}
  638. prereqs.each do |p|
  639. result << "--#{p.name} (#{p.timestamp})\n"
  640. end
  641. latest_prereq = @prerequisites.collect{|n| application[n].timestamp}.max
  642. result << "latest-prerequisite time: #{latest_prereq}\n"
  643. result << "................................\n\n"
  644. return result
  645. end
  646. # ----------------------------------------------------------------
  647. # Rake Module Methods
  648. #
  649. class << self
  650. # Clear the task list. This cause rake to immediately forget all the
  651. # tasks that have been assigned. (Normally used in the unit tests.)
  652. def clear
  653. Rake.application.clear
  654. end
  655. # List of all defined tasks.
  656. def tasks
  657. Rake.application.tasks
  658. end
  659. # Return a task with the given name. If the task is not currently
  660. # known, try to synthesize one from the defined rules. If no rules are
  661. # found, but an existing file matches the task name, assume it is a file
  662. # task with no dependencies or actions.
  663. def [](task_name)
  664. Rake.application[task_name]
  665. end
  666. # TRUE if the task name is already defined.
  667. def task_defined?(task_name)
  668. Rake.application.lookup(task_name) != nil
  669. end
  670. # Define a task given +args+ and an option block. If a rule with the
  671. # given name already exists, the prerequisites and actions are added to
  672. # the existing task. Returns the defined task.
  673. def define_task(*args, &block)
  674. Rake.application.define_task(self, *args, &block)
  675. end
  676. # Define a rule for synthesizing tasks.
  677. def create_rule(*args, &block)
  678. Rake.application.create_rule(*args, &block)
  679. end
  680. # Apply the scope to the task name according to the rules for
  681. # this kind of task. Generic tasks will accept the scope as
  682. # part of the name.
  683. def scope_name(scope, task_name)
  684. (scope + [task_name]).join(':')
  685. end
  686. end # class << Rake::Task
  687. end # class Rake::Task
  688. ###########################################################################
  689. # A FileTask is a task that includes time based dependencies. If any of a
  690. # FileTask's prerequisites have a timestamp that is later than the file
  691. # represented by this task, then the file must be rebuilt (using the
  692. # supplied actions).
  693. #
  694. class FileTask < Task
  695. # Is this file task needed? Yes if it doesn't exist, or if its time stamp
  696. # is out of date.
  697. def needed?
  698. ! File.exist?(name) || out_of_date?(timestamp)
  699. end
  700. # Time stamp for file task.
  701. def timestamp
  702. if File.exist?(name)
  703. File.mtime(name.to_s)
  704. else
  705. Rake::EARLY
  706. end
  707. end
  708. private
  709. # Are there any prerequisites with a later time than the given time stamp?
  710. def out_of_date?(stamp)
  711. @prerequisites.any? { |n| application[n].timestamp > stamp}
  712. end
  713. # ----------------------------------------------------------------
  714. # Task class methods.
  715. #
  716. class << self
  717. # Apply the scope to the task name according to the rules for this kind
  718. # of task. File based tasks ignore the scope when creating the name.
  719. def scope_name(scope, task_name)
  720. task_name
  721. end
  722. end
  723. end # class Rake::FileTask
  724. ###########################################################################
  725. # A FileCreationTask is a file task that when used as a dependency will be
  726. # needed if and only if the file has not been created. Once created, it is
  727. # not re-triggered if any of its dependencies are newer, nor does trigger
  728. # any rebuilds of tasks that depend on it whenever it is updated.
  729. #
  730. class FileCreationTask < FileTask
  731. # Is this file task needed? Yes if it doesn't exist.
  732. def needed?
  733. ! File.exist?(name)
  734. end
  735. # Time stamp for file creation task. This time stamp is earlier
  736. # than any other time stamp.
  737. def timestamp
  738. Rake::EARLY
  739. end
  740. end
  741. ###########################################################################
  742. # Same as a regular task, but the immediate prerequisites are done in
  743. # parallel using Ruby threads.
  744. #
  745. class MultiTask < Task
  746. private
  747. def invoke_prerequisites(args, invocation_chain)
  748. threads = @prerequisites.collect { |p|
  749. Thread.new(p) { |r| application[r].invoke_with_call_chain(args, invocation_chain) }
  750. }
  751. threads.each { |t| t.join }
  752. end
  753. end
  754. end # module Rake
  755. ## ###########################################################################
  756. # Task Definition Functions ...
  757. # Declare a basic task.
  758. #
  759. # Example:
  760. # task :clobber => [:clean] do
  761. # rm_rf "html"
  762. # end
  763. #
  764. def task(*args, &block)
  765. Rake::Task.define_task(*args, &block)
  766. end
  767. # Declare a file task.
  768. #
  769. # Example:
  770. # file "config.cfg" => ["config.template"] do
  771. # open("config.cfg", "w") do |outfile|
  772. # open("config.template") do |infile|
  773. # while line = infile.gets
  774. # outfile.puts line
  775. # end
  776. # end
  777. # end
  778. # end
  779. #
  780. def file(*args, &block)
  781. Rake::FileTask.define_task(*args, &block)
  782. end
  783. # Declare a file creation task.
  784. # (Mainly used for the directory command).
  785. def file_create(args, &block)
  786. Rake::FileCreationTask.define_task(args, &block)
  787. end
  788. # Declare a set of files tasks to create the given directories on demand.
  789. #
  790. # Example:
  791. # directory "testdata/doc"
  792. #
  793. def directory(dir)
  794. Rake.each_dir_parent(dir) do |d|
  795. file_create d do |t|
  796. mkdir_p t.name if ! File.exist?(t.name)
  797. end
  798. end
  799. end
  800. # Declare a task that performs its prerequisites in parallel. Multitasks does
  801. # *not* guarantee that its prerequisites will execute in any given order
  802. # (which is obvious when you think about it)
  803. #
  804. # Example:
  805. # multitask :deploy => [:deploy_gem, :deploy_rdoc]
  806. #
  807. def multitask(args, &block)
  808. Rake::MultiTask.define_task(args, &block)
  809. end
  810. # Create a new rake namespace and use it for evaluating the given block.
  811. # Returns a NameSpace object that can be used to lookup tasks defined in the
  812. # namespace.
  813. #
  814. # E.g.
  815. #
  816. # ns = namespace "nested" do
  817. # task :run
  818. # end
  819. # task_run = ns[:run] # find :run in the given namespace.
  820. #
  821. def namespace(name=nil, &block)
  822. Rake.application.in_namespace(name, &block)
  823. end
  824. # Declare a rule for auto-tasks.
  825. #
  826. # Example:
  827. # rule '.o' => '.c' do |t|
  828. # sh %{cc -o #{t.name} #{t.source}}
  829. # end
  830. #
  831. def rule(*args, &block)
  832. Rake::Task.create_rule(*args, &block)
  833. end
  834. # Describe the next rake task.
  835. #
  836. # Example:
  837. # desc "Run the Unit Tests"
  838. # task :test => [:build]
  839. # runtests
  840. # end
  841. #
  842. def desc(description)
  843. Rake.application.last_description = description
  844. end
  845. # Import the partial Rakefiles +fn+. Imported files are loaded _after_ the
  846. # current file is completely loaded. This allows the import statement to
  847. # appear anywhere in the importing file, and yet allowing the imported files
  848. # to depend on objects defined in the importing file.
  849. #
  850. # A common use of the import statement is to include files containing
  851. # dependency declarations.
  852. #
  853. # See also the --rakelibdir command line option.
  854. #
  855. # Example:
  856. # import ".depend", "my_rules"
  857. #
  858. def import(*fns)
  859. fns.each do |fn|
  860. Rake.application.add_import(fn)
  861. end
  862. end
  863. #############################################################################
  864. # This a FileUtils extension that defines several additional commands to be
  865. # added to the FileUtils utility functions.
  866. #
  867. module FileUtils
  868. RUBY_EXT = ((Config::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ?
  869. "" :
  870. Config::CONFIG['EXEEXT'])
  871. RUBY = File.join(
  872. Config::CONFIG['bindir'],
  873. Config::CONFIG['ruby_install_name'] + RUBY_EXT).
  874. sub(/.*\s.*/m, '"\&"')
  875. OPT_TABLE['sh'] = %w(noop verbose)
  876. OPT_TABLE['ruby'] = %w(noop verbose)
  877. # Run the system command +cmd+. If multiple arguments are given the command
  878. # is not run with the shell (same semantics as Kernel::exec and
  879. # Kernel::system).
  880. #
  881. # Example:
  882. # sh %{ls -ltr}
  883. #
  884. # sh 'ls', 'file with spaces'
  885. #
  886. # # check exit status after command runs
  887. # sh %{grep pattern file} do |ok, res|
  888. # if ! ok
  889. # puts "pattern not found (status = #{res.exitstatus})"
  890. # end
  891. # end
  892. #
  893. def sh(*cmd, &block)
  894. options = (Hash === cmd.last) ? cmd.pop : {}
  895. unless block_given?
  896. show_command = cmd.join(" ")
  897. show_command = show_command[0,42] + "..." unless $trace
  898. # TODO code application logic heref show_command.length > 45
  899. block = lambda { |ok, status|
  900. ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
  901. }
  902. end
  903. if RakeFileUtils.verbose_flag == :default
  904. options[:verbose] = true
  905. else
  906. options[:verbose] ||= RakeFileUtils.verbose_flag
  907. end
  908. options[:noop] ||= RakeFileUtils.nowrite_flag
  909. rake_check_options options, :noop, :verbose
  910. rake_output_message cmd.join(" ") if options[:verbose]
  911. unless options[:noop]
  912. res = rake_system(*cmd)
  913. status = $?
  914. status = PseudoStatus.new(1) if !res && status.nil?
  915. block.call(res, status)
  916. end
  917. end
  918. def rake_system(*cmd)
  919. Rake::AltSystem.system(*cmd)
  920. end
  921. private :rake_system
  922. # Run a Ruby interpreter with the given arguments.
  923. #
  924. # Example:
  925. # ruby %{-pe '$_.upcase!' <README}
  926. #
  927. def ruby(*args,&block)
  928. options = (Hash === args.last) ? args.pop : {}
  929. if args.length > 1 then
  930. sh(*([RUBY] + args + [options]), &block)
  931. else
  932. sh("#{RUBY} #{args.first}", options, &block)
  933. end
  934. end
  935. LN_SUPPORTED = [true]
  936. # Attempt to do a normal file link, but fall back to a copy if the link
  937. # fails.
  938. def safe_ln(*args)
  939. unless LN_SUPPORTED[0]
  940. cp(*args)
  941. else
  942. begin
  943. ln(*args)
  944. rescue StandardError, NotImplementedError => ex
  945. LN_SUPPORTED[0] = false
  946. cp(*args)
  947. end
  948. end
  949. end
  950. # Split a file path into individual directory names.
  951. #
  952. # Example:
  953. # split_all("a/b/c") => ['a', 'b', 'c']
  954. #
  955. def split_all(path)
  956. head, tail = File.split(path)
  957. return [tail] if head == '.' || tail == '/'
  958. return [head, tail] if head == '/'
  959. return split_all(head) + [tail]
  960. end
  961. end
  962. #############################################################################
  963. # RakeFileUtils provides a custom version of the FileUtils methods that
  964. # respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
  965. #
  966. module RakeFileUtils
  967. include FileUtils
  968. class << self
  969. attr_accessor :verbose_flag, :nowrite_flag
  970. end
  971. RakeFileUtils.verbose_flag = :default
  972. RakeFileUtils.nowrite_flag = false
  973. $fileutils_verbose = true
  974. $fileutils_nowrite = false
  975. FileUtils::OPT_TABLE.each do |name, opts|
  976. default_options = []
  977. if opts.include?(:verbose) || opts.include?("verbose")
  978. default_options << ':verbose => RakeFileUtils.verbose_flag'
  979. end
  980. if opts.include?(:noop) || opts.include?("noop")
  981. default_options << ':noop => RakeFileUtils.nowrite_flag'
  982. end
  983. next if default_options.empty?
  984. module_eval(<<-EOS, __FILE__, __LINE__ + 1)
  985. def #{name}( *args, &block )
  986. super(
  987. *rake_merge_option(args,
  988. #{default_options.join(', ')}
  989. ), &block)
  990. end
  991. EOS
  992. end
  993. # Get/set the verbose flag controlling output from the FileUtils utilities.
  994. # If verbose is true, then the utility method is echoed to standard output.
  995. #
  996. # Examples:
  997. # verbose # return the current value of the verbose flag
  998. # verbose(v) # set the verbose flag to _v_.
  999. # verbose(v) { code } # Execute code with the verbose flag set temporarily to _v_.
  1000. # # Return to the original value when code is done.
  1001. def verbose(value=nil)
  1002. oldvalue = RakeFileUtils.verbose_flag
  1003. RakeFileUtils.verbose_flag = value unless value.nil?
  1004. if block_given?
  1005. begin
  1006. yield
  1007. ensure
  1008. RakeFileUtils.verbose_flag = oldvalue
  1009. end
  1010. end
  1011. RakeFileUtils.verbose_flag
  1012. end
  1013. # Get/set the nowrite flag controlling output from the FileUtils utilities.
  1014. # If verbose is true, then the utility method is echoed to standard output.
  1015. #
  1016. # Examples:
  1017. # nowrite # return the current value of the nowrite flag
  1018. # nowrite(v) # set the nowrite flag to _v_.
  1019. # nowrite(v) { code } # Execute code with the nowrite flag set temporarily to _v_.
  1020. # # Return to the original value when code is done.
  1021. def nowrite(value=nil)
  1022. oldvalue = RakeFileUtils.nowrite_flag
  1023. RakeFileUtils.nowrite_flag = value unless value.nil?
  1024. if block_given?
  1025. begin
  1026. yield
  1027. ensure
  1028. RakeFileUtils.nowrite_flag = oldvalue
  1029. end
  1030. end
  1031. oldvalue
  1032. end
  1033. # Use this function to prevent protentially destructive ruby code from
  1034. # running when the :nowrite flag is set.
  1035. #
  1036. # Example:
  1037. #
  1038. # when_writing("Building Project") do
  1039. # project.build
  1040. # end
  1041. #
  1042. # The following code will build the project under normal conditions. If the
  1043. # nowrite(true) flag is set, then the example will print:
  1044. # DRYRUN: Building Project
  1045. # instead of actually building the project.
  1046. #
  1047. def when_writing(msg=nil)
  1048. if RakeFileUtils.nowrite_flag
  1049. puts "DRYRUN: #{msg}" if msg
  1050. else
  1051. yield
  1052. end
  1053. end
  1054. # Merge the given options with the default values.
  1055. def rake_merge_option(args, defaults)
  1056. if Hash === args.last
  1057. defaults.update(args.last)
  1058. args.pop
  1059. end
  1060. args.push defaults
  1061. args
  1062. end
  1063. private :rake_merge_option
  1064. # Send the message to the default rake output (which is $stderr).
  1065. def rake_output_message(message)
  1066. $stderr.puts(message)
  1067. end
  1068. private :rake_output_message
  1069. # Check that the options do not contain options not listed in +optdecl+. An
  1070. # ArgumentError exception is thrown if non-declared options are found.
  1071. def rake_check_options(options, *optdecl)
  1072. h = options.dup
  1073. optdecl.each do |name|
  1074. h.delete name
  1075. end
  1076. raise ArgumentError, "no such option: #{h.keys.join(' ')}" unless h.empty?
  1077. end
  1078. private :rake_check_options
  1079. extend self
  1080. end
  1081. #############################################################################
  1082. # Include the FileUtils file manipulation functions in the top level module,
  1083. # but mark them private so that they don't unintentionally define methods on
  1084. # other objects.
  1085. include RakeFileUtils
  1086. private(*FileUtils.instance_methods(false))
  1087. private(*RakeFileUtils.instance_methods(false))
  1088. ######################################################################
  1089. module Rake
  1090. ###########################################################################
  1091. # A FileList is essentially an array with a few helper methods defined to
  1092. # make file manipulation a bit easier.
  1093. #
  1094. # FileLists are lazy. When given a list of glob patterns for possible files
  1095. # to be included in the file list, instead of searching the file structures
  1096. # to find the files, a FileList holds the pattern for latter use.
  1097. #
  1098. # This allows us to define a number of FileList to match any number of
  1099. # files, but only search out the actual files when then FileList itself is
  1100. # actually used. The key is that the first time an element of the
  1101. # FileList/Array is requested, the pending patterns are resolved into a real
  1102. # list of file names.
  1103. #
  1104. class FileList
  1105. include Cloneable
  1106. # == Method Delegation
  1107. #
  1108. # The lazy evaluation magic of FileLists happens by implementing all the
  1109. # array specific methods to call +resolve+ before delegating the heavy
  1110. # lifting to an embedded array object (@items).
  1111. #
  1112. # In addition, there are two kinds of delegation calls. The regular kind
  1113. # delegates to the @items array and returns the result directly. Well,
  1114. # almost directly. It checks if the returned value is the @items object
  1115. # itself, and if so will return the FileList object instead.
  1116. #
  1117. # The second kind of delegation call is used in methods that normally
  1118. # return a new Array object. We want to capture the return value of these
  1119. # methods and wrap them in a new FileList object. We enumerate these
  1120. # methods in the +SPECIAL_RETURN+ list below.
  1121. # List of array methods (that are not in +Object+) that need to be
  1122. # delegated.
  1123. ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
  1124. # List of additional methods that must be delegated.
  1125. MUST_DEFINE = %w[to_a inspect]
  1126. # List of methods that should not be delegated here (we define special
  1127. # versions of them explicitly below).
  1128. MUST_NOT_DEFINE = %w[to_a to_ary partition *]
  1129. # List of delegated methods that return new array values which need
  1130. # wrapping.
  1131. SPECIAL_RETURN = %w[
  1132. map collect sort sort_by select find_all reject grep
  1133. compact flatten uniq values_at
  1134. + - & |
  1135. ]
  1136. DELEGATING_METHODS = (ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
  1137. # Now do the delegation.
  1138. DELEGATING_METHODS.each_with_index do |sym, i|
  1139. if SPECIAL_RETURN.include?(sym)
  1140. ln = __LINE__+1
  1141. class_eval %{
  1142. def #{sym}(*args, &block)
  1143. resolve
  1144. result = @items.send(:#{sym}, *args, &block)
  1145. FileList.new.import(result)
  1146. end
  1147. }, __FILE__, ln
  1148. else
  1149. ln = __LINE__+1
  1150. class_eval %{
  1151. def #{sym}(*args, &block)
  1152. resolve
  1153. result = @items.send(:#{sym}, *args, &block)
  1154. result.object_id == @items.object_id ? self : result
  1155. end
  1156. }, __FILE__, ln
  1157. end
  1158. end
  1159. # Create a file list from the globbable patterns given. If you wish to
  1160. # perform multiple includes or excludes at object build time, use the
  1161. # "yield self" pattern.
  1162. #
  1163. # Example:
  1164. # file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')
  1165. #
  1166. # pkg_files = FileList.new('lib/**/*') do |fl|
  1167. # fl.exclude(/\bCVS\b/)
  1168. # end
  1169. #
  1170. def initialize(*patterns)
  1171. @pending_add = []
  1172. @pending = false
  1173. @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
  1174. @exclude_procs = DEFAULT_IGNORE_PROCS.dup
  1175. @exclude_re = nil
  1176. @items = []
  1177. patterns.each { |pattern| include(pattern) }
  1178. yield self if block_given?
  1179. end
  1180. # Add file names defined by glob patterns to the file list. If an array
  1181. # is given, add each element of the array.
  1182. #
  1183. # Example:
  1184. # file_list.include("*.java", "*.cfg")
  1185. # file_list.include %w( math.c lib.h *.o )
  1186. #
  1187. def include(*filenames)
  1188. # TODO: check for pending
  1189. filenames.each do |fn|
  1190. if fn.respond_to? :to_ary
  1191. include(*fn.to_ary)
  1192. else
  1193. @pending_add << fn
  1194. end
  1195. end
  1196. @pending = true
  1197. self
  1198. end
  1199. alias :add :include
  1200. # Register a list of file name patterns that should be excluded from the
  1201. # list. Patterns may be regular expressions, glob patterns or regular
  1202. # strings. In addition, a block given to exclude will remove entries that
  1203. # return true when given to the block.
  1204. #
  1205. # Note that glob patterns are expanded against the file system. If a file
  1206. # is explicitly added to a file list, but does not exist in the file
  1207. # system, then an glob pattern in the exclude list will not exclude the
  1208. # file.
  1209. #
  1210. # Examples:
  1211. # FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
  1212. # FileList['a.c', 'b.c'].exclude(/^a/) => ['b.c']
  1213. #
  1214. # If "a.c" is a file, then ...
  1215. # FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']
  1216. #
  1217. # If "a.c" is not a file, then ...
  1218. # FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']
  1219. #
  1220. def exclude(*patterns, &block)
  1221. patterns.each do |pat|
  1222. @exclude_patterns << pat
  1223. end
  1224. if block_given?
  1225. @exclude_procs << block
  1226. end
  1227. resolve_exclude if ! @pending
  1228. self
  1229. end
  1230. # Clear all the exclude patterns so that we exclude nothing.
  1231. def clear_exclude
  1232. @exclude_patterns = []
  1233. @exclude_procs = []
  1234. calculate_exclude_regexp if ! @pending
  1235. self
  1236. end
  1237. # Define equality.
  1238. def ==(array)
  1239. to_ary == array
  1240. end
  1241. # Return the internal array object.
  1242. def to_a
  1243. resolve
  1244. @items
  1245. end
  1246. # Return the internal array object.
  1247. def to_ary
  1248. to_a
  1249. end
  1250. # Lie about our class.
  1251. def is_a?(klass)
  1252. klass == Array || super(klass)
  1253. end
  1254. alias kind_of? is_a?
  1255. # Redefine * to return either a string or a new file list.
  1256. def *(other)
  1257. result = @items * other
  1258. case result
  1259. when Array
  1260. FileList.new.import(result)
  1261. else
  1262. result
  1263. end
  1264. end
  1265. # Resolve all the pending adds now.
  1266. def resolve
  1267. if @pending
  1268. @pending = false
  1269. @pending_add.each do |fn| resolve_add(fn) end
  1270. @pending_add = []
  1271. resolve_exclude
  1272. end
  1273. self
  1274. end
  1275. def calculate_exclude_regexp
  1276. ignores = []
  1277. @exclude_patterns.each do |pat|
  1278. case pat
  1279. when Regexp
  1280. ignores << pat
  1281. when /[*?]/
  1282. Dir[pat].each do |p| ignores << p end
  1283. else
  1284. ignores << Regexp.quote(pat)
  1285. end
  1286. end
  1287. if ignores.empty?
  1288. @exclude_re = /^$/
  1289. else
  1290. re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
  1291. @exclude_re = Regexp.new(re_str)
  1292. end
  1293. end
  1294. def resolve_add(fn)
  1295. case fn
  1296. when %r{[*?\[\{]}
  1297. add_matching(fn)
  1298. else
  1299. self << fn
  1300. end
  1301. end
  1302. private :resolve_add
  1303. def resolve_exclude
  1304. calculate_exclude_regexp
  1305. reject! { |fn| exclude?(fn) }
  1306. self
  1307. end
  1308. private :resolve_exclude
  1309. # Return a new FileList with the results of running +sub+ against each
  1310. # element of the oringal list.
  1311. #
  1312. # Example:
  1313. # FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
  1314. #
  1315. def sub(pat, rep)
  1316. inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
  1317. end
  1318. # Return a new FileList with the results of running +gsub+ against each
  1319. # element of the original list.
  1320. #
  1321. # Example:
  1322. # FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
  1323. # => ['lib\\test\\file', 'x\\y']
  1324. #
  1325. def gsub(pat, rep)
  1326. inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
  1327. end
  1328. # Same as +sub+ except that the oringal file list is modified.
  1329. def sub!(pat, rep)
  1330. each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
  1331. self
  1332. end
  1333. # Same as +gsub+ except that the original file list is modified.
  1334. def gsub!(pat, rep)
  1335. each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
  1336. self
  1337. end
  1338. # Apply the pathmap spec to each of the included file names, returning a
  1339. # new file list with the modified paths. (See String#pathmap for
  1340. # details.)
  1341. def pathmap(spec=nil)
  1342. collect { |fn| fn.pathmap(spec) }
  1343. end
  1344. # Return a new FileList with <tt>String#ext</tt> method applied
  1345. # to each member of the array.
  1346. #
  1347. # This method is a shortcut for:
  1348. #
  1349. # array.collect { |item| item.ext(newext) }
  1350. #
  1351. # +ext+ is a user added method for the Array class.
  1352. def ext(newext='')
  1353. collect { |fn| fn.ext(newext) }
  1354. end
  1355. # Grep each of the files in the filelist using the given pattern. If a
  1356. # block is given, call the block on each matching line, passing the file
  1357. # name, line number, and the matching line of text. If no block is given,
  1358. # a standard emac style file:linenumber:line message will be printed to
  1359. # standard out.
  1360. def egrep(pattern, *options)
  1361. each do |fn|
  1362. open(fn, "rb", *options) do |inf|
  1363. count = 0
  1364. inf.each do |line|
  1365. count += 1
  1366. if pattern.match(line)
  1367. if block_given?
  1368. yield fn, count, line
  1369. else
  1370. puts "#{fn}:#{count}:#{line}"
  1371. end
  1372. end
  1373. end
  1374. end
  1375. end
  1376. end
  1377. # Return a new file list that only contains file names from the current
  1378. # file list that exist on the file system.
  1379. def existing
  1380. select { |fn| File.exist?(fn) }
  1381. end
  1382. # Modify the current file list so that it contains only file name that
  1383. # exist on the file system.
  1384. def existing!
  1385. resolve
  1386. @items = @items.select { |fn| File.exist?(fn) }
  1387. self
  1388. end
  1389. # FileList version of partition. Needed because the nested arrays should
  1390. # be FileLists in this version.
  1391. def partition(&block) # :nodoc:
  1392. resolve
  1393. result = @items.partition(&block)
  1394. [
  1395. FileList.new.import(result[0]),
  1396. FileList.new.import(result[1]),
  1397. ]
  1398. end
  1399. # Convert a FileList to a string by joining all elements with a space.
  1400. def to_s
  1401. resolve
  1402. self.join(' ')
  1403. end
  1404. # Add matching glob patterns.
  1405. def add_matching(pattern)
  1406. Dir[pattern].each do |fn|
  1407. self << fn unless exclude?(fn)
  1408. end
  1409. end
  1410. private :add_matching
  1411. # Should the given file name be excluded?
  1412. def exclude?(fn)
  1413. calculate_exclude_regexp unless @exclude_re
  1414. fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
  1415. end
  1416. DEFAULT_IGNORE_PATTERNS = [
  1417. /(^|[\/\\])CVS([\/\\]|$)/,
  1418. /(^|[\/\\])\.svn([\/\\]|$)/,
  1419. /\.bak$/,
  1420. /~$/
  1421. ]
  1422. DEFAULT_IGNORE_PROCS = [
  1423. proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
  1424. ]
  1425. # @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
  1426. def import(array)
  1427. @items = array
  1428. self
  1429. end
  1430. class << self
  1431. # Create a new file list including the files listed. Similar to:
  1432. #
  1433. # FileList.new(*args)
  1434. def [](*args)
  1435. new(*args)
  1436. end
  1437. end
  1438. end # FileList
  1439. end
  1440. module Rake
  1441. class << self
  1442. # Yield each file or directory component.
  1443. def each_dir_parent(dir) # :nodoc:
  1444. old_length = nil
  1445. while dir != '.' && dir.length != old_length
  1446. yield(dir)
  1447. old_length = dir.length
  1448. dir = File.dirname(dir)
  1449. end
  1450. end
  1451. end
  1452. end # module Rake
  1453. # Alias FileList to be available at the top level.
  1454. FileList = Rake::FileList
  1455. #############################################################################
  1456. module Rake
  1457. # Default Rakefile loader used by +import+.
  1458. class DefaultLoader
  1459. def load(fn)
  1460. Kernel.load(File.expand_path(fn))
  1461. end
  1462. end
  1463. # EarlyTime is a fake timestamp that occurs _before_ any other time value.
  1464. class EarlyTime
  1465. include Comparable
  1466. include Singleton
  1467. def <=>(other)
  1468. -1
  1469. end
  1470. def to_s
  1471. "<EARLY TIME>"
  1472. end
  1473. end
  1474. EARLY = EarlyTime.instance
  1475. end # module Rake
  1476. #############################################################################
  1477. # Extensions to time to allow comparisons with an early time class.
  1478. #
  1479. class Time
  1480. alias rake_original_time_compare :<=>
  1481. def <=>(other)
  1482. if Rake::EarlyTime === other
  1483. - other.<=>(self)
  1484. else
  1485. rake_original_time_compare(other)
  1486. end
  1487. end
  1488. end # class Time
  1489. module Rake
  1490. ####################################################################
  1491. # The NameSpace class will lookup task names in the the scope
  1492. # defined by a +namespace+ command.
  1493. #
  1494. class NameSpace
  1495. # Create a namespace lookup object using the given task manager
  1496. # and the list of scopes.
  1497. def initialize(task_manager, scope_list)
  1498. @task_manager = task_manager
  1499. @scope = scope_list.dup
  1500. end
  1501. # Lookup a task named +name+ in the namespace.
  1502. def [](name)
  1503. @task_manager.lookup(name, @scope)
  1504. end
  1505. # Return the list of tasks defined in this and nested namespaces.
  1506. def tasks
  1507. @task_manager.tasks_in_scope(@scope)
  1508. end
  1509. end # NameSpace
  1510. ####################################################################
  1511. # The TaskManager module is a mixin for managing tasks.
  1512. module TaskManager
  1513. # Track the last comment made in the Rakefile.
  1514. attr_accessor :last_description
  1515. alias :last_comment :last_description # Backwards compatibility
  1516. def initialize
  1517. super
  1518. @tasks = Hash.new
  1519. @rules = Array.new
  1520. @scope = Array.new
  1521. @last_description = nil
  1522. end
  1523. def create_rule(*args, &block)
  1524. pattern, arg_names, deps = resolve_args(args)
  1525. pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
  1526. @rules << [pattern, deps, block]
  1527. end
  1528. def define_task(task_class, *args, &block)
  1529. task_name, arg_names, deps = resolve_args(args)
  1530. task_name = task_class.scope_name(@scope, task_name)
  1531. deps = [deps] unless deps.respond_to?(:to_ary)
  1532. deps = deps.collect {|d| d.to_s }
  1533. task = intern(task_class, task_name)
  1534. task.set_arg_names(arg_names) unless arg_names.empty?
  1535. task.add_description(@last_description)
  1536. @last_description = nil
  1537. task.enhance(deps, &block)
  1538. task
  1539. end
  1540. # Lookup a task. Return an existing task if found, otherwise
  1541. # create a task of the current type.
  1542. def intern(task_class, task_name)
  1543. @tasks[task_name.to_s] ||= task_class.new(task_name, self)
  1544. end
  1545. # Find a matching task for +task_name+.
  1546. def [](task_name, scopes=nil)
  1547. task_name = task_name.to_s
  1548. self.lookup(task_name, scopes) or
  1549. enhance_with_matching_rule(task_name) or
  1550. synthesize_file_task(task_name) or
  1551. fail "Don't know how to build task '#{task_name}'"
  1552. end
  1553. def synthesize_file_task(task_name)
  1554. return nil unless File.exist?(task_name)

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