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.
- data/CHANGELOG +17 -0
- data/README.textile +10 -34
- data/TODO.txt +21 -4
- data/bin/nake +3 -0
- data/bin/nrake +4 -0
- data/bin/rake2nake +1 -0
- data/bin/snake +41 -0
- data/bm/Rakefile +28 -0
- data/bm/bms.rb +36 -2
- data/bm/tasks.rb +21 -0
- data/deps.rb +5 -0
- data/deps.rip +5 -0
- data/examples/description.rb +33 -0
- data/examples/rules.rb +0 -0
- data/features/description.feature +0 -0
- data/features/rules.feature +0 -0
- data/lib/nake.rb +12 -5
- data/lib/nake/abstract_task.rb +175 -0
- data/lib/nake/args.rb +15 -5
- data/lib/nake/colors.rb +12 -3
- data/lib/nake/dsl.rb +51 -36
- data/lib/nake/file_task.rb +3 -11
- data/lib/nake/rake.rb +38 -0
- data/lib/nake/rule.rb +35 -0
- data/lib/nake/struct_hash.rb +22 -0
- data/lib/nake/task.rb +2 -143
- data/lib/nake/template.rb +51 -0
- data/nake.pre.gemspec +1 -1
- data/prerelease.log +10 -0
- data/spec/nake/abstract_task_spec.rb +0 -0
- data/spec/nake/args_spec.rb +0 -0
- data/spec/nake/rake_spec.rb +0 -0
- data/spec/nake/rule_spec.rb +72 -0
- data/spec/nake/struct_hash_spec.rb +0 -0
- data/spec/nake/tasks/clean_spec.rb +0 -0
- data/spec/nake/tasks/gem_spec.rb +0 -0
- data/spec/nake/tasks/release_spec.rb +0 -0
- data/spec/nake/tasks/rip_spec.rb +0 -0
- data/spec/nake/tasks/spec_spec.rb +0 -0
- data/spec/nake/template_spec.rb +84 -0
- data/spec/stubs/database.yml.erb +9 -0
- data/spec/stubs/database.yml.tt +9 -0
- data/tasks.rb +4 -5
- metadata +79 -50
- data/Rakefile +0 -8
data/lib/nake/args.rb
CHANGED
@@ -2,8 +2,17 @@
|
|
2
2
|
|
3
3
|
require "nake/dsl"
|
4
4
|
|
5
|
-
argument("-H", "--help") do
|
6
|
-
|
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",
|
55
|
-
Nake.args["--debug",
|
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 }
|
data/lib/nake/colors.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
13
|
-
|
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 }
|
data/lib/nake/dsl.rb
CHANGED
@@ -4,52 +4,67 @@ require "nake"
|
|
4
4
|
require "nake/task"
|
5
5
|
require "nake/file_task"
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module Nake
|
8
|
+
module DSL
|
9
|
+
include Nake
|
10
|
+
def argument(*names, &block)
|
11
|
+
Nake.args[*names] = block
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
data/lib/nake/file_task.rb
CHANGED
@@ -1,19 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require "nake/
|
3
|
+
require "nake/abstract_task"
|
4
4
|
|
5
5
|
module Nake
|
6
|
-
class FileTask <
|
6
|
+
class FileTask < AbstractTask
|
7
7
|
alias_method :path, :name
|
8
|
-
|
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?
|
data/lib/nake/rake.rb
ADDED
@@ -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
|
data/lib/nake/rule.rb
ADDED
@@ -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
|
data/lib/nake/task.rb
CHANGED
@@ -1,147 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "nake/colors"
|
4
|
-
require "nake/argv"
|
1
|
+
require "nake/abstract_task"
|
5
2
|
|
6
3
|
module Nake
|
7
|
-
|
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
|