sprout 0.7.246 → 1.0.0.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 (211) hide show
  1. data/CHANGELOG.md +10 -0
  2. data/Gemfile +28 -0
  3. data/MIT-LICENSE +3 -2
  4. data/POSTINSTALL.rdoc +28 -0
  5. data/README.textile +152 -0
  6. data/bin/sprout +1 -131
  7. data/bin/sprout-generator +10 -0
  8. data/bin/sprout-library +11 -0
  9. data/bin/sprout-tool +10 -0
  10. data/lib/sprout.rb +4 -500
  11. data/lib/sprout/archive_unpacker.rb +122 -206
  12. data/lib/sprout/base.rb +90 -0
  13. data/lib/sprout/concern.rb +30 -0
  14. data/lib/sprout/dir.rb +23 -0
  15. data/lib/sprout/errors.rb +94 -0
  16. data/lib/sprout/executable.rb +496 -0
  17. data/lib/sprout/executable/boolean.rb +35 -0
  18. data/lib/sprout/executable/collection_param.rb +53 -0
  19. data/lib/sprout/executable/file_param.rb +53 -0
  20. data/lib/sprout/executable/files.rb +26 -0
  21. data/lib/sprout/executable/number.rb +10 -0
  22. data/lib/sprout/executable/param.rb +222 -0
  23. data/lib/sprout/executable/parameter_factory.rb +28 -0
  24. data/lib/sprout/executable/path.rb +21 -0
  25. data/lib/sprout/executable/paths.rb +21 -0
  26. data/lib/sprout/executable/string_param.rb +15 -0
  27. data/lib/sprout/executable/strings.rb +11 -0
  28. data/lib/sprout/executable/url.rb +10 -0
  29. data/lib/sprout/executable/urls.rb +10 -0
  30. data/lib/sprout/file_target.rb +76 -0
  31. data/lib/sprout/generator/base.rb +233 -0
  32. data/lib/sprout/generator/command.rb +67 -0
  33. data/lib/sprout/generator/directory_manifest.rb +49 -0
  34. data/lib/sprout/generator/file_manifest.rb +55 -0
  35. data/lib/sprout/generator/manifest.rb +13 -0
  36. data/lib/sprout/generator/template_manifest.rb +13 -0
  37. data/lib/sprout/generators/generator/generator_generator.rb +48 -0
  38. data/lib/sprout/generators/generator/templates/generator_class.rb +17 -0
  39. data/lib/sprout/generators/generator/templates/generator_executable +9 -0
  40. data/lib/sprout/generators/generator/templates/generator_template +1 -0
  41. data/lib/sprout/generators/generator/templates/generator_test.rb +37 -0
  42. data/lib/sprout/generators/generator/templates/generator_test_helper.rb +16 -0
  43. data/lib/sprout/generators/library/library_generator.rb +20 -0
  44. data/lib/sprout/generators/library/templates/library.gemspec +19 -0
  45. data/lib/sprout/generators/library/templates/library.rb +15 -0
  46. data/lib/sprout/generators/ruby/ruby_generator.rb +59 -0
  47. data/lib/sprout/generators/ruby/templates/ruby_base.rb +10 -0
  48. data/lib/sprout/generators/ruby/templates/ruby_executable +6 -0
  49. data/lib/sprout/generators/ruby/templates/ruby_gemfile +4 -0
  50. data/lib/sprout/generators/ruby/templates/ruby_input.rb +7 -0
  51. data/lib/sprout/generators/tool/templates/Gemfile +4 -0
  52. data/lib/sprout/generators/tool/templates/tool.gemspec +22 -0
  53. data/lib/sprout/generators/tool/templates/tool.rb +38 -0
  54. data/lib/sprout/generators/tool/tool_generator.rb +36 -0
  55. data/lib/sprout/library.rb +111 -0
  56. data/lib/sprout/log.rb +1 -0
  57. data/lib/sprout/platform.rb +71 -0
  58. data/lib/sprout/process_runner.rb +80 -40
  59. data/lib/sprout/progress_bar.rb +341 -0
  60. data/lib/sprout/rdoc_parser.rb +91 -0
  61. data/lib/sprout/remote_file_loader.rb +72 -50
  62. data/lib/sprout/remote_file_target.rb +44 -152
  63. data/lib/sprout/ruby_feature.rb +167 -0
  64. data/lib/sprout/specification.rb +197 -0
  65. data/lib/sprout/string.rb +19 -0
  66. data/lib/sprout/system.rb +35 -0
  67. data/lib/sprout/system/base_system.rb +225 -0
  68. data/lib/sprout/system/java_system.rb +9 -0
  69. data/lib/sprout/system/osx_system.rb +26 -0
  70. data/lib/sprout/system/unix_system.rb +72 -0
  71. data/lib/sprout/system/vista_system.rb +16 -0
  72. data/lib/sprout/system/win_nix_system.rb +41 -0
  73. data/lib/sprout/system/win_system.rb +76 -0
  74. data/lib/sprout/test/sprout_test_case.rb +211 -0
  75. data/lib/sprout/version.rb +9 -4
  76. data/rakefile.rb +85 -144
  77. data/script/console +10 -0
  78. data/script/destroy +14 -0
  79. data/script/generate +14 -0
  80. data/sprout.gemspec +26 -0
  81. data/test/fixtures/archive_unpacker/copyable/some_file.exe +0 -0
  82. data/test/fixtures/archive_unpacker/copyable/some_file.rb +0 -0
  83. data/test/fixtures/archive_unpacker/copyable/some_file.swc +0 -0
  84. data/test/fixtures/archive_unpacker/tgz/some folder.tgz +0 -0
  85. data/test/fixtures/archive_unpacker/tgz/some_file.tgz +0 -0
  86. data/test/fixtures/archive_unpacker/zip/some folder.zip +0 -0
  87. data/test/fixtures/archive_unpacker/zip/some_file.zip +0 -0
  88. data/test/fixtures/examples/app_generator.rb +127 -0
  89. data/test/fixtures/examples/echo_inputs.rb +151 -0
  90. data/test/fixtures/executable/echochamber_gem/bin/echochamber +3 -0
  91. data/test/fixtures/executable/echochamber_gem/echo_chamber.rb +10 -0
  92. data/test/fixtures/executable/flex3sdk_gem/flex3sdk.rb +11 -0
  93. data/test/fixtures/executable/flex3sdk_gem/mxmlc +3 -0
  94. data/test/fixtures/executable/flex3sdk_gem/mxmlc.bat +3 -0
  95. data/test/fixtures/executable/mxmlc.rb +805 -0
  96. data/test/fixtures/executable/params/input.as +0 -0
  97. data/test/fixtures/executable/params/input2.as +0 -0
  98. data/test/fixtures/executable/params/input3.as +0 -0
  99. data/test/fixtures/executable/params/mxmlc +5 -0
  100. data/test/fixtures/executable/path with spaces/input.as b/data/test/fixtures/executable/path with → spaces/input.as +0 -0
  101. data/test/fixtures/executable/path with spaces/input2.as b/data/test/fixtures/executable/path with → spaces/input2.as +0 -0
  102. data/test/fixtures/executable/path with spaces/input3.as b/data/test/fixtures/executable/path with → spaces/input3.as +0 -0
  103. data/test/fixtures/executable/paths/folder1/file1 +0 -0
  104. data/test/fixtures/executable/paths/folder1/file2 +0 -0
  105. data/test/fixtures/executable/paths/folder1/file3 +0 -0
  106. data/test/fixtures/executable/paths/folder2/file4 +0 -0
  107. data/test/fixtures/executable/paths/folder2/file5 +0 -0
  108. data/test/fixtures/executable/paths/folder3/file6 +0 -0
  109. data/test/fixtures/executable/src/Main.as +0 -0
  110. data/test/fixtures/executable/windows_line_endings +47 -0
  111. data/test/fixtures/generators/song_generator.rb +11 -0
  112. data/test/fixtures/generators/song_subclass/least_favorite.rb +10 -0
  113. data/test/fixtures/generators/song_subclass/templates/Song.txt +3 -0
  114. data/test/fixtures/generators/temp_generator.rb +24 -0
  115. data/test/fixtures/generators/templates/Main.as +9 -0
  116. data/test/fixtures/generators/templates/OtherFileTemplate +1 -0
  117. data/test/fixtures/generators/templates/SomeFile +1 -0
  118. data/test/fixtures/generators/templates/SomeSubclassFile +2 -0
  119. data/test/fixtures/generators/templates/Song.txt +3 -0
  120. data/test/fixtures/generators/templates/destroy +0 -0
  121. data/test/fixtures/generators/templates/generate +0 -0
  122. data/test/fixtures/library/archive/Archive.swc +0 -0
  123. data/test/fixtures/library/sources/lib/a/A.as +0 -0
  124. data/test/fixtures/library/sources/lib/b/B.as +0 -0
  125. data/test/fixtures/library/sources/src/Source.as +0 -0
  126. data/test/fixtures/process_runner/chmod_script.sh +3 -0
  127. data/test/fixtures/process_runner/dir with spaces/chmod_script.sh +3 -0
  128. data/test/fixtures/process_runner/failure +5 -0
  129. data/test/fixtures/process_runner/success +4 -0
  130. data/test/fixtures/remote_file_loader/md5/echochamber-test.zip +0 -0
  131. data/test/fixtures/remote_file_loader/md5/file_with_known_md5 +0 -0
  132. data/test/fixtures/remote_file_target/bin/echochamber +3 -0
  133. data/test/fixtures/remote_file_target/bin/echochamber.bat +3 -0
  134. data/test/fixtures/remote_file_target/echochamber-test.zip +0 -0
  135. data/test/fixtures/specification/asunit4.rb +25 -0
  136. data/test/fixtures/specification/ext/AsUnit-4.1.pre.swc +0 -0
  137. data/test/fixtures/specification/flashplayer.rb +30 -0
  138. data/test/fixtures/specification/flex4sdk.rb +72 -0
  139. data/test/fixtures/specification/flexunit4.sproutspec +17 -0
  140. data/test/fixtures/specification/lib/as3reflection/Reflection.as +0 -0
  141. data/test/fixtures/specification/src/AsUnit.as +0 -0
  142. data/test/fixtures/user/mxmlc_crlf +3 -0
  143. data/test/unit/archive_unpacker_test.rb +108 -0
  144. data/test/unit/boolean_param_test.rb +38 -0
  145. data/test/unit/executable_option_parser_test.rb +142 -0
  146. data/test/unit/executable_param_test.rb +76 -0
  147. data/test/unit/executable_test.rb +237 -0
  148. data/test/unit/fake_executable_task.rb +22 -0
  149. data/test/unit/fake_other_executable.rb +20 -0
  150. data/test/unit/fake_process_runner.rb +29 -0
  151. data/test/unit/file_param_test.rb +61 -0
  152. data/test/unit/file_target_test.rb +42 -0
  153. data/test/unit/files_param_test.rb +72 -0
  154. data/test/unit/generator_generator_test.rb +85 -0
  155. data/test/unit/generator_test.rb +333 -0
  156. data/test/unit/library_generator_test.rb +41 -0
  157. data/test/unit/library_test.rb +88 -0
  158. data/test/unit/osx_system_test.rb +20 -0
  159. data/test/unit/path_param_test.rb +43 -0
  160. data/test/unit/paths_param_test.rb +53 -0
  161. data/test/unit/platform_test.rb +76 -0
  162. data/test/unit/process_runner_test.rb +104 -0
  163. data/test/unit/rdoc_parser_test.rb +15 -0
  164. data/test/unit/remote_file_loader_test.rb +34 -0
  165. data/test/unit/remote_file_target_test.rb +105 -0
  166. data/test/unit/ruby_feature_test.rb +108 -0
  167. data/test/unit/ruby_generator_test.rb +70 -0
  168. data/test/unit/specification_test.rb +73 -0
  169. data/test/unit/sprout_test.rb +170 -0
  170. data/test/unit/sprout_test_helper.rb +18 -0
  171. data/test/unit/string_param_test.rb +19 -0
  172. data/test/unit/string_test.rb +20 -0
  173. data/test/unit/strings_param_test.rb +27 -0
  174. data/test/unit/test_helper.rb +1 -0
  175. data/test/unit/tool_generator_test.rb +43 -0
  176. data/test/unit/unix_system_test.rb +52 -0
  177. data/test/unit/user_test.rb +147 -0
  178. data/test/unit/vista_system_test.rb +40 -0
  179. data/test/unit/win_nix_system_test.rb +26 -0
  180. data/test/unit/win_system_test.rb +61 -0
  181. metadata +318 -113
  182. data/doc/Bundle +0 -14
  183. data/doc/Generator +0 -35
  184. data/doc/Library +0 -63
  185. data/doc/Task +0 -21
  186. data/doc/Tool +0 -20
  187. data/lib/platform.rb +0 -113
  188. data/lib/progress_bar.rb +0 -354
  189. data/lib/sprout/builder.rb +0 -51
  190. data/lib/sprout/bundle_resolver.rb +0 -349
  191. data/lib/sprout/commands/generate.rb +0 -9
  192. data/lib/sprout/dynamic_accessors.rb +0 -40
  193. data/lib/sprout/general_tasks.rb +0 -6
  194. data/lib/sprout/generator.rb +0 -7
  195. data/lib/sprout/generator/base_mixins.rb +0 -186
  196. data/lib/sprout/generator/named_base.rb +0 -227
  197. data/lib/sprout/project_model.rb +0 -278
  198. data/lib/sprout/simple_resolver.rb +0 -88
  199. data/lib/sprout/tasks/erb_resolver.rb +0 -118
  200. data/lib/sprout/tasks/gem_wrap_task.rb +0 -214
  201. data/lib/sprout/tasks/git_task.rb +0 -134
  202. data/lib/sprout/tasks/library_task.rb +0 -118
  203. data/lib/sprout/tasks/sftp_task.rb +0 -248
  204. data/lib/sprout/tasks/ssh_task.rb +0 -153
  205. data/lib/sprout/tasks/tool_task.rb +0 -836
  206. data/lib/sprout/tasks/zip_task.rb +0 -158
  207. data/lib/sprout/tool_task_model.rb +0 -19
  208. data/lib/sprout/user.rb +0 -415
  209. data/lib/sprout/version_file.rb +0 -89
  210. data/lib/sprout/zip_util.rb +0 -61
  211. data/samples/gem_wrap/rakefile.rb +0 -17
@@ -0,0 +1,23 @@
1
+
2
+ class Dir
3
+
4
+ ##
5
+ # Return true if the directory has no children.
6
+ #
7
+ # Code found here: http://www.ruby-forum.com/topic/84762
8
+ def empty?
9
+ Dir.glob("#{ path }/*", File::FNM_DOTMATCH) do |e|
10
+ return false unless %w( . .. ).include?(File::basename(e))
11
+ end
12
+ return true
13
+ end
14
+
15
+ ##
16
+ # Return true if the provided path has no children.
17
+ #
18
+ # Code found here: http://www.ruby-forum.com/topic/84762
19
+ def self.empty? path
20
+ new(path).empty?
21
+ end
22
+ end
23
+
@@ -0,0 +1,94 @@
1
+
2
+ module Sprout
3
+
4
+ ##
5
+ # A module, below which, all errors should be found.
6
+ #
7
+ module Errors
8
+
9
+ ##
10
+ # A general Sprout Error was encountered.
11
+ class SproutError < StandardError; end
12
+
13
+ ##
14
+ # An error in the Executable was encountered.
15
+ class ExecutableError < SproutError; end
16
+
17
+ ##
18
+ # An error in a Generator was encountered.
19
+ class GeneratorError < SproutError; end
20
+
21
+ ##
22
+ # Unable to find the expected template for a Generator.
23
+ class MissingGeneratorError < GeneratorError; end
24
+
25
+ ##
26
+ # Unable to find the expected template for a Generator.
27
+ class MissingTemplateError < GeneratorError; end
28
+
29
+ ##
30
+ # There was a problem with the requested
31
+ # unpack operation.
32
+ class ArchiveUnpackerError < SproutError; end
33
+
34
+ ##
35
+ # The unpacked file was already found in the destination
36
+ # directory and the ArchiveUnpacker was not asked to clobber.
37
+ class DestinationExistsError < ArchiveUnpackerError; end
38
+
39
+ ##
40
+ # Sprouts was unable to accomplish the request.
41
+ class ExecutionError < SproutError; end
42
+
43
+ ##
44
+ # Requested parameter or accessor already exists.
45
+ class DuplicateMemberError < ExecutableError; end
46
+
47
+ ##
48
+ # Error when registering executables.
49
+ class ExecutableRegistrationError < ExecutableError; end
50
+
51
+ ##
52
+ # Could not find requested ExecutableTarget
53
+ class MissingExecutableError < ExecutableError; end
54
+
55
+ ##
56
+ # Required argument was not provided
57
+ class MissingArgumentError < ExecutableError; end
58
+
59
+ ##
60
+ # An argument was provided that was not valid
61
+ class InvalidArgumentError < ExecutableError; end
62
+
63
+ ##
64
+ # There was an error in ProcessRunner
65
+ class ProcessRunnerError < SproutError; end
66
+
67
+ ##
68
+ # There was a problem requiring a requested file
69
+ class LoadError < SproutError; end
70
+
71
+ ##
72
+ # Error on remote file download
73
+ class RemoteFileLoaderError < StandardError; end
74
+
75
+ ##
76
+ # An unexpected input was used or method was called.
77
+ class UsageError < SproutError; end
78
+
79
+ ##
80
+ # Can't figure out how to unpack this type of file.
81
+ # Try again with a .zip, .tgz, or .tar.gz
82
+ class UnknownArchiveType < SproutError; end
83
+
84
+ ##
85
+ # Error when a feature is not in a valid state
86
+ class ValidationError < SproutError; end
87
+
88
+ ##
89
+ # Could not meet the requested version requirement.
90
+ class VersionRequirementNotMetError < SproutError; end
91
+
92
+ end
93
+ end
94
+
@@ -0,0 +1,496 @@
1
+ require 'sprout/executable/param'
2
+ require 'sprout/executable/collection_param'
3
+ require 'sprout/executable/boolean'
4
+ require 'sprout/executable/number'
5
+ require 'sprout/executable/string_param'
6
+ require 'sprout/executable/strings'
7
+ require 'sprout/executable/file_param'
8
+ require 'sprout/executable/files'
9
+ require 'sprout/executable/path'
10
+ require 'sprout/executable/paths'
11
+ require 'sprout/executable/url'
12
+ require 'sprout/executable/urls'
13
+ require 'sprout/executable/parameter_factory'
14
+
15
+ module Sprout
16
+
17
+ ##
18
+ # The Sprout::Executable module is a Domain Specific Language
19
+ # for describing Command Line Interface (CLI) applications.
20
+ #
21
+ # This module can be included by any class, and depending on how that class
22
+ # is used, one can either parse command line arguments into meaningful,
23
+ # structured data, or delegate ruby code and configuration to an existing,
24
+ # external command line process.
25
+ #
26
+ # Following is an example of how one could define an executable Ruby
27
+ # application using this module:
28
+ #
29
+ # :include: ../../test/fixtures/examples/echo_inputs.rb
30
+ #
31
+ module Executable
32
+ include RubyFeature
33
+
34
+ DEFAULT_FILE_EXPRESSION = '/**/**/*'
35
+ DEFAULT_PREFIX = '--'
36
+ DEFAULT_SHORT_PREFIX = '-'
37
+
38
+ extend Concern
39
+
40
+ module ClassMethods
41
+ ##
42
+ # +add_param+ is the workhorse of the Task.
43
+ # This method is used to add new shell parameters to the executable interface.
44
+ #
45
+ # +name+ is a symbol or string that represents the parameter that you would like to add
46
+ # such as :debug or :source_path.
47
+ #
48
+ # +type+ is a class reference of the Executable::Param that you'd like to use.
49
+ # At the time of this writing, add_param will accept 2 class references that
50
+ # do not extend Param - String and File. The ParameterFactory will automatically
51
+ # resolve these to the correct data type when they are created.
52
+ #
53
+ # Boolean true or false
54
+ # File Path to a file
55
+ # Number Any number
56
+ # Path Path to a directory
57
+ # String Any string value
58
+ # Url Basic URL
59
+ #
60
+ # Files Collection of files
61
+ # Paths Collection of directories
62
+ # Strings Collection of arbitrary strings
63
+ # Urls Collection of URLs
64
+ #
65
+ # Be sure to check out the Sprout::Executable::Param class to learn more about
66
+ # working with executable parameters.
67
+ #
68
+ # Once parameters have been added using the +add_param+ method, clients
69
+ # can set and get those parameters from any newly created executable instance,
70
+ # or from the command line.
71
+ #
72
+ # In the case of an executable delegate, parameter values will be sent to the
73
+ # command line executable in the order they are added using +add_param+.
74
+ #
75
+ # In the case of a Ruby executable, command line parameters will be interpreted
76
+ # in the order they are defined using +add_param+.
77
+ #
78
+ def add_param(name, type, options=nil) # :yields: Sprout::Executable::Param
79
+ 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?
80
+ raise Sprout::Errors::UsageError.new "The first parameter (name:SymbolOrString) is required" if name.nil?
81
+ raise Sprout::Errors::UsageError.new "The second parameter (type:Class) is required" if type.nil?
82
+ raise Sprout::Errors::UsageError.new "The type parameter must be a Class by reference" if !type.is_a?(Class)
83
+
84
+ options ||= {}
85
+ options[:name] = name
86
+ options[:type] = type
87
+ #options[:description] ||= Sprout::RDocParser.description_for_caller caller.shift
88
+
89
+ create_param_accessors options
90
+ static_parameter_collection << options
91
+ options
92
+ end
93
+
94
+ def add_param_alias new_name, old_name
95
+ create_param_accessors :name => new_name, :real_name => old_name
96
+ end
97
+
98
+ def static_parameter_collection
99
+ @static_parameter_collection ||= []
100
+ end
101
+
102
+ def static_default_value_collection
103
+ @static_default_value_collection ||= []
104
+ end
105
+
106
+ def set key, value
107
+ set_default_value key, value
108
+ end
109
+
110
+ private
111
+
112
+ def accessor_can_be_defined_at name
113
+ if(instance_defines? name)
114
+ message = "add_param called with a name that is already in use (#{name}=) on (#{self})"
115
+ raise Sprout::Errors::DuplicateMemberError.new(message)
116
+ end
117
+ end
118
+
119
+ def create_param_accessors options
120
+ name = options[:name]
121
+ real_name = options[:real_name] || name
122
+ accessor_can_be_defined_at name
123
+
124
+ # define the writer:
125
+ define_method("#{name}=") do |value|
126
+ if(!options[:writer].nil?)
127
+ value = self.send(options[:writer], value)
128
+ end
129
+ param_hash[real_name].value = value
130
+ instance_variable_set("@#{name}", value)
131
+ end
132
+
133
+ # define the reader:
134
+ define_method(name) do
135
+ if(options[:reader].nil?)
136
+ if(param_hash[real_name].nil?)
137
+ 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"
138
+ end
139
+ param_hash[real_name].value
140
+ else
141
+ self.send(options[:reader])
142
+ end
143
+ end
144
+ end
145
+
146
+ def instance_defines? name
147
+ # In Ruby 1.9.1 instance_methods are symbols,
148
+ # In Ruby 1.8.7 instance_methods are strings.
149
+ # Boo.
150
+ self.instance_methods.include?(name.to_s) ||
151
+ self.instance_methods.include?(name)
152
+ end
153
+
154
+ def set_default_value key, value
155
+ if(!defined? key)
156
+ raise Sprout::Errors::UsageError.new("Cannot set default value (#{value}) for unknown parameter (#{key})")
157
+ end
158
+ static_default_value_collection << { :name => key, :value => value }
159
+ end
160
+ end
161
+
162
+ module InstanceMethods
163
+ ##
164
+ # The default RubyGem that we will use when requesting our executable.
165
+ #
166
+ # Classes that include the Executable can set the default value for this property
167
+ # at the class level with:
168
+ #
169
+ # set :pkg_name, 'sprout-sometoolname'
170
+ #
171
+ # But that value can be overridden on each instance like:
172
+ #
173
+ # executable = SomeToolTask.new
174
+ # executable.pkg_name = 'sprout-othertoolname'
175
+ #
176
+ # This parameter is required - either from the including class or instance
177
+ # configuration.
178
+ #
179
+ attr_accessor :pkg_name
180
+
181
+ ##
182
+ # The default RubyGem version that we will use when requesting our executable.
183
+ #
184
+ # Classes that include the Task can set the default value for this property
185
+ # at the class level with:
186
+ #
187
+ # set :pkg_version, '>= 1.0.3'
188
+ #
189
+ # But that value can be overriden on each instance like:
190
+ #
191
+ # executable = SomeToolTask.new
192
+ # too.pkg_version = '>= 2.0.0'
193
+ #
194
+ # This parameter is required - either from the including class or instance
195
+ # configuration.
196
+ #
197
+ attr_accessor :pkg_version
198
+
199
+
200
+ ##
201
+ # The default command line prefix that should be used in front of parameter
202
+ # names.
203
+ #
204
+ # The default value for this parameter is '--', but some command line
205
+ # applications (like MXMLC) prefer '-'.
206
+ #
207
+ attr_accessor :default_prefix
208
+
209
+ ##
210
+ # The default command line prefix for short name parameters.
211
+ #
212
+ # This value defaults to '-', but can be changed to whatever a particular
213
+ # tool prefers.
214
+ #
215
+ attr_accessor :default_short_prefix
216
+
217
+ ##
218
+ # The default Sprout executable that we will use for this executable.
219
+ #
220
+ # Classes that include the Task can set the default value for this property
221
+ # at the class level with:
222
+ #
223
+ # set :executable, :mxmlc
224
+ #
225
+ # But that value can be overriden on each instance like:
226
+ #
227
+ # executable = SomeToolTask.new
228
+ # too.executable :compc
229
+ #
230
+ # This parameter is required - either from the including class or instance
231
+ # configuration.
232
+ #
233
+ attr_accessor :executable
234
+
235
+ ##
236
+ # Configure the executable instance to output failure messages to
237
+ # stderr and abort with non-zero response.
238
+ attr_accessor :abort_on_failure
239
+
240
+ ##
241
+ # If the executable is configured as a Rake::Task, it will extract the
242
+ # Rake::Task[:name] property and apply it to this field.
243
+ #
244
+ # Concrete parameters can pull this value from their +belongs_to+
245
+ # parameter.
246
+ attr_accessor :rake_task_name
247
+
248
+ attr_reader :param_hash
249
+ attr_reader :params
250
+ attr_reader :prerequisites
251
+
252
+ def initialize
253
+ super
254
+ @abort_on_failure = true
255
+ @appended_args = nil
256
+ @prepended_args = nil
257
+ @param_hash = {}
258
+ @params = []
259
+ @prerequisites = []
260
+ @option_parser = OptionParser.new
261
+ @default_prefix = DEFAULT_PREFIX
262
+ @default_short_prefix = DEFAULT_SHORT_PREFIX
263
+ initialize_parameters
264
+ initialize_defaults
265
+ end
266
+
267
+ def parse! commandline_options
268
+ begin
269
+ option_parser.parse! commandline_options
270
+ parse_extra_options! commandline_options
271
+ validate unless help_requested? commandline_options
272
+ rescue StandardError => e
273
+ handle_parse_error e
274
+ end
275
+ end
276
+
277
+ ##
278
+ # Execute the feature after calling parse
279
+ # with command line arguments.
280
+ #
281
+ # Subclasses will generally override this method
282
+ # if they are a Ruby executable, but if you're
283
+ # just delegating to an external CLI application,
284
+ # calling execute will wind up executing the
285
+ # external process.
286
+ def execute
287
+ execute_delegate
288
+ end
289
+
290
+ ##
291
+ # Call the provided executable delegate.
292
+ #
293
+ # This method is generally called from Rake task wrappers.
294
+ #
295
+ def execute_delegate
296
+ exe = Sprout::Executable.load(executable, pkg_name, pkg_version).path
297
+ Sprout.current_system.execute exe, to_shell
298
+ end
299
+
300
+ def prepare
301
+ params.each do |param|
302
+ param.prepare
303
+ end
304
+ end
305
+
306
+ def to_rake args
307
+ update_rake_task_name_from_args args
308
+ yield self if block_given?
309
+ prepare
310
+ file_task = file args do
311
+ execute
312
+ end
313
+ file_task.prerequisites << task(Sprout::Library::TASK_NAME)
314
+ prerequisites.each do |prereq|
315
+ file_task.prerequisites << prereq
316
+ end
317
+ file_task
318
+ end
319
+
320
+ def to_help
321
+ option_parser.to_s
322
+ end
323
+
324
+ # Create a string that represents this configured executable for shell execution
325
+ def to_shell
326
+ return @to_shell_proc.call(self) unless @to_shell_proc.nil?
327
+
328
+ result = []
329
+ result << @prepended_args unless @prepended_args.nil?
330
+ params.each do |param|
331
+ if(param.visible?)
332
+ result << param.to_shell
333
+ end
334
+ end
335
+ result << @appended_args unless @appended_args.nil?
336
+ return result.join(' ')
337
+ end
338
+
339
+ ##
340
+ # Called by Parameters like :path and :paths
341
+ #
342
+ def default_file_expression
343
+ @default_file_expression ||= Sprout::Executable::DEFAULT_FILE_EXPRESSION
344
+ end
345
+
346
+ protected
347
+
348
+ def update_rake_task_name_from_args args
349
+ self.rake_task_name = parse_rake_task_args args
350
+ end
351
+
352
+ def parse_rake_task_args args
353
+ return args if args.is_a?(Symbol) || args.is_a?(String)
354
+ args.each_pair do |key, value|
355
+ return key
356
+ end
357
+ nil
358
+ end
359
+
360
+ def parse_extra_options! options
361
+ options.each do |value|
362
+ params.each do |param|
363
+ if param.hidden_name?
364
+ self.send "#{param.name}=", value
365
+ break
366
+ end
367
+ end
368
+ end
369
+ end
370
+
371
+ private
372
+
373
+ def help_requested? options
374
+ options.include? '--help'
375
+ end
376
+
377
+ def handle_parse_error error
378
+ if(abort_on_failure)
379
+ parts = []
380
+ parts << nil
381
+ parts << "[ERROR - #{error.class.name}] #{error.message}"
382
+ parts << nil
383
+ parts << option_parser.to_s
384
+ parts << nil
385
+ abort parts.join("\n")
386
+ else
387
+ raise error
388
+ end
389
+ end
390
+
391
+ def initialize_parameters
392
+ add_help_param
393
+ assembled_parameter_collection.each do |declaration|
394
+ param = initialize_parameter declaration
395
+ short = param.option_parser_short_name
396
+
397
+ option_parser.on short,
398
+ param.option_parser_declaration,
399
+ param.description do |value|
400
+ if(param.is_a?(CollectionParam) && param.delimiter == '+=')
401
+ eval "self.#{param.name} << '#{value}'"
402
+ else
403
+ self.send "#{param.name}=", value
404
+ end
405
+ end
406
+ end
407
+ end
408
+
409
+ def initialize_defaults
410
+ assembled_default_parameter_collection.reverse.each do |option|
411
+ #puts ">> updating default on: #{self} for: #{option[:name]} with: #{option[:value]}"
412
+ self.send "#{option[:name]}=", option[:value]
413
+ end
414
+ end
415
+
416
+ def assembled_parameter_collection
417
+ assembled_static_collection :static_parameter_collection
418
+ end
419
+
420
+ def assembled_default_parameter_collection
421
+ assembled_static_collection :static_default_value_collection
422
+ end
423
+
424
+ def assembled_static_collection collection_name
425
+ collection = []
426
+ clazz = self.class
427
+ while clazz do
428
+ if clazz.respond_to?(collection_name)
429
+ collection.concat clazz.send(collection_name)
430
+ end
431
+ clazz = clazz.superclass
432
+ end
433
+ collection
434
+ end
435
+
436
+ def add_help_param
437
+ option_parser.on '--help', 'Display this help message' do
438
+ puts option_parser.to_s
439
+ exit
440
+ end
441
+ end
442
+
443
+ def initialize_parameter declaration
444
+ name = declaration[:name]
445
+ name_s = name.to_s
446
+ type = declaration[:type]
447
+
448
+ # First ensure the named accessor doesn't yet exist...
449
+ if(parameter_hash_includes? name)
450
+ raise Sprout::Errors::ExecutableError.new("ToolTask.add_param called with existing parameter name: #{name_s}")
451
+ end
452
+
453
+ create_parameter declaration
454
+ end
455
+
456
+ def create_parameter declaration
457
+ param = ParameterFactory.create declaration[:type]
458
+ param.belongs_to = self
459
+
460
+ begin
461
+ declaration.each_pair do |key, value|
462
+ param.send "#{key}=", value
463
+ end
464
+ rescue ArgumentError
465
+ raise Sprout::Errors::UsageError.new "Unexpected parameter option encountered with: #{key} and value: #{value}"
466
+ end
467
+
468
+ raise Sprout::Errors::UsageError.new "Parameter name is required" if(param.name.nil?)
469
+
470
+ param_hash[param.name.to_sym] = param
471
+ params << param
472
+
473
+ # Expose this parameter to command line arguments:
474
+ #add_commandline_param param
475
+
476
+ param
477
+ end
478
+
479
+ def parameter_hash_includes? name
480
+ param_hash.has_key? name.to_sym
481
+ end
482
+
483
+ def validate
484
+ params.each do |param|
485
+ param.validate
486
+ end
487
+ end
488
+
489
+ def option_parser
490
+ @option_parser
491
+ end
492
+
493
+ end
494
+ end
495
+ end
496
+