nucleon 0.1.0 → 0.1.1
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/Gemfile +4 -8
- data/Gemfile.lock +0 -28
- data/README.rdoc +13 -5
- data/Rakefile +9 -1
- data/VERSION +1 -1
- data/bin/nucleon +55 -0
- data/lib/core/codes.rb +107 -0
- data/lib/core/config/collection.rb +57 -0
- data/lib/core/config/options.rb +70 -0
- data/lib/core/config.rb +342 -0
- data/lib/core/core.rb +54 -0
- data/lib/core/errors.rb +84 -0
- data/lib/core/facade.rb +283 -0
- data/lib/core/gems.rb +80 -0
- data/lib/core/manager.rb +594 -0
- data/lib/core/mixin/action/commit.rb +58 -0
- data/lib/core/mixin/action/project.rb +53 -0
- data/lib/core/mixin/action/push.rb +52 -0
- data/lib/core/mixin/config/collection.rb +53 -0
- data/lib/core/mixin/config/options.rb +39 -0
- data/lib/core/mixin/macro/object_interface.rb +361 -0
- data/lib/core/mixin/macro/plugin_interface.rb +380 -0
- data/lib/core/mixin/settings.rb +46 -0
- data/lib/core/mixin/sub_config.rb +148 -0
- data/lib/core/mod/hash.rb +29 -0
- data/lib/core/plugin/action.rb +371 -0
- data/lib/core/plugin/base.rb +313 -0
- data/lib/core/plugin/command.rb +98 -0
- data/lib/core/plugin/event.rb +53 -0
- data/lib/core/plugin/extension.rb +12 -0
- data/lib/core/plugin/project.rb +890 -0
- data/lib/core/plugin/template.rb +80 -0
- data/lib/core/plugin/translator.rb +38 -0
- data/lib/core/util/cli.rb +353 -0
- data/lib/core/util/console.rb +237 -0
- data/lib/core/util/data.rb +404 -0
- data/lib/core/util/disk.rb +114 -0
- data/lib/core/util/git.rb +43 -0
- data/lib/core/util/liquid.rb +17 -0
- data/lib/core/util/logger.rb +147 -0
- data/lib/core/util/package.rb +93 -0
- data/lib/core/util/shell.rb +239 -0
- data/lib/nucleon/action/add.rb +69 -0
- data/lib/nucleon/action/create.rb +52 -0
- data/lib/nucleon/action/extract.rb +49 -0
- data/lib/nucleon/action/remove.rb +51 -0
- data/lib/nucleon/action/save.rb +53 -0
- data/lib/nucleon/action/update.rb +37 -0
- data/lib/nucleon/command/bash.rb +146 -0
- data/lib/nucleon/event/regex.rb +52 -0
- data/lib/nucleon/project/git.rb +465 -0
- data/lib/nucleon/project/github.rb +108 -0
- data/lib/nucleon/template/json.rb +16 -0
- data/lib/nucleon/template/wrapper.rb +16 -0
- data/lib/nucleon/template/yaml.rb +16 -0
- data/lib/nucleon/translator/json.rb +27 -0
- data/lib/nucleon/translator/yaml.rb +27 -0
- data/lib/nucleon.rb +18 -15
- data/locales/en.yml +3 -132
- data/nucleon.gemspec +66 -27
- data/spec/core/util/console_spec.rb +489 -0
- metadata +109 -96
data/lib/core/config.rb
ADDED
@@ -0,0 +1,342 @@
|
|
1
|
+
|
2
|
+
module Nucleon
|
3
|
+
class Config
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Global interface
|
7
|
+
|
8
|
+
extend Mixin::ConfigOptions
|
9
|
+
extend Mixin::ConfigCollection
|
10
|
+
|
11
|
+
#-----------------------------------------------------------------------------
|
12
|
+
# Instance generators
|
13
|
+
|
14
|
+
def self.ensure(config)
|
15
|
+
case config
|
16
|
+
when Nucleon::Config
|
17
|
+
return config
|
18
|
+
when Hash
|
19
|
+
return new(config)
|
20
|
+
end
|
21
|
+
return new
|
22
|
+
end
|
23
|
+
|
24
|
+
#---
|
25
|
+
|
26
|
+
def self.init(options, contexts = [], hierarchy = [], defaults = {})
|
27
|
+
contexts = contexts(contexts, hierarchy)
|
28
|
+
config = new(get_options(contexts), defaults)
|
29
|
+
config.import(options) unless Util::Data.empty?(options)
|
30
|
+
return config
|
31
|
+
end
|
32
|
+
|
33
|
+
#---
|
34
|
+
|
35
|
+
def self.init_flat(options, contexts = [], defaults = {})
|
36
|
+
return init(options, contexts, [], defaults)
|
37
|
+
end
|
38
|
+
|
39
|
+
#-----------------------------------------------------------------------------
|
40
|
+
# Constructor / Destructor
|
41
|
+
|
42
|
+
def initialize(data = {}, defaults = {}, force = true)
|
43
|
+
@force = force
|
44
|
+
@properties = {}
|
45
|
+
|
46
|
+
if defaults.is_a?(Hash) && ! defaults.empty?
|
47
|
+
defaults = symbol_map(defaults)
|
48
|
+
end
|
49
|
+
|
50
|
+
case data
|
51
|
+
when Nucleon::Config
|
52
|
+
@properties = Util::Data.merge([ defaults, data.export ], force)
|
53
|
+
when Hash
|
54
|
+
@properties = {}
|
55
|
+
if data.is_a?(Hash)
|
56
|
+
@properties = Util::Data.merge([ defaults, symbol_map(data) ], force)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#-----------------------------------------------------------------------------
|
62
|
+
# Checks
|
63
|
+
|
64
|
+
def empty?
|
65
|
+
@properties.empty?
|
66
|
+
end
|
67
|
+
|
68
|
+
#---
|
69
|
+
|
70
|
+
def has_key?(keys)
|
71
|
+
get(keys) ? true : false
|
72
|
+
end
|
73
|
+
|
74
|
+
#-----------------------------------------------------------------------------
|
75
|
+
# Property accessors / modifiers
|
76
|
+
|
77
|
+
def keys
|
78
|
+
@properties.keys
|
79
|
+
end
|
80
|
+
|
81
|
+
#---
|
82
|
+
|
83
|
+
def fetch(data, keys, default = nil, format = false)
|
84
|
+
if keys.is_a?(String) || keys.is_a?(Symbol)
|
85
|
+
keys = [ keys ]
|
86
|
+
end
|
87
|
+
key = keys.shift.to_sym
|
88
|
+
|
89
|
+
if data.has_key?(key)
|
90
|
+
value = data[key]
|
91
|
+
|
92
|
+
if keys.empty?
|
93
|
+
return filter(value, format)
|
94
|
+
else
|
95
|
+
return fetch(data[key], keys, default, format)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
return filter(default, format)
|
99
|
+
end
|
100
|
+
protected :fetch
|
101
|
+
|
102
|
+
#---
|
103
|
+
|
104
|
+
def modify(data, keys, value = nil)
|
105
|
+
if keys.is_a?(String) || keys.is_a?(Symbol)
|
106
|
+
keys = [ keys ]
|
107
|
+
end
|
108
|
+
|
109
|
+
key = keys.shift.to_sym
|
110
|
+
has_key = data.has_key?(key)
|
111
|
+
existing = {
|
112
|
+
:key => key,
|
113
|
+
:value => ( has_key ? data[key] : nil )
|
114
|
+
}
|
115
|
+
|
116
|
+
if keys.empty?
|
117
|
+
existing[:value] = data[key] if has_key
|
118
|
+
|
119
|
+
if value.nil?
|
120
|
+
data.delete(key) if has_key
|
121
|
+
else
|
122
|
+
data[key] = value
|
123
|
+
end
|
124
|
+
else
|
125
|
+
data[key] = {} unless has_key
|
126
|
+
existing = modify(data[key], keys, value)
|
127
|
+
end
|
128
|
+
|
129
|
+
return existing
|
130
|
+
end
|
131
|
+
protected :modify
|
132
|
+
|
133
|
+
#---
|
134
|
+
|
135
|
+
def get(keys, default = nil, format = false)
|
136
|
+
return fetch(@properties, array(keys).flatten, default, format)
|
137
|
+
end
|
138
|
+
|
139
|
+
#---
|
140
|
+
|
141
|
+
def [](name, default = nil, format = false)
|
142
|
+
get(name, default, format)
|
143
|
+
end
|
144
|
+
|
145
|
+
#---
|
146
|
+
|
147
|
+
def get_array(keys, default = [])
|
148
|
+
return get(keys, default, :array)
|
149
|
+
end
|
150
|
+
|
151
|
+
#---
|
152
|
+
|
153
|
+
def get_hash(keys, default = {})
|
154
|
+
return get(keys, default, :hash)
|
155
|
+
end
|
156
|
+
|
157
|
+
#---
|
158
|
+
|
159
|
+
def init(keys, default = nil)
|
160
|
+
return set(keys, get(keys, default))
|
161
|
+
end
|
162
|
+
|
163
|
+
#---
|
164
|
+
|
165
|
+
def set(keys, value)
|
166
|
+
modify(@properties, array(keys).flatten, value)
|
167
|
+
return self
|
168
|
+
end
|
169
|
+
|
170
|
+
#---
|
171
|
+
|
172
|
+
def []=(name, value)
|
173
|
+
set(name, value)
|
174
|
+
end
|
175
|
+
|
176
|
+
#---
|
177
|
+
|
178
|
+
def delete(keys, default = nil)
|
179
|
+
existing = modify(@properties, array(keys).flatten, nil)
|
180
|
+
return existing[:value] if existing[:value]
|
181
|
+
return default
|
182
|
+
end
|
183
|
+
|
184
|
+
#---
|
185
|
+
|
186
|
+
def clear
|
187
|
+
@properties = {}
|
188
|
+
return self
|
189
|
+
end
|
190
|
+
|
191
|
+
#-----------------------------------------------------------------------------
|
192
|
+
# Import / Export
|
193
|
+
|
194
|
+
def import_base(properties, options = {})
|
195
|
+
config = Config.new(options, { :force => @force }).set(:context, :hash)
|
196
|
+
import_type = config.get(:import_type, :override)
|
197
|
+
|
198
|
+
properties = properties.export if properties.is_a?(Nucleon::Config)
|
199
|
+
|
200
|
+
case properties
|
201
|
+
when Hash
|
202
|
+
data = [ @properties, symbol_map(properties) ]
|
203
|
+
data = data.reverse if import_type != :override
|
204
|
+
|
205
|
+
@properties = Util::Data.merge(data, config)
|
206
|
+
|
207
|
+
when String, Symbol
|
208
|
+
properties = self.class.lookup(properties.to_s, {}, config)
|
209
|
+
|
210
|
+
data = [ @properties, symbol_map(properties) ]
|
211
|
+
data = data.reverse if import_type != :override
|
212
|
+
|
213
|
+
@properties = Util::Data.merge(data, config)
|
214
|
+
|
215
|
+
when Array
|
216
|
+
properties.each do |item|
|
217
|
+
import_base(item, config)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
return self
|
222
|
+
end
|
223
|
+
protected :import_base
|
224
|
+
|
225
|
+
#---
|
226
|
+
|
227
|
+
def import(properties, options = {})
|
228
|
+
return import_base(properties, options)
|
229
|
+
end
|
230
|
+
|
231
|
+
#---
|
232
|
+
|
233
|
+
def defaults(defaults, options = {})
|
234
|
+
config = Config.new(options).set(:import_type, :default)
|
235
|
+
return import_base(defaults, config)
|
236
|
+
end
|
237
|
+
|
238
|
+
#---
|
239
|
+
|
240
|
+
def export
|
241
|
+
return @properties
|
242
|
+
end
|
243
|
+
|
244
|
+
#-----------------------------------------------------------------------------
|
245
|
+
# Utilities
|
246
|
+
|
247
|
+
def self.symbol_map(data)
|
248
|
+
return Util::Data.symbol_map(data)
|
249
|
+
end
|
250
|
+
|
251
|
+
#---
|
252
|
+
|
253
|
+
def symbol_map(data)
|
254
|
+
return self.class.symbol_map(data)
|
255
|
+
end
|
256
|
+
|
257
|
+
#---
|
258
|
+
|
259
|
+
def self.string_map(data)
|
260
|
+
return Util::Data.string_map(data)
|
261
|
+
end
|
262
|
+
|
263
|
+
#---
|
264
|
+
|
265
|
+
def string_map(data)
|
266
|
+
return self.class.string_map(data)
|
267
|
+
end
|
268
|
+
|
269
|
+
#-----------------------------------------------------------------------------
|
270
|
+
|
271
|
+
def self.filter(data, method = false)
|
272
|
+
return Util::Data.filter(data, method)
|
273
|
+
end
|
274
|
+
|
275
|
+
#---
|
276
|
+
|
277
|
+
def filter(data, method = false)
|
278
|
+
return self.class.filter(data, method)
|
279
|
+
end
|
280
|
+
|
281
|
+
#-----------------------------------------------------------------------------
|
282
|
+
|
283
|
+
def self.array(data, default = [], split_string = false)
|
284
|
+
return Util::Data.array(data, default, split_string)
|
285
|
+
end
|
286
|
+
|
287
|
+
#---
|
288
|
+
|
289
|
+
def array(data, default = [], split_string = false)
|
290
|
+
return self.class.array(data, default, split_string)
|
291
|
+
end
|
292
|
+
|
293
|
+
#---
|
294
|
+
|
295
|
+
def self.hash(data, default = {})
|
296
|
+
data = data.export if data.is_a?(Nucleon::Config)
|
297
|
+
return Util::Data.hash(data, default)
|
298
|
+
end
|
299
|
+
|
300
|
+
#---
|
301
|
+
|
302
|
+
def hash(data, default = {})
|
303
|
+
return self.class.hash(data, default)
|
304
|
+
end
|
305
|
+
|
306
|
+
#---
|
307
|
+
|
308
|
+
def self.string(data, default = '')
|
309
|
+
return Util::Data.string(data, default)
|
310
|
+
end
|
311
|
+
|
312
|
+
#---
|
313
|
+
|
314
|
+
def string(data, default = '')
|
315
|
+
return self.class.string(data, default)
|
316
|
+
end
|
317
|
+
|
318
|
+
#---
|
319
|
+
|
320
|
+
def self.symbol(data, default = :undefined)
|
321
|
+
return Util::Data.symbol(data, default)
|
322
|
+
end
|
323
|
+
|
324
|
+
#---
|
325
|
+
|
326
|
+
def symbol(data, default = :undefined)
|
327
|
+
return self.class.symbol(data, default)
|
328
|
+
end
|
329
|
+
|
330
|
+
#---
|
331
|
+
|
332
|
+
def self.test(data)
|
333
|
+
return Util::Data.test(data)
|
334
|
+
end
|
335
|
+
|
336
|
+
#---
|
337
|
+
|
338
|
+
def test(data)
|
339
|
+
return self.class.test(data)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
data/lib/core/core.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Nucleon
|
3
|
+
class Core < Config
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Properties
|
7
|
+
|
8
|
+
@@logger = Util::Logger.new('core')
|
9
|
+
@@ui = Util::Console.new('core')
|
10
|
+
|
11
|
+
#-----------------------------------------------------------------------------
|
12
|
+
# Constructor / Destructor
|
13
|
+
|
14
|
+
def initialize(data = {}, defaults = {}, force = true)
|
15
|
+
super(data, defaults, force)
|
16
|
+
|
17
|
+
class_label = self.class.to_s.downcase.gsub(/^nucleon::/, '')
|
18
|
+
|
19
|
+
@logger = Util::Logger.new(delete(:logger, class_label))
|
20
|
+
@ui = Util::Console.new(Config.new(export).defaults({ :resource => class_label }))
|
21
|
+
|
22
|
+
logger.debug('Initialized instance logger and interface')
|
23
|
+
end
|
24
|
+
|
25
|
+
#-----------------------------------------------------------------------------
|
26
|
+
# Accessor / Modifiers
|
27
|
+
|
28
|
+
attr_accessor :logger, :ui
|
29
|
+
|
30
|
+
#---
|
31
|
+
|
32
|
+
def self.logger
|
33
|
+
return @@logger
|
34
|
+
end
|
35
|
+
|
36
|
+
#---
|
37
|
+
|
38
|
+
def self.ui
|
39
|
+
return @@ui
|
40
|
+
end
|
41
|
+
|
42
|
+
#-----------------------------------------------------------------------------
|
43
|
+
# General utilities
|
44
|
+
|
45
|
+
def ui_group(resource)
|
46
|
+
ui_resource = ui.resource
|
47
|
+
ui.resource = resource
|
48
|
+
yield
|
49
|
+
|
50
|
+
ensure
|
51
|
+
ui.resource = ui_resource
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/core/errors.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
|
2
|
+
module Nucleon
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
#-----------------------------------------------------------------------------
|
6
|
+
# Base error (based on VagrantError)
|
7
|
+
|
8
|
+
class NucleonError < StandardError
|
9
|
+
|
10
|
+
#---------------------------------------------------------------------------
|
11
|
+
# Error constructor / destructor
|
12
|
+
|
13
|
+
def initialize(*args)
|
14
|
+
key = args.shift if args.first.is_a?(Symbol)
|
15
|
+
message = args.shift if args.first.is_a?(Hash)
|
16
|
+
message ||= {}
|
17
|
+
|
18
|
+
@extra_data = message.dup
|
19
|
+
|
20
|
+
message[:key] ||= error_key
|
21
|
+
message[:namespace] ||= error_namespace
|
22
|
+
message[:key] = key if key
|
23
|
+
|
24
|
+
if message[:key]
|
25
|
+
message = translate_error(message)
|
26
|
+
else
|
27
|
+
message = error_message
|
28
|
+
end
|
29
|
+
|
30
|
+
super(message)
|
31
|
+
end
|
32
|
+
|
33
|
+
#---------------------------------------------------------------------------
|
34
|
+
# Property accessor / modifiers
|
35
|
+
|
36
|
+
attr_accessor :extra_data
|
37
|
+
|
38
|
+
#---
|
39
|
+
|
40
|
+
def self.error_key(key = nil, namespace = nil)
|
41
|
+
define_method(:error_key) { key }
|
42
|
+
error_namespace(namespace) if namespace
|
43
|
+
end
|
44
|
+
def error_key; nil; end # Default
|
45
|
+
|
46
|
+
#---
|
47
|
+
|
48
|
+
def self.error_message(message)
|
49
|
+
define_method(:error_message) { message }
|
50
|
+
end
|
51
|
+
def error_message; "No error message"; end # Default
|
52
|
+
|
53
|
+
#---
|
54
|
+
|
55
|
+
def self.error_namespace(namespace)
|
56
|
+
define_method(:error_namespace) { namespace }
|
57
|
+
end
|
58
|
+
def error_namespace; "nucleon.errors"; end # Default
|
59
|
+
|
60
|
+
#---
|
61
|
+
|
62
|
+
def self.status_code(code)
|
63
|
+
define_method(:status_code) { code }
|
64
|
+
end
|
65
|
+
def status_code; 1; end # Default
|
66
|
+
|
67
|
+
#---------------------------------------------------------------------------
|
68
|
+
# Utilities
|
69
|
+
|
70
|
+
def translate_error(options)
|
71
|
+
return nil unless options[:key]
|
72
|
+
I18n.t("#{options[:namespace]}.#{options[:key]}", options)
|
73
|
+
end
|
74
|
+
protected :translate_error
|
75
|
+
end
|
76
|
+
|
77
|
+
#-----------------------------------------------------------------------------
|
78
|
+
# Specialized errors
|
79
|
+
|
80
|
+
class BatchError < NucleonError
|
81
|
+
error_key(:batch_error)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|