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,80 +0,0 @@
1
- module Detroit
2
-
3
- # All assemblies and tracks have a maintenance sub-track.
4
- # For this reason stop names `reset`, `clean` and `purge`
5
- # are reserved names and MUST not be used as stop names
6
- # in defining custom lines.
7
- MAINTENANCE_TRACK = [:reset, :clean, :purge]
8
-
9
- # Returns Hash of name and Circuit instance pairs.
10
- def self.assembly_systems
11
- @assembly_system ||= {}
12
- end
13
-
14
- # Define a new assembly system.
15
- def self.assembly_system(name, &block)
16
- assembly_systems[name.to_sym] = AssemblySystem.new(name, &block)
17
- end
18
-
19
- # The AssemblySystem class encapsulates a set of interrelated
20
- # assembly lines, or _tracks_.
21
- class AssemblySystem
22
-
23
- # Name of the assembly system.
24
- attr :name
25
-
26
- # Returns a Hash of track names mapped to list of stops.
27
- attr :lines
28
-
29
- # Lines are also called `tracks`.
30
- alias_method :tracks, :lines
31
-
32
- # Create a new instance.
33
- def initialize(name, &block)
34
- @name = name.to_sym
35
- @lines = {:maintenance => MAINTENANCE_TRACK}
36
- instance_eval(&block) if block
37
- end
38
-
39
- # Define an assembly line.
40
- def line(name, *stops)
41
- if stops.empty?
42
- @lines[name.to_sym]
43
- else
44
- @lines[name.to_sym] = stops.map{ |s| s.to_sym }
45
- end
46
- end
47
-
48
- # Lines are also called tracks.
49
- alias_method :track, :line
50
-
51
- # Lookup track by name and (optional) stop. If the stop belongs
52
- # to the maintenance sub-track then the maintenance sub-track will
53
- # be returned instead of the track itself.
54
- #
55
- # The Application class uses this to simplify track lookup.
56
- def get_track(name, stop=nil)
57
- name = name.to_sym
58
- if stop
59
- stop = stop.to_sym
60
- if MAINTENANCE_TRACK.include?(stop.to_sym)
61
- track = MAINTENANCE_TRACK
62
- else
63
- track = tracks[name]
64
- raise "Unknown track `#{name}'." unless track
65
- unless track.include?(stop)
66
- raise "Unknown stop `#{stop}` for track `#{name}'."
67
- end
68
- end
69
- else
70
- track = tracks[name]
71
- end
72
- track
73
- end
74
-
75
- # Did I mention that `line` and `track` are synonyms?
76
- alias_method :get_line, :get_track
77
-
78
- end
79
-
80
- end
@@ -1,203 +0,0 @@
1
- module Detroit
2
-
3
- # Detroit configuration. Configuration comes from a main +Routine+
4
- # and/or +.routine+ files.
5
- class Config
6
- #instance_methods.each{ |m| private m unless /^__/ =~ m.to_s }
7
-
8
- # Configuration directory name (most likely a hidden "dot" directory).
9
- DIRECTORY = "detroit"
10
-
11
- # File identifier used to find a project's Assembly(s).
12
- FILE_EXTENSION = "assembly"
13
-
14
- # Current POM::Project object.
15
- #attr :project
16
-
17
- # The list of a project's assembly files.
18
- #
19
- # @return [Array<String>] routine files
20
- attr :assemblies
21
-
22
- # Service configurations from Assembly or *.assembly files.
23
- #
24
- # @return [Hash] service settings
25
- attr :services
26
-
27
- # Service defaults. This is a mapping of service names to
28
- # default settings. Very useful for when using the same
29
- # service more than once.
30
- #
31
- # @return [Hash] default settings
32
- attr :defaults
33
-
34
- #
35
- def initialize(assembly_files=nil)
36
- if assembly_files && !assembly_files.empty?
37
- @assembly_filenames = assembly_files
38
- else
39
- @assembly_filenames = nil
40
- end
41
-
42
- @assemblies = {}
43
- @services = {}
44
- @defaults = {}
45
-
46
- @loaded_plugins = {}
47
-
48
- load_plugins
49
- load_defaults
50
- load_assemblies
51
- end
52
-
53
- #--
54
- # TODO: Use this, or pass in via initialize?
55
- #++
56
- def project
57
- Detroit.project
58
- end
59
-
60
- # Load a plugin.
61
- def load_plugin(name)
62
- @loaded_plugins[name] ||= (
63
- begin
64
- require "detroit-#{name}"
65
- rescue LoadError => e
66
- $stderr.puts "ERROR: #{e.message.capitalize}"
67
- $stderr.puts " Perhaps `gem install detroit-#{name}`?"
68
- exit -1
69
- end
70
- name # true ?
71
- )
72
- end
73
-
74
- # Pre-load plugins using `.detroit/plugins.rb`.
75
- def load_plugins
76
- if file = project.root.glob('{.,}#{DIRECTORY}/plugins{,.rb}').first
77
- require file
78
- else
79
- self.defaults = {}
80
- end
81
- end
82
-
83
- # Load defaults from `.detroit/defaults.yml`.
84
- def load_defaults
85
- if file = project.root.glob('{.,}#{DIRECTORY}/defaults{,.yml,.yaml}').first
86
- self.defaults = YAML.load(File.new(file))
87
- else
88
- self.defaults = {}
89
- end
90
- end
91
-
92
- #
93
- def load_assemblies
94
- assembly_filenames.each do |file|
95
- load_assembly_file(file)
96
- end
97
- end
98
-
99
- #
100
- def load_assembly_file(file)
101
- @assemblies[file] = Assembly.load(File.new(file))
102
- @services.merge!(assemblies[file].services)
103
- end
104
-
105
- # Set defaults.
106
- def defaults=(hash)
107
- @defaults = hash.to_h
108
- end
109
-
110
- # If a `Assembly` or `.assembly` file exists, then it is returned. Otherwise
111
- # all `*.assembly` files are loaded. To load `*.assembly` files from another
112
- # directory add the directory to config options file.
113
- def assembly_filenames
114
- @assembly_filenames ||= (
115
- files = []
116
- ## match 'Assembly' or '.assembly' file
117
- files = project.root.glob("{,.,*.}#{FILE_EXTENSION}{,.rb,.yml,.yaml}", :casefold)
118
- ## only files
119
- files = files.select{ |f| File.file?(f) }
120
- ##
121
- if files.empty?
122
- ## match '.detroit/*.assembly' or 'detroit/*.assembly'
123
- files += project.root.glob("{,.}#{DIRECTORY}/*.#{FILE_EXTENSION}", :casefold)
124
- ## match 'task/*.assembly' (OLD SCHOOL)
125
- files += project.root.glob("{task,tasks}/*.#{FILE_EXTENSION}", :casefold)
126
- ## only files
127
- files = files.select{ |f| File.file?(f) }
128
- end
129
- files
130
- )
131
- end
132
-
133
- #
134
- def each(&block)
135
- services.each(&block)
136
- end
137
-
138
- #
139
- def size
140
- services.size
141
- end
142
-
143
- =begin
144
- # If using a `Routine` file and want to import antoher file then use
145
- # `import:` entry.
146
- def load_detroit_file(file)
147
- #@dir = File.dirname(file)
148
-
149
- assemblies[file] =
150
-
151
- # TODO: can we just read the first line of the file and go from there?
152
- #text = File.read(file).strip
153
-
154
- ## if yaml vs. ruby file
155
- #if (/\A---/ =~ text || /\.(yml|yaml)$/ =~ File.extname(file))
156
- # #data = parse_detroit_file_yaml(text, file)
157
- # YAML.load(text)
158
- #else
159
- # data = parse_detroit_file_ruby(text, file)
160
- #end
161
-
162
- ## extract defaults
163
- #if defaults = data.delete('defaults')
164
- # @defaults.merge!(defaults)
165
- #end
166
-
167
- ## import other files
168
- #if import = data.delete('import')
169
- # [import].flatten.each do |glob|
170
- # routine(glob)
171
- # end
172
- #end
173
-
174
- ## require plugins
175
- #if plugins = data.delete('plugins')
176
- # [plugins].flatten.each do |file|
177
- # require file
178
- # end
179
- #end
180
-
181
- #@services.update(data)
182
- end
183
- =end
184
-
185
- ## Parse a YAML-based routine.
186
- #def parse_detroit_file_yaml(text, file)
187
- # YAMLParser.parse(self, text, file)
188
- #end
189
-
190
- ## Parse a Ruby-based routine.
191
- #def parse_detroit_file_ruby(text, file)
192
- # RubyParser.parse(self, text, file)
193
- #end
194
-
195
- ## TODO: Should the +dir+ be relative to the file or project.root?
196
- #def routine(glob)
197
- # pattern = File.join(@dir, glob)
198
- # Dir[pattern].each{ |f| load_detroit_file(f) }
199
- #end
200
-
201
- end
202
-
203
- end
@@ -1,129 +0,0 @@
1
- module Detroit
2
-
3
- # The control module is a function module that extends
4
- # the toplevel Detroit namespace module.
5
- module Control
6
-
7
- # Location of standard plugins.
8
- #PLUGIN_DIRECTORY = File.dirname(__FILE__) + '/plugins'
9
-
10
- # Returns Array of standard plugin file names.
11
- #def standard_plugins
12
- # Dir[PLUGIN_DIRECTORY + '/*.rb']
13
- #end
14
-
15
- # Universal acccess to the current project.
16
- #
17
- # TODO: Is Control#project being used?
18
- def project
19
- @project ||= POM::Project.find
20
- end
21
-
22
- # Returns Application given options.
23
- def application(options={})
24
- Application.new(options)
25
- end
26
-
27
- # Run the command line interface.
28
- def cli(*argv)
29
- cli_options = {
30
- :system => nil, :assemblies => [],
31
- :trace=>nil, :trial=>nil, :debug=>nil, :quiet=>nil, :verbose=>nil,
32
- :force=>nil, :multitask=>nil, :skip=>[]
33
- }
34
-
35
- usage = cli_usage(cli_options)
36
- usage.parse!(argv)
37
-
38
- #if /\.assembly$/ =~ argv[0]
39
- # job = argv[1]
40
- # begin
41
- # application(cli_options).runscript(argv[0], job)
42
- # rescue => error
43
- # $stderr.puts error.message
44
- # exit -1
45
- # end
46
- #else
47
- begin
48
- application(cli_options).start(*argv)
49
- rescue => error
50
- if $DEBUG
51
- raise error
52
- else
53
- $stderr.puts error.message
54
- exit -1
55
- end
56
- end
57
- #end
58
- end
59
-
60
- # Returns an instance of OptionParser.
61
- def cli_usage(options)
62
- @usage ||= (
63
- OptionParser.new do |usage|
64
- usage.banner = "Usage: detroit [<track>:]<stop> [options]"
65
- usage.on('-m', '--multitask', "Run work elements in parallel.") do
66
- options[:multitask] = true
67
- end
68
- usage.on('-S', '--skip [SERVICE]', 'Skip a service.') do |skip|
69
- options[:skip] << skip
70
- end
71
-
72
- usage.on('-s', '--system=NAME', "Select assembly system. Default is `standard'.") do |system|
73
- options[:system] = system
74
- end
75
- usage.on('-a', '--assembly [FILE]', 'Use specific assembly file(s).') do |file|
76
- options[:assemblies] << file
77
- end
78
-
79
- usage.on('-F', '--force', "Force operations.") do
80
- options[:force] = true
81
- end
82
- usage.on('--trace', "Run in TRACE mode.") do
83
- #$TRACE = true
84
- options[:trace] = true
85
- end
86
- usage.on('--trial', "Run in TRIAL mode (no disk writes).") do
87
- #$TRIAL = true
88
- options[:trial] = true
89
- end
90
- # TODO: do we really need verbose?
91
- usage.on('--verbose', "Provide extra output.") do
92
- options[:verbose] = true
93
- end
94
- usage.on('-q', '--quiet', "Run silently.") do
95
- options[:quiet] = true
96
- end
97
-
98
- usage.on('-I=PATH', "Add directory to $LOAD_PATH") do |dirs|
99
- dirs.to_list.each do |dir|
100
- $LOAD_PATH.unshift(dir)
101
- end
102
- end
103
- usage.on('--debug', "Run with $DEBUG set to true.") do
104
- $DEBUG = true
105
- options[:debug] = true # DEPRECATE?
106
- end
107
- usage.on('--warn', "Run with $VERBOSE set to true.") do
108
- $VERBOSE = true # wish this were called $WARN
109
- end
110
- usage.on_tail('--help [TOOL]', "Display this help message.") do |tool|
111
- if tool
112
- application.display_help(tool)
113
- else
114
- puts usage
115
- end
116
- exit
117
- end
118
- usage.on_tail('-c', '--config TOOL', "Produce a configuration template.") do |tool|
119
- puts application.config_template(tool).to_yaml
120
- exit
121
- end
122
- end
123
- )
124
- end
125
-
126
- end
127
-
128
- extend Control
129
- end
@@ -1,102 +0,0 @@
1
- module Detroit
2
-
3
- # Custom tool is used to create "quicky" services.
4
- #
5
- # This is a useful alternative to writing a full-blown plugin
6
- # when the need is simple.
7
- #
8
- class Custom < Tool
9
-
10
- # Default track(s) in which this plugin operates.
11
- DEFAULT_TRACK = "main"
12
-
13
- # Which track(s) to run this custom plugin.
14
- attr_accessor :track
15
-
16
- # Special writer to allow single track or a list of tracks.
17
- def track=(val)
18
- @track = val.to_list #[val].flatten
19
- end
20
-
21
- # Plural alias for #track.
22
- alias_accessor :tracks, :track
23
-
24
- alias_accessor :on, :track
25
-
26
- private
27
-
28
- SPECIAL_OPTIONS = %w{
29
- service track tracks on active priority project
30
- trial trace verbose force quiet
31
- }
32
-
33
- # Instantiate new custom plugin.
34
- #
35
- # FIXME: Custom#initialize seems to be running twice at startup. Why?
36
- #
37
- # This works by interpreting the service configuration as a hash of
38
- # stop names to ruby code.
39
- #
40
- def initialize(options)
41
- super(options)
42
- options.each do |stop, script|
43
- # skip specific names used for configuration
44
- next if SPECIAL_OPTIONS.include? stop
45
- # remaining options are names of track stops
46
- #tracks.each do |t|
47
- src = %{
48
- def station_#{stop}
49
- #{script}
50
- end
51
- }
52
- (class << self; self; end).module_eval(src)
53
- #end
54
- end
55
- end
56
-
57
- # Set initial attribute defaults.
58
- def initialize_defaults
59
- @track = [DEFAULT_TRACK]
60
- end
61
-
62
- #
63
- def method_missing(s, *a, &b)
64
- if s.to_s.end_with?('=')
65
- # stop = s.to_s.chomp('=')
66
- # if !SPECIAL_OPTIONS.include?(stop)
67
- # (class << self; self; end).module_eval %{
68
- # def station_#{stop}
69
- # #{a.first}
70
- # end
71
- # }
72
- # end
73
- else
74
- if @context.respond_to?(s)
75
- @context.__send__(s,*a,&b)
76
- else
77
- super(s, *a, &b)
78
- end
79
- end
80
- end
81
-
82
- # @todo should only respond to stop names and special options.
83
- #def respond_to?(s)
84
- # return true if SPECIAL_OPTIONS.include?(s.to_s)
85
- # return true
86
- #end
87
-
88
- # RUBY 1.9
89
- def respond_to_missing?(name, privy)
90
- #return true if name.to_s.start_with?('station_')
91
- return true if name.to_s.end_with?('=')
92
- return true if @context.respond_to?(name)
93
- false
94
- end
95
-
96
- def inspect
97
- "#<Custom @on=#{track.join(',')}>"
98
- end
99
-
100
- end
101
-
102
- end