teapot 0.9.10 → 1.0.0.pre.rc1
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.
- 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
|