Skip to content

Instantly share code, notes, and snippets.

@robertzx
Forked from rsanders/gist:192485
Created February 6, 2012 02:49
Show Gist options
  • Select an option

  • Save robertzx/1749230 to your computer and use it in GitHub Desktop.

Select an option

Save robertzx/1749230 to your computer and use it in GitHub Desktop.

Revisions

  1. @rsanders rsanders created this gist Sep 24, 2009.
    308 changes: 308 additions & 0 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,308 @@
    # Rake Quick Reference
    # by Greg Houston
    # http://ghouston.blogspot.com/2008/07/rake-quick-reference.html


    # -----------------------------------------------------------------------------
    # Running Rake
    # -----------------------------------------------------------------------------
    # running rake from the command-line:
    # rake --help
    # --help shows all the command-line options, a few are listed here.
    # rake
    # (no arguments, runs the default task)
    # rake uses the script: rakefile, Rakefile, rakefile.rb or Rakefile.rb
    # rake will search parent directories for the file.
    # rake -f build.rb
    # -f specifies the rakefile file to run
    # rake target target2
    # target and target2 are the names of the tasks to run (instead of default)
    # rake -n
    # -n shows a dry-run of which tasks would get called
    # rake -T
    # -T shows all task which have descriptions
    # rake -P
    # -P shows task dependencies

    # -----------------------------------------------------------------------------
    # Tasks
    # -----------------------------------------------------------------------------
    task :default => :target
    # defines a task named :default
    # rake will run :default when no other task is specified on the command line
    # => :target, makes the task named :target a prerequisite
    # rake will ensure prerequisite tasks have completed before invoking this task

    task :target => :source
    # defines a task named :target with prerequisite :source
    # e.g. rake will ensure :source is invoked before :target

    task :source => [:x, :y]
    # defines a task named :source
    # => [:x, :y] shows how to set multiple prerequisites
    # all prerequisites must complete before this task will execute
    # right now we have defined a chain of prerequisites
    # :default => :target => :source => [:x, :y]
    # invoking :default will first invoke :x, :y, :source, :target

    task :a => :b
    task :b => :a
    # rake will raise an error if you invoke tasks with circular dependencies:
    # Circular dependency detected: TOP => a => b => a

    task :hello_world do
    puts 'hello world!'
    end
    # task behavior is given as a block of code using "do ... end"
    # dont use ruby's { } block syntax, precedence rules will break it
    # when the task is invoked, the block of code is executed

    task :target => :z do
    # ruby code
    end
    # since :target is already defined
    # +adds+ the prerequisite :z
    # +adds+ code to execute when :target is invoked
    # tasks in rake have a collection of dependencies
    # and a collection of blocks to execute

    task :target2 => :source
    # defines :target2 which also depends on :source
    # rake will only invoke :source once, even if both
    # :target and :target2 are invoked
    # tasks are only invoked once!

    task :example_target do
    puts Rake::Task[:target].inspect
    # Rake::Task holds a collection of all tasks. Access a task using: [name]

    puts Rake::Task[:target].investigation
    # investigation displays some details about a task.
    # useful for figuring out why a task was called or not.
    end

    task :target do |t|
    puts t.name #=> target
    puts t.class #=> Rake::Task
    end
    # task code blocks can accept an option argument (t in this example)
    # which is a reference to the task object.

    task :call_invoke do
    Rake::Task[:target].invoke
    end
    # calling invoke on a task directly (not recommended).
    # :target is only run once, even if invoke is called many times.
    # calling invoke will execute the prerequisites of :target

    task :call_execute do
    Rake::Task[:target].execute( nil )
    end
    # execute the task directly (not recommended).
    # execute can run :target many times.
    # calling execute will +not+ execute prerequisites.

    task :example_failure do
    raise 'i do not like green eggs and ham!'
    end
    # raising an exception is a good way to exit rake with a detailed error message
    # most continuous integration tools will detect the failure

    task :copy, :source, :target, :needs => :other_task do |t, args|
    puts "copy #{args.source} to #{args.target}"
    # args[:source] also works
    end
    # rake 0.8 adds support for task arguments
    #
    # task named :copy with arguments :source and :target, depends on :other_task
    # t = task object
    # args = arguments (instance of Rake::TaskArguments)
    #
    # command-line usage:
    # rake copy[file1,file2]
    # rake "copy[path with spaces/file1,file2]"
    #
    # rakefile usage:
    # none (as of rake v0.8.1)
    # calling .invoke and .execute is possible (not recommended)

    task :copy_some_files do
    cp 'one_file', 'destination'
    cp 'another_file', 'destination', :verbose => true
    end
    # rake includes the FileUtils module which has many
    # file system manipulation methods. FileUtils#cp copies a file.
    # see http://www.ruby-doc.org/core/classes/FileUtils.html
    # rake wraps FileUtils in Rake::FileUtils to add the :verbose option

    task :additional_commands do
    ruby 'my_ruby_script.rb' # run a ruby interpreter
    sh 'build.bat' # run a shell command
    safe_ln 'fileone.txt', 'filetwo.txt' # link or copy (as supported by OS)
    split_all("a/b/c") #=> ['a', 'b', 'c'] (split directory into an array)
    end
    # rake adds a few new commands
    # see http://rake.rubyforge.org/classes/FileUtils.html

    multitask :c_and_d_in_parallel => [:c, :d]
    # using multitask, immediate prerequisites are invoked on separate threads

    # -----------------------------------------------------------------------------
    # File and Directory Tasks
    # -----------------------------------------------------------------------------
    directory 'tests/out'
    # defines a directory task named 'tests/out' which will
    # create the 'tests/out' directory if it doesn't
    # already exist.

    file 'path/target.txt' => 'path/source.txt' do
    cp 'path/source.txt', 'path/target.txt'
    end
    # defines a file task named 'path/target.txt' which will
    # get invoked if the file 'path/source.txt' is newer.
    # file tasks look at the timestamp of the prerequisites

    def copy_file( source_file, target_file, task_symbol )
    desc "cp from #{source_file}"
    file target_file => [source_file] do |t|
    cp source_file, target_file, :verbose => true
    end
    task task_symbol => target_file
    end
    # example of a method which creates tasks.
    # copy_file makes a file task to copy the source_file to target_file
    # copy_file make task named task_symbol to depend on the target_file
    #
    # usage:
    copy_file( 'path/foo.txt', 'path/foobar.txt', :copy_foo )

    # -----------------------------------------------------------------------------
    # FileList
    # -----------------------------------------------------------------------------
    FileList['data/**/*', 'out/non-existing-file.txt']
    # rake FileList can glob files from the disk,
    # and/or collect files that dont exist.
    # FileList globs are lazy, they are resolved when first used.

    FileList['data/**/*'].exclude('*.txt')
    # .exclude globs
    # resolves against the file system, e.g. wont match files that don't exist

    FileList['data/**/*'].exclude {|path| path =~ /delete_me/ }
    # .exclude can use block to exclude everything where the block returns true.
    # example: exclude files when path matches the regular expression /delete_me/
    # FileList contains many other useful methods.
    # see http://rake.rubyforge.org/classes/Rake/FileList.html

    FileList['data/*'].each do |source|
    target = source.sub('data', 'out')
    file target => source do
    cp source, target, :verbose => true
    end
    desc "copies all data files"
    task :copy_data_files => target
    end
    # example using FileList to create tasks to perform a copy

    file 'target.txt' => 'source.txt' do |f|
    cp f.prerequisites[0], f.name, :verbose => true
    end
    # file tasks blocks can access the task object
    # f.prerequisites[0] is 'source.txt'
    # f.name is 'target.txt'

    # -----------------------------------------------------------------------------
    # String extensions
    # -----------------------------------------------------------------------------
    # Rake adds methods to String...
    # see http://rake.rubyforge.org/classes/String.html
    #
    'path/file.txt'.ext( 'html') #=> path/file.html (replace extension)
    'path/file.txt'.pathmap('%p') #=> 'path/file.txt' (full path)
    'path/file.txt'.pathmap('%f') #=> 'file.txt' (file)
    'path/file.txt'.pathmap('%n') #=> 'file' (file name, no ext)
    'path/file.txt'.pathmap('%x') #=> '.txt' (file extension)
    'path/file.txt'.pathmap('%X') #=> 'path/file' (full path, no extension)
    'x/y/z/file.txt'.pathmap('%d') #=> 'x/y/z' (directory path)
    'x/y/z/file.txt'.pathmap('%2d') #=> 'x/y' (directory path depth 2)
    'x/y/z/file.txt'.pathmap('%-2d') #=> 'y/z' (directory path depth 2 from end)
    'x/y/z/file.txt'.pathmap('%d%s%f') #=> 'x/y/z\file.txt' (%s = alt separator)
    'x/y/z/file.txt'.gsub('/','\\') #=> 'x\y\z\file.txt' (gsub works better)
    ''.pathmap('%%') #=> '%' (percent sign)
    'a/b/c'.pathmap('%{a,apple}p') #=> 'apple/b/c' use {} to replace using regex
    'a/b/c'.pathmap('%{a,x;b,y}p') #=> 'x/y/c' use {;} to replace multiple patterns
    'a/b/c'.pathmap('%{a,*}p') {|m| "(#{m})"} #=> '(a)/b/c' * calls block for match

    # -----------------------------------------------------------------------------
    # Namespace
    # -----------------------------------------------------------------------------
    namespace :ns do
    task :target
    end
    task :default => "ns:target"
    # defines a namespace named :ns
    # defines a task named "ns:target"
    # sets "ns:target" as a prerequisite of :default
    # use namespace to organize code and avoid task name conflicts

    namespace :ns do
    task :alpha => :beta
    task :beta
    end
    # within a namespace, you can refer to another task in the namespace directly
    # you dont need
    # task :alpha => 'ns:beta'

    task :dog
    task :farmer
    namespace :animal do
    task :cat => :dog
    task :dog => :farmer
    end
    # namespaces will look for tasks within their own namespace
    # animal:cat's prerequisite is animal:dog, not :dog
    # i dont know of a way to reference :dog instead of animal:dog inside
    # the namespace block. animal:dog hides :dog!
    # animal:dog's prerequisite is :farmer (outer scope) since there isn't
    # an animal:farmer defined.

    task 'animal:cow' => :dog
    # animal:cow is defined outside the namespace block
    # animal:cow's prerequisite is :dog, not animal:dog
    # animal:cow will look for prerequisites in the outer scope
    # animal:cow will not automatically look for tasks in the animal namespace

    namespace :animal do
    task :calf => :cow
    end
    # animal:calf's prerequisite is the 'animal:cow' defined above. as expected.

    namespace :demo do
    file 'out/demo.txt' => ['in/demo.txt', :hello]
    task :hello
    end
    # file task name is only 'out/demo.txt', the namespace doesn't change the name
    # however the scope lookup applies, 'out/demo.txt' prereq is demo:hello

    # -----------------------------------------------------------------------------
    # Rules
    # -----------------------------------------------------------------------------
    rule /out\/.*\.txt/ => proc {|t| t.pathmap('data/%n.txt')} do |t|
    cp t.source, t.name
    end
    task :use_rule => 'out/some_file.txt'
    # see the rake documentation and tutorials for rules.
    # rake allows defining rules, they describe how to generate a file from another
    # in practice, i've found rules can get hard to read
    # instead i generate tasks using a FileList (more readable)...
    FileList.new('data/*.txt').each do |f|
    target = f.pathmap('out/%f')
    file target => f do
    cp f, target, :verbose => true
    end
    task :use_rule => target
    end

    # -----------------------------------------------------------------------------
    # Clean and Clobber
    # -----------------------------------------------------------------------------