nucleon 0.1.10 → 0.1.11

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.10
1
+ 0.1.11
@@ -14,7 +14,7 @@ class Core < Config
14
14
  #-----------------------------------------------------------------------------
15
15
  # Constructor / Destructor
16
16
 
17
- def initialize(data = {}, defaults = {}, force = true)
17
+ def initialize(data = {}, defaults = {}, force = true, set_initialized = true)
18
18
  super(data, defaults, force)
19
19
 
20
20
  @class_color = Util::Data.ensure_value(delete(:class_color, :cyan), :cyan)
@@ -24,6 +24,14 @@ class Core < Config
24
24
  self.ui = Config.new(export).defaults({ :resource => Util::Console.colorize(@class_label, @class_color) })
25
25
 
26
26
  logger.debug('Initialized instance logger and interface')
27
+ @initialized = true if set_initialized
28
+ end
29
+
30
+ #-----------------------------------------------------------------------------
31
+ # Checks
32
+
33
+ def initialized?
34
+ @initialized
27
35
  end
28
36
 
29
37
  #-----------------------------------------------------------------------------
@@ -95,12 +95,13 @@ module PluginInterface
95
95
  data = get_hash(_plural) unless data
96
96
 
97
97
  providers = [ providers ] if providers && ! providers.is_a?(Array)
98
+ providers.collect! { |elem| elem.to_sym }
98
99
 
99
100
  logger.debug("Initializing #{_plugin_type} plugin data: #{data.inspect}")
100
101
  logger.debug("Providers: #{providers.inspect}")
101
102
 
102
103
  symbol_map(data).each do |provider, instance_settings|
103
- if ! providers || providers.include?(provider.to_s)
104
+ if ! providers || providers.include?(provider)
104
105
  if _single_instance
105
106
  logger.debug("Initializing single instance plugin: #{instance_settings.inspect}")
106
107
 
@@ -14,11 +14,13 @@ class Base < Core
14
14
  set_meta(config.delete(:meta, Config.new))
15
15
 
16
16
  # No logging statements aove this line!!
17
- super(config.import({ :logger => "#{plugin_type}->#{plugin_provider}" }))
17
+ super(config.import({ :logger => "#{plugin_type}->#{plugin_provider}" }), {}, true, false)
18
18
  myself.plugin_name = name
19
19
 
20
20
  logger.debug("Normalizing #{plugin_type} plugin #{plugin_name} with meta data: #{meta.inspect}")
21
21
  normalize(false)
22
+
23
+ @initialized = true
22
24
  end
23
25
 
24
26
  #---
@@ -30,12 +32,6 @@ class Base < Core
30
32
  #-----------------------------------------------------------------------------
31
33
  # Checks
32
34
 
33
- def initialized?(options = {})
34
- return true
35
- end
36
-
37
- #---
38
-
39
35
  def quiet?
40
36
  @quiet
41
37
  end
@@ -49,6 +49,11 @@ class Project < Base
49
49
  ui.resource = plugin_name
50
50
  logger = plugin_name
51
51
 
52
+ unless reload
53
+ @cache = Util::Cache.new(directory, Nucleon.sha1(plugin_name), '.project_cache')
54
+ init_cache
55
+ end
56
+
52
57
  if keys = delete(:keys, nil)
53
58
  set(:private_key, keys[:private_key])
54
59
  set(:public_key, keys[:public_key])
@@ -117,6 +122,12 @@ class Project < Base
117
122
  #-----------------------------------------------------------------------------
118
123
  # Property accessor / modifiers
119
124
 
125
+ def cache
126
+ @cache
127
+ end
128
+
129
+ #---
130
+
120
131
  def reference
121
132
  get(:reference, nil)
122
133
  end
@@ -298,6 +309,13 @@ class Project < Base
298
309
  #-----------------------------------------------------------------------------
299
310
  # Project operations
300
311
 
312
+ def init_cache
313
+ # Override in providers if needed
314
+ end
315
+ protected :init_cache
316
+
317
+ #---
318
+
301
319
  def init_auth
302
320
  if can_persist?
303
321
  localize do
@@ -443,6 +461,15 @@ class Project < Base
443
461
  success
444
462
  end
445
463
 
464
+ #---
465
+
466
+ def ignore(files)
467
+ return unless directory
468
+ files = nil
469
+ files = yield if block_given?
470
+ commit(files, { :message => "Adding project ignores." }) if files
471
+ end
472
+
446
473
  #-----------------------------------------------------------------------------
447
474
  # Subproject operations
448
475
 
@@ -0,0 +1,149 @@
1
+
2
+ module Nucleon
3
+ module Util
4
+ class Cache < Core
5
+
6
+ @@cache_lock = Mutex.new
7
+
8
+ #-----------------------------------------------------------------------------
9
+
10
+ # This class already inherits much of what we need from the core config class.
11
+ # Right now we just have to worry about persistence
12
+
13
+ #-----------------------------------------------------------------------------
14
+ # Constructor / Destructor
15
+
16
+ def initialize(root_path, id, cache_dir = '.cache', force = true)
17
+ super({}, {}, force)
18
+
19
+ @cache_dir = cache_dir
20
+ @cache_root = File.join(root_path, cache_dir)
21
+ FileUtils.mkdir_p(base_path) unless File.directory?(base_path)
22
+
23
+ @cache_id = id.to_sym
24
+ @cache_translator = Nucleon.type_default(:translator)
25
+ @cache_filename = "#{id}.#{translator}"
26
+ @cache_path = File.join(@cache_root, @cache_filename)
27
+ end
28
+
29
+ #-----------------------------------------------------------------------------
30
+ # Property accessors / modifiers
31
+
32
+ def base_path
33
+ @cache_root
34
+ end
35
+
36
+ #---
37
+
38
+ def directory_name
39
+ @cache_dir
40
+ end
41
+
42
+ #---
43
+
44
+ def id
45
+ @cache_id
46
+ end
47
+
48
+ #---
49
+
50
+ def translator
51
+ @cache_translator
52
+ end
53
+
54
+ #---
55
+
56
+ def file
57
+ @cache_path
58
+ end
59
+
60
+ #---
61
+
62
+ def get(keys, default = nil, format = false)
63
+ result = super
64
+
65
+ if result.nil?
66
+ load
67
+ result = super
68
+ end
69
+ result
70
+ end
71
+
72
+ #---
73
+
74
+ def set(keys, value)
75
+ result = super
76
+ save if initialized?
77
+ result
78
+ end
79
+
80
+ #---
81
+
82
+ def delete(keys, default = nil)
83
+ result = super
84
+ save if initialized?
85
+ result
86
+ end
87
+
88
+ #---
89
+
90
+ def clear
91
+ result = super
92
+ save if initialized?
93
+ result
94
+ end
95
+
96
+ #-----------------------------------------------------------------------------
97
+ # Operations
98
+
99
+ def import_base(properties, options = {})
100
+ config = Config.ensure(options)
101
+
102
+ result = super
103
+ save if initialized? && ! config.get(:no_save, false)
104
+ result
105
+ end
106
+
107
+ #---
108
+
109
+ def load
110
+ success = false
111
+
112
+ @@cache_lock.synchronize do
113
+ logger.info("Loading #{translator} translated cache from #{file}")
114
+
115
+ parser = CORL.translator({}, translator)
116
+ raw = Disk.read(file)
117
+
118
+ if parser && raw && ! raw.empty?
119
+ logger.debug("Cache file contents: #{raw}")
120
+ parse_properties = Data.hash(parser.parse(raw))
121
+
122
+ import(parse_properties, { :no_save => true }) unless parse_properties.empty?
123
+ success = true
124
+ end
125
+ end
126
+ success
127
+ end
128
+ protected :load
129
+
130
+ #---
131
+
132
+ def save
133
+ success = false
134
+
135
+ @@cache_lock.synchronize do
136
+ if renderer = CORL.translator({}, translator)
137
+ rendering = renderer.generate(export)
138
+
139
+ if Disk.write(file, rendering)
140
+ success = true
141
+ end
142
+ end
143
+ end
144
+ success
145
+ end
146
+ protected :save
147
+ end
148
+ end
149
+ end
@@ -11,6 +11,8 @@ class Disk
11
11
  @@separator = false
12
12
  @@description = ''
13
13
 
14
+ @@file_lock = Mutex.new
15
+
14
16
  #-----------------------------------------------------------------------------
15
17
  # Utilities
16
18
 
@@ -36,13 +38,15 @@ class Disk
36
38
  reset = true if ! mode.empty? && mode != @@files[file_name][:mode]
37
39
  end
38
40
 
39
- if ! @@files.has_key?(file_name) || ! @@files[file_name][:file] || reset
40
- @@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
41
- unless mode.empty? || ( mode == 'r' && ! ::File.exists?(file_name) )
42
- @@files[file_name] = {
43
- :file => ::File.open(file_name, mode),
44
- :mode => mode,
45
- }
41
+ @@file_lock.synchronize do
42
+ if ! @@files.has_key?(file_name) || ! @@files[file_name][:file] || reset
43
+ @@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
44
+ unless mode.empty? || ( mode == 'r' && ! ::File.exists?(file_name) )
45
+ @@files[file_name] = {
46
+ :file => ::File.open(file_name, mode),
47
+ :mode => mode,
48
+ }
49
+ end
46
50
  end
47
51
  end
48
52
  return nil unless @@files[file_name]
@@ -52,14 +56,17 @@ class Disk
52
56
  #---
53
57
 
54
58
  def self.read(file_name, options = {})
59
+ result = nil
55
60
  options[:mode] = ( options[:mode] ? options[:mode] : 'r' )
56
61
  file = open(file_name, options)
57
62
 
58
63
  if file
59
- file.pos = 0 if options[:mode] == 'r'
60
- return file.read
64
+ @@file_lock.synchronize do
65
+ file.pos = 0 if options[:mode] == 'r'
66
+ result = file.read
67
+ end
61
68
  end
62
- return nil
69
+ return result
63
70
  end
64
71
 
65
72
  #---
@@ -67,23 +74,29 @@ class Disk
67
74
  def self.write(file_name, data, options = {})
68
75
  options[:mode] = ( options[:mode] ? options[:mode] : 'w' )
69
76
  file = open(file_name, options)
77
+ result = nil
70
78
 
71
79
  if file
72
- file.pos = 0 if options[:mode] == 'w'
73
- success = file.write(data)
74
- begin
75
- file.flush
76
- rescue # In case the file is already closed
80
+ @@file_lock.synchronize do
81
+ file.pos = 0 if options[:mode] == 'w'
82
+ result = file.write(data)
83
+ begin
84
+ file.flush
85
+ rescue # In case the file is already closed
86
+ end
77
87
  end
78
- return success
79
88
  end
80
- return nil
89
+ return result
81
90
  end
82
91
 
83
92
  #---
84
93
 
85
94
  def self.delete(file_path)
86
- return ::File.delete(file_path)
95
+ result = nil
96
+ @@file_lock.synchronize do
97
+ result = ::File.delete(file_path)
98
+ end
99
+ result
87
100
  end
88
101
 
89
102
  #---
@@ -91,10 +104,12 @@ class Disk
91
104
  def self.log(data, options = {})
92
105
  reset = ( options[:file_name] || options[:mode] )
93
106
  file = open(( options[:file_name] ? options[:file_name] : 'log.txt' ), options, reset)
94
- if file
95
- file.write("--------------------------------------\n") if @@separator
96
- file.write("#{@@description}\n") if @@description
97
- file.write("#{data}\n")
107
+ if file
108
+ @@file_lock.synchronize do
109
+ file.write("--------------------------------------\n") if @@separator
110
+ file.write("#{@@description}\n") if @@description
111
+ file.write("#{data}\n")
112
+ end
98
113
  end
99
114
  end
100
115
 
@@ -108,8 +123,10 @@ class Disk
108
123
  end
109
124
 
110
125
  file_names.each do |file_name|
111
- @@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
112
- @@files.delete(file_name)
126
+ @@file_lock.synchronize do
127
+ @@files[file_name][:file].close if @@files[file_name] && @@files[file_name][:file]
128
+ @@files.delete(file_name)
129
+ end
113
130
  end
114
131
  end
115
132
  end
@@ -10,7 +10,7 @@ class Liquid
10
10
  #---
11
11
 
12
12
  def method_missing(method, *args, &block)
13
- @code.call(method, args, block)
13
+ @code.call(method, args, &block)
14
14
  end
15
15
  end
16
16
  end
@@ -16,11 +16,11 @@ class Shell < Core
16
16
  attr_accessor :status
17
17
  attr_reader :command
18
18
 
19
- def initialize(command)
19
+ def initialize(command, status = nil)
20
20
  @command = command
21
21
  @output = ''
22
22
  @errors = ''
23
- @status = Nucleon.code.success
23
+ @status = status.nil? ? Nucleon.code.success : status
24
24
  end
25
25
 
26
26
  #---
@@ -195,10 +195,26 @@ class Git < Plugin::Project
195
195
  result
196
196
  end
197
197
  end
198
-
198
+
199
+ #-----------------------------------------------------------------------------
200
+ # Operations
201
+
202
+ def init_cache
203
+ ignore(cache.directory_name)
204
+ end
205
+
199
206
  #-----------------------------------------------------------------------------
200
207
  # Basic Git operations
201
208
 
209
+ def ignore(files)
210
+ super do
211
+ ensure_in_gitignore(files)
212
+ '.gitignore'
213
+ end
214
+ end
215
+
216
+ #---
217
+
202
218
  def load_revision
203
219
  return super do
204
220
  if new?
@@ -529,6 +545,35 @@ class Git < Plugin::Project
529
545
  result
530
546
  end
531
547
  protected :git_exec
548
+
549
+ #---
550
+
551
+ def ensure_in_gitignore(files)
552
+ files = [ files ] unless files.is_a?(Array)
553
+ changes = false
554
+
555
+ gitignore_file = File.join(directory, '.gitignore')
556
+ ignore_raw = Util::Disk.read(gitignore_file)
557
+ ignores = []
558
+ ignores = ignore_raw.split("\n") if ignore_raw && ! ignore_raw.empty?
559
+
560
+ files.each do |file|
561
+ found = false
562
+ unless ignores.empty?
563
+ ignores.each do |ignore|
564
+ if ignore.strip.match(/^#{file}\/?$/)
565
+ found = true
566
+ end
567
+ end
568
+ end
569
+ unless found
570
+ ignores << file
571
+ changes = true
572
+ end
573
+ end
574
+ Util::Disk.write(gitignore_file, ignores.join("\n")) if changes
575
+ end
576
+ protected :ensure_in_gitignore
532
577
  end
533
578
  end
534
579
  end
@@ -164,7 +164,8 @@ nucleon_require(core_dir, :core)
164
164
  [ :liquid,
165
165
  :cli,
166
166
  :disk,
167
- :package,
167
+ :package,
168
+ :cache,
168
169
  :shell,
169
170
  :ssh
170
171
  ].each do |name|
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "nucleon"
8
- s.version = "0.1.10"
8
+ s.version = "0.1.11"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Adrian Webb"]
12
- s.date = "2014-03-28"
12
+ s.date = "2014-04-02"
13
13
  s.description = "\nA framework that provides a simple foundation for building Ruby applications that are:\n\n* Highly configurable (with both distributed and persistent configurations)\n* Extremely pluggable and extendable\n* Easily parallel\n\nNote: This framework is still very early in development!\n"
14
14
  s.email = "adrian.webb@coralnexus.com"
15
15
  s.executables = ["nucleon"]
@@ -54,6 +54,7 @@ Gem::Specification.new do |s|
54
54
  "lib/core/plugin/project.rb",
55
55
  "lib/core/plugin/template.rb",
56
56
  "lib/core/plugin/translator.rb",
57
+ "lib/core/util/cache.rb",
57
58
  "lib/core/util/cli.rb",
58
59
  "lib/core/util/console.rb",
59
60
  "lib/core/util/data.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nucleon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-28 00:00:00.000000000 Z
12
+ date: 2014-04-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: log4r
16
- requirement: &12902440 !ruby/object:Gem::Requirement
16
+ requirement: &23185960 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *12902440
24
+ version_requirements: *23185960
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: i18n
27
- requirement: &12901680 !ruby/object:Gem::Requirement
27
+ requirement: &23185380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0.6'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *12901680
35
+ version_requirements: *23185380
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: netrc
38
- requirement: &12900600 !ruby/object:Gem::Requirement
38
+ requirement: &23184460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0.7'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *12900600
46
+ version_requirements: *23184460
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: deep_merge
49
- requirement: &13008240 !ruby/object:Gem::Requirement
49
+ requirement: &23183740 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *13008240
57
+ version_requirements: *23183740
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &13007120 !ruby/object:Gem::Requirement
60
+ requirement: &23183200 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '1.7'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *13007120
68
+ version_requirements: *23183200
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sshkey
71
- requirement: &13006360 !ruby/object:Gem::Requirement
71
+ requirement: &23182520 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '1.6'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *13006360
79
+ version_requirements: *23182520
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: childprocess
82
- requirement: &13005560 !ruby/object:Gem::Requirement
82
+ requirement: &23181760 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 0.5.0
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *13005560
90
+ version_requirements: *23181760
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: celluloid
93
- requirement: &13004820 !ruby/object:Gem::Requirement
93
+ requirement: &23181040 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0.15'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *13004820
101
+ version_requirements: *23181040
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rugged
104
- requirement: &13004340 !ruby/object:Gem::Requirement
104
+ requirement: &23180540 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0.19'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *13004340
112
+ version_requirements: *23180540
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: octokit
115
- requirement: &13003800 !ruby/object:Gem::Requirement
115
+ requirement: &23179980 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '2.7'
121
121
  type: :runtime
122
122
  prerelease: false
123
- version_requirements: *13003800
123
+ version_requirements: *23179980
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: bundler
126
- requirement: &13003000 !ruby/object:Gem::Requirement
126
+ requirement: &23253080 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: '1.2'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *13003000
134
+ version_requirements: *23253080
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: jeweler
137
- requirement: &13002380 !ruby/object:Gem::Requirement
137
+ requirement: &23251720 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: '2.0'
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *13002380
145
+ version_requirements: *23251720
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: rspec
148
- requirement: &13001880 !ruby/object:Gem::Requirement
148
+ requirement: &23250760 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: '2.10'
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *13001880
156
+ version_requirements: *23250760
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: rdoc
159
- requirement: &13001400 !ruby/object:Gem::Requirement
159
+ requirement: &23249360 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ~>
@@ -164,10 +164,10 @@ dependencies:
164
164
  version: '3.12'
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *13001400
167
+ version_requirements: *23249360
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: yard
170
- requirement: &13097020 !ruby/object:Gem::Requirement
170
+ requirement: &23248640 !ruby/object:Gem::Requirement
171
171
  none: false
172
172
  requirements:
173
173
  - - ~>
@@ -175,7 +175,7 @@ dependencies:
175
175
  version: '0.8'
176
176
  type: :development
177
177
  prerelease: false
178
- version_requirements: *13097020
178
+ version_requirements: *23248640
179
179
  description: ! '
180
180
 
181
181
  A framework that provides a simple foundation for building Ruby applications that
@@ -236,6 +236,7 @@ files:
236
236
  - lib/core/plugin/project.rb
237
237
  - lib/core/plugin/template.rb
238
238
  - lib/core/plugin/translator.rb
239
+ - lib/core/util/cache.rb
239
240
  - lib/core/util/cli.rb
240
241
  - lib/core/util/console.rb
241
242
  - lib/core/util/data.rb