rake的file task如何决定是否执行
在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
经过一番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