teapot 0.9.10 → 1.0.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/README.md +3 -4
- data/Rakefile +3 -6
- data/bin/teapot +3 -7
- data/lib/teapot/build.rb +166 -18
- data/lib/teapot/configuration.rb +0 -1
- data/lib/teapot/context.rb +37 -21
- data/lib/teapot/controller/build.rb +24 -7
- data/lib/teapot/controller/fetch.rb +1 -1
- data/lib/teapot/controller.rb +1 -0
- data/lib/teapot/definition.rb +1 -1
- data/lib/teapot/dependency.rb +2 -6
- data/lib/teapot/environment/base.rb +7 -15
- data/lib/teapot/environment/constructor.rb +28 -0
- data/lib/teapot/environment/flatten.rb +42 -1
- data/lib/teapot/environment/system.rb +3 -3
- data/lib/teapot/extractors/linker_extractor.rb +2 -2
- data/lib/teapot/loader.rb +9 -11
- data/lib/teapot/name.rb +4 -0
- data/lib/teapot/package.rb +5 -4
- data/lib/teapot/repository.rb +29 -1
- data/lib/teapot/rule.rb +196 -0
- data/lib/teapot/rulebook.rb +91 -0
- data/lib/teapot/target.rb +15 -40
- data/lib/teapot/version.rb +1 -1
- data/{lib/teapot/build/targets/application.rb → spec/teapot/build_spec.rb} +26 -29
- data/{test/test_teapot.rb → spec/teapot/context_spec.rb} +13 -13
- data/spec/teapot/dependency_spec.rb +113 -0
- data/spec/teapot/environment_spec.rb +91 -0
- data/{lib/teapot/build/graph.rb → spec/teapot/name_spec.rb} +26 -26
- data/{test/test_substitutions.rb → spec/teapot/substitutions_spec.rb} +36 -36
- data/{test → spec/teapot}/teapot.rb +1 -1
- data/teapot.gemspec +16 -9
- metadata +98 -51
- data/lib/teapot/build/component.rb +0 -69
- data/lib/teapot/build/file_list.rb +0 -67
- data/lib/teapot/build/linker.rb +0 -49
- data/lib/teapot/build/target.rb +0 -76
- data/lib/teapot/build/targets/compiler.rb +0 -83
- data/lib/teapot/build/targets/directory.rb +0 -63
- data/lib/teapot/build/targets/executable.rb +0 -56
- data/lib/teapot/build/targets/external.rb +0 -91
- data/lib/teapot/build/targets/files.rb +0 -82
- data/lib/teapot/build/targets/library.rb +0 -117
- data/lib/teapot/commands.rb +0 -139
- data/lib/teapot/controller/run.rb +0 -43
- data/lib/teapot/graph.rb +0 -136
- data/test/test_dependency.rb +0 -112
- data/test/test_environment.rb +0 -102
@@ -36,15 +36,15 @@ module Teapot
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def self.convert_to_shell(
|
40
|
-
Hash[values.map{|key, value| [
|
39
|
+
def self.convert_to_shell(environment)
|
40
|
+
Hash[environment.values.map{|key, value| [
|
41
41
|
key.to_s.upcase,
|
42
42
|
shell_escape(value)
|
43
43
|
]}]
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.dump(environment, io = STDOUT)
|
47
|
-
environment.
|
47
|
+
environment.values.each do |key, value|
|
48
48
|
io.puts "#{key}:".rjust(20).color(:magenta) + " #{value.inspect}"
|
49
49
|
end
|
50
50
|
end
|
@@ -28,7 +28,7 @@ module Teapot
|
|
28
28
|
roots = []
|
29
29
|
libraries = []
|
30
30
|
paths = []
|
31
|
-
|
31
|
+
|
32
32
|
# Extract include directories:
|
33
33
|
flags.each do |option|
|
34
34
|
if option.to_s =~ /^-L(.+)/
|
@@ -37,7 +37,7 @@ module Teapot
|
|
37
37
|
libraries << Pathname($1)
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
libraries.each do |name|
|
42
42
|
archive_name = "lib#{name}.a"
|
43
43
|
|
data/lib/teapot/loader.rb
CHANGED
@@ -22,13 +22,15 @@ require 'teapot/project'
|
|
22
22
|
require 'teapot/target'
|
23
23
|
require 'teapot/generator'
|
24
24
|
require 'teapot/configuration'
|
25
|
+
require 'teapot/rule'
|
25
26
|
|
26
27
|
require 'teapot/name'
|
27
|
-
|
28
|
+
|
29
|
+
require 'build/files'
|
28
30
|
|
29
31
|
module Teapot
|
30
|
-
LOADER_VERSION = "0.
|
31
|
-
MINIMUM_LOADER_VERSION = "0
|
32
|
+
LOADER_VERSION = "1.0.0"
|
33
|
+
MINIMUM_LOADER_VERSION = "1.0"
|
32
34
|
|
33
35
|
class IncompatibleTeapotError < StandardError
|
34
36
|
def initialize(package, version)
|
@@ -47,18 +49,14 @@ module Teapot
|
|
47
49
|
end
|
48
50
|
|
49
51
|
class Loader
|
52
|
+
Files = ::Build::Files
|
53
|
+
|
50
54
|
class Definitions < Array
|
51
55
|
def default_configuration
|
52
56
|
find{|definition| Configuration === definition}
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
56
|
-
# Provides build_directory and build_external methods
|
57
|
-
include Build::Helpers
|
58
|
-
|
59
|
-
# Provides run_executable and other related methods.
|
60
|
-
include Commands::Helpers
|
61
|
-
|
62
60
|
def initialize(context, package)
|
63
61
|
@context = context
|
64
62
|
@package = package
|
@@ -134,9 +132,9 @@ module Teapot
|
|
134
132
|
# Load a teapot.rb file relative to the root of the @package.
|
135
133
|
def load(path)
|
136
134
|
absolute_path = @package.path + path
|
137
|
-
|
135
|
+
|
138
136
|
raise NonexistantTeapotError.new(absolute_path) unless File.exist?(absolute_path)
|
139
|
-
|
137
|
+
|
140
138
|
self.instance_eval(absolute_path.read, absolute_path.to_s)
|
141
139
|
|
142
140
|
if @version == nil
|
data/lib/teapot/name.rb
CHANGED
data/lib/teapot/package.rb
CHANGED
@@ -18,19 +18,20 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require '
|
21
|
+
require 'build/files'
|
22
22
|
|
23
23
|
require 'teapot/context'
|
24
24
|
require 'teapot/environment'
|
25
|
-
require 'teapot/commands'
|
26
25
|
|
27
26
|
require 'teapot/definition'
|
28
27
|
|
29
28
|
module Teapot
|
29
|
+
Path = Build::Files::Path
|
30
|
+
|
30
31
|
class Package
|
31
32
|
def initialize(path, name, options = {})
|
32
33
|
# The path where the package is (or will be) located:
|
33
|
-
@path = path
|
34
|
+
@path = Path[path]
|
34
35
|
|
35
36
|
# Get the name of the package from the options, if provided:
|
36
37
|
if options[:name]
|
@@ -49,7 +50,7 @@ module Teapot
|
|
49
50
|
|
50
51
|
# Copy the options provided:
|
51
52
|
@options = options
|
52
|
-
|
53
|
+
end
|
53
54
|
|
54
55
|
attr :name
|
55
56
|
attr :path
|
data/lib/teapot/repository.rb
CHANGED
@@ -18,10 +18,38 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require '
|
21
|
+
require 'rexec'
|
22
22
|
|
23
23
|
module Teapot
|
24
24
|
module Git
|
25
|
+
module Commands
|
26
|
+
class CommandError < StandardError
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.run(*args, &block)
|
30
|
+
options = Hash === args.last ? args.pop : {}
|
31
|
+
options[:passthrough] ||= :all
|
32
|
+
|
33
|
+
args = args.flatten.collect &:to_s
|
34
|
+
|
35
|
+
puts args.join(' ').color(:blue) + " in #{options[:chdir] || Dir.getwd}"
|
36
|
+
|
37
|
+
task = RExec::Task.open(args, options, &block)
|
38
|
+
|
39
|
+
if task.wait == 0
|
40
|
+
true
|
41
|
+
else
|
42
|
+
raise CommandError.new("Non-zero exit status: #{args.join(' ')}!")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.run!(*args, &block)
|
47
|
+
run(*args, &block)
|
48
|
+
rescue CommandError
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
25
53
|
class Repository
|
26
54
|
def initialize(root, options = {})
|
27
55
|
@root = root
|
data/lib/teapot/rule.rb
ADDED
@@ -0,0 +1,196 @@
|
|
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
|
+
# A rule is a function with a specific set of input and output parameters, which can match against a given set of specific inputs and outputs. For example, there might be several rules for compiling, but the specific rules depend on the language being compiled.
|
23
|
+
class Rule
|
24
|
+
class Parameter
|
25
|
+
def initialize(direction, name, options = {}, &block)
|
26
|
+
@direction = direction
|
27
|
+
@name = name
|
28
|
+
|
29
|
+
@options = options
|
30
|
+
|
31
|
+
@dynamic = block_given? ? Proc.new(&block) : nil
|
32
|
+
end
|
33
|
+
|
34
|
+
attr :direction
|
35
|
+
attr :name
|
36
|
+
|
37
|
+
attr :options
|
38
|
+
|
39
|
+
def dynamic?
|
40
|
+
@dynamic != nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def implicit?
|
44
|
+
dynamic? and @options[:implicit]
|
45
|
+
end
|
46
|
+
|
47
|
+
def typed?
|
48
|
+
@options[:typed]
|
49
|
+
end
|
50
|
+
|
51
|
+
def applicable? arguments
|
52
|
+
# The parameter is either optional, or is included in the argument list, otherwise we fail.
|
53
|
+
unless @options[:optional] or arguments.include?(@name)
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
|
57
|
+
value = arguments[@name]
|
58
|
+
|
59
|
+
# If the parameter is optional, and wasn't provided, we are okay.
|
60
|
+
if @options[:optional]
|
61
|
+
return true if value == nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# If the parameter is typed, and we don't match the expected type, we fail.
|
65
|
+
if type = @options[:typed]
|
66
|
+
return false unless type === value
|
67
|
+
end
|
68
|
+
|
69
|
+
# If a pattern is provided, we must match it.
|
70
|
+
if pattern = @options[:pattern]
|
71
|
+
return Array(value).all? {|item| pattern.match(item)}
|
72
|
+
end
|
73
|
+
|
74
|
+
return true
|
75
|
+
end
|
76
|
+
|
77
|
+
def compute(arguments)
|
78
|
+
if implicit?
|
79
|
+
@dynamic.call(arguments)
|
80
|
+
elsif dynamic?
|
81
|
+
@dynamic.call(arguments[@name], arguments)
|
82
|
+
else
|
83
|
+
arguments[@name]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def inspect
|
88
|
+
"#{direction}:#{@name} (#{options.inspect})"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize(process_name, type)
|
93
|
+
@name = process_name + "." + type
|
94
|
+
@full_name = @name.gsub(/[^\w]/, '_')
|
95
|
+
|
96
|
+
@process_name = process_name.gsub('-', '_').to_sym
|
97
|
+
@type = type
|
98
|
+
|
99
|
+
@apply = nil
|
100
|
+
|
101
|
+
@parameters = []
|
102
|
+
end
|
103
|
+
|
104
|
+
# compile.cpp
|
105
|
+
attr :name
|
106
|
+
|
107
|
+
# compile
|
108
|
+
attr :process_name
|
109
|
+
|
110
|
+
# compile_cpp
|
111
|
+
attr :full_name
|
112
|
+
|
113
|
+
attr :primary_output
|
114
|
+
|
115
|
+
def input(name, options = {}, &block)
|
116
|
+
@parameters << Parameter.new(:input, name, options, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
def parameter(name, options = {}, &block)
|
120
|
+
@parameters << Parameter.new(:argument, name, options, &block)
|
121
|
+
end
|
122
|
+
|
123
|
+
def output(name, options = {}, &block)
|
124
|
+
@parameters << Parameter.new(:output, name, options, &block)
|
125
|
+
|
126
|
+
@primary_output ||= @parameters.last
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if this rule can process these parameters
|
130
|
+
def applicable?(arguments)
|
131
|
+
@parameters.each do |parameter|
|
132
|
+
next if parameter.implicit?
|
133
|
+
|
134
|
+
return false unless parameter.applicable?(arguments)
|
135
|
+
end
|
136
|
+
|
137
|
+
return true
|
138
|
+
end
|
139
|
+
|
140
|
+
def normalize(arguments)
|
141
|
+
Hash[
|
142
|
+
@parameters.collect do |parameter|
|
143
|
+
[parameter.name, parameter.compute(arguments)]
|
144
|
+
end
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
148
|
+
def files(arguments)
|
149
|
+
input_files = []
|
150
|
+
output_files = []
|
151
|
+
|
152
|
+
@parameters.each do |parameter|
|
153
|
+
# This could probably be improved a bit, we are assuming all parameters are file based:
|
154
|
+
value = arguments[parameter.name]
|
155
|
+
|
156
|
+
next unless value
|
157
|
+
|
158
|
+
case parameter.direction
|
159
|
+
when :input
|
160
|
+
input_files << value
|
161
|
+
when :output
|
162
|
+
output_files << value
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
return Build::Files::Composite.new(input_files), Build::Files::Composite.new(output_files)
|
167
|
+
end
|
168
|
+
|
169
|
+
def apply(&block)
|
170
|
+
@apply = Proc.new(&block)
|
171
|
+
end
|
172
|
+
|
173
|
+
def apply!(scope, arguments)
|
174
|
+
scope.instance_exec(arguments, &@apply) if @apply
|
175
|
+
end
|
176
|
+
|
177
|
+
def result(arguments)
|
178
|
+
if @primary_output
|
179
|
+
arguments[@primary_output.name]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def to_s
|
184
|
+
"<#{self.class.name} #{@name.dump}>"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class NoApplicableRule < StandardError
|
189
|
+
def initialize(name, arguments)
|
190
|
+
super "No applicable rule with name #{name}.* for parameters: #{arguments.inspect}"
|
191
|
+
|
192
|
+
@name = name
|
193
|
+
@arguments = arguments
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,91 @@
|
|
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/rule'
|
22
|
+
|
23
|
+
module Teapot
|
24
|
+
class Rulebook
|
25
|
+
def initialize
|
26
|
+
@rules = {}
|
27
|
+
@processes = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
attr :rules
|
31
|
+
|
32
|
+
def << rule
|
33
|
+
@rules[rule.name] = rule
|
34
|
+
|
35
|
+
# A cache for fast process/file-type lookup:
|
36
|
+
processes = @processes[rule.process_name] ||= []
|
37
|
+
processes << rule
|
38
|
+
end
|
39
|
+
|
40
|
+
def [] name
|
41
|
+
@rules[name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def with(superclass, state = {})
|
45
|
+
task_class = Class.new(superclass)
|
46
|
+
|
47
|
+
# Define methods for all processes, e.g. task_class#compile
|
48
|
+
@processes.each do |key, rules|
|
49
|
+
# Define general rules, which use rule applicability for disambiguation:
|
50
|
+
task_class.send(:define_method, key) do |arguments, &block|
|
51
|
+
rule = rules.find{|rule| rule.applicable? arguments }
|
52
|
+
|
53
|
+
if rule
|
54
|
+
update(rule, arguments, &block)
|
55
|
+
else
|
56
|
+
raise NoApplicableRule.new(key, arguments)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Define methods for all rules, e.g. task_class#compile_cpp
|
62
|
+
@rules.each do |key, rule|
|
63
|
+
task_class.send(:define_method, rule.full_name) do |arguments, &block|
|
64
|
+
update(rule, arguments, &block)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
state.each do |key, value|
|
69
|
+
task_class.send(:define_method, key) do
|
70
|
+
value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
return task_class
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.for(environment)
|
78
|
+
rulebook = self.new
|
79
|
+
|
80
|
+
environment.defined.each do |name, define|
|
81
|
+
object = define.klass.new(*name.split('.', 2))
|
82
|
+
|
83
|
+
object.instance_eval(&define.block)
|
84
|
+
|
85
|
+
rulebook << object
|
86
|
+
end
|
87
|
+
|
88
|
+
return rulebook
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/teapot/target.rb
CHANGED
@@ -19,10 +19,11 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require 'pathname'
|
22
|
-
require 'teapot/build'
|
23
22
|
require 'teapot/dependency'
|
24
23
|
require 'teapot/definition'
|
25
24
|
|
25
|
+
require 'teapot/rulebook'
|
26
|
+
|
26
27
|
module Teapot
|
27
28
|
class BuildError < StandardError
|
28
29
|
end
|
@@ -32,19 +33,23 @@ module Teapot
|
|
32
33
|
|
33
34
|
def initialize(context, package, name)
|
34
35
|
super context, package, name
|
35
|
-
|
36
|
+
|
36
37
|
@build = nil
|
38
|
+
|
39
|
+
@rulebook = Rulebook.new
|
37
40
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def environment_for_configuration(configuration)
|
41
|
+
|
42
|
+
attr :rulebook
|
43
|
+
|
44
|
+
def provision_chain(configuration)
|
44
45
|
# Reduce the number of keystrokes for good health:
|
45
46
|
context = configuration.context
|
46
47
|
|
47
48
|
chain = Dependency::chain(context.selection, dependencies, context.targets.values)
|
49
|
+
end
|
50
|
+
|
51
|
+
def environment_for_configuration(configuration)
|
52
|
+
chain = provision_chain(configuration)
|
48
53
|
|
49
54
|
environments = []
|
50
55
|
|
@@ -63,45 +68,15 @@ module Teapot
|
|
63
68
|
default platforms_path configuration.platforms_path
|
64
69
|
default build_prefix {platforms_path + "cache/#{platform_name}-#{variant}"}
|
65
70
|
default install_prefix {platforms_path + "#{platform_name}-#{variant}"}
|
66
|
-
|
67
|
-
append buildflags {"-I#{install_prefix + "include"}"}
|
68
|
-
append linkflags {"-L#{install_prefix + "lib"}"}
|
69
71
|
end
|
70
72
|
end
|
71
|
-
|
73
|
+
|
72
74
|
def build(&block)
|
73
75
|
if block_given?
|
74
|
-
@build =
|
76
|
+
@build = block
|
75
77
|
end
|
76
78
|
|
77
79
|
return @build
|
78
80
|
end
|
79
|
-
|
80
|
-
def build!(configuration)
|
81
|
-
return unless @build
|
82
|
-
|
83
|
-
local_environment = environment_for_configuration(configuration)
|
84
|
-
|
85
|
-
@build.call(local_environment)
|
86
|
-
end
|
87
|
-
|
88
|
-
# Specify a default block which is used to run the configuration.
|
89
|
-
def run(&block)
|
90
|
-
if block_given?
|
91
|
-
@run = block
|
92
|
-
end
|
93
|
-
|
94
|
-
return @run
|
95
|
-
end
|
96
|
-
|
97
|
-
def run!(configuration)
|
98
|
-
return unless @run
|
99
|
-
|
100
|
-
local_environment = environment_for_configuration(configuration)
|
101
|
-
|
102
|
-
if @run
|
103
|
-
@run.call(local_environment)
|
104
|
-
end
|
105
|
-
end
|
106
81
|
end
|
107
82
|
end
|
data/lib/teapot/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright,
|
1
|
+
# Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -18,38 +18,35 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require 'teapot/build
|
22
|
-
require 'teapot/
|
21
|
+
require 'teapot/build'
|
22
|
+
require 'teapot/environment'
|
23
23
|
|
24
|
-
module Teapot
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
def subdirectory
|
36
|
-
"Applications/#{@name}"
|
37
|
-
end
|
38
|
-
|
39
|
-
def << target
|
40
|
-
if target.respond_to? :subdirectory
|
41
|
-
target.options[:subdirectory] = subdirectory
|
42
|
-
end
|
43
|
-
|
44
|
-
super
|
45
|
-
end
|
24
|
+
module Teapot::BuildSpec
|
25
|
+
class DummyTarget
|
26
|
+
def name
|
27
|
+
"dummy-target"
|
28
|
+
end
|
29
|
+
|
30
|
+
def build
|
31
|
+
lambda do
|
32
|
+
# This is technically incorrect, because this Top graph node specifies no outputs. But, for testing, it's fine.
|
33
|
+
fs.touch "bob"
|
46
34
|
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe Teapot::Build do
|
39
|
+
let(:environment) {Teapot::Environment.hash(foo: 'bar')}
|
40
|
+
|
41
|
+
it "should create a simple build graph" do
|
42
|
+
expect(FileUtils::NoWrite).to receive(:touch).with("bob").once
|
43
|
+
expect(FileUtils::Verbose).to receive(:touch).with("bob").once
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
self << Application.target(self, *args, &block)
|
51
|
-
end
|
45
|
+
controller = Teapot::Build::Controller.new do |controller|
|
46
|
+
controller.add_target(DummyTarget.new, environment)
|
52
47
|
end
|
48
|
+
|
49
|
+
controller.update!
|
53
50
|
end
|
54
51
|
end
|
55
52
|
end
|
@@ -18,25 +18,25 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
-
require "minitest/autorun"
|
22
|
-
|
23
21
|
require 'teapot/context'
|
24
22
|
|
25
|
-
|
26
|
-
ROOT =
|
23
|
+
module Teapot::ContextSpec
|
24
|
+
ROOT = Build::Files::Path.new(__dir__)
|
27
25
|
|
28
|
-
|
29
|
-
|
26
|
+
describe Teapot::Context do
|
27
|
+
it "should load teapot.rb file" do
|
28
|
+
context = Teapot::Context.new(ROOT)
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
# There is one configuration:
|
31
|
+
expect(context.configurations.count).to be == 1
|
33
32
|
|
34
|
-
|
35
|
-
|
33
|
+
# No targets were defined:
|
34
|
+
expect(context.targets.count).to be == 0
|
36
35
|
|
37
|
-
|
36
|
+
default_configuration = context.configuration
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
# 13 defined packages + 1 implicit package.
|
39
|
+
expect(default_configuration.packages.count).to be == 14
|
40
|
+
end
|
41
41
|
end
|
42
42
|
end
|