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.
- data/CHANGELOG.md +10 -0
- data/Gemfile +28 -0
- data/MIT-LICENSE +3 -2
- data/POSTINSTALL.rdoc +28 -0
- data/README.textile +152 -0
- data/bin/sprout +1 -131
- data/bin/sprout-generator +10 -0
- data/bin/sprout-library +11 -0
- data/bin/sprout-tool +10 -0
- data/lib/sprout.rb +4 -500
- data/lib/sprout/archive_unpacker.rb +122 -206
- data/lib/sprout/base.rb +90 -0
- data/lib/sprout/concern.rb +30 -0
- data/lib/sprout/dir.rb +23 -0
- data/lib/sprout/errors.rb +94 -0
- data/lib/sprout/executable.rb +496 -0
- data/lib/sprout/executable/boolean.rb +35 -0
- data/lib/sprout/executable/collection_param.rb +53 -0
- data/lib/sprout/executable/file_param.rb +53 -0
- data/lib/sprout/executable/files.rb +26 -0
- data/lib/sprout/executable/number.rb +10 -0
- data/lib/sprout/executable/param.rb +222 -0
- data/lib/sprout/executable/parameter_factory.rb +28 -0
- data/lib/sprout/executable/path.rb +21 -0
- data/lib/sprout/executable/paths.rb +21 -0
- data/lib/sprout/executable/string_param.rb +15 -0
- data/lib/sprout/executable/strings.rb +11 -0
- data/lib/sprout/executable/url.rb +10 -0
- data/lib/sprout/executable/urls.rb +10 -0
- data/lib/sprout/file_target.rb +76 -0
- data/lib/sprout/generator/base.rb +233 -0
- data/lib/sprout/generator/command.rb +67 -0
- data/lib/sprout/generator/directory_manifest.rb +49 -0
- data/lib/sprout/generator/file_manifest.rb +55 -0
- data/lib/sprout/generator/manifest.rb +13 -0
- data/lib/sprout/generator/template_manifest.rb +13 -0
- data/lib/sprout/generators/generator/generator_generator.rb +48 -0
- data/lib/sprout/generators/generator/templates/generator_class.rb +17 -0
- data/lib/sprout/generators/generator/templates/generator_executable +9 -0
- data/lib/sprout/generators/generator/templates/generator_template +1 -0
- data/lib/sprout/generators/generator/templates/generator_test.rb +37 -0
- data/lib/sprout/generators/generator/templates/generator_test_helper.rb +16 -0
- data/lib/sprout/generators/library/library_generator.rb +20 -0
- data/lib/sprout/generators/library/templates/library.gemspec +19 -0
- data/lib/sprout/generators/library/templates/library.rb +15 -0
- data/lib/sprout/generators/ruby/ruby_generator.rb +59 -0
- data/lib/sprout/generators/ruby/templates/ruby_base.rb +10 -0
- data/lib/sprout/generators/ruby/templates/ruby_executable +6 -0
- data/lib/sprout/generators/ruby/templates/ruby_gemfile +4 -0
- data/lib/sprout/generators/ruby/templates/ruby_input.rb +7 -0
- data/lib/sprout/generators/tool/templates/Gemfile +4 -0
- data/lib/sprout/generators/tool/templates/tool.gemspec +22 -0
- data/lib/sprout/generators/tool/templates/tool.rb +38 -0
- data/lib/sprout/generators/tool/tool_generator.rb +36 -0
- data/lib/sprout/library.rb +111 -0
- data/lib/sprout/log.rb +1 -0
- data/lib/sprout/platform.rb +71 -0
- data/lib/sprout/process_runner.rb +80 -40
- data/lib/sprout/progress_bar.rb +341 -0
- data/lib/sprout/rdoc_parser.rb +91 -0
- data/lib/sprout/remote_file_loader.rb +72 -50
- data/lib/sprout/remote_file_target.rb +44 -152
- data/lib/sprout/ruby_feature.rb +167 -0
- data/lib/sprout/specification.rb +197 -0
- data/lib/sprout/string.rb +19 -0
- data/lib/sprout/system.rb +35 -0
- data/lib/sprout/system/base_system.rb +225 -0
- data/lib/sprout/system/java_system.rb +9 -0
- data/lib/sprout/system/osx_system.rb +26 -0
- data/lib/sprout/system/unix_system.rb +72 -0
- data/lib/sprout/system/vista_system.rb +16 -0
- data/lib/sprout/system/win_nix_system.rb +41 -0
- data/lib/sprout/system/win_system.rb +76 -0
- data/lib/sprout/test/sprout_test_case.rb +211 -0
- data/lib/sprout/version.rb +9 -4
- data/rakefile.rb +85 -144
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/sprout.gemspec +26 -0
- data/test/fixtures/archive_unpacker/copyable/some_file.exe +0 -0
- data/test/fixtures/archive_unpacker/copyable/some_file.rb +0 -0
- data/test/fixtures/archive_unpacker/copyable/some_file.swc +0 -0
- data/test/fixtures/archive_unpacker/tgz/some folder.tgz +0 -0
- data/test/fixtures/archive_unpacker/tgz/some_file.tgz +0 -0
- data/test/fixtures/archive_unpacker/zip/some folder.zip +0 -0
- data/test/fixtures/archive_unpacker/zip/some_file.zip +0 -0
- data/test/fixtures/examples/app_generator.rb +127 -0
- data/test/fixtures/examples/echo_inputs.rb +151 -0
- data/test/fixtures/executable/echochamber_gem/bin/echochamber +3 -0
- data/test/fixtures/executable/echochamber_gem/echo_chamber.rb +10 -0
- data/test/fixtures/executable/flex3sdk_gem/flex3sdk.rb +11 -0
- data/test/fixtures/executable/flex3sdk_gem/mxmlc +3 -0
- data/test/fixtures/executable/flex3sdk_gem/mxmlc.bat +3 -0
- data/test/fixtures/executable/mxmlc.rb +805 -0
- data/test/fixtures/executable/params/input.as +0 -0
- data/test/fixtures/executable/params/input2.as +0 -0
- data/test/fixtures/executable/params/input3.as +0 -0
- data/test/fixtures/executable/params/mxmlc +5 -0
- data/test/fixtures/executable/path with spaces/input.as b/data/test/fixtures/executable/path with → spaces/input.as +0 -0
- data/test/fixtures/executable/path with spaces/input2.as b/data/test/fixtures/executable/path with → spaces/input2.as +0 -0
- data/test/fixtures/executable/path with spaces/input3.as b/data/test/fixtures/executable/path with → spaces/input3.as +0 -0
- data/test/fixtures/executable/paths/folder1/file1 +0 -0
- data/test/fixtures/executable/paths/folder1/file2 +0 -0
- data/test/fixtures/executable/paths/folder1/file3 +0 -0
- data/test/fixtures/executable/paths/folder2/file4 +0 -0
- data/test/fixtures/executable/paths/folder2/file5 +0 -0
- data/test/fixtures/executable/paths/folder3/file6 +0 -0
- data/test/fixtures/executable/src/Main.as +0 -0
- data/test/fixtures/executable/windows_line_endings +47 -0
- data/test/fixtures/generators/song_generator.rb +11 -0
- data/test/fixtures/generators/song_subclass/least_favorite.rb +10 -0
- data/test/fixtures/generators/song_subclass/templates/Song.txt +3 -0
- data/test/fixtures/generators/temp_generator.rb +24 -0
- data/test/fixtures/generators/templates/Main.as +9 -0
- data/test/fixtures/generators/templates/OtherFileTemplate +1 -0
- data/test/fixtures/generators/templates/SomeFile +1 -0
- data/test/fixtures/generators/templates/SomeSubclassFile +2 -0
- data/test/fixtures/generators/templates/Song.txt +3 -0
- data/test/fixtures/generators/templates/destroy +0 -0
- data/test/fixtures/generators/templates/generate +0 -0
- data/test/fixtures/library/archive/Archive.swc +0 -0
- data/test/fixtures/library/sources/lib/a/A.as +0 -0
- data/test/fixtures/library/sources/lib/b/B.as +0 -0
- data/test/fixtures/library/sources/src/Source.as +0 -0
- data/test/fixtures/process_runner/chmod_script.sh +3 -0
- data/test/fixtures/process_runner/dir with spaces/chmod_script.sh +3 -0
- data/test/fixtures/process_runner/failure +5 -0
- data/test/fixtures/process_runner/success +4 -0
- data/test/fixtures/remote_file_loader/md5/echochamber-test.zip +0 -0
- data/test/fixtures/remote_file_loader/md5/file_with_known_md5 +0 -0
- data/test/fixtures/remote_file_target/bin/echochamber +3 -0
- data/test/fixtures/remote_file_target/bin/echochamber.bat +3 -0
- data/test/fixtures/remote_file_target/echochamber-test.zip +0 -0
- data/test/fixtures/specification/asunit4.rb +25 -0
- data/test/fixtures/specification/ext/AsUnit-4.1.pre.swc +0 -0
- data/test/fixtures/specification/flashplayer.rb +30 -0
- data/test/fixtures/specification/flex4sdk.rb +72 -0
- data/test/fixtures/specification/flexunit4.sproutspec +17 -0
- data/test/fixtures/specification/lib/as3reflection/Reflection.as +0 -0
- data/test/fixtures/specification/src/AsUnit.as +0 -0
- data/test/fixtures/user/mxmlc_crlf +3 -0
- data/test/unit/archive_unpacker_test.rb +108 -0
- data/test/unit/boolean_param_test.rb +38 -0
- data/test/unit/executable_option_parser_test.rb +142 -0
- data/test/unit/executable_param_test.rb +76 -0
- data/test/unit/executable_test.rb +237 -0
- data/test/unit/fake_executable_task.rb +22 -0
- data/test/unit/fake_other_executable.rb +20 -0
- data/test/unit/fake_process_runner.rb +29 -0
- data/test/unit/file_param_test.rb +61 -0
- data/test/unit/file_target_test.rb +42 -0
- data/test/unit/files_param_test.rb +72 -0
- data/test/unit/generator_generator_test.rb +85 -0
- data/test/unit/generator_test.rb +333 -0
- data/test/unit/library_generator_test.rb +41 -0
- data/test/unit/library_test.rb +88 -0
- data/test/unit/osx_system_test.rb +20 -0
- data/test/unit/path_param_test.rb +43 -0
- data/test/unit/paths_param_test.rb +53 -0
- data/test/unit/platform_test.rb +76 -0
- data/test/unit/process_runner_test.rb +104 -0
- data/test/unit/rdoc_parser_test.rb +15 -0
- data/test/unit/remote_file_loader_test.rb +34 -0
- data/test/unit/remote_file_target_test.rb +105 -0
- data/test/unit/ruby_feature_test.rb +108 -0
- data/test/unit/ruby_generator_test.rb +70 -0
- data/test/unit/specification_test.rb +73 -0
- data/test/unit/sprout_test.rb +170 -0
- data/test/unit/sprout_test_helper.rb +18 -0
- data/test/unit/string_param_test.rb +19 -0
- data/test/unit/string_test.rb +20 -0
- data/test/unit/strings_param_test.rb +27 -0
- data/test/unit/test_helper.rb +1 -0
- data/test/unit/tool_generator_test.rb +43 -0
- data/test/unit/unix_system_test.rb +52 -0
- data/test/unit/user_test.rb +147 -0
- data/test/unit/vista_system_test.rb +40 -0
- data/test/unit/win_nix_system_test.rb +26 -0
- data/test/unit/win_system_test.rb +61 -0
- metadata +318 -113
- data/doc/Bundle +0 -14
- data/doc/Generator +0 -35
- data/doc/Library +0 -63
- data/doc/Task +0 -21
- data/doc/Tool +0 -20
- data/lib/platform.rb +0 -113
- data/lib/progress_bar.rb +0 -354
- data/lib/sprout/builder.rb +0 -51
- data/lib/sprout/bundle_resolver.rb +0 -349
- data/lib/sprout/commands/generate.rb +0 -9
- data/lib/sprout/dynamic_accessors.rb +0 -40
- data/lib/sprout/general_tasks.rb +0 -6
- data/lib/sprout/generator.rb +0 -7
- data/lib/sprout/generator/base_mixins.rb +0 -186
- data/lib/sprout/generator/named_base.rb +0 -227
- data/lib/sprout/project_model.rb +0 -278
- data/lib/sprout/simple_resolver.rb +0 -88
- data/lib/sprout/tasks/erb_resolver.rb +0 -118
- data/lib/sprout/tasks/gem_wrap_task.rb +0 -214
- data/lib/sprout/tasks/git_task.rb +0 -134
- data/lib/sprout/tasks/library_task.rb +0 -118
- data/lib/sprout/tasks/sftp_task.rb +0 -248
- data/lib/sprout/tasks/ssh_task.rb +0 -153
- data/lib/sprout/tasks/tool_task.rb +0 -836
- data/lib/sprout/tasks/zip_task.rb +0 -158
- data/lib/sprout/tool_task_model.rb +0 -19
- data/lib/sprout/user.rb +0 -415
- data/lib/sprout/version_file.rb +0 -89
- data/lib/sprout/zip_util.rb +0 -61
- data/samples/gem_wrap/rakefile.rb +0 -17
@@ -0,0 +1,167 @@
|
|
1
|
+
|
2
|
+
module Sprout
|
3
|
+
|
4
|
+
##
|
5
|
+
# This class represents a Feature that is written in
|
6
|
+
# Ruby code that exists on the other side of the
|
7
|
+
# Ruby load path.
|
8
|
+
#
|
9
|
+
# The idea here, is that one can +include+ the Sprout::RubyFeature
|
10
|
+
# module into their concrete class, and then accept
|
11
|
+
# requests to +register+ and +load+ from clients that
|
12
|
+
# are interested in pluggable features.
|
13
|
+
#
|
14
|
+
# An example is as follows:
|
15
|
+
#
|
16
|
+
# require 'sprout'
|
17
|
+
#
|
18
|
+
# class MyClass
|
19
|
+
# include Sprout::RubyFeature
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# In some other Ruby file:
|
23
|
+
#
|
24
|
+
# MyClass.load :other, 'other_gem', '>= 1.0pre'
|
25
|
+
#
|
26
|
+
# In the desired Ruby file:
|
27
|
+
#
|
28
|
+
# class OtherClass
|
29
|
+
# include Sprout::Executable
|
30
|
+
#
|
31
|
+
# set :name, :other
|
32
|
+
# set :pkg_name, 'other_gem'
|
33
|
+
# set :pkg_version, '1.0.pre'
|
34
|
+
#
|
35
|
+
# # do something...
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# MyClass.register OtherClass.new
|
39
|
+
#
|
40
|
+
module RubyFeature
|
41
|
+
|
42
|
+
extend Concern
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
|
46
|
+
##
|
47
|
+
# Register a new feature for future lookups
|
48
|
+
def register entity
|
49
|
+
validate_registration entity
|
50
|
+
registered_entities.unshift entity
|
51
|
+
entity
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Load a feature by name.
|
56
|
+
def load name_or_names, pkg_name=nil, version_requirement=nil
|
57
|
+
entity = entity_for name_or_names, pkg_name, version_requirement
|
58
|
+
if(entity.nil?)
|
59
|
+
# Try to require the pkg_name:
|
60
|
+
require_ruby_package pkg_name unless pkg_name.nil?
|
61
|
+
# Update any entities that registered from our require:
|
62
|
+
update_registered_entities
|
63
|
+
# search for the requested entity:
|
64
|
+
entity = entity_for name_or_names, pkg_name, version_requirement
|
65
|
+
end
|
66
|
+
|
67
|
+
if(entity.nil?)
|
68
|
+
message = "The requested entity: (#{name_or_names}) with pkg_name: (#{pkg_name}) and version: "
|
69
|
+
message << "(#{version_requirement}) does not appear to be loaded."
|
70
|
+
message << "\n"
|
71
|
+
message << "We did find (#{registered_entities.size}) registered entities in that package:\n\n"
|
72
|
+
registered_entities.each do |other|
|
73
|
+
message << ">> name: (#{other.name}) pkg_name: (#{other.pkg_name}) pkg_version: (#{other.pkg_version})\n"
|
74
|
+
end
|
75
|
+
message << "\n\nYou may need to update your Gemfile and run 'bundle install' "
|
76
|
+
message << "to update your local gems.\n\n"
|
77
|
+
raise Sprout::Errors::LoadError.new message
|
78
|
+
end
|
79
|
+
entity
|
80
|
+
end
|
81
|
+
|
82
|
+
def clear_entities!
|
83
|
+
@registered_entities = []
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def validate_registration entity
|
89
|
+
if(!entity.respond_to?(:name) || entity.name.nil?)
|
90
|
+
raise Sprout::Errors::UsageError.new "Cannot register a RubyFeature without a 'name' getter"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Used by the Generator::Base to update inputs from
|
96
|
+
# empty class definitions to instances..
|
97
|
+
def update_registered_entities
|
98
|
+
end
|
99
|
+
|
100
|
+
def entity_for name_or_names, pkg_name, version_requirement
|
101
|
+
#puts "+++++++++++++++++++++++++++"
|
102
|
+
#puts ">> entity_for #{name} pkg_name: #{pkg_name} version: #{version_requirement}"
|
103
|
+
#registered_entities.each do |entity|
|
104
|
+
#puts ">> entity: #{entity.name} pkg_name: #{entity.pkg_name} version: #{entity.pkg_version}"
|
105
|
+
#end
|
106
|
+
registered_entities.select do |entity|
|
107
|
+
satisfies_name?(entity, name_or_names) &&
|
108
|
+
satisfies_platform?(entity) &&
|
109
|
+
satisfies_pkg_name?(entity, pkg_name) &&
|
110
|
+
satisfies_version?(entity, version_requirement)
|
111
|
+
end.first
|
112
|
+
end
|
113
|
+
def satisfies_environment? entity, environment
|
114
|
+
#puts ">> env: #{entity.environment} vs. #{environment}"
|
115
|
+
environment.nil? || !entity.respond_to?(:environment) || entity.environment.to_s == environment.to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
def satisfies_pkg_name? entity, expected
|
119
|
+
#puts ">> pkg_name: #{entity.pkg_name} vs. #{expected}"
|
120
|
+
expected.nil? || !entity.respond_to?(:pkg_name) || entity.pkg_name.to_s == expected.to_s
|
121
|
+
end
|
122
|
+
|
123
|
+
def satisfies_name? entity, expected
|
124
|
+
#puts ">> name: #{entity.name} vs. #{expected}"
|
125
|
+
return true if expected.nil? || !entity.respond_to?(:name)
|
126
|
+
if expected.is_a?(Array)
|
127
|
+
return expected.include? entity.name
|
128
|
+
end
|
129
|
+
return expected.to_s == entity.name.to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
def satisfies_platform? entity
|
133
|
+
#puts">> satisfies platform?"
|
134
|
+
return true if !entity.respond_to?(:platform) || entity.platform.nil?
|
135
|
+
#puts ">> platform: #{entity.platform}"
|
136
|
+
Sprout.current_system.can_execute?(entity.platform)
|
137
|
+
end
|
138
|
+
|
139
|
+
def satisfies_version? entity, version_requirement=nil
|
140
|
+
return true if version_requirement.nil?
|
141
|
+
req_version = Gem::Requirement.create version_requirement
|
142
|
+
req_version.satisfied_by?(Gem::Version.create(entity.pkg_version))
|
143
|
+
end
|
144
|
+
|
145
|
+
def require_ruby_package name
|
146
|
+
begin
|
147
|
+
require name
|
148
|
+
rescue LoadError => e
|
149
|
+
raise Sprout::Errors::LoadError.new "Could not load the required file (#{name}) - Maybe you need to run 'gem install #{name}' or maybe 'bundle install'?"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# An entity has the following parameters:
|
155
|
+
# name
|
156
|
+
# pkg_name
|
157
|
+
# pkg_version
|
158
|
+
# platform
|
159
|
+
#
|
160
|
+
def registered_entities
|
161
|
+
@registered_entities ||= []
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
@@ -0,0 +1,197 @@
|
|
1
|
+
|
2
|
+
module Sprout
|
3
|
+
|
4
|
+
##
|
5
|
+
# Sprouts provides us with the ability to distribute source files,
|
6
|
+
# precompiled libraries, and remote executables. It does all of
|
7
|
+
# this by (ab)using RubyGems.
|
8
|
+
#
|
9
|
+
# RubyGems gives us the ability to version-manage, and distribute
|
10
|
+
# arbitrary text and binary payloads.
|
11
|
+
#
|
12
|
+
# In order to support Flash development, we have one major problem
|
13
|
+
# that RubyGems does not solve for us. This is the fact that
|
14
|
+
# many elements of our executable chain are not open-source, and we do
|
15
|
+
# not have the rights to directly distribute them.
|
16
|
+
#
|
17
|
+
# This restriction means that many of our tools and dependencies cannot be
|
18
|
+
# packaged and distributed _directly_ within a RubyGem (or from
|
19
|
+
# any server other than Adobe's as a matter of fact).
|
20
|
+
#
|
21
|
+
# In order to overcome this restriction, we have introduced
|
22
|
+
# a Sprout::Specification. This is a regular Ruby file with regular
|
23
|
+
# Ruby code in it. The main idea behind this file, is that it
|
24
|
+
# needs to be given a name and available in your load path.
|
25
|
+
#
|
26
|
+
# Whenever a rake build task (Sprout::Executable) or library task,
|
27
|
+
# (Sprout::Library) is encountered, it will call
|
28
|
+
# Sprout::Executable.load or Sprout::Library.load (respectively).
|
29
|
+
#
|
30
|
+
# These methods will attempt to +require+ the provided
|
31
|
+
# specification and - if it's in your load path - the specification
|
32
|
+
# will be loaded, and any relevant file targets will be returned.
|
33
|
+
#
|
34
|
+
# There are many ways to get Ruby code into your load path.
|
35
|
+
# One of the easiest to package it up in a RubyGem and
|
36
|
+
# configure the +require_paths+ parameter of your Gem::Specification.
|
37
|
+
#
|
38
|
+
# http://docs.rubygems.org/read/chapter/20#require_paths
|
39
|
+
#
|
40
|
+
# To learn more about packaging RubyGems:
|
41
|
+
#
|
42
|
+
# http://docs.rubygems.org/read/chapter/20#page85
|
43
|
+
# http://rubygems.rubyforge.org/rdoc/Gem/Specification.html
|
44
|
+
#
|
45
|
+
# To learn more about published RubyGems:
|
46
|
+
#
|
47
|
+
# http://rubygems.org/pages/gem_docs
|
48
|
+
#
|
49
|
+
# To package a SWC library into a Sprout RubyGem, you would create a file (usually)
|
50
|
+
# named [project_name.spec] in the root of the project.
|
51
|
+
#
|
52
|
+
# This is your Gem::Specification.
|
53
|
+
#
|
54
|
+
# You would also create a file named [projet_name.rb] and put that
|
55
|
+
# into the root of the project or some other folder that you have added to
|
56
|
+
# the Gem::Specification.require_paths parameter.
|
57
|
+
#
|
58
|
+
# == Example: Include a file directly in the RubyGem
|
59
|
+
#
|
60
|
+
# In the case of AsUnit, this file would be named asunit4.rb and it's contents
|
61
|
+
# are as follows:
|
62
|
+
#
|
63
|
+
# :include:../../test/fixtures/specification/asunit4.rb
|
64
|
+
#
|
65
|
+
# == Example: Refer to files that are not in the RubyGem
|
66
|
+
#
|
67
|
+
# For projects like the Flex SDK, we can't distribute many of the required files,
|
68
|
+
# so we can refer to these files in our Sprout::Specification as +remote_file_targets+.
|
69
|
+
#
|
70
|
+
# :include:../../test/fixtures/specification/flex4sdk.rb
|
71
|
+
#
|
72
|
+
# == Example: Create custom downloads for each supported platform
|
73
|
+
#
|
74
|
+
# For projects like the Flash Player itself, we need to refer to different
|
75
|
+
# downloadable content for each supported platform.
|
76
|
+
#
|
77
|
+
# :include:../../test/fixtures/specification/flashplayer.rb
|
78
|
+
#
|
79
|
+
# == Packaging and Sharing
|
80
|
+
#
|
81
|
+
# Public RubyGems are hosted at http://rubygems.org.
|
82
|
+
class Specification
|
83
|
+
|
84
|
+
attr_accessor :name
|
85
|
+
attr_accessor :version
|
86
|
+
|
87
|
+
attr_reader :file_targets
|
88
|
+
attr_reader :load_path
|
89
|
+
|
90
|
+
##
|
91
|
+
# Create a new Sprout::Specification.
|
92
|
+
#
|
93
|
+
# This method will yield the new Sprout::Specification to the provided block,
|
94
|
+
# and delegate most configuration parameters to a {Gem::Specification}[http://rubygems.rubyforge.org/rdoc/Gem/Specification.html].
|
95
|
+
#
|
96
|
+
# To learn more about what parameters are available and/or required, please
|
97
|
+
# check out RubyGems documentation for their {Gem::Specification}[http://rubygems.rubyforge.org/rdoc/Gem/Specification.html].
|
98
|
+
#
|
99
|
+
def initialize
|
100
|
+
filename = Sprout.file_from_caller caller.first
|
101
|
+
@load_path = File.dirname filename
|
102
|
+
@name = File.basename(filename).gsub('.rb', '')
|
103
|
+
yield self if block_given?
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Add a remote file target to this RubyGem so that when it
|
108
|
+
# is loaded, Sprouts will go fetch this file from the network.
|
109
|
+
#
|
110
|
+
# Each time this method is called, a new Sprout::RemoteFiletarget instance will be yielded to
|
111
|
+
# the provided block and resolved after the block completes.
|
112
|
+
#
|
113
|
+
# After this block is evaluated, Sprouts will first check the collection
|
114
|
+
# of env_names to see if the expected paths are available. If a valid
|
115
|
+
# env_name is found, Sprouts will return the path to the requested
|
116
|
+
# executable from the environment variable.
|
117
|
+
#
|
118
|
+
# If no env_names are set, or the requested executable is not found within
|
119
|
+
# any that are identified, Sprouts will check to see if the archive
|
120
|
+
# has already been unpacked into the expected location:
|
121
|
+
#
|
122
|
+
# #{SPROUT_HOME}/cache/#{SPROUT_VERSION}/flex4sdk/#{md5}/4.0.pre
|
123
|
+
#
|
124
|
+
# If the archive been unpacked, Sprouts will return the path to the
|
125
|
+
# requested executable.
|
126
|
+
#
|
127
|
+
# If the archive has not been unpacked, Sprouts will check to see if the
|
128
|
+
# archive has been downloaded to:
|
129
|
+
#
|
130
|
+
# #{SPROUT_HOME}/cache/#{SPROUT_VERSION}/flex4sdk/#{md5}.zip
|
131
|
+
#
|
132
|
+
# If the archive has been downloaded, it will be unpacked and the path
|
133
|
+
# to the requested executable will be returned.
|
134
|
+
#
|
135
|
+
# If the archive has not been downloaded, it will be downloaded, unpacked
|
136
|
+
# and the path to the requested executable will be returned.
|
137
|
+
def add_remote_file_target &block
|
138
|
+
target = RemoteFileTarget.new do |t|
|
139
|
+
configure_target t, &block
|
140
|
+
end
|
141
|
+
target.resolve
|
142
|
+
register_file_target target
|
143
|
+
end
|
144
|
+
|
145
|
+
# Add a file to the RubyGem itself. This is a great way to package smallish libraries in either
|
146
|
+
# source or already-packaged form. For example, one might add a SWC to a RubyGem library.
|
147
|
+
#
|
148
|
+
# Each time this method is called, a new Sprout::FileTarget instance will be yielded to the
|
149
|
+
# provided block, and added to a collection for packaging.
|
150
|
+
#
|
151
|
+
# Sprout::Specification.new do |s|
|
152
|
+
# ...
|
153
|
+
# s.add_file_target do |t|
|
154
|
+
# t.platform = :universal
|
155
|
+
# t.add_executable :asdoc, 'bin/asdoc'
|
156
|
+
# end
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
def add_file_target &block
|
160
|
+
target = FileTarget.new do |t|
|
161
|
+
configure_target t, &block
|
162
|
+
end
|
163
|
+
register_file_target target
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def configure_target t, &block
|
169
|
+
t.load_path = load_path
|
170
|
+
t.pkg_name = name
|
171
|
+
t.pkg_version = version
|
172
|
+
yield t if block_given?
|
173
|
+
end
|
174
|
+
|
175
|
+
def register_file_target target
|
176
|
+
register_items target.executables, Sprout::Executable, target
|
177
|
+
# Reversing the libraries makes it so that definitions like:
|
178
|
+
#
|
179
|
+
# target.add_library :swc, 'abcd'
|
180
|
+
# target.add_library :src, 'efgh'
|
181
|
+
#
|
182
|
+
# When loading, if no name is specified, the :swc will be
|
183
|
+
# returned to clients.
|
184
|
+
register_items target.libraries.reverse, Sprout::Library, target
|
185
|
+
end
|
186
|
+
|
187
|
+
def register_items collection, source, target
|
188
|
+
collection.each do |item|
|
189
|
+
item.pkg_name = target.pkg_name
|
190
|
+
item.pkg_version = target.pkg_version
|
191
|
+
source.register item
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
class String
|
3
|
+
|
4
|
+
# "FooBar".snake_case #=> "foo_bar"
|
5
|
+
def snake_case
|
6
|
+
gsub(/\B[A-Z]/, '_\&').downcase
|
7
|
+
end
|
8
|
+
|
9
|
+
# "foo_bar".camel_case #=> "FooBar"
|
10
|
+
def camel_case
|
11
|
+
str = gsub(/^[a-z]|_+[a-z]/) { |a| a.upcase }
|
12
|
+
str.gsub(/_/, '')
|
13
|
+
end
|
14
|
+
|
15
|
+
def dash_case
|
16
|
+
self.snake_case.gsub('_', '-')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'sprout/system/base_system'
|
2
|
+
require 'sprout/system/unix_system'
|
3
|
+
require 'sprout/system/java_system'
|
4
|
+
require 'sprout/system/osx_system'
|
5
|
+
require 'sprout/system/win_system'
|
6
|
+
require 'sprout/system/win_nix_system'
|
7
|
+
require 'sprout/system/vista_system'
|
8
|
+
|
9
|
+
module Sprout
|
10
|
+
|
11
|
+
module System
|
12
|
+
|
13
|
+
# This is the factory that one should
|
14
|
+
# generally be used to create new, concrete
|
15
|
+
# System objects.
|
16
|
+
#
|
17
|
+
# A typical example follows:
|
18
|
+
#
|
19
|
+
# system = System.create
|
20
|
+
# Dir.chdir system.home
|
21
|
+
# system.execute "pwd" # /home/yourusername
|
22
|
+
#
|
23
|
+
def self.create
|
24
|
+
p = Sprout::Platform.new
|
25
|
+
return VistaSystem.new if p.vista?
|
26
|
+
return WinNixSystem.new if p.windows_nix?
|
27
|
+
return WinSystem.new if p.windows?
|
28
|
+
return JavaSystem.new if p.java?
|
29
|
+
return OSXSystem.new if p.mac?
|
30
|
+
return UnixSystem.new
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,225 @@
|
|
1
|
+
|
2
|
+
module Sprout::System
|
3
|
+
|
4
|
+
# The abstract base class for all supported system/platform types.
|
5
|
+
# In general, users are created by calling the +create+ factory method
|
6
|
+
# on the +System+ module.
|
7
|
+
#
|
8
|
+
# System.create
|
9
|
+
#
|
10
|
+
# Assuming you call the create method, you should wind up with
|
11
|
+
# a concrete system that matches your system, and these concrete
|
12
|
+
# users will generally be derived from this base class.
|
13
|
+
#
|
14
|
+
class BaseSystem
|
15
|
+
|
16
|
+
##
|
17
|
+
# Get the home path for a system on a particular operating system.
|
18
|
+
#
|
19
|
+
# This path will be different, depending on which system owns
|
20
|
+
# the curren process, and which operating system they are on.
|
21
|
+
#
|
22
|
+
def home
|
23
|
+
@home ||= find_home
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Set the home path for a system on a particular operating system.
|
28
|
+
#
|
29
|
+
# If you request the home path before setting it, we will
|
30
|
+
# attempt to determine the home path of the current system for
|
31
|
+
# the current operating system.
|
32
|
+
#
|
33
|
+
# This is just a simple way to override the default behavior.
|
34
|
+
#
|
35
|
+
def home=(home)
|
36
|
+
@home = home
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Some operating systems (like OS X and Windows) have a
|
41
|
+
# specific location where applications are expected to store
|
42
|
+
# files for a particular system. This location is generally
|
43
|
+
# a subdirectory of +home+.
|
44
|
+
#
|
45
|
+
# The value of this location will usually be overridden in
|
46
|
+
# concrete System classes.
|
47
|
+
#
|
48
|
+
def library
|
49
|
+
return home
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Instantiate and return a new Sprout::ProcessRunner so
|
54
|
+
# that we can execute it.
|
55
|
+
#
|
56
|
+
def get_process_runner
|
57
|
+
Sprout::ProcessRunner.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def can_execute? platform
|
61
|
+
platform == :universal
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Creates a new process, executes the command
|
66
|
+
# and returns whatever the process wrote to stdout, or stderr.
|
67
|
+
#
|
68
|
+
# Raises a +Sprout::Errors::ExecutionError+ if the process writes to stderr
|
69
|
+
#
|
70
|
+
def execute(tool, options='')
|
71
|
+
Sprout::Log.puts(">> Execute: #{tool} options: #{options}")
|
72
|
+
runner = get_and_execute_process_runner(tool, options)
|
73
|
+
error = runner.read_err
|
74
|
+
result = runner.read
|
75
|
+
|
76
|
+
if(result.size > 0)
|
77
|
+
Sprout::Log.puts result
|
78
|
+
end
|
79
|
+
|
80
|
+
if(error.size > 0)
|
81
|
+
raise Sprout::Errors::ExecutionError.new("[ERROR] #{error}")
|
82
|
+
end
|
83
|
+
|
84
|
+
result || error
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Creates and returns the process without
|
89
|
+
# attempting to read or write to the stream.
|
90
|
+
# This is useful for interacting with
|
91
|
+
# long-lived CLI processes like FCSH or FDB.
|
92
|
+
#
|
93
|
+
def execute_silent(tool, options='')
|
94
|
+
return get_and_execute_process_runner(tool, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Execute a new process in a separate thread.
|
99
|
+
# This can be useful for processes that take
|
100
|
+
# an especially long time to execute.
|
101
|
+
#
|
102
|
+
# Threads are complicated - use with caution...
|
103
|
+
#
|
104
|
+
def execute_thread(tool, options='')
|
105
|
+
if(Log.debug)
|
106
|
+
return ThreadMock.new
|
107
|
+
else
|
108
|
+
return Thread.new do
|
109
|
+
execute(tool, options)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Clean the provided +path+ String for the current
|
116
|
+
# operating system.
|
117
|
+
#
|
118
|
+
# Each operating system behaves differently when we
|
119
|
+
# attempt to execute a file with spaces in the +path+
|
120
|
+
# to the file.
|
121
|
+
#
|
122
|
+
# Subclasses will generally override this method and
|
123
|
+
# clean the path appropriately for their operating
|
124
|
+
# system.
|
125
|
+
#
|
126
|
+
def clean_path(path)
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Different operating systems will store Application data
|
131
|
+
# different default locations.
|
132
|
+
#
|
133
|
+
# Subclasses will generally override this method and
|
134
|
+
# return the appropriate location for their operating system.
|
135
|
+
#
|
136
|
+
# +name+ String value of the Application name for which we'd
|
137
|
+
# like to store data.
|
138
|
+
#
|
139
|
+
def application_home(name)
|
140
|
+
return File.join(library, format_application_name(name.to_s));
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Template method that should be overridden by
|
145
|
+
# subclasses.
|
146
|
+
#
|
147
|
+
def format_application_name(name)
|
148
|
+
name
|
149
|
+
end
|
150
|
+
|
151
|
+
protected
|
152
|
+
|
153
|
+
def env_homedrive
|
154
|
+
ENV['HOMEDRIVE']
|
155
|
+
end
|
156
|
+
|
157
|
+
def env_homepath
|
158
|
+
ENV['HOMEPATH']
|
159
|
+
end
|
160
|
+
|
161
|
+
def env_homedrive_and_homepath
|
162
|
+
drive = env_homedrive
|
163
|
+
path = env_homepath
|
164
|
+
"#{drive}:#{path}" if drive && path
|
165
|
+
end
|
166
|
+
|
167
|
+
def env_userprofile
|
168
|
+
ENV['USERPROFILE']
|
169
|
+
end
|
170
|
+
|
171
|
+
def env_home
|
172
|
+
ENV['HOME']
|
173
|
+
end
|
174
|
+
|
175
|
+
def tilde_home
|
176
|
+
File.expand_path("~")
|
177
|
+
end
|
178
|
+
|
179
|
+
def alt_separator?
|
180
|
+
File::ALT_SEPARATOR
|
181
|
+
end
|
182
|
+
|
183
|
+
def worst_case_home
|
184
|
+
return "C:\\" if alt_separator?
|
185
|
+
return "/"
|
186
|
+
end
|
187
|
+
|
188
|
+
def find_home
|
189
|
+
[:env_userprofile, :env_home, :env_homedrive_and_homepath].each do |key|
|
190
|
+
value = self.send(key)
|
191
|
+
return value unless value.nil?
|
192
|
+
end
|
193
|
+
|
194
|
+
begin
|
195
|
+
return tilde_home
|
196
|
+
rescue StandardError
|
197
|
+
worst_case_home
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
protected
|
202
|
+
|
203
|
+
##
|
204
|
+
# Get a process runner and execute the provided +executable+,
|
205
|
+
# with the provided +options+.
|
206
|
+
#
|
207
|
+
# +executable+ String path to the external executable file.
|
208
|
+
#
|
209
|
+
# +options+ String commandline options to send to the +executable+.
|
210
|
+
#
|
211
|
+
def get_and_execute_process_runner tool, options=nil
|
212
|
+
runner = get_process_runner
|
213
|
+
runner.execute_open4 clean_path(tool), options
|
214
|
+
runner
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
class ThreadMock # :nodoc:
|
220
|
+
def alive?
|
221
|
+
return false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|