nucleon 0.1.19 → 0.2.0

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.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +1 -0
  4. data/TODO.rdoc +0 -3
  5. data/VERSION +1 -1
  6. data/bin/nucleon +19 -0
  7. data/lib/core/config.rb +11 -7
  8. data/lib/core/environment.rb +338 -0
  9. data/lib/core/facade.rb +150 -98
  10. data/lib/core/manager.rb +160 -249
  11. data/lib/core/mixin/action/project.rb +2 -2
  12. data/lib/core/mixin/macro/plugin_interface.rb +11 -11
  13. data/lib/core/plugin/action.rb +277 -24
  14. data/lib/core/plugin/base.rb +22 -14
  15. data/lib/core/plugin/command.rb +1 -1
  16. data/lib/core/plugin/event.rb +3 -3
  17. data/lib/core/plugin/extension.rb +1 -1
  18. data/lib/core/plugin/project.rb +15 -15
  19. data/lib/core/plugin/template.rb +1 -1
  20. data/lib/core/plugin/translator.rb +1 -1
  21. data/lib/core/util/cache.rb +1 -1
  22. data/lib/core/util/cli.rb +32 -3
  23. data/lib/core/util/console.rb +30 -10
  24. data/lib/core/util/data.rb +11 -3
  25. data/lib/core/util/logger.rb +1 -1
  26. data/lib/core/util/shell.rb +6 -3
  27. data/lib/core/util/ssh.rb +148 -24
  28. data/lib/nucleon/action/extract.rb +11 -4
  29. data/lib/nucleon/action/{add.rb → project/add.rb} +13 -4
  30. data/lib/nucleon/action/{create.rb → project/create.rb} +12 -3
  31. data/lib/nucleon/action/{remove.rb → project/remove.rb} +11 -2
  32. data/lib/nucleon/action/{save.rb → project/save.rb} +11 -2
  33. data/lib/nucleon/action/{update.rb → project/update.rb} +11 -2
  34. data/lib/nucleon/command/bash.rb +1 -1
  35. data/lib/nucleon/event/regex.rb +1 -1
  36. data/lib/nucleon/project/git.rb +3 -3
  37. data/lib/nucleon/template/{json.rb → JSON.rb} +1 -1
  38. data/lib/nucleon/template/{yaml.rb → YAML.rb} +1 -1
  39. data/lib/nucleon/template/wrapper.rb +1 -1
  40. data/lib/nucleon/translator/{json.rb → JSON.rb} +1 -1
  41. data/lib/nucleon/translator/{yaml.rb → YAML.rb} +1 -1
  42. data/lib/nucleon_base.rb +26 -15
  43. data/locales/en.yml +69 -44
  44. data/nucleon.gemspec +129 -11
  45. data/rdoc/site/0.1.19/ARCHITECTURE_rdoc.html +634 -0
  46. data/rdoc/site/0.1.19/Hash.html +347 -0
  47. data/rdoc/site/0.1.19/Kernel.html +413 -0
  48. data/rdoc/site/0.1.19/Nucleon.html +570 -0
  49. data/rdoc/site/0.1.19/Nucleon/Action.html +280 -0
  50. data/rdoc/site/0.1.19/Nucleon/Action/Add.html +458 -0
  51. data/rdoc/site/0.1.19/Nucleon/Action/Create.html +415 -0
  52. data/rdoc/site/0.1.19/Nucleon/Action/Extract.html +413 -0
  53. data/rdoc/site/0.1.19/Nucleon/Action/Remove.html +461 -0
  54. data/rdoc/site/0.1.19/Nucleon/Action/Save.html +434 -0
  55. data/rdoc/site/0.1.19/Nucleon/Action/Update.html +381 -0
  56. data/rdoc/site/0.1.19/Nucleon/Codes.html +563 -0
  57. data/rdoc/site/0.1.19/Nucleon/Command.html +275 -0
  58. data/rdoc/site/0.1.19/Nucleon/Command/Bash.html +544 -0
  59. data/rdoc/site/0.1.19/Nucleon/Config.html +1623 -0
  60. data/rdoc/site/0.1.19/Nucleon/Config/Collection.html +509 -0
  61. data/rdoc/site/0.1.19/Nucleon/Config/Options.html +489 -0
  62. data/rdoc/site/0.1.19/Nucleon/Core.html +635 -0
  63. data/rdoc/site/0.1.19/Nucleon/Errors.html +275 -0
  64. data/rdoc/site/0.1.19/Nucleon/Errors/BatchError.html +281 -0
  65. data/rdoc/site/0.1.19/Nucleon/Errors/NucleonError.html +657 -0
  66. data/rdoc/site/0.1.19/Nucleon/Errors/SSHUnavailable.html +281 -0
  67. data/rdoc/site/0.1.19/Nucleon/Event.html +275 -0
  68. data/rdoc/site/0.1.19/Nucleon/Event/Regex.html +467 -0
  69. data/rdoc/site/0.1.19/Nucleon/Facade.html +2336 -0
  70. data/rdoc/site/0.1.19/Nucleon/Gems.html +635 -0
  71. data/rdoc/site/0.1.19/Nucleon/Manager.html +1828 -0
  72. data/rdoc/site/0.1.19/Nucleon/Mixin.html +284 -0
  73. data/rdoc/site/0.1.19/Nucleon/Mixin/Action.html +277 -0
  74. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Commit.html +381 -0
  75. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Project.html +395 -0
  76. data/rdoc/site/0.1.19/Nucleon/Mixin/Action/Push.html +371 -0
  77. data/rdoc/site/0.1.19/Nucleon/Mixin/Colors.html +545 -0
  78. data/rdoc/site/0.1.19/Nucleon/Mixin/ConfigCollection.html +481 -0
  79. data/rdoc/site/0.1.19/Nucleon/Mixin/ConfigOptions.html +449 -0
  80. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro.html +276 -0
  81. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro/ObjectInterface.html +695 -0
  82. data/rdoc/site/0.1.19/Nucleon/Mixin/Macro/PluginInterface.html +682 -0
  83. data/rdoc/site/0.1.19/Nucleon/Mixin/Settings.html +481 -0
  84. data/rdoc/site/0.1.19/Nucleon/Mixin/SubConfig.html +887 -0
  85. data/rdoc/site/0.1.19/Nucleon/Parallel.html +325 -0
  86. data/rdoc/site/0.1.19/Nucleon/Parallel/ClassMethods.html +325 -0
  87. data/rdoc/site/0.1.19/Nucleon/Parallel/InstanceMethods.html +334 -0
  88. data/rdoc/site/0.1.19/Nucleon/Plugin.html +282 -0
  89. data/rdoc/site/0.1.19/Nucleon/Plugin/Action.html +1368 -0
  90. data/rdoc/site/0.1.19/Nucleon/Plugin/Action/Option.html +459 -0
  91. data/rdoc/site/0.1.19/Nucleon/Plugin/Base.html +1737 -0
  92. data/rdoc/site/0.1.19/Nucleon/Plugin/Command.html +721 -0
  93. data/rdoc/site/0.1.19/Nucleon/Plugin/Event.html +442 -0
  94. data/rdoc/site/0.1.19/Nucleon/Plugin/Extension.html +281 -0
  95. data/rdoc/site/0.1.19/Nucleon/Plugin/Project.html +2864 -0
  96. data/rdoc/site/0.1.19/Nucleon/Plugin/Template.html +476 -0
  97. data/rdoc/site/0.1.19/Nucleon/Plugin/Translator.html +371 -0
  98. data/rdoc/site/0.1.19/Nucleon/Project.html +276 -0
  99. data/rdoc/site/0.1.19/Nucleon/Project/Git.html +1801 -0
  100. data/rdoc/site/0.1.19/Nucleon/Project/Github.html +549 -0
  101. data/rdoc/site/0.1.19/Nucleon/Template.html +277 -0
  102. data/rdoc/site/0.1.19/Nucleon/Template/Json.html +329 -0
  103. data/rdoc/site/0.1.19/Nucleon/Template/Wrapper.html +329 -0
  104. data/rdoc/site/0.1.19/Nucleon/Template/Yaml.html +329 -0
  105. data/rdoc/site/0.1.19/Nucleon/Translator.html +276 -0
  106. data/rdoc/site/0.1.19/Nucleon/Translator/Json.html +366 -0
  107. data/rdoc/site/0.1.19/Nucleon/Translator/Yaml.html +366 -0
  108. data/rdoc/site/0.1.19/Nucleon/Util.html +285 -0
  109. data/rdoc/site/0.1.19/Nucleon/Util/CLI.html +388 -0
  110. data/rdoc/site/0.1.19/Nucleon/Util/CLI/Parser.html +1183 -0
  111. data/rdoc/site/0.1.19/Nucleon/Util/Cache.html +780 -0
  112. data/rdoc/site/0.1.19/Nucleon/Util/Console.html +1294 -0
  113. data/rdoc/site/0.1.19/Nucleon/Util/Data.html +1399 -0
  114. data/rdoc/site/0.1.19/Nucleon/Util/Disk.html +522 -0
  115. data/rdoc/site/0.1.19/Nucleon/Util/Git.html +361 -0
  116. data/rdoc/site/0.1.19/Nucleon/Util/Liquid.html +365 -0
  117. data/rdoc/site/0.1.19/Nucleon/Util/Logger.html +806 -0
  118. data/rdoc/site/0.1.19/Nucleon/Util/Package.html +558 -0
  119. data/rdoc/site/0.1.19/Nucleon/Util/SSH.html +910 -0
  120. data/rdoc/site/0.1.19/Nucleon/Util/SSH/Keypair.html +453 -0
  121. data/rdoc/site/0.1.19/Nucleon/Util/Shell.html +686 -0
  122. data/rdoc/site/0.1.19/Nucleon/Util/Shell/Result.html +497 -0
  123. data/rdoc/site/0.1.19/README_rdoc.html +312 -0
  124. data/rdoc/site/0.1.19/TODO_rdoc.html +267 -0
  125. data/rdoc/site/0.1.19/created.rid +60 -0
  126. data/rdoc/site/0.1.19/images/add.png +0 -0
  127. data/rdoc/site/0.1.19/images/brick.png +0 -0
  128. data/rdoc/site/0.1.19/images/brick_link.png +0 -0
  129. data/rdoc/site/0.1.19/images/bug.png +0 -0
  130. data/rdoc/site/0.1.19/images/bullet_black.png +0 -0
  131. data/rdoc/site/0.1.19/images/bullet_toggle_minus.png +0 -0
  132. data/rdoc/site/0.1.19/images/bullet_toggle_plus.png +0 -0
  133. data/rdoc/site/0.1.19/images/date.png +0 -0
  134. data/rdoc/site/0.1.19/images/delete.png +0 -0
  135. data/rdoc/site/0.1.19/images/find.png +0 -0
  136. data/rdoc/site/0.1.19/images/loadingAnimation.gif +0 -0
  137. data/rdoc/site/0.1.19/images/macFFBgHack.png +0 -0
  138. data/rdoc/site/0.1.19/images/package.png +0 -0
  139. data/rdoc/site/0.1.19/images/page_green.png +0 -0
  140. data/rdoc/site/0.1.19/images/page_white_text.png +0 -0
  141. data/rdoc/site/0.1.19/images/page_white_width.png +0 -0
  142. data/rdoc/site/0.1.19/images/plugin.png +0 -0
  143. data/rdoc/site/0.1.19/images/ruby.png +0 -0
  144. data/rdoc/site/0.1.19/images/tag_blue.png +0 -0
  145. data/rdoc/site/0.1.19/images/tag_green.png +0 -0
  146. data/rdoc/site/0.1.19/images/transparent.png +0 -0
  147. data/rdoc/site/0.1.19/images/wrench.png +0 -0
  148. data/rdoc/site/0.1.19/images/wrench_orange.png +0 -0
  149. data/rdoc/site/0.1.19/images/zoom.png +0 -0
  150. data/rdoc/site/0.1.19/index.html +311 -0
  151. data/rdoc/site/0.1.19/js/darkfish.js +155 -0
  152. data/rdoc/site/0.1.19/js/jquery.js +18 -0
  153. data/rdoc/site/0.1.19/js/navigation.js +142 -0
  154. data/rdoc/site/0.1.19/js/search.js +94 -0
  155. data/rdoc/site/0.1.19/js/search_index.js +1 -0
  156. data/rdoc/site/0.1.19/js/searcher.js +228 -0
  157. data/rdoc/site/0.1.19/rdoc.css +543 -0
  158. data/rdoc/site/0.1.19/table_of_contents.html +1541 -0
  159. metadata +140 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b1235f5a25a31be0dc6c8291d2b81a2acf7f53a8
4
- data.tar.gz: 12b4bfce18a0dee640ee3192def3394c8ce404fe
3
+ metadata.gz: 538f4bb7721e53ea65e86fcd9dabe27a3def5f67
4
+ data.tar.gz: 4fa312d8415f9db8d1b29537c95749358252a598
5
5
  SHA512:
6
- metadata.gz: 23d165b074de631f79469f11ba947ccead4fd1cfce9b6219edec419db9abf9506167c498044a9bd2e606b2c5c6c08195eb94a6afe47641f29010caf4336ebd81
7
- data.tar.gz: 90e7d32a20a4d4fd697733e9c6a5194572836e1281d18f8927935649671438beec83c31d43d4cfdfc566ee4223eee15341a6ee4ecb3f0c399888fc7154db8187
6
+ metadata.gz: afe85d0df90e8f5114d1d929e9806c01077ea5bbb293c4cef5aa886dc8a678e8a29baf653de081306a1873f9702f0da1d99f7776976b603600b3c4e283b1fb11
7
+ data.tar.gz: cd73b96970c6fc5ce2e29e1965bccd66b32c26d051f542c707de49bd0f99063bcd0c0f83d56eb7528cb794d5f62d4dfb57e4ec899db76ae8b1a8c936d66eef86
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source "http://rubygems.org"
3
3
  gem "log4r", "~> 1.1"
4
4
  gem "i18n", "~> 0.6"
5
5
  gem "netrc", "~> 0.7"
6
+ gem "highline", "~> 1.6"
6
7
 
7
8
  gem "deep_merge", "~> 1.0"
8
9
  gem "multi_json", "~> 1.7"
@@ -106,6 +106,7 @@ DEPENDENCIES
106
106
  celluloid (~> 0.15)
107
107
  childprocess (~> 0.5)
108
108
  deep_merge (~> 1.0)
109
+ highline (~> 1.6)
109
110
  i18n (~> 0.6)
110
111
  jeweler (~> 2.0)
111
112
  log4r (~> 1.1)
data/TODO.rdoc CHANGED
@@ -1,13 +1,10 @@
1
1
  == Nucleon tasks to complete before 1.0 release
2
2
 
3
- * Namespace implementation
4
- * Meta (composite) actions
5
3
  * Execution plans
6
4
  * Error handling improvements
7
5
  * Full code documentation
8
6
  * Full coverage unit tests (starting with core Nucleon unit testing library)
9
7
  * Performance improvements
10
- * Ensure fault tolerance for Actor managers
11
8
  * Deeper GitHub API integration in project provider
12
9
  * UI console color profiles
13
10
  * Localization improvements
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.19
1
+ 0.2.0
@@ -1,3 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ Signal.trap("INT") { exit 1 }
4
+
5
+ #---
6
+
2
7
  require 'nucleon'
8
+
9
+ # Set version info
10
+
11
+ module Nucleon; module Util; module CLI
12
+ class Parser
13
+ def version
14
+ version = Nucleon.VERSION
15
+ "Nucleon: #{version} (Apache License, Version 2.0) -- https://github.com/coralnexus/nucleon/tree/v#{version}"
16
+ end
17
+ end
18
+ end; end; end
19
+
20
+ # Execute
21
+
3
22
  exit(Nucleon.executable(ARGV, :nucleon))
@@ -44,7 +44,7 @@ class Config
44
44
  @properties = {}
45
45
 
46
46
  if defaults.is_a?(Hash) && ! defaults.empty?
47
- defaults = symbol_map(defaults)
47
+ defaults = symbol_map(defaults.clone)
48
48
  end
49
49
 
50
50
  case data
@@ -53,7 +53,7 @@ class Config
53
53
  when Hash
54
54
  @properties = {}
55
55
  if data.is_a?(Hash)
56
- @properties = Util::Data.merge([ defaults, symbol_map(data) ], force)
56
+ @properties = Util::Data.merge([ defaults, symbol_map(data.clone) ], force)
57
57
  end
58
58
  end
59
59
  end
@@ -83,8 +83,11 @@ class Config
83
83
  def fetch(data, keys, default = nil, format = false)
84
84
  if keys.is_a?(String) || keys.is_a?(Symbol)
85
85
  keys = [ keys ]
86
- end
87
- key = keys.shift.to_sym
86
+ end
87
+
88
+ keys = keys.flatten.compact
89
+ key = keys.shift.to_sym
90
+
88
91
  if data.has_key?(key)
89
92
  value = data[key]
90
93
 
@@ -105,6 +108,7 @@ class Config
105
108
  keys = [ keys ]
106
109
  end
107
110
 
111
+ keys = keys.flatten.compact
108
112
  key = keys.shift.to_sym
109
113
  has_key = data.has_key?(key)
110
114
  existing = {
@@ -203,7 +207,7 @@ class Config
203
207
 
204
208
  case properties
205
209
  when Hash
206
- data = [ @properties, symbol_map(properties) ]
210
+ data = [ @properties, symbol_map(properties.clone) ]
207
211
  data = data.reverse if import_type != :override
208
212
 
209
213
  @properties = Util::Data.merge(data, config)
@@ -217,7 +221,7 @@ class Config
217
221
  @properties = Util::Data.merge(data, config)
218
222
 
219
223
  when Array
220
- properties.each do |item|
224
+ properties.clone.each do |item|
221
225
  import_base(item, config)
222
226
  end
223
227
  end
@@ -242,7 +246,7 @@ class Config
242
246
  #---
243
247
 
244
248
  def export
245
- return @properties
249
+ return @properties.clone
246
250
  end
247
251
 
248
252
  #-----------------------------------------------------------------------------
@@ -0,0 +1,338 @@
1
+
2
+ module Nucleon
3
+ class Environment
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Constructor / Destructor
7
+
8
+ def initialize
9
+ @plugin_types = {}
10
+
11
+ @load_info = {}
12
+ @active_info = {}
13
+ end
14
+
15
+ #-----------------------------------------------------------------------------
16
+ # Plugin type accessor / modifiers
17
+
18
+ def namespaces
19
+ @plugin_types.keys
20
+ end
21
+
22
+ #---
23
+
24
+ def plugin_types(namespace)
25
+ namespace = namespace.to_sym
26
+
27
+ return [] unless @plugin_types.has_key?(namespace)
28
+ @plugin_types[namespace].keys
29
+ end
30
+
31
+ #---
32
+
33
+ def define_plugin_type(namespace, plugin_type, default_provider = nil)
34
+ namespace = namespace.to_sym
35
+
36
+ @plugin_types[namespace] = {} unless @plugin_types.has_key?(namespace)
37
+ @plugin_types[namespace][sanitize_id(plugin_type)] = default_provider
38
+ end
39
+
40
+ #---
41
+
42
+ def define_plugin_types(namespace, type_info)
43
+ if type_info.is_a?(Hash)
44
+ type_info.each do |plugin_type, default_provider|
45
+ define_plugin_type(namespace, plugin_type, default_provider)
46
+ end
47
+ end
48
+ end
49
+
50
+ #---
51
+
52
+ def plugin_type_defined?(namespace, plugin_type)
53
+ namespace = namespace.to_sym
54
+
55
+ return false unless @plugin_types.has_key?(namespace)
56
+ @plugin_types[namespace].has_key?(sanitize_id(plugin_type))
57
+ end
58
+
59
+ #---
60
+
61
+ def plugin_type_default(namespace, plugin_type)
62
+ namespace = namespace.to_sym
63
+
64
+ return nil unless @plugin_types.has_key?(namespace)
65
+ @plugin_types[namespace][sanitize_id(plugin_type)]
66
+ end
67
+
68
+ #-----------------------------------------------------------------------------
69
+ # Loaded plugin accessor / modifiers
70
+
71
+ def define_plugin(namespace, plugin_type, base_path, file, &code)
72
+ namespace = namespace.to_sym
73
+ plugin_type = sanitize_id(plugin_type)
74
+
75
+ @load_info[namespace] = {} unless @load_info.has_key?(namespace)
76
+ @load_info[namespace][plugin_type] = {} unless @load_info[namespace].has_key?(plugin_type)
77
+
78
+ plugin_info = parse_plugin_info(namespace, plugin_type, base_path, file)
79
+
80
+ unless @load_info[namespace][plugin_type].has_key?(plugin_info[:provider])
81
+ data = {
82
+ :namespace => namespace,
83
+ :type => plugin_type,
84
+ :file => file,
85
+ :provider => plugin_info[:provider],
86
+ :directory => plugin_info[:directory],
87
+ :class_components => plugin_info[:class_components]
88
+ }
89
+ code.call(data) if code
90
+
91
+ @load_info[namespace][plugin_type][plugin_info[:provider]] = data
92
+ end
93
+ end
94
+
95
+ #---
96
+
97
+ def loaded_plugin(namespace, plugin_type, provider)
98
+ namespace = namespace.to_sym
99
+ plugin_type = sanitize_id(plugin_type)
100
+ provider = sanitize_id(provider)
101
+ info = nil
102
+
103
+ if @load_info.has_key?(namespace) &&
104
+ @load_info[namespace].has_key?(plugin_type) &&
105
+ @load_info[namespace][plugin_type].has_key?(provider)
106
+
107
+ info = @load_info[namespace][plugin_type][provider]
108
+ end
109
+ info
110
+ end
111
+
112
+ #---
113
+
114
+ def loaded_plugins(namespace = nil, plugin_type = nil, provider = nil, default = {})
115
+ namespace = namespace.to_sym if namespace
116
+ plugin_type = sanitize_id(plugin_type) if plugin_type
117
+ provider = sanitize_id(provider) if provider
118
+ results = default
119
+
120
+ if namespace && @load_info.has_key?(namespace)
121
+ if plugin_type && @load_info[namespace].has_key?(plugin_type)
122
+ if provider && @load_info[namespace][plugin_type].has_key?(provider)
123
+ results = @load_info[namespace][plugin_type][provider]
124
+ elsif ! provider
125
+ results = @load_info[namespace][plugin_type]
126
+ end
127
+ elsif ! plugin_type
128
+ results = @load_info[namespace]
129
+ end
130
+ elsif ! namespace
131
+ results = @load_info
132
+ end
133
+ results
134
+ end
135
+
136
+ #---
137
+
138
+ def plugin_has_type?(namespace, plugin_type)
139
+ namespace = namespace.to_sym
140
+
141
+ return false unless @load_info.has_key?(namespace)
142
+ @load_info[namespace].has_key?(sanitize_id(plugin_type))
143
+ end
144
+
145
+ #---
146
+
147
+ def plugin_has_provider?(namespace, plugin_type, provider)
148
+ namespace = namespace.to_sym
149
+ plugin_type = sanitize_id(plugin_type)
150
+ provider = sanitize_id(provider)
151
+
152
+ return false unless @load_info.has_key?(namespace) && @load_info[namespace].has_key?(plugin_type)
153
+ @load_info[namespace][plugin_type].has_key?(provider)
154
+ end
155
+
156
+ #-----------------------------------------------------------------------------
157
+ # Active plugin accessor / modifiers
158
+
159
+ def create_plugin(namespace, plugin_type, provider, options = {}, &code)
160
+ namespace = namespace.to_sym
161
+ plugin_type = sanitize_id(plugin_type)
162
+ provider = sanitize_id(provider)
163
+
164
+ unless plugin_type_defined?(namespace, plugin_type)
165
+ return nil
166
+ end
167
+
168
+ if type_info = loaded_plugin(namespace, plugin_type, provider)
169
+ ids = Util::Data.array(type_info[:class].register_ids).flatten
170
+ instance_options = Config.new(options).export
171
+ instance_options = Util::Data.subset(instance_options, ids, true)
172
+ instance_name = "#{provider}_" + Nucleon.sha1(instance_options)
173
+
174
+ @active_info[namespace] = {} unless @active_info.has_key?(namespace)
175
+ @active_info[namespace][plugin_type] = {} unless @active_info[namespace].has_key?(plugin_type)
176
+
177
+ unless instance_name && @active_info[namespace][plugin_type].has_key?(instance_name)
178
+ type_info[:instance_name] = instance_name
179
+
180
+ options = code.call(type_info, options) if code
181
+ plugin = type_info[:class].new(namespace, plugin_type, provider, options)
182
+
183
+ @active_info[namespace][plugin_type][instance_name] = plugin
184
+ end
185
+ return @active_info[namespace][plugin_type][instance_name]
186
+ end
187
+ nil
188
+ end
189
+
190
+ #---
191
+
192
+ def get_plugin(namespace, plugin_type, plugin_name)
193
+ namespace = namespace.to_sym
194
+ plugin_type = sanitize_id(plugin_type)
195
+
196
+ if @active_info.has_key?(namespace) && @active_info[namespace].has_key?(plugin_type)
197
+ @active_info[namespace][plugin_type].each do |instance_name, plugin|
198
+ if plugin.plugin_name.to_s == plugin_name.to_s
199
+ return plugin
200
+ end
201
+ end
202
+ end
203
+ nil
204
+ end
205
+
206
+ #---
207
+
208
+ def remove_plugin(namespace, plugin_type, instance_name, &code)
209
+ namespace = namespace.to_sym
210
+ plugin_type = sanitize_id(plugin_type)
211
+
212
+ if @active_info.has_key?(namespace) && @active_info[namespace].has_key?(plugin_type)
213
+ plugin = @active_info[namespace][plugin_type]
214
+ @active_info[namespace][plugin_type].delete(instance_name)
215
+ code.call(plugin) if code
216
+ end
217
+ end
218
+
219
+ #---
220
+
221
+ def active_plugins(namespace = nil, plugin_type = nil, provider = nil)
222
+ namespace = namespace.to_sym if namespace
223
+ plugin_type = sanitize_id(plugin_type) if plugin_type
224
+ provider = sanitize_id(provider) if provider
225
+ results = {}
226
+
227
+ if namespace && @active_info.has_key?(namespace)
228
+ if plugin_type && @active_info[namespace].has_key?(plugin_type)
229
+ if provider && ! @active_info[namespace][plugin_type].keys.empty?
230
+ @active_info[namespace][plugin_type].each do |instance_name, plugin|
231
+ plugin = @active_info[namespace][plugin_type][instance_name]
232
+ results[instance_name] = plugin if plugin.plugin_provider == provider
233
+ end
234
+ elsif ! provider
235
+ results = @active_info[namespace][plugin_type]
236
+ end
237
+ elsif ! plugin_type
238
+ results = @active_info[namespace]
239
+ end
240
+ elsif ! namespace
241
+ results = @active_info
242
+ end
243
+ results
244
+ end
245
+
246
+ #-----------------------------------------------------------------------------
247
+ # Utilities
248
+
249
+ def class_name(name, separator = '::', want_array = FALSE)
250
+ components = []
251
+
252
+ case name
253
+ when String, Symbol
254
+ components = name.to_s.split(separator)
255
+ when Array
256
+ components = name
257
+ end
258
+
259
+ components.collect! do |value|
260
+ value = value.to_s.strip
261
+ value[0] = value.capitalize[0] if value =~ /^[a-z]/
262
+ value
263
+ end
264
+
265
+ if want_array
266
+ return components
267
+ end
268
+ components.join(separator)
269
+ end
270
+
271
+ #---
272
+
273
+ def class_const(name, separator = '::')
274
+ components = class_name(name, separator, TRUE)
275
+ constant = Object
276
+
277
+ components.each do |component|
278
+ constant = constant.const_defined?(component) ?
279
+ constant.const_get(component) :
280
+ constant.const_missing(component)
281
+ end
282
+ constant
283
+ end
284
+
285
+ #---
286
+
287
+ def sanitize_id(id_component)
288
+ id_component.to_s.gsub(/([a-z0-9])(?:\-|\_)?([A-Z])/, '\1_\2').downcase.to_sym
289
+ end
290
+ protected :sanitize_id
291
+
292
+ #---
293
+
294
+ def sanitize_class(class_component)
295
+ class_component.to_s.split('_').collect {|elem| elem.slice(0,1).capitalize + elem.slice(1..-1) }.join('')
296
+ end
297
+ protected :sanitize_class
298
+
299
+ #---
300
+
301
+ def plugin_class(namespace, plugin_type)
302
+ class_const([ sanitize_class(namespace), :plugin, sanitize_class(plugin_type) ])
303
+ end
304
+
305
+ #---
306
+
307
+ def parse_plugin_info(namespace, plugin_type, base_path, file)
308
+ dir_components = base_path.split(File::SEPARATOR)
309
+ file_components = file.split(File::SEPARATOR)
310
+
311
+ file_name = file_components.pop.sub(/\.rb/, '')
312
+ directory = file_components.join(File::SEPARATOR)
313
+
314
+ file_class = sanitize_class(file_name)
315
+ group_components = file_components - dir_components
316
+
317
+ class_components = [ sanitize_class(namespace), sanitize_class(plugin_type) ]
318
+
319
+ if ! group_components.empty?
320
+ group_name = group_components.collect {|elem| elem.downcase }.join('_')
321
+ provider = [ group_name, file_name ].join('_')
322
+
323
+ group_components = group_components.collect {|elem| sanitize_class(elem) }
324
+ class_components = [ class_components, group_components, file_class ].flatten
325
+ else
326
+ provider = file_name
327
+ class_components = [ class_components, file_class ].flatten
328
+ end
329
+
330
+ {
331
+ :directory => directory,
332
+ :provider => sanitize_id(provider),
333
+ :class_components => class_components
334
+ }
335
+ end
336
+ protected :parse_plugin_info
337
+ end
338
+ end