nucleon 0.1.1 → 0.1.2
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.lock +2 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/nucleon +1 -53
- data/lib/core/core.rb +21 -3
- data/lib/core/facade.rb +146 -53
- data/lib/core/gems.rb +16 -13
- data/lib/core/manager.rb +67 -51
- data/lib/core/mixin/action/commit.rb +19 -25
- data/lib/core/mixin/action/project.rb +28 -16
- data/lib/core/mixin/action/push.rb +11 -21
- data/lib/core/plugin/action.rb +26 -14
- data/lib/core/plugin/base.rb +6 -4
- data/lib/core/util/cli.rb +20 -8
- data/lib/core/util/data.rb +0 -8
- data/lib/nucleon.rb +3 -161
- data/lib/nucleon/action/add.rb +28 -34
- data/lib/nucleon/action/create.rb +23 -28
- data/lib/nucleon/action/extract.rb +3 -3
- data/lib/nucleon/action/remove.rb +30 -26
- data/lib/nucleon/action/save.rb +26 -26
- data/lib/nucleon/action/update.rb +13 -18
- data/lib/nucleon/project/git.rb +2 -2
- data/lib/nucleon_base.rb +184 -0
- data/locales/en.yml +47 -41
- data/nucleon.gemspec +3 -2
- metadata +31 -30
data/lib/core/gems.rb
CHANGED
@@ -52,28 +52,31 @@ module Gems
|
|
52
52
|
#---
|
53
53
|
|
54
54
|
def self.register_gem(spec)
|
55
|
-
name = spec.name
|
55
|
+
name = spec.name.to_sym
|
56
56
|
base_path = File.join(spec.full_gem_path, 'lib')
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
if name == :nucleon
|
59
|
+
logger.debug("Setting Nucleon core gemspec")
|
60
|
+
@@core = spec
|
61
|
+
@@gems[name] = {
|
62
|
+
:spec => spec,
|
63
|
+
:base_path => base_path,
|
64
|
+
:namespaces => [ :nucleon ]
|
65
|
+
}
|
66
|
+
else
|
67
|
+
Manager.connection.register(base_path) do |data|
|
68
|
+
namespace = data[:namespace]
|
69
|
+
plugin_path = data[:directory]
|
61
70
|
|
62
|
-
|
71
|
+
logger.info("Registering gem #{name} at #{plugin_path} at #{Time.now}")
|
63
72
|
|
64
|
-
unless @@gems.has_key?(name)
|
65
73
|
@@gems[name] = {
|
66
74
|
:spec => spec,
|
67
75
|
:base_path => base_path,
|
68
76
|
:namespaces => []
|
69
77
|
}
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
if name == 'nucleon'
|
74
|
-
logger.debug("Setting Nucleon core gemspec")
|
75
|
-
@@core = spec
|
76
|
-
end
|
78
|
+
@@gems[name][:namespaces] << namespace unless @@gems[name][:namespaces].include?(namespace)
|
79
|
+
end
|
77
80
|
end
|
78
81
|
end
|
79
82
|
end
|
data/lib/core/manager.rb
CHANGED
@@ -51,12 +51,18 @@ class Manager
|
|
51
51
|
|
52
52
|
#---
|
53
53
|
|
54
|
+
def myself
|
55
|
+
Actor.current
|
56
|
+
end
|
57
|
+
|
58
|
+
#---
|
59
|
+
|
54
60
|
def namespaces
|
55
61
|
@namespaces.keys
|
56
62
|
end
|
57
63
|
|
58
|
-
def define_namespace(*
|
59
|
-
|
64
|
+
def define_namespace(*names)
|
65
|
+
names.each do |namespace|
|
60
66
|
@namespaces[namespace.to_sym] = true
|
61
67
|
end
|
62
68
|
end
|
@@ -123,24 +129,28 @@ class Manager
|
|
123
129
|
|
124
130
|
#---
|
125
131
|
|
126
|
-
def reload
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
132
|
+
def reload(core = false, &code)
|
133
|
+
logger.info("Loading Nucleon plugins at #{Time.now}")
|
134
|
+
|
135
|
+
if core
|
136
|
+
Celluloid.logger = logger
|
131
137
|
|
132
|
-
|
138
|
+
define_namespace :nucleon
|
139
|
+
|
140
|
+
define_type :extension => nil, # Core
|
141
|
+
:action => :update, # Core
|
142
|
+
:project => :git, # Core
|
143
|
+
:command => :bash, # Core
|
144
|
+
:event => :regex, # Utility
|
145
|
+
:template => :json, # Utility
|
146
|
+
:translator => :json # Utility
|
147
|
+
end
|
133
148
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
:template => :json, # Utility
|
140
|
-
:translator => :json # Utility
|
141
|
-
|
142
|
-
load_plugins(true)
|
143
|
-
logger.info("Finished initializing Nucleon plugin system at #{Time.now}")
|
149
|
+
# Allow block level namespace and type registration
|
150
|
+
code.call(:define, myself) if code
|
151
|
+
|
152
|
+
load_plugins(core, &code)
|
153
|
+
logger.info("Finished loading Nucleon plugins at #{Time.now}")
|
144
154
|
end
|
145
155
|
|
146
156
|
#---
|
@@ -160,30 +170,33 @@ class Manager
|
|
160
170
|
|
161
171
|
#---
|
162
172
|
|
163
|
-
def load_plugins(
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
173
|
+
def load_plugins(core = false, &code)
|
174
|
+
if core
|
175
|
+
# Register core plugins
|
176
|
+
logger.info("Initializing core plugins at #{Time.now}")
|
177
|
+
register(File.join(File.dirname(__FILE__), '..'))
|
178
|
+
end
|
179
|
+
|
168
180
|
# Register external Gem defined plugins
|
169
|
-
Gems.register(
|
181
|
+
Gems.register(true)
|
170
182
|
|
171
183
|
# Register any other extension plugins
|
172
184
|
exec(:register_plugins)
|
185
|
+
|
186
|
+
# Catch any block level requests before autoloading
|
187
|
+
code.call(:load, myself) if code
|
173
188
|
|
174
189
|
# Autoload all registered plugins
|
175
190
|
autoload
|
176
191
|
end
|
192
|
+
protected :load_plugins
|
177
193
|
|
178
194
|
#---
|
179
195
|
|
180
196
|
def register(base_path, &code)
|
181
197
|
namespaces.each do |namespace|
|
182
198
|
namespace_path = File.join(base_path, namespace.to_s)
|
183
|
-
|
184
|
-
if File.directory?(namespace_path)
|
185
|
-
register_namespace(namespace, namespace_path, &code)
|
186
|
-
end
|
199
|
+
register_namespace(namespace, namespace_path, &code)
|
187
200
|
end
|
188
201
|
end
|
189
202
|
|
@@ -217,7 +230,7 @@ class Manager
|
|
217
230
|
logger.info("Registering #{base_directory} at #{Time.now}")
|
218
231
|
|
219
232
|
Dir.glob(File.join(base_directory, '*.rb')).each do |file|
|
220
|
-
add_build_info(namespace, plugin_type, file)
|
233
|
+
add_build_info(namespace, plugin_type, file, &code)
|
221
234
|
end
|
222
235
|
end
|
223
236
|
end
|
@@ -243,7 +256,7 @@ class Manager
|
|
243
256
|
:provider => provider,
|
244
257
|
:directory => directory,
|
245
258
|
:file => file
|
246
|
-
}
|
259
|
+
}
|
247
260
|
code.call(data) if code
|
248
261
|
|
249
262
|
logger.debug("Plugin #{type} loaded: #{data.inspect}")
|
@@ -276,22 +289,14 @@ class Manager
|
|
276
289
|
|
277
290
|
#---
|
278
291
|
|
279
|
-
def
|
280
|
-
config = Config.ensure(options)
|
281
|
-
name = config.get(:name, nil)
|
282
|
-
|
292
|
+
def load_base(type, provider, options = {})
|
283
293
|
logger.info("Fetching plugin #{type} provider #{provider} at #{Time.now}")
|
294
|
+
|
295
|
+
config = Config.ensure(translate_type(type, options))
|
296
|
+
name = config.get(:name, nil)
|
297
|
+
|
284
298
|
logger.debug("Plugin options: #{config.export.inspect}")
|
285
299
|
|
286
|
-
default_provider = type_default(type)
|
287
|
-
|
288
|
-
if options.is_a?(Hash) || options.is_a?(Nucleon::Config)
|
289
|
-
config = Config.ensure(translate_type(type, options))
|
290
|
-
provider = config.get(:provider, provider)
|
291
|
-
options = config.export
|
292
|
-
end
|
293
|
-
provider = default_provider unless provider
|
294
|
-
|
295
300
|
if name
|
296
301
|
logger.debug("Looking up existing instance of #{name}")
|
297
302
|
|
@@ -300,7 +305,20 @@ class Manager
|
|
300
305
|
end
|
301
306
|
|
302
307
|
return existing_instance if existing_instance
|
303
|
-
create(type, provider,
|
308
|
+
create(type, provider, options)
|
309
|
+
end
|
310
|
+
|
311
|
+
#---
|
312
|
+
|
313
|
+
def load(type, provider = nil, options = {})
|
314
|
+
default_provider = type_default(type)
|
315
|
+
|
316
|
+
# Allow options to override provider
|
317
|
+
config = Config.ensure(options)
|
318
|
+
provider = config.get(:provider, provider)
|
319
|
+
provider = default_provider unless provider
|
320
|
+
|
321
|
+
load_base(type, provider, config)
|
304
322
|
end
|
305
323
|
|
306
324
|
#---
|
@@ -309,7 +327,7 @@ class Manager
|
|
309
327
|
logger.info("Fetching multiple plugins of #{type} at #{Time.now}")
|
310
328
|
|
311
329
|
group = ( build_hash ? {} : [] )
|
312
|
-
klass =
|
330
|
+
klass = plugin_class(type)
|
313
331
|
data = klass.build_info(type, data) if klass.respond_to?(:build_info)
|
314
332
|
|
315
333
|
logger.debug("Translated plugin data: #{data.inspect}")
|
@@ -522,10 +540,10 @@ class Manager
|
|
522
540
|
# Utilities
|
523
541
|
|
524
542
|
def translate_type(type, options)
|
525
|
-
klass =
|
543
|
+
klass = plugin_class(type)
|
526
544
|
logger.debug("Executing option translation for: #{klass.inspect}")
|
527
545
|
|
528
|
-
options = klass.send(:translate, options) if klass.respond_to?(
|
546
|
+
options = klass.send(:translate, options) if klass.respond_to?(:translate)
|
529
547
|
options
|
530
548
|
end
|
531
549
|
|
@@ -535,7 +553,7 @@ class Manager
|
|
535
553
|
klass = provider_class(namespace, type, provider)
|
536
554
|
logger.debug("Executing option translation for: #{klass.inspect}")
|
537
555
|
|
538
|
-
options = klass.send(:translate, options) if klass.respond_to?(
|
556
|
+
options = klass.send(:translate, options) if klass.respond_to?(:translate)
|
539
557
|
options
|
540
558
|
end
|
541
559
|
|
@@ -579,16 +597,14 @@ class Manager
|
|
579
597
|
|
580
598
|
#---
|
581
599
|
|
582
|
-
def
|
600
|
+
def plugin_class(type)
|
583
601
|
class_const([ :nucleon, :plugin, type ])
|
584
602
|
end
|
585
|
-
protected :base_plugin_class
|
586
603
|
|
587
604
|
#---
|
588
605
|
|
589
606
|
def provider_class(namespace, type, provider)
|
590
607
|
class_const([ namespace, type, provider ])
|
591
608
|
end
|
592
|
-
protected :provider_class
|
593
609
|
end
|
594
610
|
end
|
@@ -5,34 +5,28 @@ module Action
|
|
5
5
|
module Commit
|
6
6
|
|
7
7
|
#-----------------------------------------------------------------------------
|
8
|
-
#
|
8
|
+
# Settings
|
9
9
|
|
10
|
-
def
|
10
|
+
def commit_config(optional = true)
|
11
|
+
|
11
12
|
if optional
|
12
|
-
|
13
|
-
'--commit',
|
14
|
-
'nucleon.core.mixins.commit.options.commit'
|
15
|
-
)
|
13
|
+
register :commit, :bool, :false, 'nucleon.core.mixin.action.commit.options.commit'
|
16
14
|
else
|
17
|
-
|
15
|
+
settings[:commit] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
register :allow_empty, :bool, false, 'nucleon.core.mixin.action.commit.options.allow_empty'
|
19
|
+
register :propogate_commit, :bool, false, 'nucleon.core.mixin.action.commit.options.propogate_commit'
|
20
|
+
|
21
|
+
register :message, :str, '', 'nucleon.core.mixin.action.commit.options.message'
|
22
|
+
|
23
|
+
register :author, :str, nil, 'nucleon.core.mixin.action.commit.options.author' do |value|
|
24
|
+
if value.nil? || value.strip =~ /^[A-Za-z\s]+<\s*[^@]+@[^>]+\s*>$/
|
25
|
+
next true
|
26
|
+
end
|
27
|
+
warn('corl.core.mixins.action.commit.errors.author', { :value => value })
|
28
|
+
false
|
18
29
|
end
|
19
|
-
|
20
|
-
parser.option_bool(:allow_empty, false,
|
21
|
-
'--empty',
|
22
|
-
'nucleon.core.mixins.commit.options.empty'
|
23
|
-
)
|
24
|
-
parser.option_bool(:propogate, false,
|
25
|
-
'--propogate',
|
26
|
-
'nucleon.core.mixins.commit.options.propogate'
|
27
|
-
)
|
28
|
-
parser.option_str(:message, '',
|
29
|
-
'--message COMMIT_MESSAGE',
|
30
|
-
'nucleon.core.mixins.commit.options.message'
|
31
|
-
)
|
32
|
-
parser.option_str(:author, nil,
|
33
|
-
'--author COMMIT_AUTHOR',
|
34
|
-
'nucleon.core.mixins.commit.options.author'
|
35
|
-
)
|
36
30
|
end
|
37
31
|
|
38
32
|
#-----------------------------------------------------------------------------
|
@@ -46,7 +40,7 @@ module Commit
|
|
46
40
|
:allow_empty => settings[:allow_empty],
|
47
41
|
:message => settings[:message],
|
48
42
|
:author => settings[:author],
|
49
|
-
:propogate => settings[:
|
43
|
+
:propogate => settings[:propogate_commit]
|
50
44
|
}))
|
51
45
|
end
|
52
46
|
success
|
@@ -5,25 +5,37 @@ module Action
|
|
5
5
|
module Project
|
6
6
|
|
7
7
|
#-----------------------------------------------------------------------------
|
8
|
-
#
|
8
|
+
# Settings
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
'
|
18
|
-
|
19
|
-
|
10
|
+
def project_config
|
11
|
+
project_plugins = CORL.loaded_plugins(:project)
|
12
|
+
|
13
|
+
register :project_provider, :str, :git, 'nucleon.core.mixin.action.project.options.project_provider' do |value|
|
14
|
+
value = value.to_sym
|
15
|
+
|
16
|
+
unless project_plugins.keys.include?(value)
|
17
|
+
warn('nucleon.core.mixin.action.project.errors.project_provider', { :value => value, :choices => project_plugins.keys.join(", ") })
|
18
|
+
next false
|
19
|
+
end
|
20
|
+
true
|
20
21
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
register :project_reference, :str, nil, 'nucleon.core.mixin.action.project.options.project_reference' do |value|
|
23
|
+
success = true
|
24
|
+
if info = CORL.plugin_class(:project).translate_reference(value)
|
25
|
+
if ! project_plugins.keys.include?(info[:provider].to_sym)
|
26
|
+
warn('nucleon.core.mixin.action.project.errors.project_reference', {
|
27
|
+
:value => value,
|
28
|
+
:provider => info[:provider],
|
29
|
+
:reference => info[:reference],
|
30
|
+
:url => info[:url],
|
31
|
+
:revision => info[:revision]
|
32
|
+
})
|
33
|
+
success = false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
success
|
26
37
|
end
|
38
|
+
register :revision, :str, :master
|
27
39
|
end
|
28
40
|
|
29
41
|
#-----------------------------------------------------------------------------
|
@@ -5,30 +5,20 @@ module Action
|
|
5
5
|
module Push
|
6
6
|
|
7
7
|
#-----------------------------------------------------------------------------
|
8
|
-
#
|
8
|
+
# Settings
|
9
9
|
|
10
|
-
def
|
10
|
+
def push_config(optional = true)
|
11
|
+
|
11
12
|
if optional
|
12
|
-
|
13
|
-
'--push',
|
14
|
-
'nucleon.core.mixins.push.options.push'
|
15
|
-
)
|
13
|
+
register :push, :bool, false, 'nucleon.core.mixin.action.push.options.push'
|
16
14
|
else
|
17
|
-
|
15
|
+
settings[:push] = true
|
18
16
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
parser.option_str(:remote, :edit,
|
25
|
-
'--remote PROJECT_REMOTE',
|
26
|
-
'nucleon.core.mixins.push.options.remote'
|
27
|
-
)
|
28
|
-
parser.option_str(:revision, :master,
|
29
|
-
'--revision PROJECT_REVISION',
|
30
|
-
'nucleon.core.mixins.push.options.revision'
|
31
|
-
)
|
17
|
+
|
18
|
+
register :remote, :str, :edit, 'nucleon.core.mixin.action.push.options.remote'
|
19
|
+
register :revision, :str, :master, 'nucleon.core.mixin.action.push.options.revision'
|
20
|
+
|
21
|
+
register :propogate_push, :bool, false, 'nucleon.core.mixin.action.push.options.propogate_push'
|
32
22
|
end
|
33
23
|
|
34
24
|
#-----------------------------------------------------------------------------
|
@@ -40,7 +30,7 @@ module Push
|
|
40
30
|
if project && settings[:push]
|
41
31
|
success = project.push(settings[:remote], extended_config(:push, {
|
42
32
|
:revision => settings[:revision],
|
43
|
-
:propogate => settings[:
|
33
|
+
:propogate => settings[:propogate_push]
|
44
34
|
}))
|
45
35
|
end
|
46
36
|
success
|
data/lib/core/plugin/action.rb
CHANGED
@@ -7,12 +7,12 @@ class Action < Base
|
|
7
7
|
# Default option interface
|
8
8
|
|
9
9
|
class Option
|
10
|
-
def initialize(provider, name, type, default, locale = nil, &validator)
|
10
|
+
def initialize(namespace, provider, name, type, default, locale = nil, &validator)
|
11
11
|
@provider = provider
|
12
12
|
@name = name
|
13
13
|
@type = type
|
14
14
|
@default = default
|
15
|
-
@locale = locale.nil? ? "
|
15
|
+
@locale = locale.nil? ? "#{namespace}.actions.#{provider}.options.#{name}" : locale
|
16
16
|
@validator = validator if validator
|
17
17
|
end
|
18
18
|
|
@@ -67,8 +67,8 @@ class Action < Base
|
|
67
67
|
exec_safe(provider, { :settings => Config.ensure(options), :quiet => quiet })
|
68
68
|
end
|
69
69
|
|
70
|
-
def self.exec_cli(provider, args, quiet = false)
|
71
|
-
results = exec_safe(provider, { :args => args, :quiet => quiet })
|
70
|
+
def self.exec_cli(provider, args, quiet = false, name = :nucleon)
|
71
|
+
results = exec_safe(provider, { :args => args, :quiet => quiet, :executable => name })
|
72
72
|
results[:status]
|
73
73
|
end
|
74
74
|
|
@@ -114,6 +114,12 @@ class Action < Base
|
|
114
114
|
#-----------------------------------------------------------------------------
|
115
115
|
# Property accessor / modifiers
|
116
116
|
|
117
|
+
def namespace
|
118
|
+
:nucleon
|
119
|
+
end
|
120
|
+
|
121
|
+
#---
|
122
|
+
|
117
123
|
def config
|
118
124
|
get(:config)
|
119
125
|
end
|
@@ -136,11 +142,11 @@ class Action < Base
|
|
136
142
|
name = name.to_sym
|
137
143
|
|
138
144
|
if block_given?
|
139
|
-
option = Option.new(plugin_provider, name, type, default, locale) do |value, success|
|
145
|
+
option = Option.new(namespace, plugin_provider, name, type, default, locale) do |value, success|
|
140
146
|
yield(value, success)
|
141
147
|
end
|
142
148
|
else
|
143
|
-
option = Option.new(plugin_provider, name, type, default, locale)
|
149
|
+
option = Option.new(namespace, plugin_provider, name, type, default, locale)
|
144
150
|
end
|
145
151
|
|
146
152
|
config[name] = option
|
@@ -170,10 +176,10 @@ class Action < Base
|
|
170
176
|
|
171
177
|
#---
|
172
178
|
|
173
|
-
def configure
|
179
|
+
def configure
|
174
180
|
yield if block_given?
|
175
181
|
|
176
|
-
usage = "#{
|
182
|
+
usage = "#{plugin_provider} "
|
177
183
|
arguments.each do |arg|
|
178
184
|
arg_config = config[arg.to_sym]
|
179
185
|
|
@@ -232,7 +238,8 @@ class Action < Base
|
|
232
238
|
logger.debug("Parse successful: #{export.inspect}")
|
233
239
|
|
234
240
|
elsif @parser.options[:help] && ! quiet?
|
235
|
-
|
241
|
+
executable = delete(:executable, '')
|
242
|
+
puts I18n.t('nucleon.core.exec.help.usage') + ": #{executable} " + help + "\n"
|
236
243
|
|
237
244
|
else
|
238
245
|
if @parser.options[:help]
|
@@ -290,13 +297,13 @@ class Action < Base
|
|
290
297
|
|
291
298
|
#---
|
292
299
|
|
293
|
-
def validate
|
300
|
+
def validate(*args)
|
294
301
|
# TODO: Add extension hooks and logging
|
295
302
|
|
296
303
|
# Validate all of the configurations
|
297
304
|
success = true
|
298
305
|
config.export.each do |name, option|
|
299
|
-
success = false unless option.validate(settings[name])
|
306
|
+
success = false unless option.validate(settings[name], *args)
|
300
307
|
end
|
301
308
|
if success
|
302
309
|
# Check for missing arguments (in case of internal execution mode)
|
@@ -312,7 +319,7 @@ class Action < Base
|
|
312
319
|
|
313
320
|
#---
|
314
321
|
|
315
|
-
def execute
|
322
|
+
def execute(skip_validate = false, skip_hooks = false)
|
316
323
|
logger.info("Executing action #{plugin_provider}")
|
317
324
|
|
318
325
|
myself.status = code.success
|
@@ -320,8 +327,13 @@ class Action < Base
|
|
320
327
|
|
321
328
|
if processed?
|
322
329
|
begin
|
323
|
-
|
324
|
-
|
330
|
+
if skip_validate || validate
|
331
|
+
yield if block_given? && ( skip_hooks || extension_check(:exec_init) )
|
332
|
+
myself.status = extension_set(:exec_exit) unless skip_hooks
|
333
|
+
else
|
334
|
+
puts "\n" + I18n.t('corl.core.exec.help.usage') + ': ' + help + "\n" unless quiet?
|
335
|
+
myself.status = code.validation_failed
|
336
|
+
end
|
325
337
|
ensure
|
326
338
|
cleanup
|
327
339
|
end
|