teapot 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: efe943a787623142f2f892d4b91fbbd55ff623e0
4
- data.tar.gz: 62551632283c22eb90bac52fdfebaf1caa331962
3
+ metadata.gz: 64f2a0edc8ff6b5841b0ff8cf5e2cb7d35ef977c
4
+ data.tar.gz: 41621d952ff9bd058b74a6ff7d2c95feb199f849
5
5
  SHA512:
6
- metadata.gz: 849356a7ede4e858cb2551ac95be4a6a4aa385913be803032e580c804c2f64bc4f3d340ed1bf3adf868a5bdea06a503a48eabf3533e6cfd3a7a0efc27e382557
7
- data.tar.gz: 30b8d32b64da3cab383e7dc97bac312d4fcd14d095cfffd6c47a3d929b5bef17ea94b37a864e5a76d08ca83f0d8b695b115f36685a9c3893e8eb857ba79a2a95
6
+ metadata.gz: 6d7a7cbe915fc27ebbd148658b4731cc093d8e905a3444120ba511f35b19ebc6c2d670956d411e2fcfce742d14591081581ac551757999fba397e08d5c1518a2
7
+ data.tar.gz: 08421526dd8288ae6e009ceca30ccea7200c3cc9f04b4687e5f53f0ab175cdf316bb943b11911d54f9fa5990117fe525c1a843ea5f10b574717a63ffe5e10267
@@ -30,16 +30,76 @@ require 'teapot/commands'
30
30
  require 'teapot/definition'
31
31
 
32
32
  module Teapot
33
+ # Very similar to a set but uses a specific callback for object identity.
34
+ class IdentitySet
35
+ include Enumerable
36
+
37
+ def initialize(contents = [], &block)
38
+ @table = {}
39
+ @identity = block
40
+
41
+ contents.each do |object|
42
+ add(object)
43
+ end
44
+ end
45
+
46
+ def initialize_dup(other)
47
+ @table = other.table.dup
48
+ end
49
+
50
+ attr :table
51
+
52
+ def add(object)
53
+ @table[@identity[object]] = object
54
+ end
55
+
56
+ alias << add
57
+
58
+ def remove(object)
59
+ @table.delete(@identity[object])
60
+ end
61
+
62
+ def include?(object)
63
+ @table.include?(@identity[object])
64
+ end
65
+
66
+ def each(&block)
67
+ @table.each_value(&block)
68
+ end
69
+
70
+ def size
71
+ @table.size
72
+ end
73
+
74
+ def clear
75
+ @table.clear
76
+ end
77
+
78
+ alias count size
79
+
80
+ def to_s
81
+ @table.to_s
82
+ end
83
+ end
84
+
33
85
  class Configuration < Definition
34
- Import = Struct.new(:name, :options)
86
+ Import = Struct.new(:name, :explicit, :options)
35
87
 
36
- def initialize(context, package, name, packages = Set.new, options = {})
88
+ DEFAULT_OPTIONS = {
89
+ :import => true
90
+ }
91
+
92
+ def initialize(context, package, name, packages = [], options = nil)
37
93
  super context, package, name
38
94
 
39
- @options = options
95
+ if options
96
+ @options = options
97
+ else
98
+ @options = DEFAULT_OPTIONS.dup
99
+ end
40
100
 
41
- @packages = packages
42
- @imports = []
101
+ @packages = IdentitySet.new(packages, &:name)
102
+ @imports = IdentitySet.new(&:name)
43
103
 
44
104
  @visibility = :private
45
105
  end
@@ -69,17 +129,17 @@ module Teapot
69
129
  options = options ? @options.merge(options) : @options.dup
70
130
 
71
131
  @packages << Package.new(packages_path + name.to_s, name, options)
132
+
133
+ if options[:import] == true
134
+ import(name, false)
135
+ elsif String === options[:import]
136
+ import(options[:import])
137
+ end
72
138
  end
73
139
 
74
140
  # Specifies that this package will import additional configuration records from another definition.
75
- def import(name)
76
- @imports << Import.new(name, @options.dup)
77
- end
78
-
79
- # Require and import the named package.
80
- def import!(name, options = nil)
81
- require(name, options)
82
- import(name)
141
+ def import(name, explicit = true)
142
+ @imports << Import.new(name, explicit, @options.dup)
83
143
  end
84
144
 
85
145
  # Create a group for configuration options which will be only be active within the group block.
@@ -134,39 +194,61 @@ module Teapot
134
194
  # Process all import directives and return a new configuration based on the current configuration. Import directives bring packages and other import directives from the specififed configuration definition.
135
195
  def materialize
136
196
  # Potentially no materialization is required:
137
- return self if @imports.count == 0
138
-
139
- # Before trying to materialize, we should load all possible packages:
140
- @packages.each do |package|
141
- @context.load(package) rescue nil
142
- end
143
-
144
- # Create a new configuration which will represent the materialised version:
145
- configuration = self.class.new(@context, @package, @name, @packages.dup, @options.dup)
197
+ return false if @imports.count == 0
146
198
 
147
199
  # Enumerate all imports and attempt to resolve the packages:
148
- @imports.each do |import|
149
- named_configuration = @context.configurations[import.name]
200
+ begin
201
+ updated = false
150
202
 
151
- if named_configuration && named_configuration != self
152
- configuration.append(named_configuration.materialize, import.options)
153
- else
154
- # It couldn't be resolved...
155
- configuration.imports << import
203
+ # Before trying to materialize, we should load all possible packages:
204
+ @packages.each do |package|
205
+ @context.load(package) rescue nil
156
206
  end
157
- end
207
+
208
+ imports = @imports
209
+ @imports = IdentitySet.new(&:name)
210
+
211
+ imports.each do |import|
212
+ named_configuration = @context.configurations[import.name]
213
+
214
+ if named_configuration && named_configuration != self
215
+ updated = self.merge(named_configuration, import.options) || updated
216
+ else
217
+ # It couldn't be resolved...
218
+ @imports << import
219
+ end
220
+ end
221
+ end while updated
158
222
 
159
- return configuration
223
+ return true
160
224
  end
161
225
 
162
- def append(configuration, options)
163
- @packages += configuration.packages.collect do |package|
164
- package.dup.tap{|package| package.options = options.merge(package.options)}
226
+ # Merge an external configuration into this configuration. We won't override already defined packages.
227
+ def merge(configuration, options)
228
+ updated = false
229
+
230
+ configuration.packages.each do |external_package|
231
+ # The top level configuration will override packages that are defined by imported configurations. This is desirable behaviour, as it allows us to flatten the configuration but provide overrides if required.
232
+ unless @packages.include? external_package
233
+ options = options.merge(external_package.options)
234
+
235
+ @packages << Package.new(packages_path + external_package.name, external_package.name, options)
236
+
237
+ updated = true
238
+ end
165
239
  end
166
240
 
167
- @imports += configuration.imports.collect do |import|
168
- import.dup.tap{|import| import.options = options.merge(import.options)}
241
+ configuration.imports.each do |external_import|
242
+ unless @imports.include? external_import
243
+ options = options.merge(external_import.options)
244
+
245
+ @imports << Import.new(external_import.name, external_import.explicit, options)
246
+
247
+ updated = true
248
+ end
169
249
  end
250
+
251
+ return updated
170
252
  end
171
253
 
172
254
  def to_s
@@ -65,7 +65,7 @@ module Teapot
65
65
  end
66
66
 
67
67
  # Materialize the configuration:
68
- @configuration = @configuration.materialize if @configuration
68
+ @configuration.materialize if @configuration
69
69
  end
70
70
 
71
71
  attr :root
@@ -40,7 +40,7 @@ module Teapot
40
40
  end
41
41
 
42
42
  # Resolve any/all imports:
43
- configuration = configuration.materialize
43
+ configuration.materialize
44
44
 
45
45
  previously_unresolved = unresolved
46
46
  unresolved = context.unresolved(configuration.packages)
@@ -61,7 +61,7 @@ module Teapot
61
61
  end
62
62
  end
63
63
  when Configuration
64
- definition = definition.materialize
64
+ definition.materialize
65
65
 
66
66
  definition.packages.each do |package|
67
67
  if package.local?
@@ -73,7 +73,7 @@ module Teapot
73
73
  end
74
74
  end
75
75
 
76
- definition.imports.each do |import|
76
+ definition.imports.select(&:explicit).each do |import|
77
77
  log "\t\t- unmaterialised import #{import.name}".color(:red)
78
78
  end
79
79
  end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Teapot
22
- VERSION = "0.9.6"
22
+ VERSION = "0.9.7"
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teapot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-10 00:00:00.000000000 Z
11
+ date: 2013-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rainbow