2009-11-06 2 views
18

Jestem nowy w Rake i używam go do budowania projektów .net. Interesuje mnie zadanie Podsumowania, które drukuje podsumowanie tego, co zostało zrobione. Chcę, aby to zadanie zawsze było wywoływane, bez względu na to, jakie prowizje zostały wywołane.Jak wykonać zadanie rake po wszystkich innych zadaniach? (to jest zadanie Rake AfterBuild)

Czy istnieje prosty sposób na osiągnięcie tego?

Dzięki


Aktualizacja na pytanie, odpowiadając na Patrick's answer czego chcę to po zadaniu uruchomić raz po wszystkich innych zadań, więc wyjście chcę jest:

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 

i Jeśli nie ma nagród, wszelka dalsza pomoc jest doceniana. (Sadily Nie sądzę, że mogę zaoferować inną nagrodę.)

Odpowiedz

10

Publikowanie tego jako nowej odpowiedzi, aby zachować drugą. Jest to o wiele mniej eleganckie, ponieważ muszę dostać się do odwagi Rake'a i ręcznie zaktualizować listę zadań, ale działa.

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) 

Wyjścia:

$ rake test1 
test1 
after 

$ rake test1 test2 
test1 
test2 
after 
+0

WSPANIAŁE! To jest dokładnie to, czego chcę. Chciałbym wiedzieć, co tu się dzieje. Czy możesz dać mi więcej informacji o tym, co się dzieje? W międzyczasie zobaczę, co mogę znaleźć w Google. – Chasler

+0

OK. Rozumiem, co się dzieje. Dobra robota. Dzięki. – Chasler

+2

Pewnie. Na marginesie, jestem na konferencji i wyśledziłem Jima Weiricha (autora rake), aby sprawdzić, czy to najlepszy sposób na rozwiązanie problemu. Jego odpowiedzią było to, że Rake nie ma wbudowanego sposobu, aby to zrobić, ale jest otwarty na łatkę, jeśli ktoś może wymyślić uogólnioną metodę robienia tego. Tak więc kod: Aplikacja Rake ma czytnik do śledzenia zadań do wykonania o nazwie "top_level_tasks". Ponieważ jest to tylko odczyt, musimy go przeczytać, zaktualizować, a następnie użyć parametru instance_variable_set, aby ponownie wprowadzić zmiany do aplikacji. Jeśli był czytany, napiszmy to wszystko w jednym wierszu. –

1

ja nie wiem, czy to jest najlepszy sposób, ale to prostsze:

Dodać wszystkie swoje „zadania publiczne” jedynki Podsumowanie które wywołują prawdziwy zadania.

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

Powinieneś być w stanie to zrobić z 'poprawić':

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

Spowoduje 'my_after_task' powoływać się po 'my_task'.

Jeśli chcesz zastosować to do wszystkich zadań, tylko pętla nad wszystkimi zadaniami i nazywają wzmocnienia dla każdego:

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

Pełny plik testowy:

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 

a wyjście:

$ rake test1 
test1 
after 

$ rake test2 
test2 
after 
+0

Dzięki. Obawiam się, że nie wyjaśniłem wyraźnie mojego pytania. Chcę, aby po wykonaniu zadania uruchomił się raz, po zakończeniu innych zadań. sposób: $ rake test1 test2 byłoby wyjście test1 test2 po $ kasę test1 test1 po $ natarcia test2 test2 po Każdy pomysł, jak sprawić, by to się stało? – Chasler

+0

Ach, ok, znalazłem dla ciebie rozwiązanie. Mniej elegancki, ale działa. Jeśli jesteś zainteresowany, mogę szczegółowo wyjaśnić, co robię, aby to zadziałało ... –

4

Oprócz brzydkiego Rake.application.instance_variable_set można poprawić ostatnie zadanie z linii poleceń tak:

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

To powinno zrobić dokładnie to, czego potrzebujesz do zrobienia!

+0

Masz jeden "koniec" na końcu, którego nie powinno tam być, jak sądzę. –

+0

Dzięki, Konstantin! Poprawiłem to. – awendt

+0

Interesujące. Przyjmowane poniżej rozwiązanie działa i nie musiałem modyfikować skryptu przez wieki, ale następnym razem przyjrzę się użyciu tej metody. Jest zdecydowanie bardziej elegancki. – Chasler

4

Można użyć wywołania Kernel.trap i dołączyć do sygnału "Exit". Będzie strzelał zarówno po normalnym, jak i anormalnym wyjściu.

Umieścić to na początku swojej Rakefile:

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

Teraz każdy razem dokonać „ostatecznego” zadanie zostanie wykonane na samym końcu programu. nieważne co.

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

Cool. Dzięki. Spróbuję tego następnym razem, kiedy będę tego potrzebować. – Chasler

10

Znaleziony ten prosty elegancki odpowiedź here, który wykorzystuje metodę Ruby at_exit.

Warto zauważyć, że metoda zdefiniowana po at_exit będzie uruchamiana za każdym razem, gdy skrypt rake będzie wywoływany niezależnie od uruchomienia zadania lub wykonania dowolnego zadania. Obejmuje to podczas uruchamiania rake -T (aby wyświetlić listę dostępnych zadań). Upewnij się, że at_exit wykonuje tylko cokolwiek, jeśli poprzednie zadanie powiedziało mu, aby to zrobił.

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? } 

shell

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

też nie trzeba, aby uruchomić zadanie, jeśli nie chcą.

at_exit do 
    puts "cleanup" 
end 

lub uczynić go uruchomić metodę

def on_exit_do_cleanup 
    puts "cleanup" 
end 

at_exit { on_exit_do_cleanup } 

A może chcesz się upewnić, że tylko zrobić porządki jeśli zadanie faktycznie prowadził tak że rake -T nie będzie też zrobić porządki.

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

co to jest $ !. zero? oznacza ...? –

+0

'$!' Zawiera ostatni podniesiony błąd, a 'x.nil?' Zwraca prawdę, jeśli 'x' jest' nil', więc '... if $ !. nil?' Upewnia się, że zadanie czyszczenia działa tylko jeśli nie było błędów w tym uruchomieniu skryptu. (Edytowana odpowiedź w celu wyjaśnienia) – Nate

0

Jeśli ktoś przyszedł tu szukając jak uruchomić zadanie przed wszystkie inne zadania (np zadanie ładowanie specjalny ENV), można nadal korzystać z tej samej metody wzmocnienia, z wyjątkiem tylko pierwsze twierdzenie:

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