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
@@ -0,0 +1,200 @@
1
+ module Detroit
2
+
3
+ ##
4
+ # This base class can be used for tools that do not need
5
+ # all of the utility methods provided by the regular Tool
6
+ # class.
7
+ #
8
+ class BasicTool
9
+ include BasicUtils
10
+
11
+ # Call this method to register a tool with an assembly.
12
+ # A tool can only belong to one assembly, but migration
13
+ # adapters can be defined to allow tools from one assembly
14
+ # to work with another (COMING SOON).
15
+ #
16
+ # @param [Assembly] a (optional)
17
+ # Assembly for which this tool is designed.
18
+ #
19
+ # @example
20
+ # class SomeTool < Tool
21
+ # assembly Standard
22
+ #
23
+ # @return [Assembly] Assembly module.
24
+ def self.assembly(a=nil)
25
+ #include(@assembly = a) if a
26
+ include(a) if a
27
+ @assembly
28
+ end
29
+
30
+ #
31
+ def self.assembly=(a)
32
+ @assembly = a
33
+ end
34
+
35
+ ## Specify a supported station. This is used by the `chain?` method to
36
+ ## determine if station is supporte by a tool. This is more convenient
37
+ ## then overridding `chain?` method.
38
+ #def self.station(name, alt=nil)
39
+ # define_method("station_#{name}") do |options={}|
40
+ # meth = method(alt || name)
41
+ # case meth.arity
42
+ # when 0
43
+ # meth.call()
44
+ # else
45
+ # meth.call(options)
46
+ # end
47
+ # end
48
+ #end
49
+
50
+ # Returns a Class which is a new subclass of the current class.
51
+ #def self.factory(&block)
52
+ # Class.new(self, &block)
53
+ #end
54
+
55
+ # Override the usual new method in order to apply prerequisites.
56
+ #
57
+ # @return [BasicTool]
58
+ def self.new(options={})
59
+ tool = allocate
60
+ # TODO: I don't exactly like this, but how else to get project
61
+ # into the tool befire running `#prerequiste`?
62
+ tool.project = options['project']
63
+ ancestors.reverse_each do |anc|
64
+ next if (anc == BasicObject || anc == Object || anc == Kernel)
65
+ if anc.instance_methods.include?(:prerequisite)
66
+ pre = anc.instance_method(:prerequisite)
67
+ pre.bind(tool).call
68
+ end
69
+ end
70
+ tool.send(:initialize, options)
71
+ tool
72
+ end
73
+
74
+ # Returns list of writer method names. This is used for reference.
75
+ #
76
+ # @return [Array<String>]
77
+ def self.options(tool_class=self)
78
+ i = tool_class.ancestors.index(Tool)
79
+ m = []
80
+ tool_class.ancestors[0..i].each do |sc|
81
+ sc.public_instance_methods(false).each do |pm|
82
+ next if pm !~ /\w+=$/
83
+ next if %w{taguri=}.include?(m.to_s)
84
+ m << pm.to_s.chomp('=')
85
+ end
86
+ end
87
+ m
88
+ end
89
+
90
+ # Override this method if the tool's availability is conditional.
91
+ #
92
+ # @return [Boolean]
93
+ def self.available?
94
+ true
95
+ end
96
+
97
+ # This pre-initialization procedure is run before #initialize and
98
+ # for all ancestors, so `#super` should never be called within it.
99
+ # The method is intended to be used to require dependencies for a tool,
100
+ # so that tool's dependencies are only required when needed. But it can
101
+ # also be used to set pre-option attribute defaults.
102
+ #
103
+ # @example
104
+ # def prerequisite
105
+ # require 'ostruct'
106
+ # @gravy = true
107
+ # end
108
+ #
109
+ # @return [void]
110
+ def prerequisite
111
+ end
112
+
113
+ # Create a new tool object.
114
+ #
115
+ # This sets up utility extensions and assigns options to setter attributes
116
+ # if they exist and values are not nil. That last point is important.
117
+ # You must use 'false' to purposely negate an option, as +nil+ will instead
118
+ # allow any default setting to be used.
119
+ #
120
+ # @return [void]
121
+ def initialize(options={})
122
+ initialize_options(@options = options)
123
+ end
124
+
125
+ # Called by `#initialize` to call writers from given options.
126
+ #
127
+ # @return [void]
128
+ def initialize_options(options)
129
+ options.each do |k, v|
130
+ #send("#{k}=", v) unless v.nil? #if respond_to?("#{k}=") && !v.nil?
131
+ if respond_to?("#{k}=")
132
+ send("#{k}=", v) unless v.nil? #if respond_to?("#{k}=") && !v.nil?
133
+ else
134
+ warn "#{self.class.name} does not respond to `#{k}=`."
135
+ end
136
+ end
137
+ end
138
+
139
+ # Access to all options passed into `#initialize`.
140
+ #
141
+ # @return [Hash]
142
+ attr :options
143
+
144
+ #
145
+ # @todo Is this needed?
146
+ #
147
+ def title
148
+ self.class.name
149
+ end
150
+
151
+ # Does this tool attach to the specified station?
152
+ #
153
+ # By default this checks for the definition of a public method in the tool
154
+ # class with the same name as the station. Note, it does not use `respond_to?`
155
+ # to do this, which would find any such method in the class hierarchy. Instead
156
+ # it specifically checks for a definition in the tool class itself. This
157
+ # helps prevent potential accidental name clashes between support methods
158
+ # and station names.
159
+ #
160
+ def assemble?(station, options={})
161
+ self.class.public_methods(false).include?(station.to_sym)
162
+ end
163
+
164
+ #
165
+ def assemble(station, options={})
166
+ meth = method(station)
167
+
168
+ case meth.arity
169
+ when 0
170
+ meth.call()
171
+ else
172
+ meth.call(options)
173
+ end
174
+ end
175
+
176
+ # Project instance.
177
+ def project=(project)
178
+ @project = project
179
+ end
180
+
181
+ # Project instance.
182
+ def project
183
+ @project #||= Project.factory(root)
184
+ end
185
+
186
+ # Shortcut to project metadata.
187
+ def metadata
188
+ project.metadata
189
+ end
190
+
191
+ # Project root directory.
192
+ #
193
+ # @return [Pathname]
194
+ def root
195
+ @project.root
196
+ end
197
+
198
+ end
199
+
200
+ end
@@ -0,0 +1,66 @@
1
+ module Detroit
2
+
3
+ ##
4
+ # Common utility methods included in all tools.
5
+ #
6
+ module BasicUtils
7
+
8
+ # Glob for finding root of a project.
9
+ def root_pattern
10
+ "{.index,.git,.hg,.svn,_darcs}"
11
+ end
12
+
13
+ # Project root directory.
14
+ def root
15
+ @root ||= (
16
+ path = nil
17
+ home = File.expand_path('~')
18
+
19
+ while dir != home && dir != '/'
20
+ if Dir[root_pattern].first
21
+ path = dir
22
+ break
23
+ end
24
+ dir = File.dirname(dir)
25
+ end
26
+
27
+ Pathname.new(path || Dir.pwd)
28
+ )
29
+ end
30
+
31
+ # Configuration.
32
+ def config
33
+ @config ||= Config.new(root)
34
+ end
35
+
36
+ #
37
+ def naming_policy
38
+ @naming_policy ||= (
39
+ if config.naming_policy
40
+ Array(config.naming_policy)
41
+ else
42
+ ['down', 'ext']
43
+ end
44
+ )
45
+ end
46
+
47
+ #
48
+ def apply_naming_policy(name, ext)
49
+ naming_policy.each do |policy|
50
+ case policy.to_s
51
+ when /^low/, /^down/
52
+ name = name.downcase
53
+ when /^up/
54
+ name = name.upcase
55
+ when /^cap/
56
+ name = name.capitalize
57
+ when /^ext/
58
+ name = name + ".#{ext}"
59
+ end
60
+ end
61
+ name
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -1,137 +1,3 @@
1
- #__DIR__ = File.dirname(__FILE__)
2
-
3
- #Dir[File.join(__DIR__, 'core_ext', '*.rb')].each do |file|
4
- # require file
5
- #end
6
-
7
- #require 'facets'
8
- require 'facets/to_hash'
9
- require 'facets/module/basename'
10
- require 'facets/module/alias_accessor'
11
- require 'facets/pathname'
12
- #require 'facets/boolean'
13
-
14
- class Array
15
-
16
- def to_list
17
- self
18
- end
19
-
1
+ Dir[File.dirname(__FILE__) + '/core_ext/**/*.rb'].each do |file|
2
+ require file
20
3
  end
21
-
22
- class NilClass
23
-
24
- def to_list
25
- []
26
- end
27
-
28
- end
29
-
30
- class String
31
-
32
- # Helper method for cleaning list options.
33
- # This will split the option on ':' or ';'
34
- # if it is a string, rather than an array.
35
- # And it will make sure there are no nil elements.
36
-
37
- def to_list
38
- split(/[:;,\n]/).map{ |s| s.strip }
39
- end
40
-
41
- end
42
-
43
- # TODO: Replace these with facets/shellwords !!!
44
-
45
- #
46
- class Array #:nodoc:
47
-
48
- # Convert an array into commandline parameters.
49
- # The array is accepted in the format of Ruby
50
- # method arguments --ie. [arg1, arg2, ..., hash]
51
-
52
- def to_console
53
- #flags = (Hash===last ? pop : {})
54
- #flags = flags.to_console
55
- #flags + ' ' + join(" ")
56
- to_argv.join(' ')
57
- end
58
-
59
- # TODO: DEPRECATE
60
- alias_method :to_params, :to_console
61
-
62
- #
63
- def to_argv
64
- flags = (Hash===last ? pop : {})
65
- flags = flags.to_argv
66
- flags + self
67
- end
68
-
69
- # def to_console
70
- # flags = (Hash===last ? pop : {})
71
- # flags = flags.collect do |f,v|
72
- # m = f.to_s.size == 1 ? '-' : '--'
73
- # case v
74
- # when Array
75
- # v.collect{ |e| "#{m}#{f} '#{e}'" }.join(' ')
76
- # when true
77
- # "#{m}#{f}"
78
- # when false, nil
79
- # ''
80
- # else
81
- # "#{m}#{f} '#{v}'"
82
- # end
83
- # end
84
- # return (flags + self).join(" ")
85
- # end
86
-
87
- end
88
-
89
- class Hash
90
-
91
- # Convert a Hash into command line arguments.
92
- # The array is accepted in the format of Ruby
93
- # method arguments --ie. [arg1, arg2, ..., hash]
94
- def to_console
95
- to_argv.join(' ')
96
- end
97
-
98
- # Convert a Hash into command line parameters.
99
- # The array is accepted in the format of Ruby
100
- # method arguments --ie. [arg1, arg2, ..., hash]
101
- def to_argv
102
- flags = map do |f,v|
103
- m = f.to_s.size == 1 ? '-' : '--'
104
- case v
105
- when Array
106
- v.collect{ |e| "#{m}#{f}='#{e}'" }.join(' ')
107
- when true
108
- "#{m}#{f}"
109
- when false, nil
110
- ''
111
- else
112
- "#{m}#{f}='#{v}'"
113
- end
114
- end
115
- end
116
-
117
- # Turn a hash into arguments.
118
- #
119
- # h = { :list => [1,2], :base => "HI" }
120
- # h.argumentize #=> [ [], { :list => [1,2], :base => "HI" } ]
121
- # h.argumentize(:list) #=> [ [1,2], { :base => "HI" } ]
122
- #
123
- def argumentize(args_field=nil)
124
- config = dup
125
- if args_field
126
- args = [config.delete(args_field)].flatten.compact
127
- else
128
- args = []
129
- end
130
- args << config
131
- return args
132
- end
133
-
134
- alias_method :command_vector, :argumentize
135
-
136
- end
137
-
@@ -2,6 +2,9 @@
2
2
  # see it as a "heavy" dependency. But really that is far from true, consider
3
3
  # the facet that the following libs are all that it used.
4
4
 
5
+ require 'facets/pathname'
6
+ #require 'facets/boolean'
7
+
5
8
  require 'facets/array/not_empty'
6
9
  require 'facets/module/basename'
7
10
  require 'facets/module/alias_accessor'
@@ -1,4 +1,5 @@
1
1
  # TODO: Improve the naming scheme of these methods.
2
+ # TODO: Replace these with facets/shellwords ?
2
3
 
3
4
  #
4
5
  class Array #:nodoc:
@@ -1,6 +1,8 @@
1
1
  module Detroit
2
2
 
3
- # The Mail utility module provides an easy to use +email+ method.
3
+ ##
4
+ # The Mail utility module provides an easy to use `email` method.
5
+ #
4
6
  module EmailUtils
5
7
 
6
8
  # Email function to easily send out an email.
@@ -0,0 +1,55 @@
1
+ module Detroit
2
+
3
+ # Execute a sepcific detroit tool.
4
+ #
5
+ # Note this uses the executable gem to automatically
6
+ # "cli-ify" a tool class.
7
+ #
8
+ def self.tool_exec(*argv)
9
+ require 'executable'
10
+
11
+ tool, stop = argv.shift.split(':')
12
+
13
+ raise "No tool specified." unless tool
14
+ raise "No tool stop specified." unless stop
15
+
16
+ begin
17
+ require "detroit-#{tool}"
18
+ rescue LoadError
19
+ raise "Unknown tool. Perhaps try `gem install detroit-#{tool}`."
20
+ end
21
+
22
+ tool_class = Detroit.tools[tool]
23
+
24
+ exec_class = Class.new(tool_class) do
25
+ include Executable
26
+
27
+ # TODO: Fix executable, to at least super if defined super.
28
+ define_method(:initialize) do
29
+ tool_class.instance_method(:initialize).bind(self).call
30
+ end
31
+
32
+ # Show this message.
33
+ def help!
34
+ cli.show_help
35
+ exit
36
+ end
37
+ alias :h! :help!
38
+
39
+ define_method(:call) do |*args|
40
+ if assemble?(stop.to_sym)
41
+ assemble(stop.to_sym)
42
+ else
43
+ raise "#{tool} does not know how to #{stop}."
44
+ end
45
+ end
46
+ end
47
+
48
+ #exec_class.send(:define_method, :command_name) do
49
+ # tool
50
+ #end
51
+
52
+ exec_class.run(argv)
53
+ end
54
+
55
+ end