2009-11-06 4 views
18

Я новичок в Rake и использую его для создания проектов .net. Меня интересует сводная задача, в которой выдается сводка о том, что было сделано. Я хочу, чтобы эту задачу всегда вызывали, независимо от того, с какими задачами вызывается rake.Как выполнить задачу Rake Task после всех других задач? (т. е. задача Rake AfterBuild)

Есть ли простой способ достичь этого?

Благодаря


Update на вопрос, отвечая на Patrick's answer то, что я хочу, это после того, как задача выполняется один раз после того, как все другие задачи, поэтому выход я хочу это:

task :test1 do 
    puts 'test1' 
end 

task :test2 do 
    puts 'test2' 
end 

Rake::Task.tasks.each do |t| 
    <Insert rake magic here> 
# t.enhance do 
# puts 'after' 
# end 
end 

$ rake test1 
test1 
after 

$rake test2 
test2 
after 

$rake test1 test2 
test1 
test2 
after 

и если

task :test3 =>[:test1, :test2] 
    puts 'test3' 
end 

    $rake test3 
test1 
test2 
test3 
after 

Несмотря на то, что щедрота ушла, дальнейшая помощь очень ценится. (Sadily я не думаю, что я могу предложить еще одну награду.)

ответ

10

Опубликовать это как новый ответ, чтобы сохранить другой доступный. Это намного менее изящно, так как мне нужно войти в кишки Rake и вручную обновить список задач, но он работает.

task :test1 do 
    puts 'test1' 
end 

task :test2 do 
    puts 'test2' 
end 

task :after do 
    puts 'after' 
end 

# top_level_tasks is't writable so we need to do this ugly 
# instance_variable_set hack... 
current_tasks = Rake.application.top_level_tasks 
current_tasks << :after 
Rake.application.instance_variable_set(:@top_level_tasks, current_tasks) 

Выходы:

$ rake test1 
test1 
after 

$ rake test1 test2 
test1 
test2 
after 
+0

GREAT! Это именно то, что я хочу. Мне было бы интересно узнать, что здесь происходит. Можете ли вы дать мне больше разъяснений о том, что происходит? Между тем, я посмотрю, что я могу найти в Google. – Chasler

+0

ОК. Я понимаю, что происходит. Хорошая работа. Благодарю. – Chasler

+2

Несомненно. В стороне, я на конференции и выследил Джима Вейриха (автора грабли), чтобы убедиться, что это лучший способ решить проблему. Его ответ заключался в том, что у Рейка нет встроенного способа сделать это, но он открыт для патча, если кто-то может придумать обобщенный метод для этого. Итак, код: приложение Rake имеет считыватель для отслеживания задач для запуска под названием «top_level_tasks». Поскольку он только для чтения, нам нужно его прочитать, обновить, а затем использовать instance_variable_set, чтобы вернуть это изменение в приложение. Если бы это было прочитано, мы могли бы все это в одной строке. –

1

Я не знаю, если это лучший способ, но это проще:

сделать все «общественные задачи» Резюме те, которые требуют реального задания.

task :compile => :realcompile do 
    summary stuff 
end 
35

Вы должны быть в состоянии сделать это с помощью 'усиления':

Rake::Task["my_task"].enhance do 
    Rake::Task["my_after_task"].invoke 
end 

Это приведет к 'my_after_task', который будет вызван после того, как 'my_task'.

Если вы хотите применить это ко всем задачам, просто цикл по всем задачам и вызвать усиления для каждого:

Rake::Task.tasks.each do |t| 
    t.enhance do 
    Rake::Task["my_after_task"].invoke 
    end 
end 

Полный тестовый файл:

task :test1 do 
    puts 'test1' 
end 

task :test2 do 
    puts 'test2' 
end 

Rake::Task.tasks.each do |t| 
    t.enhance do 
    puts 'after' 
    end 
end 

И выход:

$ rake test1 
test1 
after 

$ rake test2 
test2 
after 
+0

Спасибо. Боюсь, я не сформулировал свой вопрос четко. Я хочу, чтобы последующая задача выполнялась один раз, после завершения других задач. Итак: $ рейки test1 test2 бы выход test1 test2 после $ рек test1 test1 после $ рейки test2 test2 после Любой идеи, как сделать это произошло? – Chasler

+0

А, ну, нашел решение для вас. Менее элегантный, но он работает. Если вам интересно, я могу подробно объяснить, что я делаю, чтобы заставить это работать ... –

4

Помимо уродливой Rake.application.instance_variable_set, вы можете улучшить последнюю задачу в командной строке следующим образом:

last_task = Rake.application.top_level_tasks.last 
    Rake::Task[last_task].enhance do 
    puts 'after' 
    end 

Что должен делать именно то, что вам нужно делать!

+0

У вас есть один «конец» в конце, которого, должно быть, не должно быть. –

+0

Спасибо, Константин! Я исправил это. – awendt

+0

Интересно. Принятое ниже решение работает, и мне не пришлось изменять сценарий целую вечность, но в следующий раз я посмотрю на использование этого метода. Это определенно более элегантно. – Chasler

4

Вы можете использовать вызов Kernel.trap и подключаться к сигналу «Выход». Он срабатывает как при нормальном, так и в ненормальном выходе.

Поместите это в начале вашего rakefile:

Kernel.trap("EXIT") do 
    Rake::Task[:final].invoke 
end 

Теперь в любое время сделать «окончательное» задание будет выполняться в самом конце программы. не важно что.

task :final do 
    puts "Hit return to continue..." 
    STDIN.getc 
end 
+0

Прохладный. Благодарю. Я попробую в следующий раз, когда мне это понадобится. – Chasler

10

Найден этот простой элегантный ответ here, использующий метод Ruby, at_exit.

Следует отметить, что метод, определенный после at_exit, запускается каждый раз, когда запускается скрипт rake независимо от запуска задачи или при выполнении любой задачи. Это включает при запуске rake -T (для перечисления доступных задач). Убедитесь, что at_exit делает только что-либо, если предыдущая задача подсказывала это сделать.

rakefile.rb

desc "Lovely task a" 
task :a do 
    puts "a" 
end 

desc "Lovely task b" 
task :b do 
    puts "b" 
end 

task :cleanup do 
    puts "cleanup" 
end 

at_exit { Rake::Task[:cleanup].invoke if $!.nil? } 

оболочки

$ rake a b 
a 
b 
cleanup 
$ rake -T 
rake a # Lovely task a 
rake b # Lovely task b 
cleanup 

Вам также не нужно, чтобы сделать его запустить задачу, если вы не хотите.

at_exit do 
    puts "cleanup" 
end 

Или сделать его запустить метод

def on_exit_do_cleanup 
    puts "cleanup" 
end 

at_exit { on_exit_do_cleanup } 

И вы можете убедиться, что вы делаете только очистку, если задача на самом деле бежал так, что rake -T также не будет делать уборку.

rakefile.rb

do_cleanup = false 

desc "Lovely task a" 
task :a do 
    puts "a" 
    do_cleanup = true 
end 

desc "Lovely task b" 
task :b do 
    puts "b" 
    do_cleanup = true 
end 

task :cleanup do 
    return unless $!.nil? # No cleanup on error 
    return unless do_cleanup # No cleanup if flag is false 
    puts "cleanup" 
end 

at_exit { Rake::Task[:cleanup].invoke } 
+0

что такое $ !. ноль? обозначает ..? –

+0

'$!' Содержит последнюю поднятую ошибку, а 'x.nil?' Возвращает значение true, если 'x' является' nil' so, '... if $ !. nil?' Гарантирует, что задача очистки будет выполняться, если ошибок в этом запуске скрипта не было. (Отредактированный ответ для уточнения) – Nate

0

Если кто пришел сюда в поисках, как выполнить задачу перед тем все другие задачи (например, загрузка задачи специального окр), вы можете использовать тот же метод повышения, за исключением только первый аргумент:

task :environment do 
    env = (ENV['RACK_ENV'] || 'production').downcase 
    # do things before other tasks 
end 

# run environment task before all tasks for setup 
Rake::Task.tasks.each do |t| 
    next if t.name == 'environment' 
    t.enhance [:environment] 
end