cableguy 0.2.3 → 0.5.0.pre2

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +59 -1
  3. data/Gemfile +6 -5
  4. data/Gemfile.lock +38 -0
  5. data/LICENSE.md +20 -0
  6. data/README.md +28 -0
  7. data/Rakefile +23 -1
  8. data/bin/cable +2 -37
  9. data/cableguy.gemspec +15 -17
  10. data/lib/palmade/cableguy/builders/cable_chmod.rb +3 -5
  11. data/lib/palmade/cableguy/builders/cable_copy.rb +2 -5
  12. data/lib/palmade/cableguy/builders/cable_custom.rb +6 -3
  13. data/lib/palmade/cableguy/builders/cable_mkdir.rb +3 -6
  14. data/lib/palmade/cableguy/builders/cable_move.rb +2 -5
  15. data/lib/palmade/cableguy/builders/cable_symlink.rb +4 -7
  16. data/lib/palmade/cableguy/builders/cable_template.rb +25 -9
  17. data/lib/palmade/cableguy/builders.rb +7 -8
  18. data/lib/palmade/cableguy/cable.rb +1 -24
  19. data/lib/palmade/cableguy/cablefile.rb +107 -0
  20. data/lib/palmade/cableguy/cabler.rb +257 -53
  21. data/lib/palmade/cableguy/cabling_values.rb +54 -0
  22. data/lib/palmade/cableguy/cli.rb +232 -0
  23. data/lib/palmade/cableguy/cli_helper.rb +18 -0
  24. data/lib/palmade/cableguy/configurator.rb +19 -20
  25. data/lib/palmade/cableguy/constants.rb +17 -2
  26. data/lib/palmade/cableguy/db.rb +115 -66
  27. data/lib/palmade/cableguy/{cable_configurator.rb → legacy_configurator.rb} +1 -2
  28. data/lib/palmade/cableguy/migration.rb +37 -61
  29. data/lib/palmade/cableguy/migrator.rb +124 -0
  30. data/lib/palmade/cableguy/templatebinding.rb +23 -16
  31. data/lib/palmade/cableguy/utils.rb +6 -7
  32. data/lib/palmade/cableguy/version.rb +1 -1
  33. data/lib/palmade/cableguy.rb +19 -34
  34. data/test/.cabling_values.yml +9 -0
  35. data/test/app/Cablefile +10 -0
  36. data/test/app/cabling/base/blog.rb +21 -0
  37. data/test/app/cabling/init.rb +16 -0
  38. data/test/app/config/templates/blog.yml +10 -0
  39. data/test/app_cabling_test.rb +33 -0
  40. data/test/boboot.rb +53 -0
  41. data/test/boot_test.rb +25 -0
  42. data/test/cablefile_test.rb +44 -0
  43. data/test/cabler_test.rb +45 -0
  44. data/test/cabling/base/blog.rb +17 -0
  45. data/test/cabling/init.rb +16 -0
  46. data/test/cabling_values_test.rb +24 -0
  47. data/test/cli_lock_test.rb +28 -0
  48. data/test/cli_test.rb +88 -0
  49. data/test/configure_test.rb +31 -0
  50. data/test/db_methods_test.rb +19 -0
  51. data/test/migrate_legacy_test.rb +34 -0
  52. data/test/migrate_test.rb +39 -0
  53. data/test/test_apply/config/blog.yml +10 -0
  54. data/test/test_helper.rb +81 -0
  55. metadata +93 -29
  56. data/Manifest +0 -19
  57. data/README +0 -1
  58. data/lib/palmade/cableguy/runner.rb +0 -44
@@ -1,115 +1,319 @@
1
+ require 'logger'
2
+
1
3
  module Palmade::Cableguy
2
4
  class Cabler
3
5
  include Constants
6
+ include CliHelper
7
+
8
+ APP_CABLING_PATH = 'cabling'
9
+
10
+ DEFAULT_OPTIONS = {
11
+ :target => :development,
12
+ :location => nil,
13
+ :path => nil,
14
+ :values_path => nil,
15
+ :apply_path => nil,
16
+ :templates_path => nil,
17
+ :logger => nil,
18
+ :save_db => false,
19
+ :unload_cabling => true,
20
+ :include_global_cabling => false
21
+ }
4
22
 
5
23
  attr_reader :app_root
6
- attr_reader :builds
24
+ attr_reader :app_group
25
+ attr_reader :options
26
+
7
27
  attr_reader :cabling_path
28
+ attr_reader :app_cabling_path
8
29
  attr_reader :target
9
30
  attr_reader :location
10
- attr_reader :database
11
- attr_reader :cabler
12
- attr_reader :logger
13
- attr_reader :options
14
- attr_reader :db_path
31
+ attr_reader :apply_path
32
+
33
+ attr_reader :values_path
34
+ attr_reader :cabling_values
35
+ attr_reader :templates_path
36
+
37
+ attr_reader :cablefile
15
38
  attr_reader :db
16
- attr_accessor :targets
17
- attr_accessor :group
39
+ attr_reader :save_db
40
+ attr_reader :logger
18
41
 
19
- def initialize(app_root, options)
20
- @options = options
42
+ attr_reader :builds
43
+ attr_reader :migrator
44
+ attr_reader :app_migrator
45
+
46
+ def initialize(app_root, options = { })
47
+ @options = DEFAULT_OPTIONS.merge(options)
21
48
  @app_root = app_root
49
+ @app_group = nil
50
+
22
51
  @cabling_path = @options[:path]
52
+ @app_cabling_path = File.join(@app_root, APP_CABLING_PATH)
53
+
23
54
  @target = @options[:target]
24
55
  @location = @options[:location]
56
+
57
+ unless @options[:apply_path].nil?
58
+ @apply_path = File.expand_path(@options[:apply_path])
59
+ end
60
+
61
+ @values_path = @options[:values_path]
62
+ @cabling_values = nil
63
+
64
+ @cablefile = nil
65
+
66
+ if @options[:templates_path].nil?
67
+ @templates_path = File.join(@app_root, DEFAULT_TEMPLATES_PATH)
68
+ else
69
+ @templates_path = File.expand_path(@options[:templates_path])
70
+ end
71
+
72
+ if options[:logger]
73
+ @logger = options[:logger]
74
+ else
75
+ @logger = create_logger
76
+ end
77
+
78
+ @db = nil
79
+ @save_db = nil
25
80
  @builds = nil
26
- @logger = Logger.new($stdout)
27
- @targets = [ :development ]
28
- @db_path = File.join(@cabling_path, DB_DIRECTORY, "#{@target}.#{DB_EXTENSION}")
29
81
 
82
+ @migrator = nil
83
+ @app_migrator = nil
84
+ end
85
+
86
+ def boot
30
87
  if @options[:verbose]
31
88
  @logger.level = Logger::DEBUG
32
89
  else
33
90
  @logger.level = Logger::WARN
34
91
  end
35
92
 
36
- @db = Palmade::Cableguy::DB.new(self)
37
- end
93
+ expand_cabling_path!
38
94
 
39
- def boot
40
- @database = @db.boot
95
+ @save_db = determine_save_db
96
+ @db = Palmade::Cableguy::DB.new(self, { :save_db => @save_db }).boot
97
+
98
+ load_cabling_values
99
+ load_cablefile
41
100
 
42
101
  self
43
102
  end
44
103
 
45
- def migrate
46
- init_file = File.join(@cabling_path, 'init.rb')
47
- require init_file if File.exist?(init_file)
104
+ def set_app_group(g)
105
+ # normalize group key, to be consistent everywhere
106
+ g = g.to_s unless g.is_a?(String)
107
+
108
+ @db.group(g)
109
+ @app_group = g
110
+ end
111
+ alias :group= :set_app_group
48
112
 
49
- say_with_time "Migrating..." do
50
- Migration.new(self).boot
113
+ def values
114
+ unless @cabling_values.nil?
115
+ @cabling_values.values
116
+ else
117
+ nil
51
118
  end
119
+ end
52
120
 
53
- say "Done!"
121
+ def determine_apply_path(opts = { })
122
+ if @apply_path.nil?
123
+ ap = @app_root
124
+ else
125
+ ap = @apply_path
126
+ end
127
+
128
+ if opts[:for_templates]
129
+ File.join(ap, DEPRECATED_DEFAULT_TARGET_PATH)
130
+ else
131
+ ap
132
+ end
54
133
  end
55
134
 
56
135
  def configure
57
- @configurator = CableConfigurator.new
58
- @configurator_path = File.join(@app_root, DEFAULT_CABLEGUY_PATH)
136
+ unless @db.migrated?
137
+ migrate
138
+ end
139
+
140
+ if @db.empty?
141
+ raise 'Empty config data from [%s], did you provide some cabling data?' % @cabling_path
142
+ end
59
143
 
60
- # checks for config/cableguy.rb
61
- if File.exists?(@configurator_path)
62
- @configurator.configure(@configurator_path)
144
+ if @cablefile.configured?
145
+ check_requirements
146
+ builds = build_setups
147
+ builds.each do |s|
148
+ s.configure(self)
149
+ end
63
150
  else
64
- raise MissingFile, "Required cableguy file (#{@configurator_path}) not found!"
151
+ raise 'Cablefile not configured or not loaded, configure will not work!'
65
152
  end
66
153
 
67
- check_requirements
154
+ self
155
+ end
156
+
157
+ def migrate
158
+ cabling_paths = determine_useable_cabling_paths
68
159
 
69
- build_setups.each do |s|
70
- s.configure(self, @cabling, @target)
160
+ unless cabling_paths.empty?
161
+ cabling_paths.each do |cp|
162
+ perform_migrate(cp)
163
+ end
71
164
  end
165
+
166
+ @db.migrated!
167
+
168
+ self
72
169
  end
73
170
 
74
- def check_requirements
75
- if @configurator.include?(:requirements)
76
- @configurator.requirements(self, @cabling, @target)
171
+ def app_migrate
172
+ @db.prepare_for_use
173
+
174
+ unless @app_cabling_path.nil?
175
+ if File.exist?(@app_cabling_path)
176
+ perform_migrate(@app_cabling_path)
177
+ end
77
178
  end
78
- end
79
179
 
80
- def say(message, subitem = false)
81
- puts "#{subitem ? " ->" : "--"} #{message}"
180
+ self
82
181
  end
83
182
 
84
- def say_with_time(message)
85
- say(message)
86
- result = nil
87
- time = Benchmark.measure { result = yield }
88
- say "%.4fs" % time.real, :subitem
89
- say("#{result} rows", :subitem) if result.is_a?(Integer)
90
- result
183
+ def cabling_migrate
184
+ @db.prepare_for_use
185
+
186
+ unless @cabling_path.nil?
187
+ if @cabling_path != @app_cabling_path && File.exists?(@cabling_path)
188
+ perform_migrate(@cabling_path)
189
+ end
190
+ end
191
+
192
+ self
91
193
  end
92
194
 
93
- def require_cables(path)
94
- if path =~ /\//
95
- require(path)
96
- else
97
- require(File.join(@app_root, DEFAULT_CABLES_PATH, path))
195
+ def remigrate
196
+ if @db.migrated?
197
+ @db.reset
98
198
  end
199
+
200
+ migrate
99
201
  end
100
202
 
101
203
  protected
102
204
 
205
+ def perform_migrate(cp)
206
+ @db.prepare_for_use
207
+
208
+ if !cp.nil? && File.exists?(cp)
209
+ @migrator = Palmade::Cableguy::Migrator.boot(self, cp, :unload_cabling => @options[:unload_cabling])
210
+ @migrator.run!
211
+ end
212
+
213
+ @migrator
214
+ end
215
+
216
+ def determine_useable_cabling_paths
217
+ cabling_paths = [ ]
218
+
219
+ if !@app_cabling_path.nil? && File.exist?(@app_cabling_path)
220
+ cabling_paths << @app_cabling_path
221
+ end
222
+
223
+ if cabling_paths.empty? || @options[:include_global_cabling]
224
+ if !@cabling_path.nil? && @cabling_path != @app_cabling_path && File.exists?(@cabling_path)
225
+ cabling_paths << @cabling_path
226
+ end
227
+ end
228
+
229
+ cabling_paths
230
+ end
231
+
232
+ def expand_cabling_path!
233
+ unless @cabling_path.nil?
234
+ cpath = File.expand_path(@cabling_path)
235
+
236
+ loop do
237
+ if File.symlink?(cpath)
238
+ cpath = File.readlink(cpath)
239
+ else
240
+ break
241
+ end
242
+ end
243
+
244
+ @cabling_path = cpath
245
+ end
246
+
247
+ @cabling_path
248
+ end
249
+
250
+ def determine_save_db
251
+ save_db = nil
252
+
253
+ if @options[:save_db]
254
+ if @options[:save_db] === true
255
+ use_cabling_path = nil
256
+
257
+ cabling_paths = determine_useable_cabling_paths
258
+ unless cabling_paths.empty?
259
+ use_cabling_path = cabling_paths.first
260
+ end
261
+
262
+ unless use_cabling_path.nil?
263
+ if @location.nil?
264
+ save_db = File.join(use_cabling_path, DB_DIRECTORY, '%s.%s' % [ @target, DB_EXTENSION ])
265
+ else
266
+ save_db = File.join(use_cabling_path, DB_DIRECTORY, '%s_%s.%s' % [ @target, @location, DB_EXTENSION ])
267
+ end
268
+ end
269
+ else
270
+ save_db = @options[:save_db]
271
+ end
272
+ end
273
+
274
+ save_db
275
+ end
276
+
277
+ def load_cablefile
278
+ @cablefile = Cablefile.parse!(self)
279
+
280
+ if @app_root != @cablefile.app_root
281
+ @app_root = @cablefile.app_root
282
+ end
283
+
284
+ if @cablefile.configured?
285
+ @cablefile.cabling(self, @cablefile, @target)
286
+ end
287
+ end
288
+
289
+ def load_cabling_values
290
+ if !@values_path.nil? && File.exist?(@values_path)
291
+ @cabling_values = Palmade::Cableguy::CablingValues.load_cabling_values(self, @values_path)
292
+ else
293
+ @cabling_values = Palmade::Cableguy::CablingValues.new_empty(self)
294
+ end
295
+ end
296
+
103
297
  def build_setups
298
+ Builders.load_all_builders
299
+
104
300
  if @builds.nil?
105
- @configurator.setup_cabling(self, @cabling, @target)
106
- @builds = @configurator.setups.collect do |s|
301
+ @builds = @cablefile.setups.collect do |s|
107
302
  Cable.build(s[0], *s[1], &s[2])
108
303
  end
109
304
  else
110
305
  @builds
111
306
  end
112
307
  end
308
+
309
+ def check_requirements
310
+ if @cablefile.include?(:requirements)
311
+ @cablefile.requirements(self, @cablefile, @target)
312
+ end
313
+ end
314
+
315
+ def create_logger
316
+ Logger.new($stdout)
317
+ end
113
318
  end
114
319
  end
115
-
@@ -0,0 +1,54 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+
4
+ module Palmade::Cableguy
5
+ class CablingValues
6
+ attr_reader :cabler
7
+ attr_reader :values
8
+
9
+ def self.load_cabling_values(cabler, path)
10
+ self.new(cabler).load_values(path)
11
+ end
12
+
13
+ def self.new_empty(cabler)
14
+ self.new(cabler).empty!
15
+ end
16
+
17
+ def initialize(cabler)
18
+ @cabler = cabler
19
+ @values = nil
20
+ end
21
+
22
+ def load_values(path)
23
+ vf_contents = File.read(path)
24
+ vf_contents = ERB.new(vf_contents).result(binding)
25
+
26
+ parsed_vf = YAML.load(vf_contents)
27
+ if parsed_vf.nil? || parsed_vf == false
28
+ @values = new_values
29
+ else
30
+ @values = new_values(parsed_vf)
31
+ end
32
+
33
+ self
34
+ end
35
+
36
+ def empty!
37
+ @values = new_values
38
+
39
+ self
40
+ end
41
+
42
+ protected
43
+
44
+ def new_values(vals = nil)
45
+ if vals.nil?
46
+ h = Hash.new
47
+ else
48
+ h = Hash.new.update(vals)
49
+ end
50
+
51
+ h
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,232 @@
1
+ require 'thor'
2
+ require 'yaml'
3
+
4
+ module Palmade
5
+ module Cableguy
6
+ class CLI < Thor
7
+ include Constants
8
+
9
+ class_option :target, :default => nil
10
+ class_option :location, :default => nil
11
+
12
+ class_option :path, :default => nil
13
+ class_option :values_path, :default => nil
14
+ class_option :apply_path, :default => nil
15
+ class_option :templates_path, :default => nil
16
+
17
+ class_option :lock_file, :default => nil
18
+ class_option :unlock, :default => false, :type => :boolean
19
+ class_option :nolock, :default => false, :type => :boolean
20
+
21
+ class_option :app_root, :default => nil, :type => :string
22
+ class_option :include_global_cabling, :default => false, :type => :boolean
23
+
24
+ class_option :verbose, :default => false, :type => :boolean
25
+ class_option :silent, :default => false, :type => :boolean
26
+
27
+ class_option :save_db
28
+
29
+ attr_accessor :raise_error
30
+
31
+ desc 'configure', 'start configuring!'
32
+ def configure
33
+ cabler.configure
34
+ end
35
+
36
+ desc 'migrate', 'migrates data into sqlite'
37
+ def migrate
38
+ cabler(:save_db => true).migrate
39
+ end
40
+
41
+ desc 'version', 'show version'
42
+ def version
43
+ say Palmade::Cableguy::VERSION
44
+ end
45
+
46
+ no_tasks do
47
+ def app_path
48
+ if options[:app_root]
49
+ File.expand_path(options[:app_root])
50
+ else
51
+ File.expand_path(Dir.pwd)
52
+ end
53
+ end
54
+
55
+ def lock_file_path
56
+ file_path = options[:lock_file]
57
+
58
+ if file_path.nil?
59
+ file_path = File.join(app_path, DEFAULT_LOCK_FILE)
60
+
61
+ if !File.exists?(file_path) && File.exists?(DEFAULT_LOCK_PATH)
62
+ file_path = DEFAULT_LOCK_PATH
63
+ end
64
+ end
65
+
66
+ file_path = File.expand_path(file_path)
67
+ end
68
+
69
+ def cabler(opts = { })
70
+ if defined?(@cabler) && !@cabler.nil?
71
+ @cabler
72
+ else
73
+ lock_opts = prepare_lock_file(opts)
74
+ opts = opts.merge(lock_opts)
75
+ opts = opts.merge(Utils.symbolize_keys(options))
76
+
77
+ check_if_cabling_path_exists!(opts)
78
+ check_if_cabling_values_exists!(opts)
79
+
80
+ if opts[:save_db] == 'save_db'
81
+ opts[:save_db] = true
82
+ end
83
+
84
+ @cabler = Palmade::Cableguy.boot_cabler(app_path, opts)
85
+ end
86
+ end
87
+
88
+ def prepare_lock_file(opts = { })
89
+ default_lock_opts = { :target => DEFAULT_TARGET, :location => DEFAULT_LOCATION }
90
+
91
+ if options[:nolock]
92
+ lock_opts = default_lock_opts
93
+ else
94
+ lfp = lock_file_path
95
+
96
+ if !File.exists?(lfp) || options[:unlock]
97
+ lock_opts = default_lock_opts.dup
98
+
99
+ if !options[:target].nil? && !options[:target].empty?
100
+ lock_opts[:target] = options[:target]
101
+ end
102
+
103
+ if !options[:location].nil? && !options[:location].empty?
104
+ lock_opts[:location] = options[:location]
105
+ end
106
+
107
+ unless opts[:lock_no_persist]
108
+ File.open(lfp, 'w') { |file| file.write(YAML.dump(lock_opts)) }
109
+ end
110
+ else
111
+ lock_opts = YAML.load_file(lfp)
112
+ check_locked_values(lock_opts)
113
+ end
114
+ end
115
+
116
+ lock_opts
117
+ end
118
+
119
+ def check_locked_values(lock_opts)
120
+ if !options[:target].nil? && !options[:target].empty?
121
+ if lock_opts[:target] != options[:target]
122
+ safety_message(:target, lock_opts)
123
+
124
+ if raise_error
125
+ raise 'Lock target not the same (%s != %s)' % [ lock_opts[:target], options[:target] ]
126
+ else
127
+ exit 1
128
+ end
129
+ end
130
+ end
131
+
132
+ if !options[:location].nil? && !options[:location].empty?
133
+ if lock_opts[:location] != options[:location]
134
+ safety_message(:location, lock_opts)
135
+
136
+ if raise_error
137
+ raise 'Lock location not the same (%s != %s)' % [ lock_opts[:location], options[:location] ]
138
+ else
139
+ exit 2
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ def safety_message(val, lock_opts)
146
+ lockfile_error_message = <<-error_message
147
+ Lockfile has a setting #{val} with value '#{lock_opts[val]}' \
148
+ and it is not equal to the specified #{val} '#{options[val]}'. \
149
+ This prevents accidental overriding of the cabling database. \
150
+ You can fix this by running with cabling migrate --unlock"
151
+ error_message
152
+
153
+ say_with_format(lockfile_error_message, :red)
154
+ end
155
+
156
+ def say_with_format(msg, color = nil)
157
+ unless options[:silent]
158
+ say("-- #{msg}", color)
159
+ end
160
+ end
161
+
162
+ def check_if_cabling_values_exists!(opts)
163
+ if opts[:values_path].nil?
164
+ vp = File.expand_path(DEFAULT_CABLING_VALUES_PATH)
165
+
166
+ if File.exists?(vp)
167
+ opts[:values_path] = vp
168
+ end
169
+ else
170
+ vp = File.expand_path(opts[:values_path])
171
+
172
+ if File.exists?(vp)
173
+ opts[:values_path] = vp
174
+ else
175
+ say_with_format 'Cabling values path (%s) does not exists' % vp, :red
176
+
177
+ if raise_error
178
+ raise 'Cabling values path does not exists'
179
+ else
180
+ exit 3
181
+ end
182
+ end
183
+ end
184
+
185
+ opts[:values_path]
186
+ end
187
+
188
+ def check_if_cabling_path_exists!(opts)
189
+ if opts[:path].nil?
190
+ if ENV.include?('CABLING_PATH')
191
+ path = ENV['CABLING_PATH']
192
+ else
193
+ path = DEFAULT_CABLING_PATH
194
+ end
195
+ else
196
+ path = opts[:path]
197
+ end
198
+
199
+ if path.empty?
200
+ path = nil
201
+ else
202
+ path = File.expand_path(path)
203
+ end
204
+
205
+ if !path.nil? && File.exists?(path)
206
+ loop do
207
+ if File.symlink?(path)
208
+ path = File.readlink(path)
209
+ else
210
+ break
211
+ end
212
+ end
213
+
214
+ opts[:path] = path
215
+ elsif !opts[:path].nil?
216
+ say_with_format 'Cabling path (%s) does not exists' % opts[:path], :red
217
+
218
+ if raise_error
219
+ raise 'Cabling path does not exists'
220
+ else
221
+ exit 3
222
+ end
223
+ else
224
+ # ignore no cabling path!
225
+ end
226
+ end
227
+ end
228
+
229
+ default_task :configure
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,18 @@
1
+ require 'benchmark'
2
+
3
+ module Palmade::Cableguy
4
+ module CliHelper
5
+ def say(message, subitem = false)
6
+ puts "#{subitem ? " ->" : "--"} #{message}"
7
+ end
8
+
9
+ def say_with_time(message)
10
+ say(message)
11
+ result = nil
12
+ time = Benchmark.measure { result = yield }
13
+ say "%.4fs" % time.real, :subitem
14
+ say("#{result} rows", :subitem) if result.is_a?(Integer)
15
+ result
16
+ end
17
+ end
18
+ end