在Rake Task Management Essentials一书中有如下描述

In addition to general task behavior, the file task has a very useful feature. If source files (prerequisites) are not changed, the second attempt won't execute the file task action at all. The file task handles timestamp changes for source files, and if they are not touched, Rake decides to not run this file task

说得好像rake有记录下文件的修改时间一样,于是调试一下

file 'a.yml' => 'a.yaml' do
  cp 'a.yaml', 'a.yml'
end

binding.pry


rakefile01.debug

经过一番up、next、step……,终于搞清file task的本质,其实就是build文件:如果文件不存在,则build;如果文件日期早于其依赖的文件,则build;如果指定了--build-all或-B,则build。这里所谓的build,就是执行任务定义的block,通常里面会建立、更新任务名所指的文件

源码如下,根据needed?来判断

# rake-12.0.0/lib/rake/task.rb
def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
  new_chain = InvocationChain.append(self, invocation_chain)
  @lock.synchronize do
    if application.options.trace
      application.trace "** Invoke #{name} #{format_trace_flags}"
    end
    return if @already_invoked
    @already_invoked = true
    invoke_prerequisites(task_args, new_chain)
    execute(task_args) if needed?
  end
rescue Exception => ex
  add_chain_to(ex, new_chain)
  raise ex
end


而FileTask的needed?如下

# rake-12.0.0/lib/rake/file_task.rb
module Rake

  # A FileTask is a task that includes time based dependencies.  If any of a
  # FileTask's prerequisites have a timestamp that is later than the file
  # represented by this task, then the file must be rebuilt (using the
  # supplied actions).
  #
  class FileTask < Task

    # Is this file task needed?  Yes if it doesn't exist, or if its time stamp
    # is out of date.
    def needed?
      ! File.exist?(name) || out_of_date?(timestamp) || @application.options.build_all
    end

    # Time stamp for file task.
    def timestamp
      if File.exist?(name)
        File.mtime(name.to_s)
      else
        Rake::LATE
      end
    end

    private

    # Are there any prerequisites with a later time than the given time stamp?
    def out_of_date?(stamp)
      @prerequisites.any? { |n| application[n, @scope].timestamp > stamp }
    end