sprout 1.0.35.pre → 1.1.2.pre

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sprout might be problematic. Click here for more details.

Files changed (234) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +0 -2
  3. data/README.textile +1 -1
  4. data/VERSION +1 -1
  5. data/lib/sprout/concern.rb +5 -7
  6. data/lib/sprout/daemon.rb +183 -143
  7. data/lib/sprout/executable/base.rb +564 -0
  8. data/lib/sprout/executable.rb +1 -550
  9. data/lib/sprout/generator/base.rb +2 -3
  10. data/lib/sprout/generator.rb +2 -1
  11. data/lib/sprout/generators/ruby/templates/ruby_base.rb +1 -2
  12. data/lib/sprout/library.rb +3 -3
  13. data/lib/sprout/output_buffer.rb +35 -0
  14. data/lib/sprout/process_runner.rb +68 -17
  15. data/lib/sprout/progress_bar.rb +5 -5
  16. data/lib/sprout/remote_file_target.rb +1 -1
  17. data/lib/sprout/system/base_system.rb +3 -3
  18. data/lib/sprout/system/unix_system.rb +1 -1
  19. data/lib/sprout/{test/sprout_test_case.rb → test_helper.rb} +214 -14
  20. data/lib/sprout/version.rb +1 -1
  21. data/lib/sprout.rb +133 -2
  22. data/rakefile.rb +2 -0
  23. data/test/fixtures/examples/echo_inputs.rb +1 -2
  24. data/test/fixtures/executable/fdb.rb +7 -9
  25. data/test/fixtures/executable/flex3sdk_gem/fdb +49 -18
  26. data/test/fixtures/executable/mxmlc.rb +1 -2
  27. data/test/fixtures/executable/subclass/executable_subclass.rb +0 -1
  28. data/test/fixtures/executable/subclass/executable_superclass.rb +1 -2
  29. data/test/fixtures/specification/flex4sdk.rb +35 -24
  30. data/test/unit/archive_unpacker_test.rb +1 -1
  31. data/test/unit/boolean_param_test.rb +1 -1
  32. data/test/unit/daemon_test.rb +35 -3
  33. data/test/unit/executable_option_parser_test.rb +2 -3
  34. data/test/unit/executable_param_test.rb +1 -1
  35. data/test/unit/executable_test.rb +8 -15
  36. data/test/unit/fake_other_executable.rb +1 -2
  37. data/test/unit/file_param_test.rb +1 -1
  38. data/test/unit/file_target_test.rb +1 -1
  39. data/test/unit/files_param_test.rb +1 -1
  40. data/test/unit/generator_generator_test.rb +1 -1
  41. data/test/unit/generator_test.rb +1 -1
  42. data/test/unit/library_generator_test.rb +1 -1
  43. data/test/unit/library_test.rb +1 -1
  44. data/test/unit/osx_system_test.rb +1 -1
  45. data/test/unit/path_param_test.rb +1 -1
  46. data/test/unit/paths_param_test.rb +1 -1
  47. data/test/unit/platform_test.rb +1 -1
  48. data/test/unit/process_runner_test.rb +1 -1
  49. data/test/unit/rdoc_parser_test.rb +1 -1
  50. data/test/unit/remote_file_loader_test.rb +1 -1
  51. data/test/unit/remote_file_target_test.rb +1 -1
  52. data/test/unit/ruby_feature_test.rb +1 -1
  53. data/test/unit/ruby_generator_test.rb +1 -1
  54. data/test/unit/specification_test.rb +8 -1
  55. data/test/unit/sprout_test.rb +2 -2
  56. data/test/unit/string_param_test.rb +1 -1
  57. data/test/unit/string_test.rb +1 -1
  58. data/test/unit/strings_param_test.rb +1 -1
  59. data/test/unit/test_helper.rb +33 -1
  60. data/test/unit/tool_generator_test.rb +1 -1
  61. data/test/unit/unix_system_test.rb +1 -1
  62. data/test/unit/user_test.rb +1 -1
  63. data/test/unit/vista_system_test.rb +1 -1
  64. data/test/unit/win_nix_system_test.rb +1 -1
  65. data/test/unit/win_system_test.rb +1 -1
  66. data/test-stderr.log +1 -0
  67. data/test-stdout.log +237 -0
  68. metadata +15 -190
  69. data/doc/Dir.html +0 -288
  70. data/doc/Rake/Task.html +0 -184
  71. data/doc/Sprout/ArchiveUnpacker.html +0 -1246
  72. data/doc/Sprout/Base/ClassMethods.html +0 -434
  73. data/doc/Sprout/Base.html +0 -126
  74. data/doc/Sprout/Concern.html +0 -353
  75. data/doc/Sprout/Daemon/ClassMethods.html +0 -244
  76. data/doc/Sprout/Daemon/InstanceMethods.html +0 -601
  77. data/doc/Sprout/Daemon.html +0 -166
  78. data/doc/Sprout/Errors/ArchiveUnpackerError.html +0 -125
  79. data/doc/Sprout/Errors/DestinationExistsError.html +0 -133
  80. data/doc/Sprout/Errors/DuplicateMemberError.html +0 -132
  81. data/doc/Sprout/Errors/ExecutableError.html +0 -125
  82. data/doc/Sprout/Errors/ExecutableRegistrationError.html +0 -132
  83. data/doc/Sprout/Errors/ExecutionError.html +0 -121
  84. data/doc/Sprout/Errors/GeneratorError.html +0 -125
  85. data/doc/Sprout/Errors/InvalidArgumentError.html +0 -132
  86. data/doc/Sprout/Errors/LoadError.html +0 -121
  87. data/doc/Sprout/Errors/MissingArgumentError.html +0 -132
  88. data/doc/Sprout/Errors/MissingExecutableError.html +0 -132
  89. data/doc/Sprout/Errors/MissingGeneratorError.html +0 -132
  90. data/doc/Sprout/Errors/MissingTemplateError.html +0 -132
  91. data/doc/Sprout/Errors/ProcessRunnerError.html +0 -121
  92. data/doc/Sprout/Errors/RemoteFileLoaderError.html +0 -110
  93. data/doc/Sprout/Errors/SproutError.html +0 -114
  94. data/doc/Sprout/Errors/UnknownArchiveType.html +0 -122
  95. data/doc/Sprout/Errors/UsageError.html +0 -121
  96. data/doc/Sprout/Errors/ValidationError.html +0 -121
  97. data/doc/Sprout/Errors/VersionRequirementNotMetError.html +0 -121
  98. data/doc/Sprout/Errors.html +0 -101
  99. data/doc/Sprout/Executable/Boolean.html +0 -483
  100. data/doc/Sprout/Executable/ClassMethods.html +0 -417
  101. data/doc/Sprout/Executable/CollectionParam.html +0 -483
  102. data/doc/Sprout/Executable/FileParam.html +0 -484
  103. data/doc/Sprout/Executable/Files.html +0 -292
  104. data/doc/Sprout/Executable/InstanceMethods.html +0 -2006
  105. data/doc/Sprout/Executable/Number.html +0 -141
  106. data/doc/Sprout/Executable/Param.html +0 -2818
  107. data/doc/Sprout/Executable/ParameterFactory.html +0 -232
  108. data/doc/Sprout/Executable/Path.html +0 -223
  109. data/doc/Sprout/Executable/Paths.html +0 -253
  110. data/doc/Sprout/Executable/StringParam.html +0 -213
  111. data/doc/Sprout/Executable/Strings.html +0 -167
  112. data/doc/Sprout/Executable/Url.html +0 -160
  113. data/doc/Sprout/Executable/Urls.html +0 -170
  114. data/doc/Sprout/Executable.html +0 -173
  115. data/doc/Sprout/FileTarget.html +0 -1109
  116. data/doc/Sprout/Generator/Base.html +0 -1626
  117. data/doc/Sprout/Generator/Command.html +0 -690
  118. data/doc/Sprout/Generator/DirectoryManifest.html +0 -476
  119. data/doc/Sprout/Generator/FileManifest.html +0 -572
  120. data/doc/Sprout/Generator/Manifest.html +0 -377
  121. data/doc/Sprout/Generator/TemplateManifest.html +0 -196
  122. data/doc/Sprout/Generator.html +0 -689
  123. data/doc/Sprout/GeneratorGenerator.html +0 -1018
  124. data/doc/Sprout/Library.html +0 -1141
  125. data/doc/Sprout/LibraryGenerator.html +0 -309
  126. data/doc/Sprout/Log.html +0 -496
  127. data/doc/Sprout/MXMLC.html +0 -6373
  128. data/doc/Sprout/Platform.html +0 -714
  129. data/doc/Sprout/ProcessRunner.html +0 -1352
  130. data/doc/Sprout/ProgressBar.html +0 -376
  131. data/doc/Sprout/ProgressBarImpl.html +0 -2119
  132. data/doc/Sprout/ProgressBarManager.html +0 -434
  133. data/doc/Sprout/ProgressBarOutputStream.html +0 -416
  134. data/doc/Sprout/RDocParser.html +0 -211
  135. data/doc/Sprout/RemoteFileLoader.html +0 -172
  136. data/doc/Sprout/RemoteFileTarget.html +0 -679
  137. data/doc/Sprout/ReversedProgressBar.html +0 -194
  138. data/doc/Sprout/RubyFeature/ClassMethods.html +0 -1065
  139. data/doc/Sprout/RubyFeature.html +0 -155
  140. data/doc/Sprout/RubyGenerator.html +0 -764
  141. data/doc/Sprout/Specification.html +0 -767
  142. data/doc/Sprout/System/BaseSystem.html +0 -1455
  143. data/doc/Sprout/System/JavaSystem.html +0 -122
  144. data/doc/Sprout/System/OSXSystem.html +0 -335
  145. data/doc/Sprout/System/ThreadMock.html +0 -193
  146. data/doc/Sprout/System/UnixSystem.html +0 -584
  147. data/doc/Sprout/System/VistaSystem.html +0 -251
  148. data/doc/Sprout/System/WinNixSystem.html +0 -325
  149. data/doc/Sprout/System/WinSystem.html +0 -571
  150. data/doc/Sprout/System.html +0 -191
  151. data/doc/Sprout/ToolGenerator.html +0 -931
  152. data/doc/Sprout/VERSION.html +0 -128
  153. data/doc/Sprout.html +0 -144
  154. data/doc/SproutTestCase.html +0 -1412
  155. data/doc/String.html +0 -286
  156. data/doc/_index.html +0 -1035
  157. data/doc/class_list.html +0 -36
  158. data/doc/css/common.css +0 -1
  159. data/doc/css/full_list.css +0 -53
  160. data/doc/css/style.css +0 -310
  161. data/doc/file.README.html +0 -96
  162. data/doc/file.archive_unpacker.html +0 -288
  163. data/doc/file.base.html +0 -208
  164. data/doc/file.base_system.html +0 -278
  165. data/doc/file.boolean.html +0 -135
  166. data/doc/file.collection_param.html +0 -139
  167. data/doc/file.command.html +0 -126
  168. data/doc/file.concern.html +0 -136
  169. data/doc/file.daemon.html +0 -309
  170. data/doc/file.dir.html +0 -76
  171. data/doc/file.directory_manifest.html +0 -122
  172. data/doc/file.errors.html +0 -147
  173. data/doc/file.executable.html +0 -638
  174. data/doc/file.file_manifest.html +0 -109
  175. data/doc/file.file_param.html +0 -120
  176. data/doc/file.file_target.html +0 -140
  177. data/doc/file.files.html +0 -85
  178. data/doc/file.generator.html +0 -296
  179. data/doc/file.generator_class.html +0 -72
  180. data/doc/file.generator_generator.html +0 -137
  181. data/doc/file.generator_test.html +0 -92
  182. data/doc/file.generator_test_helper.html +0 -67
  183. data/doc/file.java_system.html +0 -62
  184. data/doc/file.library.html +0 -291
  185. data/doc/file.library_generator.html +0 -74
  186. data/doc/file.log.html +0 -100
  187. data/doc/file.manifest.html +0 -67
  188. data/doc/file.mxmlc.html +0 -740
  189. data/doc/file.number.html +0 -67
  190. data/doc/file.osx_system.html +0 -79
  191. data/doc/file.param.html +0 -491
  192. data/doc/file.parameter_factory.html +0 -119
  193. data/doc/file.path.html +0 -81
  194. data/doc/file.paths.html +0 -80
  195. data/doc/file.platform.html +0 -124
  196. data/doc/file.process_runner.html +0 -224
  197. data/doc/file.progress_bar.html +0 -390
  198. data/doc/file.rdoc_parser.html +0 -145
  199. data/doc/file.remote_file_loader.html +0 -117
  200. data/doc/file.remote_file_target.html +0 -176
  201. data/doc/file.ruby_base.html +0 -64
  202. data/doc/file.ruby_feature.html +0 -244
  203. data/doc/file.ruby_generator.html +0 -118
  204. data/doc/file.ruby_input.html +0 -62
  205. data/doc/file.ruby_test_case.html +0 -78
  206. data/doc/file.ruby_test_helper.html +0 -61
  207. data/doc/file.specification.html +0 -248
  208. data/doc/file.sprout.html +0 -64
  209. data/doc/file.sprout_test_case.html +0 -280
  210. data/doc/file.string.html +0 -72
  211. data/doc/file.string_param.html +0 -76
  212. data/doc/file.strings.html +0 -71
  213. data/doc/file.system.html +0 -86
  214. data/doc/file.template_manifest.html +0 -67
  215. data/doc/file.tool.html +0 -92
  216. data/doc/file.tool_generator.html +0 -90
  217. data/doc/file.unix_system.html +0 -128
  218. data/doc/file.url.html +0 -71
  219. data/doc/file.urls.html +0 -70
  220. data/doc/file.version.html +0 -71
  221. data/doc/file.vista_system.html +0 -69
  222. data/doc/file.win_nix_system.html +0 -88
  223. data/doc/file.win_system.html +0 -129
  224. data/doc/file_list.html +0 -230
  225. data/doc/frames.html +0 -13
  226. data/doc/index.html +0 -96
  227. data/doc/js/app.js +0 -202
  228. data/doc/js/full_list.js +0 -149
  229. data/doc/js/jquery.js +0 -154
  230. data/doc/method_list.html +0 -3355
  231. data/doc/top-level-namespace.html +0 -192
  232. data/lib/sprout/base.rb +0 -121
  233. data/lib/sprout/log.rb +0 -46
  234. data/test/unit/sprout_test_helper.rb +0 -33
@@ -0,0 +1,564 @@
1
+
2
+ module Sprout
3
+ module Executable
4
+ class Base
5
+
6
+ ##
7
+ # Include the Executable module so that Classes
8
+ # defined within it are available to subclasses of Base.
9
+ include Sprout::Executable
10
+
11
+ class << self
12
+ ##
13
+ # +add_param+ is the workhorse of the Task.
14
+ # This method is used to add new shell parameters to the executable interface.
15
+ #
16
+ # +name+ is a symbol or string that represents the parameter that you would like to add
17
+ # such as :debug or :source_path.
18
+ #
19
+ # +type+ is a class reference of the Executable::Param that you'd like to use.
20
+ # At the time of this writing, add_param will accept 2 class references that
21
+ # do not extend Param - String and File. The ParameterFactory will automatically
22
+ # resolve these to the correct data type when they are created.
23
+ #
24
+ # Boolean true or false
25
+ # File Path to a file
26
+ # Number Any number
27
+ # Path Path to a directory
28
+ # String Any string value
29
+ # Url Basic URL
30
+ #
31
+ # Files Collection of files
32
+ # Paths Collection of directories
33
+ # Strings Collection of arbitrary strings
34
+ # Urls Collection of URLs
35
+ #
36
+ # Be sure to check out the Sprout::Executable::Param class to learn more about
37
+ # working with executable parameters.
38
+ #
39
+ # Once parameters have been added using the +add_param+ method, clients
40
+ # can set and get those parameters from any newly created executable instance,
41
+ # or from the command line.
42
+ #
43
+ # In the case of an executable delegate, parameter values will be sent to the
44
+ # command line executable in the order they are added using +add_param+.
45
+ #
46
+ # In the case of a Ruby executable, command line parameters will be interpreted
47
+ # in the order they are defined using +add_param+.
48
+ #
49
+ def add_param(name, type, options=nil) # :yields: Sprout::Executable::Param
50
+ raise Sprout::Errors::UsageError.new "[DEPRECATED] add_param no longer uses closures, you can provide the same values as a hash in the optional last argument." if block_given?
51
+ raise Sprout::Errors::UsageError.new "The first parameter (name:SymbolOrString) is required" if name.nil?
52
+ raise Sprout::Errors::UsageError.new "The second parameter (type:Class) is required" if type.nil?
53
+ raise Sprout::Errors::UsageError.new "The type parameter must be a Class by reference" if !type.is_a?(Class)
54
+
55
+ options ||= {}
56
+ options[:name] = name
57
+ options[:type] = type
58
+ # TODO: Integrate the RDOC-parsed parameter description here:
59
+ #options[:description] ||= Sprout::RDocParser.description_for_caller caller.shift
60
+
61
+ create_param_accessors options
62
+ static_parameter_collection << options
63
+ options
64
+ end
65
+
66
+ def add_param_alias new_name, old_name
67
+ create_param_accessors :name => new_name, :real_name => old_name
68
+ end
69
+
70
+ def static_parameter_collection
71
+ @static_parameter_collection ||= []
72
+ end
73
+
74
+ def static_default_value_collection
75
+ @static_default_value_collection ||= []
76
+ end
77
+
78
+ def set key, value
79
+ set_default_value key, value
80
+ end
81
+
82
+ private
83
+
84
+ def accessor_can_be_defined_at name
85
+ if(instance_defines? name)
86
+ message = "add_param called with a name that is already in use (#{name}=) on (#{self})"
87
+ raise Sprout::Errors::DuplicateMemberError.new(message)
88
+ end
89
+ end
90
+
91
+ def create_param_accessors options
92
+ name = options[:name]
93
+ real_name = options[:real_name] || name
94
+ accessor_can_be_defined_at name
95
+
96
+ # define the writer:
97
+ define_method("#{name}=") do |value|
98
+ if(!options[:writer].nil?)
99
+ value = self.send(options[:writer], value)
100
+ end
101
+ param_hash[real_name].value = value
102
+ instance_variable_set("@#{name}", value)
103
+ end
104
+
105
+ # define the reader:
106
+ define_method(name) do
107
+ if(options[:reader].nil?)
108
+ if(param_hash[real_name].nil?)
109
+ raise Sprout::Errors::UsageError.new "Unable to use requested parameter (#{real_name}) try adding it using:\n\n add_param :#{real_name}, String\n\n"
110
+ end
111
+ param_hash[real_name].value
112
+ else
113
+ self.send(options[:reader])
114
+ end
115
+ end
116
+ end
117
+
118
+ def instance_defines? name
119
+ # In Ruby 1.9.1 instance_methods are symbols,
120
+ # In Ruby 1.8.7 instance_methods are strings.
121
+ # Boo.
122
+ self.instance_methods.include?(name.to_s) ||
123
+ self.instance_methods.include?(name)
124
+ end
125
+
126
+ def set_default_value key, value
127
+ if(!defined? key)
128
+ raise Sprout::Errors::UsageError.new("Cannot set default value (#{value}) for unknown parameter (#{key})")
129
+ end
130
+ static_default_value_collection << { :name => key, :value => value }
131
+ end
132
+ end
133
+
134
+ ##
135
+ # The default RubyGem that we will use when requesting our executable.
136
+ #
137
+ # Classes that include the Executable can set the default value for this property
138
+ # at the class level with:
139
+ #
140
+ # set :pkg_name, 'sprout-sometoolname'
141
+ #
142
+ # But that value can be overridden on each instance like:
143
+ #
144
+ # executable = SomeToolTask.new
145
+ # executable.pkg_name = 'sprout-othertoolname'
146
+ #
147
+ # This parameter is required - either from the including class or instance
148
+ # configuration.
149
+ #
150
+ attr_accessor :pkg_name
151
+
152
+ ##
153
+ # The default RubyGem version that we will use when requesting our executable.
154
+ #
155
+ # Classes that include the Task can set the default value for this property
156
+ # at the class level with:
157
+ #
158
+ # set :pkg_version, '>= 1.0.3'
159
+ #
160
+ # But that value can be overriden on each instance like:
161
+ #
162
+ # executable = SomeToolTask.new
163
+ # too.pkg_version = '>= 2.0.0'
164
+ #
165
+ # This parameter is required - either from the including class or instance
166
+ # configuration.
167
+ #
168
+ attr_accessor :pkg_version
169
+
170
+
171
+ ##
172
+ # The default command line prefix that should be used in front of parameter
173
+ # names.
174
+ #
175
+ # The default value for this parameter is '--', but some command line
176
+ # applications (like MXMLC) prefer '-'.
177
+ #
178
+ attr_accessor :default_prefix
179
+
180
+ ##
181
+ # The default command line prefix for short name parameters.
182
+ #
183
+ # This value defaults to '-', but can be changed to whatever a particular
184
+ # tool prefers.
185
+ #
186
+ attr_accessor :default_short_prefix
187
+
188
+ ##
189
+ # The default Sprout executable that we will use for this executable.
190
+ #
191
+ # Classes that include the Task can set the default value for this property
192
+ # at the class level with:
193
+ #
194
+ # set :executable, :mxmlc
195
+ #
196
+ # But that value can be overriden on each instance like:
197
+ #
198
+ # executable = SomeToolTask.new
199
+ # too.executable :compc
200
+ #
201
+ # This parameter is required - either from the including class or instance
202
+ # configuration.
203
+ #
204
+ attr_accessor :executable
205
+
206
+ ##
207
+ # Configure the executable instance to output failure messages to
208
+ # stderr and abort with non-zero response.
209
+ attr_accessor :abort_on_failure
210
+
211
+ ##
212
+ # If the executable is configured as a Rake::Task, it will extract the
213
+ # Rake::Task[:name] property and apply it to this field.
214
+ #
215
+ # Concrete parameters can pull this value from their +belongs_to+
216
+ # parameter.
217
+ attr_accessor :rake_task_name
218
+
219
+ attr_reader :param_hash
220
+ attr_reader :params
221
+ attr_reader :prerequisites
222
+
223
+ def initialize
224
+ super
225
+ @abort_on_failure = true
226
+ @appended_args = nil
227
+ @prepared = false
228
+ @prepended_args = nil
229
+ @param_hash = {}
230
+ @params = []
231
+ @prerequisites = []
232
+ @option_parser = OptionParser.new
233
+ @default_prefix = DEFAULT_PREFIX
234
+ @default_short_prefix = DEFAULT_SHORT_PREFIX
235
+ initialize_defaults
236
+ initialize_parameters
237
+ end
238
+
239
+ def parse! commandline_options
240
+ begin
241
+ option_parser.parse! commandline_options
242
+ parse_extra_options! commandline_options
243
+ validate unless help_requested? commandline_options
244
+ rescue StandardError => e
245
+ handle_parse_error e
246
+ end
247
+ end
248
+
249
+ ##
250
+ # Execute the feature after calling parse
251
+ # with command line arguments.
252
+ #
253
+ # Subclasses will generally override this method
254
+ # if they are a Ruby executable, but if you're
255
+ # just delegating to an external CLI application,
256
+ # calling execute will wind up executing the
257
+ # external process.
258
+ def execute
259
+ prepare
260
+ execute_delegate
261
+ end
262
+
263
+ def to_rake *args
264
+ # Define the file task first - so that
265
+ # desc blocks hook up to it...
266
+ outer_task = create_outer_task *args
267
+ update_rake_task_name_from_args *args
268
+ yield self if block_given?
269
+ prepare
270
+
271
+ # TODO: Tried auto-updating with library
272
+ # prerequisites, but this led to strange
273
+ # behavior with multiple registrations.
274
+ handle_library_prerequisites outer_task.prerequisites
275
+
276
+ # Add the library resolution rake task
277
+ # as a prerequisite
278
+ outer_task.prerequisites << task(Sprout::Library::TASK_NAME)
279
+ prerequisites.each do |prereq|
280
+ outer_task.prerequisites << prereq
281
+ end
282
+ outer_task
283
+ end
284
+
285
+ ##
286
+ # This will create a hash of ONLY values that are created
287
+ # using +add_param+, properties that are created with
288
+ # attr_accessor must be handled manually, or patches are welcome!
289
+ def to_hash
290
+ result = {}
291
+ params.each do |param|
292
+ result[param.name] = self.send(param.name)
293
+ end
294
+ result
295
+ end
296
+
297
+ ##
298
+ # This will ignore unknown parameters, because our very
299
+ # first use case, is when generators call other generators
300
+ # and generator A might have different parameters than
301
+ # generator B.
302
+ def from_hash hash
303
+ hash.each_pair do |key, value|
304
+ if(self.respond_to?(key))
305
+ self.send "#{key}=", value
306
+ end
307
+ end
308
+ end
309
+
310
+ def to_help
311
+ option_parser.to_s
312
+ end
313
+
314
+ # Create a string that represents this configured executable for shell execution
315
+ def to_shell
316
+ return @to_shell_proc.call(self) unless @to_shell_proc.nil?
317
+
318
+ result = []
319
+ result << @prepended_args unless @prepended_args.nil?
320
+ params.each do |param|
321
+ if(param.visible?)
322
+ result << param.to_shell
323
+ end
324
+ end
325
+ result << @appended_args unless @appended_args.nil?
326
+ return result.join(' ')
327
+ end
328
+
329
+ ##
330
+ # Called by Parameters like :path and :paths
331
+ #
332
+ def default_file_expression
333
+ @default_file_expression ||= Sprout::Executable::DEFAULT_FILE_EXPRESSION
334
+ end
335
+
336
+ protected
337
+
338
+ ##
339
+ # Call the provided executable delegate.
340
+ #
341
+ # This method is generally called from Rake task wrappers.
342
+ #
343
+ def execute_delegate
344
+ system_execute binary_path, to_shell
345
+ end
346
+
347
+ def prepare
348
+ return if @prepared
349
+ @prepared = true
350
+ params.each do |param|
351
+ param.prepare
352
+ end
353
+ end
354
+
355
+ ##
356
+ # Create the outer rake task.
357
+ # For most executables, this will be a Rake::File task,
358
+ # This is a template method that should be overridden
359
+ # for executables that do not result in the creation of
360
+ # a file.
361
+ #
362
+ # @see update_rake_task_name_from_args
363
+ def create_outer_task *args
364
+ file *args do
365
+ execute
366
+ end
367
+ end
368
+
369
+ ##
370
+ # This method will add the current task to the Rake CLEAN
371
+ # collection.
372
+ #
373
+ # Any Executable that does not create a Rake::File task
374
+ # should also override this method and prevent it from
375
+ # calling +CLEAN.add+.
376
+ #
377
+ # @see create_outer_task
378
+ def update_rake_task_name_from_args *args
379
+ self.rake_task_name = parse_rake_task_arg args.last
380
+ CLEAN.add(self.rake_task_name)
381
+ self.rake_task_name
382
+ end
383
+
384
+ def parse_rake_task_arg arg
385
+ return arg if arg.is_a?(Symbol) || arg.is_a?(String)
386
+ arg.each_pair do |key, value|
387
+ return key
388
+ end
389
+ nil
390
+ end
391
+
392
+ def parse_extra_options! options
393
+ options.each do |value|
394
+ params.each do |param|
395
+ if param.hidden_name?
396
+ self.send "#{param.name}=", value
397
+ break
398
+ end
399
+ end
400
+ end
401
+ end
402
+
403
+ ##
404
+ # This method will generally be overridden
405
+ # by subclasses and they can do whatever customization
406
+ # is necessary for a particular library type.
407
+ #
408
+ # It's important to note that this value can be
409
+ # a String path to a file (or folder), or it can
410
+ # be an Array of paths to files (or folders).
411
+ def library_added path_or_paths
412
+ end
413
+
414
+ def system_execute binary, params
415
+ Sprout.current_system.execute binary, params
416
+ end
417
+
418
+ private
419
+
420
+ def binary_path
421
+ Sprout::Executable.load(executable, pkg_name, pkg_version).path
422
+ end
423
+
424
+ def handle_library_prerequisites items
425
+ items.each do |task_name|
426
+ t = Rake.application[task_name]
427
+ if(!t.sprout_entity.nil?)
428
+ library_added t.sprout_entity.installed_project_path
429
+ end
430
+ end
431
+ end
432
+
433
+ def help_requested? options
434
+ options.include? '--help'
435
+ end
436
+
437
+ def handle_parse_error error
438
+ if(abort_on_failure)
439
+ parts = []
440
+ parts << nil
441
+ parts << "[ERROR - #{error.class.name}] #{error.message}"
442
+ parts << nil
443
+ parts << option_parser.to_s
444
+ parts << nil
445
+ abort parts.join("\n")
446
+ else
447
+ raise error
448
+ end
449
+ end
450
+
451
+ def initialize_parameters
452
+ add_help_param
453
+ assembled_parameter_collection.each do |declaration|
454
+ param = initialize_parameter declaration
455
+ short = param.option_parser_short_name
456
+
457
+ option_parser.on short,
458
+ param.option_parser_declaration,
459
+ param.description do |value|
460
+ if(param.is_a?(CollectionParam) && param.delimiter == '+=')
461
+ eval "self.#{param.name} << '#{value}'"
462
+ else
463
+ self.send "#{param.name}=", value
464
+ end
465
+ end
466
+ end
467
+ end
468
+
469
+ def initialize_defaults
470
+ assembled_default_parameter_collection.reverse.each do |option|
471
+ #puts ">> updating default on: #{self} for: #{option[:name]} with: #{option[:value]}"
472
+ self.send "#{option[:name]}=", option[:value]
473
+ end
474
+ end
475
+
476
+ def assembled_parameter_collection
477
+ assembled_static_collection :static_parameter_collection
478
+ end
479
+
480
+ def assembled_default_parameter_collection
481
+ assembled_static_collection :static_default_value_collection
482
+ end
483
+
484
+ def assembled_static_collection collection_name
485
+ collection = []
486
+ inheritance_chain.reverse.each do |clazz|
487
+ if(clazz.respond_to?(collection_name))
488
+ collection.concat clazz.send(collection_name)
489
+ end
490
+ end
491
+ collection
492
+ end
493
+
494
+ def inheritance_chain
495
+ chain = []
496
+ clazz = self.class
497
+ while clazz do
498
+ chain << clazz
499
+ clazz = clazz.superclass
500
+ end
501
+ chain
502
+ end
503
+
504
+ def add_help_param
505
+ option_parser.on '--help', 'Display this help message' do
506
+ puts option_parser.to_s
507
+ exit
508
+ end
509
+ end
510
+
511
+ def initialize_parameter declaration
512
+ name = declaration[:name]
513
+ name_s = name.to_s
514
+ type = declaration[:type]
515
+
516
+ # First ensure the named accessor doesn't yet exist...
517
+ if(parameter_hash_includes? name)
518
+ raise Sprout::Errors::ExecutableError.new("ToolTask.add_param called with existing parameter name: #{name_s}")
519
+ end
520
+
521
+ create_parameter declaration
522
+ end
523
+
524
+ def create_parameter declaration
525
+ param = ParameterFactory.create declaration[:type]
526
+ param.belongs_to = self
527
+
528
+ begin
529
+ declaration.each_pair do |key, value|
530
+ param.send "#{key}=", value
531
+ end
532
+ rescue ArgumentError
533
+ raise Sprout::Errors::UsageError.new "Unexpected parameter option encountered with: #{key} and value: #{value}"
534
+ end
535
+
536
+ raise Sprout::Errors::UsageError.new "Parameter name is required" if(param.name.nil?)
537
+
538
+ param_hash[param.name.to_sym] = param
539
+ params << param
540
+
541
+ # Expose this parameter to command line arguments:
542
+ #add_commandline_param param
543
+
544
+ param
545
+ end
546
+
547
+ def parameter_hash_includes? name
548
+ param_hash.has_key? name.to_sym
549
+ end
550
+
551
+ def validate
552
+ params.each do |param|
553
+ param.validate
554
+ end
555
+ end
556
+
557
+ def option_parser
558
+ @option_parser
559
+ end
560
+
561
+ end
562
+ end
563
+ end
564
+