nake 0.0.7 → 0.0.8.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,17 @@
2
2
 
3
3
  require "nake/dsl"
4
4
 
5
- argument("-H", "--help") do
6
- Kernel.abort "Use #{$0} -T for list of all available tasks or -i for interactive session"
5
+ argument("-H", "--help") do |task_name = nil|
6
+ if task_name
7
+ task = Task[task_name]
8
+ if task
9
+ p task # TODO
10
+ else
11
+ abort "Task #{task_name} doesn't exist"
12
+ end
13
+ else
14
+ Kernel.abort "Use #{$0} -T for list of all available tasks or -i for interactive session"
15
+ end
7
16
  end
8
17
 
9
18
  argument("-T", "--tasks") do |pattern = nil|
@@ -48,8 +57,9 @@ argument("-i", "--interactive") do |task = nil|
48
57
  end
49
58
 
50
59
  IRB.start
51
- exit!
60
+ exit! # TODO: can we do it without exit? The usecase is ./tasks.rb -i mytask, so we can set env and then run the task
52
61
  end
53
62
 
54
- Nake.args["--verbose", "--no-verbose"] = lambda { |key, value| Nake.verbose = value }
55
- Nake.args["--debug", "--no-debug"] = lambda { |key, value| Nake.debug = value }
63
+ Nake.args["--verbose", "--no-verbose"] = lambda { |key, value| Nake.verbose = value }
64
+ Nake.args["--debug", "--no-debug"] = lambda { |key, value| Nake.debug = value }
65
+ Nake.args["--coloring", "--no-coloring"] = lambda { |key, value| Nake.coloring = value }
@@ -8,6 +8,15 @@ end
8
8
 
9
9
  String.send(:include, Term::ANSIColor) # just for now, I know it's a mess
10
10
 
11
- # show colors just if you run nake directly from command line,
12
- # but not if are using nake in a script or so
13
- Term::ANSIColor.coloring = STDIN.tty?
11
+ module Term::ANSIColor
12
+ def self.coloring?
13
+ if @coloring.respond_to?(:call)
14
+ @coloring.call
15
+ else
16
+ @coloring
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ Term::ANSIColor.coloring = lambda { Nake.coloring }
@@ -4,52 +4,67 @@ require "nake"
4
4
  require "nake/task"
5
5
  require "nake/file_task"
6
6
 
7
- class Object
8
- include Nake
9
- def argument(*names, &block)
10
- Nake.args[*names] = block
11
- end
7
+ module Nake
8
+ module DSL
9
+ include Nake
10
+ def argument(*names, &block)
11
+ Nake.args[*names] = block
12
+ end
12
13
 
13
- # Rake-style task definition
14
- # task(:release, :build) do |task|
15
- # # task definition
16
- # end
17
- def task(name, *dependencies, &block)
18
- if block.nil?
19
- Task.new(name, *dependencies)
20
- else
21
- Task.new(name, *dependencies) do |task|
22
- task.define(&block)
14
+ # desc :release, "Create a new release"
15
+ # task(:release) do
16
+ # # ...
17
+ # end
18
+ def desc(task, description)
19
+ Task.new(task).description = description
20
+ end
21
+
22
+ # Rake-style task definition
23
+ # task(:release, :build) do |task|
24
+ # # task definition
25
+ # end
26
+ def task(name, *dependencies, &block)
27
+ if block.nil?
28
+ Task.new(name, *dependencies)
29
+ else
30
+ Task.new(name, *dependencies) do |task|
31
+ task.define(&block)
32
+ end
23
33
  end
24
34
  end
25
- end
26
35
 
27
- def file(path, *dependencies, &block)
28
- if block.nil?
29
- FileTask.new(path, *dependencies)
30
- else
31
- FileTask.new(path, *dependencies) do |task|
32
- task.define(&block)
36
+ def file(path, *dependencies, &block)
37
+ if block.nil?
38
+ FileTask.new(path, *dependencies)
39
+ else
40
+ FileTask.new(path, *dependencies) do |task|
41
+ task.define(&block)
42
+ end
33
43
  end
34
44
  end
35
- end
36
45
 
37
- # rule "*.o", "*.c"
38
- # rule "**/*.o", "**/.c"
39
- def rule(glob, dependency, &block)
40
- Dir.glob(glob).each do |path|
41
- FileTask.new(path) do |task|
42
- task.description = "Generate #{path}"
43
- task.define(&block)
46
+ # rule "*.o", "*.c"
47
+ # rule "**/*.o", "**/.c"
48
+ def rule(pattern, *dependencies, &block)
49
+ if block.nil?
50
+ Rule.new(pattern, *dependencies)
51
+ else
52
+ Rule.new(pattern, *dependencies) do |rule|
53
+ rule.define(&block)
54
+ end
44
55
  end
45
56
  end
46
- end
47
57
 
48
- def directory(path)
49
- FileTask.new(path) do |task|
50
- task.hidden = true # do not show in list
51
- task.description = "Create directory #{path}"
52
- task.define { mkdir_p path }
58
+ def directory(path)
59
+ FileTask.new(path) do |task|
60
+ task.hidden = true # do not show in list
61
+ task.description = "Create directory #{path}"
62
+ task.define { mkdir_p path }
63
+ end
53
64
  end
54
65
  end
55
66
  end
67
+
68
+ class Object
69
+ include Nake::DSL
70
+ end
@@ -1,19 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "nake/task"
3
+ require "nake/abstract_task"
4
4
 
5
5
  module Nake
6
- class FileTask < Task
6
+ class FileTask < AbstractTask
7
7
  alias_method :path, :name
8
- # FileTask can depend on tasks, other file tasks or just files.
9
- # If a file task depends on a task, this task isn't supposed to change anything what ...
10
- # ... if it's changing something, make sure the changing task is actually called before the file tasks are executed
11
- # If the task is changing something so the file will be generated in all cases, you should rather to use normal task
12
- # If there are some dependencies on files
13
- # FileTask.new("www/index.html") do |task|
14
- # task.file_dependencies.push(*FileList["images/**/*"])
15
- # task.dependencies.push("www") # www task exist
16
- # end
8
+
17
9
  def call(args = Array.new, options = Hash.new)
18
10
  will_run = true
19
11
  unless self.dependencies.empty?
@@ -0,0 +1,38 @@
1
+ module Rake
2
+ def self.method_missing
3
+ raise NotImplementedError
4
+ end
5
+
6
+ def self.const_missing(constant)
7
+ raise NotImplementedError, "Nake doesn't support Rake::#{constant}, please use normal Rake"
8
+ end
9
+ end
10
+
11
+ # lazy-loading FTW!
12
+ def Object.const_missing(constant)
13
+ if constant.eql?(:FileList)
14
+ begin
15
+ require "filelist"
16
+ FileList
17
+ rescue LoadError
18
+ raise LoadError, "You have to install filelist gem!"
19
+ end
20
+ end
21
+ end
22
+
23
+ module Nake
24
+ module RakeDSL
25
+ def task
26
+ end
27
+
28
+ def file
29
+ end
30
+
31
+ def rule
32
+ end
33
+
34
+ def multitask
35
+ raise NotImplementedError, "Multitask method won't be supported"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require "nake/abstract_task"
4
+
5
+ module Nake
6
+ class Rule < AbstractTask
7
+ undef_method :hidden, :hidden=
8
+ class << self
9
+ undef_method :tasks
10
+ end
11
+
12
+ def self.rules
13
+ @@rules ||= Hash.new
14
+ end
15
+
16
+ # Rule["test.o"]
17
+ # # => rule with pattern ".o"
18
+ def self.[](file)
19
+ self.rules.find { |rule| rule.match?(file.to_s) }
20
+ end
21
+
22
+ def self.[]=(pattern, rule)
23
+ self.rules[pattern.to_s] = rule
24
+ end
25
+
26
+ alias_method :pattern, :name
27
+ def match?(file)
28
+ #
29
+ end
30
+ end
31
+
32
+ # Somewhat like method_missing:
33
+ # If you can't find a task, try to look for a rule
34
+ AbstractTask.tasks.default_proc = lambda { |hash, name| Rule[name] }
35
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ # options.extend(HashStructMixin)
4
+ # options.name
5
+ # options.force?
6
+ module Nake
7
+ module HashStructMixin
8
+ def method_missing(name, *args, &block)
9
+ if args.empty? && block.nil?
10
+ # options.name
11
+ if value = self[name]
12
+ return value
13
+ # options.force?
14
+ elsif name.to_s.match(/^(.*)\?$/) && value = self[$1.to_sym]
15
+ return value
16
+ end
17
+ end
18
+
19
+ super(name, *args, &block)
20
+ end
21
+ end
22
+ end
@@ -1,147 +1,6 @@
1
- # encoding: utf-8
2
-
3
- require "nake/colors"
4
- require "nake/argv"
1
+ require "nake/abstract_task"
5
2
 
6
3
  module Nake
7
- TaskNotFound ||= Class.new(StandardError)
8
- ConfigurationError ||= Class.new(StandardError)
9
-
10
- class Task
11
- def self.[](name)
12
- self.tasks[name.to_s]
13
- end
14
-
15
- def self.[]=(name, task)
16
- self.tasks[name.to_s] = task
17
- end
18
-
19
- # @protected use Task[name] resp. Task[name] = task
20
- def self.tasks
21
- @@tasks ||= Hash.new
22
- end
23
-
24
- def self.boot
25
- self.tasks.each do |name, task|
26
- task.boot!
27
- end
28
- end
29
-
30
- # return existing task if task with given name already exist
31
- def self.new(name, *dependencies, &block)
32
- task = self[name]
33
- task && task.setup(*dependencies, &block) || super(name, *dependencies, &block)
34
- end
35
-
36
- attr_accessor :name, :description, :dependencies, :hidden, :original_args
37
- attr_reader :blocks
38
- def initialize(name, *dependencies, &block)
39
- @hidden = false
40
- @name, @blocks = name.to_sym, Array.new
41
- @dependencies = Array.new
42
- self.register
43
- self.setup(*dependencies, &block)
44
- end
45
-
46
- def config
47
- @config ||= begin
48
- Hash.new do |hash, key|
49
- raise ConfigurationError, "Configuration key #{key} in task #{name} doesn't exist"
50
- end.tap do |hash|
51
- hash.define_singleton_method(:declare) do |*keys|
52
- keys.each { |key| self[key] = nil }
53
- end
54
- end
55
- end
56
- end
57
-
58
- def setup(*dependencies, &block)
59
- self.dependencies.push(*dependencies)
60
- self.instance_exec(self, &block) if block
61
- return self
62
- end
63
-
64
- def define(&block)
65
- @blocks.push(block)
66
- end
67
-
68
- def hidden?
69
- @hidden
70
- end
71
-
72
- def run(args)
73
- self.original_args = args
74
- options = ArgvParser.extract!(args)
75
- self.call(args, options)
76
- end
77
-
78
- # NOTE: the reason why we don't have splat for args is that when we have Task["-T"]
79
- # which doesn't have any args and options, we wall just call it without any arguments,
80
- # but when we use splat, then we will have to call it at least with Hash.new for options
81
- def call(args = Array.new, options = Hash.new)
82
- unless self.dependencies.empty?
83
- info "Invoking task #{name}"
84
- self.invoke_dependencies(*args, options)
85
- end
86
- unless self.blocks.empty?
87
- note "Executing task #{name} with arguments #{args.inspect} and options #{options.inspect}"
88
- debug "Config #{self.config.inspect}"
89
- self.blocks.each do |block|
90
- block.call(*args, options)
91
- end
92
- end
93
- end
94
-
95
- def bootloaders
96
- @bootloaders ||= Array.new
97
- end
98
-
99
- def boot_dependencies
100
- @boot_dependencies ||= Array.new
101
- end
102
-
103
- def boot(*dependencies, &block)
104
- self.boot_dependencies.push(*dependencies)
105
- self.bootloaders.push(block)
106
- end
107
-
108
- def boot!
109
- unless self.boot_dependencies.empty? && self.bootloaders.empty?
110
- note "Booting #{self.name}"
111
- end
112
- while dependency = self.boot_dependencies.shift
113
- self.class[dependency].tap do |task|
114
- if task.nil?
115
- raise TaskNotFound, "Task #{dependency} doesn't exist!"
116
- end
117
- task.boot!
118
- end
119
- end
120
- while block = self.bootloaders.shift
121
- block.call
122
- end
123
- end
124
-
125
- def booted?
126
- self.bootloaders.empty? && self.boot_dependencies.empty?
127
- end
128
-
129
- def reset!
130
- self.dependencies.clear
131
- self.blocks.clear
132
- end
133
-
134
- protected
135
- def invoke_dependencies(*args, options)
136
- self.dependencies.each do |name|
137
- task = self.class[name]
138
- raise TaskNotFound, "Task with name #{name} doesn't exist" if task.nil?
139
- task.call(*args, options) # TODO: what about arguments?
140
- end
141
- end
142
-
143
- def register
144
- self.class[self.name] = self
145
- end
4
+ class Task < AbstractTask
146
5
  end
147
6
  end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ module Nake
4
+ module TaskHelpers
5
+ def template(source, target, context = Hash.new)
6
+ template = Template.new(source)
7
+ File.open(target, "w") do |file|
8
+ file.puts(template.render(context))
9
+ end
10
+ end
11
+
12
+ def erb(source, target, context = Hash.new)
13
+ template = ErbTemplate.new(source)
14
+ File.open(target, "w") do |file|
15
+ file.puts(template.render(context))
16
+ end
17
+ end
18
+ end
19
+
20
+ class Template
21
+ def initialize(path)
22
+ @path = path
23
+ end
24
+
25
+ def render(context = Hash.new)
26
+ File.read(@path) % context
27
+ end
28
+ end
29
+
30
+ class ErbTemplate
31
+ def initialize(path)
32
+ require "erb"
33
+ @path = path
34
+ end
35
+
36
+ def set_locals(context)
37
+ context.inject("") do |source, pair|
38
+ source += "#{pair.first} = context[:#{pair.first}]\n"
39
+ end
40
+ end
41
+
42
+ def source(context)
43
+ ["<% #{self.set_locals(context)} %>", File.read(@path)].join("")
44
+ end
45
+
46
+ def render(context = Hash.new)
47
+ template = ERB.new(self.source(context))
48
+ template.result(binding)
49
+ end
50
+ end
51
+ end