[Rake-devel] A handful of issues

James M. Lawrence quixoticsycophant at gmail.com
Mon Jun 7 03:03:29 EDT 2010


==== 1 - Task#needed? applies to immediate prereqs only

file "a" => "b" do
  touch "a"
end

file "b" => "c" do
  touch "b"
end

file "c" do
  touch "c"
end

task :default do
  touch ["a", "b"]
  sleep 1
  touch "c"
  p Rake::Task["a"].needed?  # => false
  # ... but "a" is needed because "c" is newer
end

==== 2 - Task#needed? can be wrong even for immediate prereqs

file "a" => "b" do
  touch "a"
end

file "b" do
  touch "b"
end

task :default do
  touch "a"
  rm_f "b"
  p Rake::Task["a"].needed?  # => false
  # ... but "a" is needed because "b" will be newly created
end

==== 3 - Filesystem timestamp granularity

memo = []

file "a" => "b" do
  memo << "a"
  touch "a"
end

file "b" do
  memo << "b"
  touch "b"
end

task :default do
  touch "a"
  rm_f "b"
  Rake::Task["a"].invoke
  p memo # => ["b"]
  # ... but should be ["b", "a"] since "b" is newer
end

==== 4 - Dependency relation should be transitive

memo = []

file "a" => "b" do
  memo << "a"
  touch "a"
end

file "b" => "c" do
  memo << "b"
  # does not create b
end

file "c" do
  memo << "c"
  touch "c"
end

task :default do
  touch ["a", "b"]
  rm_f "c"
  sleep 1 # filesystem timestamp workaround
  Rake::Task["a"].invoke
  p memo # => ["c", "b"]
  # ... but "a" is needed since it (transitively) depends on "c"
end

==== 5 - Trace output is misleading

file "a" => "b" do
  touch "a"
end

file "b" => "c" do
  touch "b"
end

file "c" do
  touch "c"
end

task :default do
  touch ["a", "b"]
  sleep 1
  touch "c"
  Rake.application.options.trace = true
  Rake::Task["a"].invoke
  # =>
  #   touch a b
  #   touch c
  #   ** Invoke a (first_time, not_needed) <--- Liar! It is needed.
  #   ** Invoke b (first_time)
  #   ** Invoke c (first_time, not_needed)
  #   ** Execute b
  #   touch b
  #   ** Execute a <--- See?
  #   touch a
end

**** Discussion

==== 1 - Task#needed? applies to immediate prereqs only

Having Task#needed? recursively check all prereqs is needlessly slow,
so the current behavior is fine.  However I think its use should be
deprecated in the published API.  We could alias it to
Task#locally_needed? and additionally write Task#globally_needed?.

==== 2 - Task#needed? can be wrong even for immediate prereqs

Should be fixed if Task#needed? (or Task#locally_needed?) is
"officially" supported.

http://github.com/quix/rake/commits/mainline-file-task-needed

==== 3 - Filesystem timestamp granularity

Unless you have ext4fs, your filesystem most likely records timestamps
only to the nearest second, making it easy to create same-time files.

The fix is easy: change timestamp comparison from > to >=.  It's a
pessimization: "When in doubt, rerun."  It sounds safer, but what
consequences lurk?

http://github.com/quix/rake/commits/mainline-timestamp-granularity

==== 4 - Dependency relation should be transitive

Let ~> denote "eventually depends on".  If a~>b and b~>c, then we want
a~>c.  Thus if c executes then a should execute, as is implied by the
dependency graph.  Parallel Rake has to assume transitivity, so its
behavior is different.

I think a file task which executes but does not update the file is
reneging.  Regarding this as an error would make regular Rake
consistent with parallel Rake, sidestepping the transitivity issue.

==== 5 - Trace output is misleading

This is related to item 1 since "not_needed" reflects Task#needed?.
Perhaps change the output to "not_immediately_needed" or some such?


More information about the Rake-devel mailing list