detroit 0.3.0 → 0.4.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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.index +59 -0
  3. data/EXAMPLE.md +66 -64
  4. data/{HISTORY.rdoc → HISTORY.md} +32 -5
  5. data/{COPYING.rdoc → LICENSE.txt} +0 -0
  6. data/README.md +142 -0
  7. data/bin/detroit +1 -1
  8. data/lib/detroit.rb +112 -40
  9. data/lib/detroit.yml +44 -29
  10. data/lib/detroit/assembly.rb +49 -193
  11. data/lib/detroit/basic_tool.rb +200 -0
  12. data/lib/detroit/basic_utils.rb +66 -0
  13. data/lib/detroit/core_ext.rb +2 -136
  14. data/lib/detroit/{tool/core_ext → core_ext}/facets.rb +3 -0
  15. data/lib/detroit/{tool/core_ext → core_ext}/filetest.rb +0 -0
  16. data/lib/detroit/{tool/core_ext → core_ext}/shell_extensions.rb +0 -0
  17. data/lib/detroit/{tool/core_ext → core_ext}/to_actual_filename.rb +0 -0
  18. data/lib/detroit/{tool/core_ext → core_ext}/to_console.rb +1 -0
  19. data/lib/detroit/{tool/core_ext → core_ext}/to_list.rb +0 -0
  20. data/lib/detroit/{tool/core_ext → core_ext}/to_yamlfrag.rb +0 -0
  21. data/lib/detroit/{tool/core_ext → core_ext}/unfold_paragraphs.rb +0 -0
  22. data/lib/detroit/{tool/email_utils.rb → email_utils.rb} +3 -1
  23. data/lib/detroit/exec.rb +55 -0
  24. data/lib/detroit/project.rb +134 -0
  25. data/lib/detroit/ruby_utils.rb +29 -0
  26. data/lib/detroit/{tool/shell_utils.rb → shell_utils.rb} +10 -5
  27. data/lib/detroit/toolchain.rb +6 -0
  28. data/lib/detroit/toolchain/cli.rb +320 -0
  29. data/lib/detroit/toolchain/config.rb +223 -0
  30. data/lib/detroit/toolchain/runner.rb +678 -0
  31. data/lib/detroit/toolchain/script.rb +248 -0
  32. data/lib/detroit/toolchain/worker.rb +84 -0
  33. data/man/detroit.1 +116 -0
  34. data/man/detroit.1.html +171 -0
  35. data/man/detroit.1.ronn +99 -0
  36. metadata +90 -51
  37. data/.ruby +0 -44
  38. data/README.rdoc +0 -132
  39. data/lib/detroit/application.rb +0 -463
  40. data/lib/detroit/assembly_system.rb +0 -80
  41. data/lib/detroit/config.rb +0 -203
  42. data/lib/detroit/control.rb +0 -129
  43. data/lib/detroit/custom.rb +0 -102
  44. data/lib/detroit/dsl.rb +0 -55
  45. data/lib/detroit/service.rb +0 -78
  46. data/lib/detroit/standard_assembly.rb +0 -51
  47. data/lib/detroit/tool.rb +0 -295
  48. data/lib/detroit/tool/core_ext.rb +0 -3
  49. data/lib/detroit/tool/project_utils.rb +0 -41
@@ -1,463 +0,0 @@
1
- module Detroit
2
-
3
- # The default assembly system to use.
4
- DEFAULT_ASSEMBLY_SYSTEM = :standard
5
-
6
- # Application class is the main controller class for running
7
- # a session of Detroit.
8
- #--
9
- # TODO: Rename Application to `Session`?
10
- #++
11
- class Application
12
-
13
- # Options (generally from #cli).
14
- attr :options
15
-
16
- # Create a new Detroit Application instance.
17
- def initialize(options)
18
- @options = options
19
- #load_standard_plugins
20
-
21
- self.skip = options[:skip]
22
- self.quiet = options[:quiet]
23
- self.system = options[:system]
24
- self.multitask = options[:multitask]
25
- self.assemblies = options[:assemblies]
26
- end
27
-
28
- # Quiet mode?
29
- def quiet?
30
- @quiet
31
- end
32
-
33
- # Set quiet mode.
34
- def quiet=(boolean)
35
- @quiet = !!boolean
36
- end
37
-
38
- # List of service names to skip.
39
- def skip
40
- @skip
41
- end
42
-
43
- # Set skip list.
44
- def skip=(list)
45
- @skip = list.to_list.map{ |s| s.downcase }
46
- end
47
-
48
- # The selected assembly system.
49
- def system
50
- @system
51
- end
52
-
53
- # Set assembly system to use.
54
- def system=(name)
55
- @system = (name || DEFAULT_ASSEMBLY_SYSTEM)
56
- end
57
-
58
- # Alias for #system.
59
- alias :assembly_system :system
60
-
61
- # Multitask mode?
62
- def multitask?
63
- @multitask
64
- end
65
-
66
- # Set multi-task mode.
67
- def multitask=(boolean)
68
- if boolean && !defined?(Parallel)
69
- puts "Parallel gem must be installed to multitask."
70
- @multitask = false
71
- else
72
- @multitask = boolean
73
- end
74
- end
75
-
76
- # List of assembly files to use.
77
- def assemblies
78
- @assemblies
79
- end
80
-
81
- #
82
- def assemblies=(files)
83
- @assemblies = files
84
- end
85
-
86
- # Detroit configuration.
87
- def config
88
- @config ||= Detroit::Config.new(assemblies)
89
- end
90
-
91
- # Provides access to the Project instance via `Detroit.project` class method.
92
- def project
93
- @project ||= POM::Project.find
94
- end
95
-
96
- # User-defined service defaults.
97
- #
98
- # Returns Hash of service defaults.
99
- def defaults
100
- config.defaults
101
- end
102
-
103
- # # Load standard plugins.
104
- # def load_standard_plugins
105
- # #::Plugin.find("detroit/*.rb").each do |file|
106
- # Detroit.standard_plugins.each do |file|
107
- # begin
108
- # require(file)
109
- # rescue => err
110
- # $stderr.puts err if $DEBUG
111
- # end
112
- # end
113
- # end
114
-
115
- # Display detailed help for a given tool.
116
- def display_help(name)
117
- if not Detroit.tools.key?(name)
118
- config.load_plugin(name)
119
- end
120
- tool = Detroit.tools[name]
121
- if tool.respond_to?(:man_page)
122
- Kernel.system "man #{tool.man_page}"
123
- else
124
- puts "Sorry, no detailed help available for `#{name}'."
125
- end
126
- end
127
-
128
- # Generates a configuration template for particular tool.
129
- # This is only used for reference purposes.
130
- def config_template(name)
131
- if not Detroit.tools.key?(name)
132
- config.load_plugin(name)
133
- end
134
- list = {name => Detroit.tools[name]}
135
- cfg = {}
136
- list.each do |srv_name, srv_class|
137
- attrs = srv_class.options #instance_methods.select{ |m| m.to_s =~ /\w+=$/ && !%w{taguri=}.include?(m.to_s) }
138
- atcfg = attrs.inject({}){ |h, m| h[m.to_s.chomp('=')] = nil; h }
139
- atcfg['service'] = srv_class.basename.downcase
140
- atcfg['active'] = false
141
- cfg[srv_name] = atcfg
142
- end
143
- cfg
144
- end
145
-
146
- # TODO: Setup all services, then ween out inactive ones?
147
- #def services
148
- #end
149
-
150
- # Active services are services defined in assembly files and do not
151
- # have their active setting turned off.
152
- #
153
- # Returns Array of active services.
154
- def active_services
155
- @active_services ||= (
156
- list = []
157
-
158
- config.each do |key, opts|
159
- next unless opts
160
- next unless opts['active'] != false
161
- next if skip.include?(key.to_s)
162
-
163
- tool_name = (
164
- opts.delete('tool') ||
165
- opts.delete('service') ||
166
- key
167
- ).to_s.downcase
168
-
169
- unless Detroit.tools.key?(tool_name)
170
- config.load_plugin(tool_name)
171
- end
172
-
173
- tool_class = Detroit.tools[tool_name]
174
-
175
- abort "Unknown tool `#{tool_name}'." unless tool_class
176
-
177
- if tool_class.available? #(project)
178
- #opts = inject_environment(opts) # TODO: DEPRECATE
179
- options = defaults[tool_name.downcase].to_h
180
- options = options.merge(common_tool_options)
181
- options = options.merge(opts)
182
-
183
- list << Service.new(key, tool_class, options) #script,
184
- #else
185
- # warn "Service #{tool_class} is not available."
186
- end
187
- end
188
-
189
- # sorting here trickles down to processing later
190
- #list = list.sort_by{ |s| s.priority || 0 }
191
-
192
- list
193
- )
194
- end
195
-
196
- # Change direectory to project root and run.
197
- def start(stop)
198
- Dir.chdir(project.root) do # change into project directory
199
- run(stop)
200
- end
201
- end
202
-
203
- # Run up to the specified +track_and_stop+.
204
- def run(track_and_stop)
205
- raise "Malformed destination -- #{track_and_stop}" unless /^\w+\:{0,1}\w+$/ =~ track_and_stop
206
-
207
- if track_and_stop
208
- name, stop = track_and_stop.split(':')
209
- name, stop = 'main', name unless stop
210
- else
211
- name = 'main'
212
- stop = nil
213
- end
214
-
215
- name = name.to_sym
216
- stop = stop.to_sym if stop
217
-
218
- assm = Detroit.assembly_systems[system]
219
-
220
- raise "Unkown assembly system `#{system}'" unless assm
221
-
222
- track = assm.get_track(name, stop)
223
-
224
- #if stop
225
- # system = track.route_with_stop(stop)
226
- # raise "Unknown stop -- #{stop}" unless system
227
-
228
- if not track.include?(stop)
229
- #overview
230
- $stderr.puts "Unknown stop for track `#{name}'."
231
- exit 0
232
- end
233
-
234
- @destination = stop
235
-
236
- # TODO: Using #preconfigure as part of the protocol should probably change.
237
-
238
- # prime the services (so as to fail early)
239
- active_services.each do |srv|
240
- srv.preconfigure if srv.respond_to?("preconfigure")
241
- end
242
-
243
- status_header(*header_message)
244
-
245
- start_time = Time.now
246
-
247
- track.each do |run_stop|
248
- next if skip.include?("#{run_stop}") # TODO: Should we really allow skipping stops?
249
- service_hooks(name, ('pre_' + run_stop.to_s).to_sym)
250
- service_calls(name, ('pre_' + run_stop.to_s).to_sym)
251
- service_calls(name, run_stop)
252
- service_calls(name, ('aft_' + run_stop.to_s).to_sym)
253
- service_hooks(name, ('aft_' + run_stop.to_s).to_sym)
254
- break if stop == run_stop
255
- end
256
-
257
- stop_time = Time.now
258
- puts "\nFinished in #{stop_time - start_time} seconds." unless quiet?
259
- end
260
-
261
- # TODO: Deprecate service hooks?
262
-
263
- #
264
- # Execute service hook for given track and destination.
265
- #
266
- # @todo Currently only stop counts, maybe add track subdirs.
267
- #
268
- def service_hooks(track, stop)
269
- #hook = dir + ("#{track}/#{stop}.rb".gsub('_', '-'))
270
- dir = hook_directory
271
- return unless dir
272
- name = stop.to_s.gsub('_', '-')
273
- hook = dir + "#{name}.rb"
274
- if hook.exist?
275
- status_line("hook", name.capitalize)
276
- hook_tool.instance_eval(hook.read)
277
- end
278
- end
279
-
280
- # Returns a project's Detroit hooks directory.
281
- def hook_directory
282
- project.root.glob("{.,}detroit/hooks").first
283
- end
284
-
285
- #
286
- def hook_tool
287
- @hook_tool ||= Tool.new(common_tool_options)
288
- end
289
-
290
- # TODO: Do we need verbose?
291
- def common_tool_options
292
- {
293
- 'project' => project,
294
- 'trial' => options[:trial],
295
- 'trace' => options[:trace],
296
- 'quiet' => options[:quiet],
297
- 'force' => options[:force],
298
- 'verbose' => options[:verbose]
299
- }
300
- end
301
-
302
- # Make service calls.
303
- #
304
- # This groups services by priority b/c groups of the same priority can be run
305
- # in parallel if the multitask option is on.
306
- def service_calls(track, stop)
307
- prioritized_services = active_services.group_by{ |srv| srv.priority }.sort_by{ |k,v| k }
308
- prioritized_services.each do |priority, services|
309
- ## remove any services specified by the --skip option on the comamndline
310
- #services = services.reject{ |srv| skip.include?(srv.key.to_s) }
311
- ## only servies that are on the track
312
- services = services.select{ |srv| srv.tracks.nil? or srv.tracks.include?(track.to_s) }
313
-
314
- tasklist = services.map{ |srv| [srv, track, stop] }
315
- if multitask?
316
- results = Parallel.in_processes(tasklist.size) do |i|
317
- run_a_service(*tasklist[i])
318
- end
319
- else
320
- tasklist.each do |args|
321
- run_a_service(*args)
322
- end
323
- end
324
- end
325
- end
326
-
327
- #
328
- # Run a service given the service, track and stop name.
329
- #
330
- def run_a_service(srv, track, stop)
331
- # run if the service supports the track and stop.
332
- #if srv.respond_to?("#{track}_#{stop}")
333
- if srv.stop?(stop, @destination)
334
- if options[:trace] #options[:verbose]
335
- #status_line("#{srv.key.to_s} (#{srv.class}##{track}_#{stop})", stop.to_s.gsub('_', '-').capitalize)
336
- status_line("#{srv.key.to_s} (#{srv.class}##{stop})", stop.to_s.gsub('_', '-').capitalize)
337
- else
338
- status_line("#{srv.key.to_s}", stop.to_s.gsub('_', '-').capitalize)
339
- end
340
- #srv.__send__("#{track}_#{stop}")
341
- srv.invoke(stop, @destination)
342
- end
343
- end
344
-
345
- # --- Print Methods -------------------------------------------------------
346
-
347
- def header_message
348
- if multitask?
349
- ["#{project.metadata.title} v#{project.metadata.version} [M]", "#{project.root}"]
350
- else
351
- ["#{project.metadata.title} v#{project.metadata.version}", "#{project.root}"]
352
- end
353
- end
354
-
355
- # Print a status header, which consists of project name and version on the
356
- # left and stop location on the right.
357
- #
358
- def status_header(left, right='')
359
- left, right = left.to_s, right.to_s
360
- #left.color = 'blue'
361
- #right.color = 'magenta'
362
- unless quiet?
363
- puts
364
- print_header(left, right)
365
- #puts "=" * io.screen_width
366
- end
367
- end
368
-
369
- # Print a status line, which consists of service name on the left
370
- # and stop name on the right.
371
- #
372
- def status_line(left, right='')
373
- left, right = left.to_s, right.to_s
374
- #left.color = 'blue'
375
- #right.color = 'magenta'
376
- unless quiet?
377
- puts
378
- #puts "-" * io.screen_width
379
- print_phase(left, right)
380
- #puts "-" * io.screen_width
381
- #puts
382
- end
383
- end
384
-
385
- #
386
- def display_action(action_item)
387
- phase, service, action, parameters = *action_item
388
- puts " %-10s %-10s %-10s" % [phase.to_s.capitalize, service.service_title, action]
389
- #status_line(service.service_title, phase.to_s.capitalize)
390
- end
391
-
392
- #
393
- def print_header(left, right)
394
- if $ansi #ANSI::SUPPORTED
395
- printline('', '', :pad=>1, :sep=>' ', :style=>[:negative, :bold], :left=>[:bold], :right=>[:bold])
396
- printline(left, right, :pad=>2, :sep=>' ', :style=>[:negative, :bold], :left=>[:bold], :right=>[:bold])
397
- printline('', '', :pad=>1, :sep=>' ', :style=>[:negative, :bold], :left=>[:bold], :right=>[:bold])
398
- else
399
- printline(left, right, :pad=>2, :sep=>'=')
400
- end
401
- end
402
-
403
- #
404
- def print_phase(left, right)
405
- if $ansi #ANSI::SUPPORTED
406
- printline(left, right, :pad=>2, :sep=>' ', :style=>[:on_white, :black, :bold], :left=>[:bold], :right=>[:bold])
407
- else
408
- printline(left, right, :pad=>2, :sep=>'-')
409
- end
410
- end
411
-
412
- #
413
- def printline(left, right='', options={})
414
- return if quiet?
415
-
416
- separator = options[:seperator] || options[:sep] || ' '
417
- padding = options[:padding] || options[:pad] || 0
418
-
419
- left, right = left.to_s, right.to_s
420
-
421
- left_size = left.size
422
- right_size = right.size
423
-
424
- #left = colorize(left)
425
- #right = colorize(right)
426
-
427
- l = padding
428
- r = -(right_size + padding)
429
-
430
- style = options[:style] || []
431
- lstyle = options[:left] || []
432
- rstyle = options[:right] || []
433
-
434
- left = lstyle.inject(left) { |s, c| ansize(s, c) }
435
- right = rstyle.inject(right){ |s, c| ansize(s, c) }
436
-
437
- line = separator * screen_width
438
- line[l, left_size] = left if left_size != 0
439
- line[r, right_size] = right if right_size != 0
440
-
441
- line = style.inject(line){ |s, c| ansize(s, c) }
442
-
443
- puts line + ansize('', :clear)
444
- end
445
-
446
- #
447
- def ansize(text, code)
448
- #return text unless text.color
449
- if RUBY_PLATFORM =~ /win/
450
- text.to_s
451
- else
452
- ANSI::Code.send(code.to_sym) + text
453
- end
454
- end
455
-
456
- #
457
- def screen_width
458
- ANSI::Terminal.terminal_width
459
- end
460
-
461
- end
462
-
463
- end #module Detroit