detroit 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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