PageRenderTime 33ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/cake.coffee

http://github.com/jashkenas/coffee-script
CoffeeScript | 88 lines | 51 code | 12 blank | 25 comment | 7 complexity | e722c6667fddfa73f29ca27743df2510 MD5 | raw file
  1. # `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
  2. # ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))
  3. # for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
  4. # and can call them from the command line, or invoke them from other tasks.
  5. #
  6. # Running `cake` with no arguments will print out a list of all the tasks in the
  7. # current directory's Cakefile.
  8. # External dependencies.
  9. fs = require 'fs'
  10. path = require 'path'
  11. helpers = require './helpers'
  12. optparse = require './optparse'
  13. CoffeeScript = require './'
  14. # Register .coffee extension
  15. CoffeeScript.register()
  16. # Keep track of the list of defined tasks, the accepted options, and so on.
  17. tasks = {}
  18. options = {}
  19. switches = []
  20. oparse = null
  21. # Mixin the top-level Cake functions for Cakefiles to use directly.
  22. helpers.extend global,
  23. # Define a Cake task with a short name, an optional sentence description,
  24. # and the function to run as the action itself.
  25. task: (name, description, action) ->
  26. [action, description] = [description, action] unless action
  27. tasks[name] = {name, description, action}
  28. # Define an option that the Cakefile accepts. The parsed options hash,
  29. # containing all of the command-line options passed, will be made available
  30. # as the first argument to the action.
  31. option: (letter, flag, description) ->
  32. switches.push [letter, flag, description]
  33. # Invoke another task in the current Cakefile.
  34. invoke: (name) ->
  35. missingTask name unless tasks[name]
  36. tasks[name].action options
  37. # Run `cake`. Executes all of the tasks you pass, in order. Note that Node's
  38. # asynchrony may cause tasks to execute in a different order than you'd expect.
  39. # If no tasks are passed, print the help screen. Keep a reference to the
  40. # original directory name, when running Cake tasks from subdirectories.
  41. exports.run = ->
  42. global.__originalDirname = fs.realpathSync '.'
  43. process.chdir cakefileDirectory __originalDirname
  44. args = process.argv[2..]
  45. CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
  46. oparse = new optparse.OptionParser switches
  47. return printTasks() unless args.length
  48. try
  49. options = oparse.parse(args)
  50. catch e
  51. return fatalError "#{e}"
  52. invoke arg for arg in options.arguments
  53. # Display the list of Cake tasks in a format similar to `rake -T`
  54. printTasks = ->
  55. relative = path.relative or path.resolve
  56. cakefilePath = path.join relative(__originalDirname, process.cwd()), 'Cakefile'
  57. console.log "#{cakefilePath} defines the following tasks:\n"
  58. for name, task of tasks
  59. spaces = 20 - name.length
  60. spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
  61. desc = if task.description then "# #{task.description}" else ''
  62. console.log "cake #{name}#{spaces} #{desc}"
  63. console.log oparse.help() if switches.length
  64. # Print an error and exit when attempting to use an invalid task/option.
  65. fatalError = (message) ->
  66. console.error message + '\n'
  67. console.log 'To see a list of all tasks/options, run "cake"'
  68. process.exit 1
  69. missingTask = (task) -> fatalError "No such task: #{task}"
  70. # When `cake` is invoked, search in the current and all parent directories
  71. # to find the relevant Cakefile.
  72. cakefileDirectory = (dir) ->
  73. return dir if fs.existsSync path.join dir, 'Cakefile'
  74. parent = path.normalize path.join dir, '..'
  75. return cakefileDirectory parent unless parent is dir
  76. throw new Error "Cakefile not found in #{process.cwd()}"