nake 0.0.7 → 0.0.8.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -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