teapot 1.0.0.pre.rc9 → 1.0.0.pre.rc10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +5 -0
- data/README.md +3 -1
- data/Rakefile +3 -1
- data/bin/teapot +1 -1
- data/lib/teapot/configuration.rb +0 -1
- data/lib/teapot/context.rb +8 -2
- data/lib/teapot/controller/build.rb +3 -6
- data/lib/teapot/controller/create.rb +2 -2
- data/lib/teapot/controller/fetch.rb +1 -1
- data/lib/teapot/dependency.rb +0 -2
- data/lib/teapot/generator.rb +2 -2
- data/lib/teapot/loader.rb +4 -4
- data/lib/teapot/{name.rb → metadata.rb} +15 -22
- data/lib/teapot/package.rb +0 -2
- data/lib/teapot/repository.rb +1 -1
- data/lib/teapot/target.rb +5 -4
- data/lib/teapot/version.rb +1 -1
- data/{lib/teapot/environment.rb → spec/teapot/metadata_spec.rb} +11 -5
- data/teapot.gemspec +1 -3
- metadata +9 -49
- data/lib/teapot/build.rb +0 -254
- data/lib/teapot/environment/base.rb +0 -62
- data/lib/teapot/environment/constructor.rb +0 -133
- data/lib/teapot/environment/evaluator.rb +0 -51
- data/lib/teapot/environment/flatten.rb +0 -102
- data/lib/teapot/environment/system.rb +0 -56
- data/lib/teapot/rule.rb +0 -188
- data/lib/teapot/rulebook.rb +0 -91
- data/spec/teapot/build_spec.rb +0 -52
- data/spec/teapot/environment_spec.rb +0 -91
- data/spec/teapot/name_spec.rb +0 -50
data/lib/teapot/build.rb
DELETED
@@ -1,254 +0,0 @@
|
|
1
|
-
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
require 'teapot/rulebook'
|
22
|
-
|
23
|
-
require 'build/files'
|
24
|
-
require 'build/graph'
|
25
|
-
require 'build/makefile'
|
26
|
-
|
27
|
-
require 'teapot/name'
|
28
|
-
|
29
|
-
require 'graphviz'
|
30
|
-
require 'process/group'
|
31
|
-
require 'system'
|
32
|
-
|
33
|
-
module Teapot
|
34
|
-
module Build
|
35
|
-
Graph = ::Build::Graph
|
36
|
-
Files = ::Build::Files
|
37
|
-
Paths = ::Build::Files::Paths
|
38
|
-
Makefile = ::Build::Makefile
|
39
|
-
|
40
|
-
class Node < Graph::Node
|
41
|
-
def initialize(controller, rule, arguments, &block)
|
42
|
-
@arguments = arguments
|
43
|
-
@rule = rule
|
44
|
-
|
45
|
-
@callback = block
|
46
|
-
|
47
|
-
inputs, outputs = rule.files(arguments)
|
48
|
-
|
49
|
-
super(controller, inputs, outputs)
|
50
|
-
end
|
51
|
-
|
52
|
-
attr :arguments
|
53
|
-
attr :rule
|
54
|
-
attr :callback
|
55
|
-
|
56
|
-
def hash
|
57
|
-
[@rule.name, @arguments].hash
|
58
|
-
end
|
59
|
-
|
60
|
-
def eql?(other)
|
61
|
-
other.kind_of?(self.class) and @rule.eql?(other.rule) and @arguments.eql?(other.arguments)
|
62
|
-
end
|
63
|
-
|
64
|
-
def apply!(scope)
|
65
|
-
@rule.apply!(scope, @arguments)
|
66
|
-
|
67
|
-
if @callback
|
68
|
-
scope.instance_exec(@arguments, &@callback)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def inspect
|
73
|
-
@rule.name.inspect
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class Top < Graph::Node
|
78
|
-
def initialize(controller, task_class, &update)
|
79
|
-
@update = update
|
80
|
-
@task_class = task_class
|
81
|
-
|
82
|
-
super(controller, Paths::NONE, Paths::NONE)
|
83
|
-
end
|
84
|
-
|
85
|
-
attr :task_class
|
86
|
-
|
87
|
-
def apply!(scope)
|
88
|
-
scope.instance_exec(&@update)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Top level nodes are always considered dirty. This ensures that enclosed nodes are run if they are dirty. The top level node has no inputs or outputs by default, so children who become dirty wouldn't mark it as dirty and thus wouldn't be run.
|
92
|
-
def requires_update?
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
def inspect
|
97
|
-
@task_class.name.inspect
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class Task < Graph::Task
|
102
|
-
def initialize(controller, walker, node, group = nil)
|
103
|
-
super(controller, walker, node)
|
104
|
-
|
105
|
-
@group = group
|
106
|
-
|
107
|
-
if wet?
|
108
|
-
#@file_system = FileUtils
|
109
|
-
@file_system = FileUtils::Verbose
|
110
|
-
else
|
111
|
-
@file_system = FileUtils::NoWrite
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
attr :file_system
|
116
|
-
alias fs file_system
|
117
|
-
|
118
|
-
def wet?
|
119
|
-
@group && @node.requires_update?
|
120
|
-
end
|
121
|
-
|
122
|
-
def update(rule, arguments, &block)
|
123
|
-
arguments = rule.normalize(arguments, self)
|
124
|
-
|
125
|
-
# A sub-graph for a particular build is isolated based on the task class used to instantiate it, so we use this as part of the key.
|
126
|
-
child_node = @controller.nodes.fetch([self.class, rule.name, arguments]) do |key|
|
127
|
-
@controller.nodes[key] = Node.new(@controller, rule, arguments, &block)
|
128
|
-
end
|
129
|
-
|
130
|
-
@children << child_node
|
131
|
-
|
132
|
-
child_node.update!(@walker)
|
133
|
-
|
134
|
-
return child_node.rule.result(arguments)
|
135
|
-
end
|
136
|
-
|
137
|
-
def run!(*arguments)
|
138
|
-
if wet?
|
139
|
-
puts Rainbow(arguments.join(' ')).blue
|
140
|
-
status = @group.spawn(*arguments)
|
141
|
-
# puts Rainbow("Finished #{arguments.inspect} with status #{status}").blue
|
142
|
-
|
143
|
-
if status != 0
|
144
|
-
raise Graph::CommandFailure.new(arguments, status)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def visit
|
150
|
-
super do
|
151
|
-
@controller.enter(self, @node)
|
152
|
-
@node.apply!(self)
|
153
|
-
@controller.exit(self, @node)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
class Controller < Graph::Controller
|
159
|
-
def initialize
|
160
|
-
@module = Module.new
|
161
|
-
|
162
|
-
@top = []
|
163
|
-
|
164
|
-
yield self
|
165
|
-
|
166
|
-
@top.freeze
|
167
|
-
|
168
|
-
@task_class = nil
|
169
|
-
|
170
|
-
super()
|
171
|
-
end
|
172
|
-
|
173
|
-
attr :top
|
174
|
-
|
175
|
-
attr :visualisation
|
176
|
-
|
177
|
-
# Because we do a depth first traversal, we can capture global state per branch, such as `@task_class`.
|
178
|
-
def traverse!(walker)
|
179
|
-
@top.each do |node|
|
180
|
-
# Capture the task class for each top level node:
|
181
|
-
@task_class = node.task_class
|
182
|
-
|
183
|
-
node.update!(walker)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def add_target(target, environment, &block)
|
188
|
-
task_class = Rulebook.for(environment).with(Task, environment: environment, target: target)
|
189
|
-
|
190
|
-
# Not sure if this is a good idea - makes debugging slightly easier.
|
191
|
-
Object.const_set("TaskClassFor#{Name.from_target(target.name).identifier}_#{self.object_id}", task_class)
|
192
|
-
|
193
|
-
@top << Top.new(self, task_class, &target.build)
|
194
|
-
end
|
195
|
-
|
196
|
-
def build_graph!
|
197
|
-
super do |walker, node|
|
198
|
-
@task_class.new(self, walker, node)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def enter(task, node)
|
203
|
-
return unless @g
|
204
|
-
|
205
|
-
parent_node = @hierarchy.last
|
206
|
-
|
207
|
-
task_node = @g.nodes[node] || @g.add_node(node, shape: 'box')
|
208
|
-
|
209
|
-
if parent_node
|
210
|
-
parent_node.connect(task_node)
|
211
|
-
end
|
212
|
-
|
213
|
-
node.inputs.map{|path| path.shortest_path(Dir.pwd)}.each do |path|
|
214
|
-
input_node = @g.nodes[path.to_s] || @g.add_node(path.to_s, shape: 'box')
|
215
|
-
input_node.connect(task_node)
|
216
|
-
end
|
217
|
-
|
218
|
-
@hierarchy << task_node
|
219
|
-
end
|
220
|
-
|
221
|
-
def exit(task, node)
|
222
|
-
return unless @g
|
223
|
-
|
224
|
-
@hierarchy.pop
|
225
|
-
|
226
|
-
task_node = @g.nodes[node] || @g.add_node(node, shape: 'box')
|
227
|
-
|
228
|
-
node.outputs.map{|path| path.shortest_path(Dir.pwd)}.each do |path|
|
229
|
-
output_node = @g.nodes[path.to_s] || @g.add_node(path.to_s, shape: 'box')
|
230
|
-
output_node.connect(task_node)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def update!
|
235
|
-
group = Process::Group.new
|
236
|
-
|
237
|
-
@g = Graphviz::Graph.new('G', rankdir: "LR")
|
238
|
-
@hierarchy = []
|
239
|
-
|
240
|
-
walker = super do |walker, node|
|
241
|
-
@task_class.new(self, walker, node, group)
|
242
|
-
end
|
243
|
-
|
244
|
-
group.wait
|
245
|
-
|
246
|
-
if ENV['BUILD_GRAPH_PDF']
|
247
|
-
Graphviz::output(@g, path: ENV['BUILD_GRAPH_PDF']) rescue nil
|
248
|
-
end
|
249
|
-
|
250
|
-
return walker
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
module Teapot
|
22
|
-
# This is the basic environment data structure which is essentially a linked list of hashes. It is primarily used for organising build configurations across a wide range of different sub-systems, e.g. platform configuration, target configuration, local project configuration, etc.
|
23
|
-
class Environment
|
24
|
-
def initialize(parent = nil, values = nil, &block)
|
25
|
-
@values = (values || {}).to_h
|
26
|
-
@parent = parent
|
27
|
-
|
28
|
-
if block_given?
|
29
|
-
Constructor.new(self).instance_exec(&block)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.hash(**values)
|
34
|
-
self.new(nil, values)
|
35
|
-
end
|
36
|
-
|
37
|
-
attr :values
|
38
|
-
attr :parent
|
39
|
-
|
40
|
-
def lookup(name)
|
41
|
-
if @values.include? name
|
42
|
-
self
|
43
|
-
elsif @parent
|
44
|
-
@parent.lookup(name)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def [] (key)
|
49
|
-
environment = lookup(key)
|
50
|
-
|
51
|
-
environment ? environment.values[key] : nil
|
52
|
-
end
|
53
|
-
|
54
|
-
def []= (key, value)
|
55
|
-
@values[key] = value
|
56
|
-
end
|
57
|
-
|
58
|
-
def to_s
|
59
|
-
"<#{self.class} #{self.values}>"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,133 +0,0 @@
|
|
1
|
-
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
module Teapot
|
22
|
-
class Environment
|
23
|
-
Default = Struct.new(:value)
|
24
|
-
Replace = Struct.new(:value)
|
25
|
-
|
26
|
-
class Define
|
27
|
-
def initialize(klass, &block)
|
28
|
-
@klass = klass
|
29
|
-
@block = block
|
30
|
-
end
|
31
|
-
|
32
|
-
attr :klass
|
33
|
-
attr :block
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
"<#{@klass.name} #{@block.source_location.join(':')}>"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class Constructor
|
41
|
-
def initialize(environment)
|
42
|
-
@environment = environment
|
43
|
-
end
|
44
|
-
|
45
|
-
def method_missing(name, value = nil, &block)
|
46
|
-
if block_given?
|
47
|
-
@environment[name] = block
|
48
|
-
else
|
49
|
-
@environment[name] = value
|
50
|
-
end
|
51
|
-
|
52
|
-
name
|
53
|
-
end
|
54
|
-
|
55
|
-
def [] key
|
56
|
-
@environment[key]
|
57
|
-
end
|
58
|
-
|
59
|
-
def default(name)
|
60
|
-
@environment[name] = Default.new(@environment[name])
|
61
|
-
|
62
|
-
return name
|
63
|
-
end
|
64
|
-
|
65
|
-
def replace(name)
|
66
|
-
@environment[name] = Replace.new(@environment[name])
|
67
|
-
|
68
|
-
return name
|
69
|
-
end
|
70
|
-
|
71
|
-
def append(name)
|
72
|
-
@environment[name] = Array(@environment[name])
|
73
|
-
|
74
|
-
return name
|
75
|
-
end
|
76
|
-
|
77
|
-
def define(klass, name, &block)
|
78
|
-
abort "#{name} isn't a string when defining #{klass}" unless String === name
|
79
|
-
|
80
|
-
@environment[name] = Define.new(klass, &block)
|
81
|
-
|
82
|
-
return name
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.combine(*environments)
|
87
|
-
# Flatten the list of environments:
|
88
|
-
environments = environments.collect do |environment|
|
89
|
-
if Environment === environment
|
90
|
-
environment.to_a
|
91
|
-
else
|
92
|
-
environment
|
93
|
-
end
|
94
|
-
end.flatten
|
95
|
-
|
96
|
-
# Resequence based on order:
|
97
|
-
first = Environment.new(nil, environments.shift)
|
98
|
-
top = first
|
99
|
-
|
100
|
-
environments.each do |tail|
|
101
|
-
top = Environment.new(top, tail)
|
102
|
-
end
|
103
|
-
|
104
|
-
return top
|
105
|
-
end
|
106
|
-
|
107
|
-
def merge(&block)
|
108
|
-
self.class.combine(
|
109
|
-
self,
|
110
|
-
self.class.new(&block)
|
111
|
-
)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Convert the hierarchy of environments to an array where the parent comes before the child.
|
115
|
-
def to_a
|
116
|
-
flat = []
|
117
|
-
|
118
|
-
flatten_to_array(flat)
|
119
|
-
|
120
|
-
return flat
|
121
|
-
end
|
122
|
-
|
123
|
-
protected
|
124
|
-
|
125
|
-
def flatten_to_array(array)
|
126
|
-
if @parent
|
127
|
-
@parent.flatten_to_array(array)
|
128
|
-
end
|
129
|
-
|
130
|
-
array << self
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|