Rakeとdry run
Rakeに-nオプションを指定するとdry runできる。ただ、dry runと言ってもタスクの実行予定が表示されるだけなので、いまいち使いどころがない。
$ cat Rakefile
task :example do
sh 'ls', '-ld', '1'
end
$ rake -n example
** Invoke example (first_time)
** Execute (dry run) example
ところで、Rakeが提供するshメソッドや、Rakeが拡張しているmkdirなどのFileUtils由来のメソッドは、nowriteの値により動作を変える。
とはいうものの、nowriteの値はrakeコマンドの-nオプションに従って設定される。上述の通り-nオプションを指定するとタスクが実行されなくなるため、タスク定義の上ではnowriteそのものにはあまり意味がない。
$ cat Rakefile
task :example do
p nowrite ? 'nowrite' : 'write'
end
$ rake
"write"
$ rake -n
** Invoke example (first_time)
** Execute (dry run) example
ただしnowriteメソッドに引数としてtrueまたはfalseを指定すると、nowriteの値を変更できる。また、その際にブロックが与えられると、そのブロック内でのみnowriteの値を変えることができる。
たとえば以下の内容のRakefileを作る。
task :example do
sh 'ls', '-ld', '1'
nowrite(true) do
sh 'ls', '-ld', '2'
end
sh 'ls', '-ld', '3'
end
rakeコマンドを実行すると、次のようにls -ld 2だけが実行されないのが分かる。
$ rake example -f r
ls -ld 1
-rw-r--r-- 1 akira 501 0 1 14 13:44 1
ls -ld 2
ls -ld 3
-rw-r--r-- 1 akira 501 0 1 14 13:44 3
これを利用して、次のようなタスク定義をすると、Rakeによるコマンド実行内容を知ることが可能となる。
task :example do
sh 'ls', '-ld', '1'
end
task :dry_run do
nowrite(true) { Rake::Task[:example].invoke }
end
タスクdry_runはnowrite(true)の中でタスクexampleを実行しているので、タスクexample内での実行内容を表示するだけで終了する。
$ rake dry_run
ls -ld 1
$ rake example
ls -ld 1
-rw-r--r-- 1 akira 501 0 1 14 13:44 1
同じようなことを他のタスクでも行いたければ、以下のようなdry_runメソッドを用意しておくとよいかもしれない。
def dry_run(task = nil)
verbose(true) do
nowrite(true) do
return yield unless task
Rake::Task[task.scope.path].invoke
end
end
end
namespace :example do
task :dry_run do |t|
dry_run(t)
end
end
dry_runメソッドは、与えられたタスクの名前からネームスペース(scope)を取得し、その名前と同じ名前のタスクをnowrite(true)の中で実行する。
verboseはnowriteとよくにたメソッドで、rakeコマンドの-vオプションまたは-qオプションに従った値を返す。nowriteと同じように引数にtrueまたはfalseをとり、その値を変更できる。ここでは、dry runのためのタスク実行で、実行内容を常に表示させるために使っている。
なお、verboseについては少し注意を要する。rakeコマンドに-vオプションも-qオプションも指定しないとき、verboseの値はObjectオブジェクトになる。このため、以下のコードは予想と違った結果になるかもしれない。
task :verbose do
puts 'verbose' if verbose
end
実行結果は次の通りとなる。
$ rake verbose -v
verbose
$ rake verbose -q
$ rake verbose
verbose
verboseのデフォルトの値が、なぜObjectオブジェクトなのかは分からないが、-vオプションが指定されたときだけメッセージを表示する、といったときには次のようにする。
task :verbose do
puts 'verbose' if verbose == true
end