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,38 @@
1
+ require 'sprout'
2
+
3
+ class <%= input.camel_case %>
4
+ NAME = '<%= input.snake_case %>'
5
+
6
+ module VERSION
7
+ MAJOR = 0
8
+ MINOR = 0
9
+ TINY = 1
10
+
11
+ STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
12
+ end
13
+
14
+ Sprout::Specification.new do |s|
15
+ s.name = <%= input.camel_case %>::NAME
16
+ s.version = <%= input.camel_case %>::VERSION::STRING
17
+
18
+ # Create an independent remote_file_target for each
19
+ # platform that must be supported independently.
20
+ #
21
+ # If the archive includes support for all platforms (:windows, :osx, :unix)
22
+ # then set platform = :universal
23
+ #
24
+ s.add_remote_file_target do |t|
25
+ t.platform = :universal
26
+ t.archive_type = :zip
27
+ t.url = "<%= url %>"
28
+ t.md5 = "<%= md5 %>"
29
+
30
+ # List all executables with their relative path within the
31
+ # unpacked archive here:
32
+ t.add_executable :<%= exe %>, "bin/<%= exe %>"
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+
@@ -0,0 +1,36 @@
1
+
2
+ module Sprout
3
+ class ToolGenerator < Generator::Base
4
+
5
+ add_param :author, String, { :default => 'Unknown' }
6
+
7
+ add_param :description, String, { :default => 'This is an unconfigured Sprout Tool' }
8
+
9
+ add_param :email, String, { :default => 'projectsprout@googlegroups.com' }
10
+
11
+ add_param :exe, String, { :default => 'executable_name' }
12
+
13
+ add_param :homepage, String, { :default => 'http://projectsprouts.org' }
14
+
15
+ add_param :md5, String, { :default => 'd6939117f1df58e216f365a12fec64f9' }
16
+
17
+ add_param :summary, String, { :default => 'Sprout Tool' }
18
+
19
+ add_param :url, String, { :default => 'http://github.com/downloads/lukebayes/project-sprouts/echochamber-test.zip' }
20
+
21
+ def manifest
22
+ directory snake_input do
23
+ template 'Gemfile'
24
+ template "#{snake_input}.gemspec", 'tool.gemspec'
25
+ template "#{snake_input}.rb", 'tool.rb'
26
+ end
27
+ end
28
+
29
+ protected
30
+
31
+ def snake_input
32
+ input.snake_case
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,111 @@
1
+
2
+ module Sprout
3
+ module Library
4
+ TASK_NAME = :resolve_sprout_libraries
5
+
6
+ include RubyFeature
7
+
8
+ class << self
9
+
10
+ ##
11
+ # Set the path within a project
12
+ # where libraries should be loaded.
13
+ def project_path=(path)
14
+ @project_path = path
15
+ end
16
+
17
+ ##
18
+ # The path within a project where
19
+ # libraries should be added.
20
+ #
21
+ # Defaults to 'lib'
22
+ def project_path
23
+ @project_path ||= 'lib'
24
+ end
25
+
26
+ ##
27
+ # Create Rake tasks that will load and install
28
+ # a particular library.
29
+ def define_task pkg_name, type=nil, version=nil
30
+ library = Sprout::Library.load type, pkg_name, version
31
+ library.installation_task = task pkg_name
32
+
33
+ define_lib_dir_task_if_necessary
34
+ path_or_paths = library.path
35
+ if path_or_paths.is_a?(Array)
36
+ # TODO: Need to add support for merging these directories
37
+ # rather than simply clobbering...
38
+ path_or_paths.each { |p| define_path_task pkg_name, library, p }
39
+ else
40
+ define_path_task pkg_name, library, path_or_paths
41
+ end
42
+ library
43
+ end
44
+
45
+ protected
46
+
47
+ def define_lib_dir_task_if_necessary
48
+ if !File.exists?(project_path)
49
+ define_file_task project_path do
50
+ FileUtils.mkdir_p project_path
51
+ Sprout::Log.puts ">> Created directory at: #{project_path}"
52
+ end
53
+ end
54
+ end
55
+
56
+ def define_path_task pkg_name, library, path
57
+ installation_path = "#{project_path}/#{pkg_name}"
58
+ if File.directory?(path)
59
+ define_directory_copy_task path, installation_path
60
+ else
61
+ define_file_copy_task path, installation_path
62
+ end
63
+ end
64
+
65
+ def define_directory_copy_task path, installation_path
66
+ define_file_task installation_path do
67
+ FileUtils.cp_r path, installation_path
68
+ Sprout::Log.puts ">> Copied files from: (#{path}) to: (#{installation_path})"
69
+ end
70
+ end
71
+
72
+ def define_file_copy_task path, installation_path
73
+ task_name = "#{installation_path}/#{File.basename(path)}"
74
+ define_file_task task_name do
75
+ FileUtils.mkdir_p installation_path
76
+ FileUtils.cp path, "#{installation_path}/"
77
+ Sprout::Log.puts ">> Copied file from: (#{path}) to: (#{task_name})"
78
+ end
79
+ end
80
+
81
+ def define_file_task name
82
+ file name do |t|
83
+ yield if block_given?
84
+ end
85
+ task Sprout::Library::TASK_NAME => name
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ # From within a Rakefile, you can load libraries
94
+ # by calling this shortcut:
95
+ #
96
+ # library :asunit4
97
+ #
98
+ # Or, if you would like to specify which registered
99
+ # library to pull from the identified package:
100
+ #
101
+ # library :asunit4, :src
102
+ #
103
+ # Or, if you'd like to specify version requirements:
104
+ #
105
+ # library :asunit4, :swc, '>= 4.2.pre'
106
+ #
107
+ def library pkg_name, type=nil, version=nil
108
+ puts ">> Library loaded!"
109
+ Sprout::Library.define_task pkg_name, type, version
110
+ end
111
+
@@ -44,3 +44,4 @@ module Sprout #:nodoc:
44
44
  end
45
45
  end
46
46
  end
47
+
@@ -0,0 +1,71 @@
1
+
2
+ module Sprout
3
+
4
+ ##
5
+ # Determine what environment we're in so that we
6
+ # can play nice with libraries, processes, executables, etc.
7
+ #
8
+ class Platform
9
+
10
+ ##
11
+ # Returns +true+ if the current platform is some flavor of Windows.
12
+ #
13
+ def windows?
14
+ (/cygwin|mswin|mingw|bccwin|wince|emx|vista/ =~ ruby_platform) != nil
15
+ end
16
+
17
+ ##
18
+ # Returns +true+ if the current platform is Vista.
19
+ #
20
+ def vista?
21
+ (/vista/ =~ ruby_platform) != nil
22
+ end
23
+
24
+ ##
25
+ # Returns +true+ if the current platform is some flavor of Unix on
26
+ # Windows. Recognized nix-ish systems are: Cygwin, Mingw and BCCWin.
27
+ #
28
+ def windows_nix?
29
+ (/cygwin|mingw|bccwin/ =~ ruby_platform) != nil
30
+ end
31
+
32
+ ##
33
+ # Returns +true+ if the current platform is some flash of OS X.
34
+ #
35
+ def mac?
36
+ (/darwin/ =~ ruby_platform) != nil
37
+ end
38
+
39
+ ##
40
+ # Returns +true+ if the current platform is not +windows?+ or +java?+.
41
+ #
42
+ def unix?
43
+ not windows? and not java?
44
+ end
45
+
46
+ ##
47
+ # Returns +true+ if the current platform is +unix?+ and not +mac?+.
48
+ #
49
+ def linux?
50
+ unix? and not mac?
51
+ end
52
+
53
+ ##
54
+ # Returns +true+ if the current platform is running in the JVM (JRuby).
55
+ #
56
+ def java?
57
+ (/java/ =~ ruby_platform) != nil
58
+ end
59
+
60
+ ##
61
+ # Instance wrapper for the global Ruby Constant, +RUBY_PLATFORM+.
62
+ #
63
+ # wrapping this global allows for much easier testing and environment simulation.
64
+ #
65
+ def ruby_platform
66
+ RUBY_PLATFORM
67
+ end
68
+
69
+ end
70
+ end
71
+
@@ -1,55 +1,42 @@
1
1
 
2
2
  module Sprout #:nodoc:
3
- class ProcessRunnerError < StandardError # :nodoc:
4
- end
5
-
6
- class ProcessRunner #:nodoc:
3
+
4
+ # The ProcessRunner is a cross-platform wrapper for executing
5
+ # external executable processes.
6
+ #
7
+ # As it turns out, Ruby handle differences very well, and
8
+ # other process libraries (like win32-open3 and open4.popen4),
9
+ # do make the experience more consistent on a given platform,
10
+ # but they don't hide the differences introduced by the
11
+ # continuing beligerence of Windows or *nix (depending on
12
+ # which side of the fence you're on).
13
+ class ProcessRunner
7
14
  attr_reader :pid,
8
15
  :r,
9
16
  :w,
10
17
  :e
11
18
 
12
- def initialize(*command)
13
- @command = command
14
- begin
15
- @alive = true
16
- usr = User.new()
17
- if(usr.is_a?(WinUser) && !usr.is_a?(CygwinUser))
18
- gem 'win32-open3'
19
- require 'win32/open3'
20
- Open3.popen3(*@command) do |w, r, e, pid|
21
- @w = w
22
- @r = r
23
- @e = e
24
- @pid = pid
25
- end
26
- else
27
- require 'open4'
28
- @pid, @w, @r, @e = open4.popen4(*@command)
29
- end
30
- rescue Errno::EACCES => e
31
- update_executable_mode(*@command)
32
- @pid, @w, @r, @e = open4.popen4(*@command)
33
- rescue Errno::ENOENT => e
34
- @alive = false
35
- part = command[0].split(' ').shift
36
- raise ProcessRunnerError.new("The expected executable was not found for command [#{part}], please check your system path and/or sprout definition")
19
+ # Execute the provided command using the open4.popen4
20
+ # library. This is generally only used by Cygwin and
21
+ # *nix variants (including OS X).
22
+ def execute_open4 *command
23
+ execute_with_block *command do
24
+ # Not sure about the join - with the 1.0 push, we're
25
+ # sending in 2 args - the exe path, and options as a string.
26
+ # This was new and was causing problems...
27
+ @pid, @w, @r, @e = open4_popen4_block *command.join(' ')
37
28
  end
38
29
  end
39
30
 
40
- def update_executable_mode(*command)
41
- parts = command.join(' ').split(' ')
42
- str = parts.shift
43
- while(parts.size > 0)
44
- if(File.exists?(str))
45
- FileUtils.chmod(744, str)
46
- return
47
- else
48
- str << " #{parts.shift}"
49
- end
31
+ # Execute the provided command using the win32-open3
32
+ # library. This is generally used even by 64-bit
33
+ # Windows installations.
34
+ def execute_win32(*command)
35
+ execute_with_block *command do
36
+ @pid, @w, @r, @e = io_popen_block *command.join(' ')
50
37
  end
51
38
  end
52
-
39
+
53
40
  def alive?
54
41
  @alive = update_status
55
42
  end
@@ -107,5 +94,58 @@ module Sprout #:nodoc:
107
94
  def read_err
108
95
  return @e.read
109
96
  end
97
+
98
+ private
99
+
100
+ def open4_popen4_block *command
101
+ require 'open4'
102
+ open4.popen4(*command)
103
+ end
104
+
105
+ def io_popen_block *command
106
+ if(RUBY_VERSION == '1.8.6' || RUBY_VERSION == '1.8.7')
107
+ win32_open3_block *command
108
+ else
109
+ require 'open3'
110
+ write, read, error, wait_thread = Open3.popen3(*command)
111
+ [wait_thread[:pid], write, read, error]
112
+ end
113
+ end
114
+
115
+ def win32_open3_block *command
116
+ write, read, error, pid = nil
117
+ gem 'win32-open3', '0.2.5'
118
+ require 'win32/open3'
119
+ Open3.popen3(*command) do |w, r, e, p|
120
+ pid = p
121
+ write = w
122
+ read = r
123
+ error = e
124
+ end
125
+ [pid, write, read, error]
126
+ end
127
+
128
+ def execute_with_block *command
129
+ begin
130
+ @alive = true
131
+ yield
132
+ rescue Errno::EACCES => eacces
133
+ update_executable_mode(*command)
134
+ yield
135
+ rescue Errno::ENOENT => enoent
136
+ @alive = false
137
+ part = command[0]
138
+ raise Sprout::Errors::ProcessRunnerError.new("The expected executable was not found for command [#{part}], please check your system path and/or sprout definition")
139
+ end
140
+ end
141
+
142
+ def update_executable_mode(*command)
143
+ str = command.shift
144
+ if(File.exists?(str))
145
+ FileUtils.chmod(0744, str)
146
+ end
147
+ end
148
+
110
149
  end
111
150
  end
151
+
@@ -0,0 +1,341 @@
1
+ # Ruby/ProgressBar - a text progress bar library
2
+ #
3
+ # Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
4
+ # All rights reserved.
5
+ # This is free software with ABSOLUTELY NO WARRANTY.
6
+ #
7
+ # You can redistribute it and/or modify it under the terms
8
+ # of Ruby's license.
9
+ #
10
+ # Modified by Luke Bayes to support progress display on
11
+ # multiple simultaneous connections, and to silence output
12
+ # during test runs.
13
+ require 'singleton'
14
+
15
+ module Sprout
16
+ class ProgressBar # :nodoc:[all]
17
+ VERSION = "0.9"
18
+ @@debug = false
19
+ @@outio = $stderr
20
+
21
+ def self.new(title, total)
22
+ return ProgressBarManager.instance.add(title, total)
23
+ end
24
+
25
+ def self.debug?
26
+ @@debug
27
+ end
28
+
29
+ def self.debug=(debug)
30
+ @@debug = debug
31
+ if(debug)
32
+ @@outio = StringIO.new
33
+ else
34
+ @@outio = $stderr
35
+ end
36
+ end
37
+
38
+ def self.outio
39
+ @@outio
40
+ end
41
+
42
+ end
43
+
44
+ class ProgressBarImpl # :nodoc:[all]
45
+
46
+ def initialize (title, total, out = STDERR)
47
+ @title = title
48
+ @total = total
49
+ @out = out
50
+ @terminal_width = 80
51
+ @bar_mark = "."
52
+ @current = 0
53
+ @previous = 0
54
+ @finished_p = false
55
+ @start_time = Time.now
56
+ @previous_time = @start_time
57
+ @title_width = 18
58
+ @format = "%-#{@title_width}s %3d%% %s %s"
59
+ @format_arguments = [:title, :percentage, :bar, :stat]
60
+ clear
61
+ show
62
+ end
63
+ attr_reader :title
64
+ attr_reader :current
65
+ attr_reader :total
66
+ attr_accessor :start_time,
67
+ :title_width,
68
+ :bar_mark
69
+
70
+ def fmt_bar
71
+ bar_width = do_percentage * @terminal_width / 100
72
+ sprintf("|%s%s|",
73
+ @bar_mark * bar_width,
74
+ " " * (@terminal_width - bar_width))
75
+ end
76
+
77
+ def fmt_percentage
78
+ do_percentage
79
+ end
80
+
81
+ def fmt_stat
82
+ if @finished_p then elapsed else eta end
83
+ end
84
+
85
+ def fmt_stat_for_file_transfer
86
+ if @finished_p then
87
+ sprintf("%s %s %s", bytes, transfer_rate, elapsed)
88
+ else
89
+ sprintf("%s %s %s", bytes, transfer_rate, eta)
90
+ end
91
+ end
92
+
93
+ def fmt_title
94
+ @title[0,(@title_width - 1)] + ":"
95
+ end
96
+
97
+ def convert_bytes (bytes)
98
+ if bytes < 1024
99
+ sprintf("%6dB", bytes)
100
+ elsif bytes < 1024 * 1000 # 1000kb
101
+ sprintf("%5.1fKB", bytes.to_f / 1024)
102
+ elsif bytes < 1024 * 1024 * 1000 # 1000mb
103
+ sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
104
+ else
105
+ sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
106
+ end
107
+ end
108
+
109
+ def transfer_rate
110
+ bytes_per_second = @current.to_f / (Time.now - @start_time)
111
+ sprintf("%s/s", convert_bytes(bytes_per_second))
112
+ end
113
+
114
+ def bytes
115
+ convert_bytes(@current)
116
+ end
117
+
118
+ def format_time (t)
119
+ t = t.to_i
120
+ sec = t % 60
121
+ min = (t / 60) % 60
122
+ hour = t / 3600
123
+ sprintf("%02d:%02d:%02d", hour, min, sec)
124
+ end
125
+
126
+ # ETA stands for Estimated Time of Arrival.
127
+ def eta
128
+ if @current == 0
129
+ "ETA: --:--:--"
130
+ else
131
+ elapsed_time = Time.now - @start_time
132
+ estimated_time = elapsed_time * @total / @current - elapsed_time
133
+ sprintf("ETA: %s", format_time(estimated_time))
134
+ end
135
+ end
136
+
137
+ def elapsed
138
+ elapsed_time = Time.now - @start_time
139
+ sprintf("Time: %s", format_time(elapsed_time))
140
+ end
141
+
142
+ def eol
143
+ if @finished_p then "\n" else "\r" end
144
+ end
145
+
146
+ def do_percentage
147
+ if @total.zero?
148
+ 100
149
+ else
150
+ @current * 100 / @total
151
+ end
152
+ end
153
+
154
+ def get_width
155
+ # return 80
156
+ # FIXME: I don't know how portable it is.
157
+ default_width = 80
158
+ begin
159
+ tiocgwinsz = 0x5413
160
+ data = [0, 0, 0, 0].pack("SSSS")
161
+ if @out.ioctl(tiocgwinsz, data) >= 0 then
162
+ unpacked = data.unpack("SSSS")
163
+ cols = unpacked[1]
164
+ # Commented this because Aptana was complaining about
165
+ # The unused variables
166
+ # rows, cols, xpixels, ypixels = data.unpack("SSSS")
167
+ if cols >= 0 then cols else default_width end
168
+ else
169
+ default_width
170
+ end
171
+ rescue Exception
172
+ default_width
173
+ end
174
+ end
175
+
176
+ def show
177
+ arguments = @format_arguments.map do |method|
178
+ method = sprintf("fmt_%s", method)
179
+ send(method)
180
+ end
181
+ line = sprintf(@format, *arguments)
182
+
183
+ width = get_width
184
+ if(line.length == width - 1)
185
+ @out.print(line + eol)
186
+ @out.flush
187
+ elsif(line.length >= width)
188
+ @terminal_width = [@terminal_width - (line.length - width + 1), 0].max
189
+ if @terminal_width == 0 then @out.print(line + eol) else show end
190
+ else # line.length < width - 1
191
+ @terminal_width += width - line.length + 1
192
+ show
193
+ end
194
+ @previous_time = Time.now
195
+ end
196
+
197
+ def show_if_needed
198
+ if @total.zero?
199
+ cur_percentage = 100
200
+ prev_percentage = 0
201
+ else
202
+ cur_percentage = (@current * 100 / @total).to_i
203
+ prev_percentage = (@previous * 100 / @total).to_i
204
+ end
205
+
206
+ # Use "!=" instead of ">" to support negative changes
207
+ if cur_percentage != prev_percentage ||
208
+ Time.now - @previous_time >= 1 || @finished_p
209
+ show
210
+ end
211
+ end
212
+
213
+ public
214
+ def clear
215
+ @out.print "\r"
216
+ @out.print(" " * (get_width - 1))
217
+ @out.print "\r"
218
+ end
219
+
220
+ def finish
221
+ @current = @total
222
+ @finished_p = true
223
+ show
224
+ end
225
+
226
+ def finished?
227
+ @finished_p
228
+ end
229
+
230
+ def file_transfer_mode
231
+ @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]
232
+ end
233
+
234
+ def format= (format)
235
+ @format = format
236
+ end
237
+
238
+ def format_arguments= (arguments)
239
+ @format_arguments = arguments
240
+ end
241
+
242
+ def halt
243
+ @finished_p = true
244
+ show
245
+ end
246
+
247
+ def inc (step = 1)
248
+ @current += step
249
+ @current = @total if @current > @total
250
+ show_if_needed
251
+ @previous = @current
252
+ end
253
+
254
+ def set (count)
255
+ if count < 0 || count > @total
256
+ @total = count
257
+ end
258
+ @current = count
259
+ show_if_needed
260
+ @previous = @current
261
+ end
262
+
263
+ def inspect
264
+ "#<ProgressBar:#{@current}/#{@total}>"
265
+ end
266
+ end
267
+
268
+ class ReversedProgressBar < ProgressBar # :nodoc:[all]
269
+ def do_percentage
270
+ 100 - super
271
+ end
272
+ end
273
+
274
+ class ProgressBarOutputStream # :nodoc:[all]
275
+ attr_reader :title
276
+
277
+ def initialize(mgr)
278
+ @mgr = mgr
279
+ @msg = ''
280
+ end
281
+
282
+ def print(msg)
283
+ @msg = msg
284
+ end
285
+
286
+ def flush
287
+ @mgr.flush
288
+ end
289
+
290
+ def to_s
291
+ return @msg.clone.split("\n").join("").split("\r").join("")
292
+ end
293
+
294
+ end
295
+
296
+ class ProgressBarManager # :nodoc:[all]
297
+ include Singleton
298
+
299
+ def initialize
300
+ @finished = {}
301
+ @bars = {}
302
+ @outs = {}
303
+ end
304
+
305
+ def add(title, total1)
306
+ # if(@bars[title])
307
+ # raise StandardError.new
308
+ # end
309
+ @outs[title] = ProgressBarOutputStream.new(self)
310
+ @bars[title] = ProgressBarImpl.new(title, total1, @outs[title])
311
+ end
312
+
313
+ def print(title)
314
+ str = ''
315
+ str += @outs[title].to_s
316
+ str += "\r"
317
+ outio.print "\r"
318
+ outio.print str
319
+ end
320
+
321
+ def outio
322
+ ProgressBar.outio
323
+ end
324
+
325
+ def flush
326
+ @bars.keys.each do |title|
327
+ print(title)
328
+ end
329
+
330
+ @bars.values.each do |bar|
331
+ if(bar.finished?)
332
+ print(bar.title)
333
+ outio.print "\n"
334
+ @outs.delete(bar.title)
335
+ @bars.delete(bar.title)
336
+ end
337
+ end
338
+ end
339
+ end
340
+ end
341
+