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,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'detroit'
3
3
  begin
4
- Detroit.cli(*ARGV)
4
+ Detroit::Toolchain.cli(ARGV)
5
5
  rescue => err
6
6
  raise err #if $DEBUG
7
7
  $stderr.puts err
@@ -11,54 +11,126 @@ module Detroit
11
11
  def self.const_missing(name)
12
12
  metadata[name.to_s.downcase] || super(name)
13
13
  end
14
-
15
- # TODO: Only here b/c of bug in Ruby 1.8.x
16
- #VERSION = "0.3.0"
17
14
  end
18
15
 
19
- # Erb is used to to script YAML-based schedule files.
20
- require 'erb'
21
-
22
- # OptionParser is used for command line parsing.
23
- require 'optparse'
16
+ require 'pathname'
17
+ require 'erb' # Erb is used to to script YAML-based schedule files.
18
+ require 'optparse' # OptionParser is used for command line parsing.
19
+ require 'yaml' # Yea like we don't all ride a YAML.
24
20
 
25
- # Yea like we don't all ride a YAML.
26
- require 'yaml'
27
-
28
- # The ANSI gem is used to colorize terminal output.
29
- require 'ansi/terminal'
21
+ require 'indexer' # Indexer is used to provide project metadata.
22
+ require 'ansi/terminal' # The ANSI gem is used to colorize terminal output.
30
23
  require 'ansi/code'
31
24
 
32
- # The parallel gem is used to (optionally) multitask services.
25
+ # The optional parallel gem is used to multitask services.
33
26
  begin
34
27
  require 'parallel'
35
28
  rescue LoadError
36
29
  end
37
30
 
38
- # POM is used to access project metadata.
39
- require 'pom'
40
-
41
- # And all the rest is Detroit, baby.
42
- if RUBY_VERSION > '1.9'
43
- require_relative 'detroit/core_ext'
44
- require_relative 'detroit/config'
45
- require_relative 'detroit/service'
46
- require_relative 'detroit/tool'
47
- require_relative 'detroit/assembly_system'
48
- require_relative 'detroit/standard_assembly'
49
- require_relative 'detroit/control'
50
- require_relative 'detroit/application'
51
- require_relative 'detroit/assembly'
52
- require_relative 'detroit/custom'
53
- else
54
- require 'detroit/core_ext'
55
- require 'detroit/config'
56
- require 'detroit/service'
57
- require 'detroit/tool'
58
- require 'detroit/assembly_system'
59
- require 'detroit/standard_assembly'
60
- require 'detroit/control'
61
- require 'detroit/application'
62
- require 'detroit/assembly'
63
- require 'detroit/custom'
31
+ require_relative 'detroit/core_ext'
32
+ require_relative 'detroit/project'
33
+ require_relative 'detroit/toolchain' #runner
34
+ require_relative 'detroit/exec'
35
+
36
+ require_relative 'detroit/basic_utils'
37
+ require_relative 'detroit/shell_utils'
38
+ require_relative 'detroit/email_utils'
39
+ require_relative 'detroit/ruby_utils'
40
+
41
+ require_relative 'detroit/basic_tool'
42
+
43
+
44
+ module Detroit
45
+
46
+ #
47
+ # Tool registry.
48
+ #
49
+ def self.tools
50
+ @tools ||= {}
51
+ end
52
+
53
+ #
54
+ # Define tool method.
55
+ #
56
+ def self.define_tool_method(name, tool_class)
57
+ (class << self; self; end).class_eval do
58
+ # raise or skip if method_defined?(name)
59
+ define_method(name) do |*a, &b|
60
+ tool_class.new(*a, &b)
61
+ end
62
+ end
63
+ end
64
+
65
+ #
66
+ # Add tool class to registry. If class name ends in `Tool` or `Base`
67
+ # it will be considered a reusable base class and not be added.
68
+ #
69
+ def self.register_tool(tool_class)
70
+ name = tool_class.basename
71
+ return if name.nil?
72
+ return if name.empty?
73
+ return if name =~ /Tool$/
74
+ return if name =~ /Base$/
75
+ tools[name.downcase] = tool_class
76
+ Tools.const_set(name, tool_class)
77
+ Detroit.define_tool_method(name, tool_class)
78
+ return tool_class
79
+ end
80
+
81
+ =begin
82
+ ##
83
+ # Per-project configuration for detroit.
84
+ #
85
+ # TODO: Do we really need this?
86
+ class Config < BasicObject
87
+ FILE = ".detroit"
88
+
89
+ def initialize(root)
90
+ @file = Dir.glob(root + FILE).first
91
+
92
+ if @file
93
+ @data = YAML.load_file(@file)
94
+ else
95
+ @data = {}
96
+ end
97
+ end
98
+
99
+ def method_missing(s, *a, &b)
100
+ @data[s.to_s]
101
+ end
102
+ end
103
+ =end
104
+
105
+ ##
106
+ # The Tools module provides an isolated namespace for Detoit's tools.
107
+ # This allows for general use of these tools by other applications,
108
+ # simply by including the Detroit::Tools module into their own namespace.
109
+ #
110
+ module Tools
111
+ end
112
+
113
+ ##
114
+ # The common base class for tools. Tool is a subclass of BasicTool that
115
+ # adds additional utility methods, in particular it adds {ShellUtils}.
116
+ # Unless there is a specific reason not to do so, this is the class
117
+ # that specific tool classes should subclass.
118
+ #
119
+ # A good tool will check to see if the state of the project is *current*
120
+ # or not to know if some stage of the tool needs to be used or not.
121
+ # For example a documentation# tool can look to see if any the files
122
+ # it would document are newer that the previous generated set of document
123
+ # file. In this case it can output a message explaining that the action
124
+ # was not needed. For example, the RDoc tool outputs the message:
125
+ # "RDocs are current (path/to/rdocs)". The tool can also support the
126
+ # `$FORCE` global to force the procedure regardless.
127
+ #
128
+ class Tool < BasicTool
129
+ include ShellUtils
130
+ end
131
+
64
132
  end
133
+
134
+ require_relative 'detroit/assembly'
135
+ #require_relative 'detroit/standard'
136
+
@@ -1,44 +1,59 @@
1
1
  ---
2
- source:
3
- - PROFILE
4
- - meta
2
+ revision: 2013
3
+ type: ruby
4
+ sources:
5
+ - var
5
6
  authors:
6
7
  - name: Trans
7
8
  email: transfire@gmail.com
8
- copyrights:
9
- - holder: Thomas Sawyer
10
- year: '2007'
11
- license: GPL3
9
+ organizations: []
12
10
  requirements:
13
11
  - name: facets
14
- - name: pom
15
- - name: qed
16
- groups:
12
+ - name: indexer
13
+ - groups:
17
14
  - test
18
15
  development: true
19
- dependencies: []
20
- alternatives: []
16
+ name: qed
17
+ - groups:
18
+ - build
19
+ development: true
20
+ name: detroit-yard
21
+ - groups:
22
+ - build
23
+ development: true
24
+ name: detroit-gem
21
25
  conflicts: []
26
+ alternatives: []
27
+ resources:
28
+ - type: home
29
+ uri: http://rubyworks.github.com/detroit
30
+ label: Homepage
31
+ - type: code
32
+ uri: http://github.com/rubyworks/detroit
33
+ label: Source Code
34
+ - type: mail
35
+ uri: http://groups.google.com/rubyworks-mailinglist
36
+ label: Mailing List
22
37
  repositories:
23
- - uri: http://github.com/proutils/detroit.git
38
+ - name: upstream
24
39
  scm: git
25
- name: upstream
26
- resources:
27
- home: http://rubyworks.github.com/detroit
28
- code: http://github.com/rubyworks/detroit
29
- mail: http://groups.google.com/rubyworks-mailinglist
30
- extra: {}
31
- load_path:
32
- - lib
33
- revision: 0
34
- created: '2007-10-10'
35
- summary: Software Production Mangement
36
- title: Detroit
37
- version: 0.3.0
40
+ uri: http://github.com/proutils/detroit.git
41
+ categories: []
42
+ copyrights:
43
+ - holder: Rubyworks
44
+ year: '2007'
45
+ license: GPL-3.0
46
+ customs: []
47
+ paths:
48
+ lib:
49
+ - lib
38
50
  name: detroit
39
- suite: detroit
51
+ title: Detroit
52
+ summary: Software Production Mangement
53
+ created: '2007-10-10'
40
54
  description: Detroit is an advanced lifecycle build system. With Detroit, build tasks
41
55
  are user defined service instances tied to stops along a track. Whenever the detroit
42
56
  console command is run, a track is followed from beginning to designated destination.
43
- organization: rubyworks
44
- date: '2012-04-01'
57
+ suite: detroit
58
+ version: 0.4.0
59
+ date: '2014-01-13'
@@ -1,219 +1,75 @@
1
1
  module Detroit
2
2
 
3
- # Assembly encapsulates a `Assembly` file and it's service instance
4
- # configurations.
5
- class Assembly
6
-
7
- # Load Scedule file.
8
- def self.load(input)
9
- new(input)
10
- end
11
-
12
- # Hash table of services.
13
- attr :services
14
-
15
- private
16
-
17
- # Initialize new Assembly instance.
18
- def initialize(file, options={})
19
- @project = options[:project]
20
-
21
- @services = {}
3
+ # Define an assembly.
4
+ #
5
+ # @return nothing.
6
+ def self.assembly(name, &block)
7
+ ass = Assembly.new(name, &block)
8
+ const_set(name, ass)
9
+ end
22
10
 
23
- @file = (String === file ? File.new(file) : file)
11
+ # Map of toolchain names to classes.
12
+ #
13
+ # @return [Hash<Symbol,Class>] All defined assemblies.
14
+ def self.assemblies
15
+ @assemblies ||= {}
16
+ end
24
17
 
25
- case File.extname(@file.path)
26
- when '.rb'
27
- instance_eval(@file.read, @file.path)
28
- when '.yml', '.yaml'
29
- @services = YAML.load(erb(@file.read))
30
- else
31
- text = @file.read
32
- if /^---/ =~ text
33
- @services = YAML.load(erb(text))
34
- else
35
- instance_eval(text, @file.path)
36
- end
37
- end
38
- end
18
+ ##
19
+ # An *assembly* is a set of production lines where each line is a list
20
+ # of named work stations.
21
+ #
22
+ class Assembly < Module
39
23
 
40
- # Define a service.
41
- def service(name, settings={}, &block)
42
- if block
43
- block_context = BlockContext.new(&block)
44
- settings.update(block_context.settings)
45
- end
46
- @services[name.to_s] = settings.rekey(&:to_s)
47
- end
24
+ def initialize(name, &block)
25
+ Detroit.assemblies[name.to_s.downcase.to_sym] = self
48
26
 
49
- alias_method :tool, :service
27
+ @lines = []
28
+ @tools = []
50
29
 
51
- #
52
- #
53
- #
54
- #
55
- def custom(name, &block)
56
- context = CustomContext.new(&block)
57
- settings = context.settings
58
- @services[name.to_s] = settings.rekey(&:to_s)
30
+ super(&block) #module_eval(&block)
59
31
  end
60
32
 
61
- # Access to project data.
62
- #
63
- # NOTE: Thinking that the project should be relative
64
- # to the Routine file itself, unless a `project` is passed
65
- # in manually through the initializer. In the mean time,
66
- # the project is just relative to the current working directory.
33
+ # Returns a list of lists of stops.
67
34
  #
68
- # TODO: Make configurable and use .ruby by default ?
69
- def project
70
- @project ||= POM::Project.find #(file_directory)
71
- end
72
-
73
- # Capitalized service names called as methods
74
- # can also define a service.
75
- def method_missing(sym, *args, &block)
76
- service_class = sym.to_s
77
- case service_class
78
- when /^[A-Z]/
79
- if Hash === args.last
80
- args.last[:service] = service_class
81
- else
82
- args << {:service=>service_class}
83
- end
84
- case args.first
85
- when String, Symbol
86
- name = args.first
87
- else
88
- name = service_class.to_s.downcase
89
- end
90
- service(name, *args, &block)
91
- else
92
- super(sym, *args, &block)
93
- end
35
+ # @return [Array<Array<Symbol>>] lines.
36
+ def lines
37
+ @lines
94
38
  end
95
39
 
96
- private
97
-
98
- # Process Routine document via ERB.
99
- def erb(text)
100
- context = ERBContext.new(project)
101
- ERB.new(text).result(context.__binding__)
40
+ # Define a chain of named links.
41
+ def line(*stations)
42
+ # TODO: raise error if stage already used ?
43
+ self.lines << stations.map{ |s| s.to_sym }
102
44
  end
103
45
 
104
- # ERBContext provides the clean context to process a Routine
105
- # as an ERB template.
106
- class ERBContext
107
- #
108
- def initialize(project)
109
- @project = project
110
- end
111
-
112
- # Access to a clean binding.
113
- def __binding__
114
- binding
115
- end
116
-
117
- # Provide access to project data.
118
- def project
119
- @project
120
- end
46
+ # Lookup a chain by a given stage name.
47
+ #
48
+ # @return nothing.
49
+ def find(station)
50
+ station = station.to_sym
121
51
 
122
- #
123
- def method_missing(name, *args)
124
- if project.respond_to?(name)
125
- project.__send__(name, *args)
126
- elsif project.metadata.respond_to?(name)
127
- project.metadata.__send__(name, *args)
128
- else
129
- super(name, *args)
130
- end
52
+ lines.find do |line|
53
+ line.include?(station)
131
54
  end
132
55
  end
133
56
 
57
+ # Add tool to toolchain.
134
58
  #
135
- class BlockContext
136
- #
137
- attr :settings
138
-
139
- #
140
- def initialize(&b)
141
- @settings = {}
142
- b.arity == 1 ? b.call(self) : instance_eval(&b)
143
- end
144
-
145
- #
146
- def set(name, value=nil, &block)
147
- if block
148
- block_context = BlockContext.new
149
- block.call(block_context)
150
- @settings[name.to_s] = block_context.settings
151
- else
152
- @settings[name.to_s] = value
153
- end
154
- end
155
-
156
- #
157
- def method_missing(symbol, value=nil, *args)
158
- case name = symbol.to_s
159
- when /=$/
160
- @settings[name.chomp('=')] = value
161
- else
162
- super(symbol, value=nil, *args)
163
- end
164
- end
59
+ # @return [Class] The tool class.
60
+ def register_tool(tool_class)
61
+ tool_class.assembly = self
62
+ @tools << tool_class
63
+ Detroit.register_tool(tool_class)
165
64
  end
166
65
 
66
+ # When the tool chain is included into a class, register
67
+ # that class as a tool.
167
68
  #
168
- class CustomContext
169
- #
170
- attr :settings
171
- #
172
- def initialize(&b)
173
- @settings = {}
174
- b.arity == 0 ? instance_eval(&b) : b.call(self)
175
- end
176
- #
177
- def method_missing(s,a=nil,*x,&b)
178
- case s.to_s
179
- when /=$/
180
- @settings[s.to_s.chomp('=').to_sym] = b ? b : a
181
- else
182
- return @settings[s] unless a
183
- @settings[s] = b ? b : a
184
- end
185
- end
186
- def respond_to?(s)
187
- @settings.key?(s.to_sym)
188
- end
69
+ # @return [void] The tool class.
70
+ def included(tool_class)
71
+ register_tool(tool_class) unless @tools.include?(tool_class)
189
72
  end
190
-
191
73
  end
192
74
 
193
- # NOTE: This is problematic, because a Scheudle file should really know from
194
- # what file it was derived.
195
-
196
- #
197
- DOMAIN = "rubyworks.github.com/detroit,2011-05-27"
198
-
199
- # TODO: If using Psych rather than Syck, then define a domain type.
200
-
201
- #if defined?(Psych) #RUBY_VERSION >= '1.9'
202
- # YAML::add_domain_type(DOMAIN, "assembly") do |type, hash|
203
- # Assembly.load(hash)
204
- # end
205
- #else
206
- YAML::add_builtin_type("assembly") do |type, value|
207
- value
208
- #case value
209
- #when String
210
- # Assembly.eval(value)
211
- #when Hash
212
- # Assembly.new(value)
213
- #else
214
- # raise "ERROR: Invalid Assembly"
215
- #end
216
- end
217
- #end
218
-
219
75
  end