Skip to content

Commit

Permalink
Fix for kite-shaped dep graphs; better workaround for FileTask#needed?
Browse files Browse the repository at this point in the history
Based on a patch by Heath Kehoe (thanks)

(cherry picked from commit 609147e)

Conflicts:

	test/test_file_task.rb
  • Loading branch information
quix committed Jun 7, 2010
1 parent 2ec3a1b commit 96faf9d
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 9 deletions.
9 changes: 1 addition & 8 deletions lib/rake/parallel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,8 @@ def invoke_parallel(*task_args)
def invoke_with_call_chain_collector(task_args, new_chain, previous_chain)
prereqs = invoke_prerequisites_collector(task_args, new_chain)
parallel = application.parallel
if needed? or parallel.tasks[self]
if needed? or prereqs.any? { |p| parallel.tasks[p] }
parallel.tasks[self] = [task_args, prereqs]
unless previous_chain == InvocationChain::EMPTY
#
# Touch the parent to propagate 'needed?' upwards. This
# works because the recursion is depth-first.
#
parallel.tasks[previous_chain.value] = true
end
end
end

Expand Down
167 changes: 166 additions & 1 deletion test/test_file_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ class TestFileTask < Test::Unit::TestCase
def setup
Task.clear
@runs = SerializedArray.new
FileUtils.rm_f FILES
FileUtils.rm_rf "testdata", :verbose => false
FileUtils.mkdir_p "testdata", :verbose => false
end

def teardown
FileUtils.rm_rf "testdata", :verbose => false
end

def test_create_dispersed_timed_files
Expand Down Expand Up @@ -119,6 +124,166 @@ def test_two_old_files_in_between
assert_equal([ANCIENT_FILE, OLDFILE, MIDDLE_AGED_FILE], @runs)
end

def test_old_file_in_between_with_missing_leaf
create_dispersed_timed_files(MIDDLE_AGED_FILE, OLDFILE)
sleep 1

file MIDDLE_AGED_FILE => OLDFILE do |t|
@runs << t.name
touch MIDDLE_AGED_FILE, :verbose => false
end
file OLDFILE => NEWFILE do |t|
@runs << t.name
touch OLDFILE, :verbose => false
end
file NEWFILE do |t|
@runs << t.name
touch NEWFILE, :verbose => false
end

Task[MIDDLE_AGED_FILE].invoke
assert_equal([NEWFILE, OLDFILE, MIDDLE_AGED_FILE], @runs)
end

def test_two_old_files_in_between_with_missing_leaf
create_dispersed_timed_files(MIDDLE_AGED_FILE, OLDFILE, ANCIENT_FILE)
sleep 1

file MIDDLE_AGED_FILE => OLDFILE do |t|
@runs << t.name
touch MIDDLE_AGED_FILE, :verbose => false
end
file OLDFILE => ANCIENT_FILE do |t|
@runs << t.name
touch OLDFILE, :verbose => false
end
file ANCIENT_FILE => NEWFILE do |t|
@runs << t.name
touch ANCIENT_FILE, :verbose => false
end
file NEWFILE do |t|
@runs << t.name
touch NEWFILE, :verbose => false
end

Task[MIDDLE_AGED_FILE].invoke
assert_equal([NEWFILE, ANCIENT_FILE, OLDFILE, MIDDLE_AGED_FILE], @runs)
end

def test_diamond_graph_with_missing_leaf
a, b, c, d = %w[a b c d].map { |n| "testdata/#{n}" }
create_timed_files(a, b, c)
sleep 1

file a => [b, c] do
@runs << a
touch a
end
file b => d do
@runs << b
touch b
end
file c => d do
@runs << c
touch c
end
file d do
@runs << d
touch d
end

Task[a].invoke
assert_equal [a, b, c, d], @runs.sort
end

def test_diamond_graph_with_new_leaf
a, b, c, d = %w[a b c d].map { |n| "testdata/#{n}" }
create_timed_files(a, b, c)
sleep 1
touch d

file a => [b, c] do
@runs << a
touch a
end
file b => d do
@runs << b
touch b
end
file c => d do
@runs << c
touch c
end
file d do
@runs << d
touch d
end

Task[a].invoke
assert_equal [a, b, c], @runs.sort
end

def test_kite_graph_with_missing_leaf
a, b, c, d, e = %w[a b c d e].map { |n| "testdata/#{n}" }
create_timed_files(a, b, c, d)
sleep 1

file a => [b, c] do
@runs << a
touch a
end
file b => d do
@runs << b
touch b
end
file c => d do
@runs << c
touch c
end
file d => e do
@runs << d
touch d
end
file e do
@runs << e
touch e
end

Task[a].invoke
assert_equal [a, b, c, d, e], @runs.sort
end

def test_kite_graph_with_new_leaf
a, b, c, d, e = %w[a b c d e].map { |n| "testdata/#{n}" }
create_timed_files(a, b, c, d)
sleep 1
touch e

file a => [b, c] do
@runs << a
touch a
end
file b => d do
@runs << b
touch b
end
file c => d do
@runs << c
touch c
end
file d => e do
@runs << d
touch d
end
file e do
@runs << e
touch e
end

Task[a].invoke
assert_equal [a, b, c, d], @runs.sort
end

# I have currently disabled this test. I'm not convinced that
# deleting the file target on failure is always the proper thing to
# do. I'm willing to hear input on this topic.
Expand Down

0 comments on commit 96faf9d

Please sign in to comment.