sprout 0.7.153-darwin

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.

@@ -0,0 +1,46 @@
1
+
2
+ module Sprout #:nodoc:
3
+ class ProcessRunnerError < StandardError # :nodoc:
4
+ end
5
+
6
+ class ProcessRunner #:nodoc:
7
+ attr_reader :pid,
8
+ :r,
9
+ :w,
10
+ :e
11
+
12
+ def initialize(*command)
13
+ @command = command
14
+ begin
15
+ usr = User.new()
16
+ if(usr.is_a?(WinUser) && !usr.is_a?(CygwinUser))
17
+ require 'win32/open3'
18
+ Open3.popen3(*@command) do |w, r, e, pid|
19
+ @w = w
20
+ @r = r
21
+ @e = e
22
+ @pid = pid
23
+ end
24
+ else
25
+ require 'open4'
26
+ @pid, @w, @r, @e = open4.popen4(*@command)
27
+ end
28
+ rescue Errno::ENOENT => e
29
+ part = command[0].split(' ').shift
30
+ raise ProcessRunnerError.new("The expected executable was not found for command [#{part}], please check your system path and/or sprout definition")
31
+ end
32
+ end
33
+
34
+ def puts(msg)
35
+ @w.puts(msg)
36
+ end
37
+
38
+ def read
39
+ return r.read
40
+ end
41
+
42
+ def read_err
43
+ return e.read
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,114 @@
1
+
2
+ module Sprout
3
+
4
+ # The ProjectModel gives you a place to describe your project so that you
5
+ # don't need to repeat yourself throughout a rakefile.
6
+ #
7
+ # The default set of properties are also used from code generators, library tasks and sometimes tools.
8
+ #
9
+ # This class should have some reasonable default values, but can be modified from any rakefile.
10
+ # If you don't find some properties that you'd like on the ProjectModel, you can simply add
11
+ # new properties and use them however you wish!
12
+ class ProjectModel < Hash
13
+
14
+ # The real name of the project, usually capitalized like a class name 'SomeProject'
15
+ attr_accessor :project_name
16
+ # The relative path to your main source directory. Defaults to 'src'
17
+ attr_accessor :src_dir
18
+ # The relative path to your library directory. Defaults to 'lib'
19
+ #
20
+ # Any remote .SWC and source libraries that are referenced in your rakefile will be installed
21
+ # into this directory. Source libraries will be placed in a folder that matches the library name,
22
+ # while SWCs will be simply placed directly into the lib_dir.
23
+ attr_accessor :lib_dir
24
+ # The folder where binary files will be created. Usually this is where any build artifacts like SWF files get placed.
25
+ attr_accessor :bin_dir
26
+ # Relative path to the folder that contains your test cases
27
+ attr_accessor :test_dir
28
+ # Relative path to the folder where compile time assets will be stored
29
+ attr_accessor :asset_dir
30
+ # The folder where compile time skins can be loaded from
31
+ attr_accessor :skin_dir
32
+ # The technology language that is being used, right now this is either 'as2' or 'as3'.
33
+ # Code generators take advantage of this setting to determine which templates to use.
34
+ attr_accessor :language
35
+
36
+ # TODO: Add clean hash interface so that users
37
+ # can simply add to this object's properties like:
38
+ # model.foo = 'bar'
39
+ # model.junk = true
40
+ # and then just as easily reference those vars from
41
+ # external generators...
42
+ def self.instance
43
+ @@instance ||= ProjectModel.new
44
+ end
45
+
46
+ def self.destroy # :nodoc:
47
+ @@instance = nil
48
+ end
49
+
50
+ def initialize
51
+ super
52
+ @project_name = ''
53
+ @src_dir = 'src'
54
+ @lib_dir = 'lib'
55
+ @bin_dir = 'bin'
56
+ @test_dir = 'test'
57
+ @asset_dir = 'assets'
58
+ @skin_dir = File.join(@asset_dir, 'skins')
59
+
60
+ @language = 'as3'
61
+
62
+ @model_dir = nil
63
+ @view_dir = nil
64
+ @controller_dir = nil
65
+ end
66
+
67
+ # Path to the project directory from which all other paths are created
68
+ def project_path
69
+ return Sprout.project_path
70
+ end
71
+
72
+ def model_dir=(dir)
73
+ @model_dir = dir
74
+ end
75
+
76
+ # Simple MVC helper for project-wide models if your project is called 'SomeProject'
77
+ # this will default to:
78
+ # SomeProject/src/someproject/models
79
+ def model_dir
80
+ if(@model_dir.nil?)
81
+ @model_dir = File.join(src_dir, project_name.downcase, 'models')
82
+ end
83
+ return @model_dir
84
+ end
85
+
86
+ def view_dir=(dir)
87
+ @view_dir = dir
88
+ end
89
+
90
+ # Simple MVC helper for project-wide views if your project is called 'SomeProject'
91
+ # this will default to:
92
+ # SomeProject/src/someproject/views
93
+ def view_dir
94
+ if(@view_dir.nil?)
95
+ @view_dir = File.join(src_dir, project_name.downcase, 'views')
96
+ end
97
+ return @view_dir
98
+ end
99
+
100
+ def controller_dir=(dir)
101
+ @controller_dir = dir
102
+ end
103
+
104
+ # Simple MVC helper for project-wide views if your project is called 'SomeProject'
105
+ # this will default to:
106
+ # SomeProject/src/someproject/controllers
107
+ def controller_dir
108
+ if(@controller_dir.nil?)
109
+ @controller_dir = File.join(src_dir, project_name.downcase, 'controllers')
110
+ end
111
+ return @controller_dir
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,233 @@
1
+
2
+ module Sprout
3
+ class RemoteFileLoaderError < StandardError #:nodoc:
4
+ end
5
+
6
+ class RemoteFileLoader #:nodoc:
7
+ include Archive::Tar
8
+
9
+ def get_remote_file(uri, target, force=false, md5=nil)
10
+ if(force || !File.exists?(target))
11
+ response = fetch(uri.to_s)
12
+ if(response_is_valid?(response, md5))
13
+ write(response, target, force)
14
+ end
15
+ end
16
+ end
17
+
18
+ def response_is_valid?(response, expected_md5sum=nil)
19
+ if(expected_md5sum)
20
+ md5 = Digest::MD5.new
21
+ md5 << response
22
+ raise BadCheckSum if (expected_md5sum != md5.hexdigest)
23
+ end
24
+ return true
25
+ end
26
+
27
+ def write(response, target, force=false)
28
+ FileUtils.makedirs(File.dirname(target))
29
+ if(force && File.exists?(target))
30
+ File.delete(target)
31
+ end
32
+ File.open(target, 'wb') do |f|
33
+ f.write(response)
34
+ end
35
+ end
36
+
37
+ def fetch(uri)
38
+ uri = URI.parse(uri)
39
+ # Download the file now to the downloads dir
40
+ # If the file is an archive (zip, gz, tar, tar.gz, dmg), extract to
41
+ # Sprouts/cache/@type/@name
42
+ # Check the location again...
43
+ progress = nil
44
+ response = nil
45
+ name = uri.path.split("/").pop
46
+
47
+ raise RemoteFileLoaderError.new("The RemoteFileTask failed for #{name}. We can only handle HTTP requests at this time, it seems you were trying: '#{uri.scheme}'") if uri.scheme != 'http'
48
+ begin
49
+ open(uri.to_s, :content_length_proc => lambda {|t|
50
+ if t && t > 0
51
+ progress = ProgressBar.new(name, t)
52
+ progress.file_transfer_mode
53
+ progress.set(0)
54
+ else
55
+ progress = ProgressBar.new(name, 0)
56
+ progress.file_transfer_mode
57
+ progress.set(0)
58
+ end
59
+ },
60
+ :progress_proc => lambda {|s|
61
+ progress.set s if progress
62
+ }) {|f|
63
+ response = f.read
64
+ progress.finish
65
+ }
66
+ rescue SocketError => e
67
+ raise RemoteFileLoaderError.new("[ERROR] #{e.to_s}")
68
+ rescue OpenURI::HTTPError => e
69
+ raise RemoteFileLoaderError.new("[ERROR] Failed to load file from: '#{uri.to_s}'\n[REMOTE ERROR] #{e.io.read.strip}")
70
+ rescue Errno::ECONNREFUSED => e
71
+ raise Errno::ECONNREFUSED.new("[ERROR] Connection refused at: '#{uri.to_s}'")
72
+ end
73
+
74
+ return response
75
+ end
76
+
77
+ def unpack_downloaded_file(file_name, dir)
78
+ if(!File.exists?(dir))
79
+ if(is_zip?(file_name))
80
+ unpack_zip(file_name, dir)
81
+ elsif(is_targz?(file_name))
82
+ unpack_targz(file_name, dir)
83
+ elsif(is_dmg?(file_name))
84
+ unpack_dmg(file_name, dir)
85
+ elsif(is_swc?(file_name))
86
+ # just copy the swc...
87
+ elsif(is_rb?(file_name))
88
+ return
89
+ elsif(is_exe?(file_name))
90
+ FileUtils.mkdir_p(dir)
91
+ File.mv(file_name, dir)
92
+ else
93
+ raise UsageError.new("RemoteFileTask does not know how to unpack files of type: #{file_name}")
94
+ end
95
+ end
96
+ end
97
+
98
+ def unpack_zip(zip_file, dir)
99
+ # Avoid the rubyzip Segmentation Fault bug
100
+ # at least on os x...
101
+ if(RUBY_PLATFORM =~ /darwin/)
102
+ # Unzipping on OS X
103
+ FileUtils.makedirs(dir)
104
+ zip_dir = File.expand_path(File.dirname(zip_file))
105
+ zip_name = File.basename(zip_file)
106
+ output = File.expand_path(dir)
107
+ #puts ">> zip_dir: #{zip_dir} zip_name: #{zip_name} output: #{output}"
108
+ %x(cd #{zip_dir};unzip #{zip_name} -d #{output})
109
+ else
110
+ retries = 0
111
+ begin
112
+ retries += 1
113
+ Zip::ZipFile::open(zip_file) do |zf|
114
+ zf.each do |e|
115
+ fpath = File.join(dir, e.name)
116
+ FileUtils.mkdir_p(File.dirname(fpath))
117
+ # Disgusting, Gross Hack to fix DOS/Ruby Bug
118
+ # That makes the zip library throw a ZipDestinationFileExistsError
119
+ # When the zip archive includes two files whose names
120
+ # differ only by extension.
121
+ # This bug actually appears in the File.exists? implementation
122
+ # throwing false positives!
123
+ # If you're going to use this code, be sure you extract
124
+ # into a new, empty directory as existing files will be
125
+ # clobbered...
126
+ if(File.exists?(fpath) && !File.directory?(fpath))
127
+ hackpath = fpath + 'hack'
128
+ zf.extract(e, hackpath)
129
+ File.copy(hackpath, fpath)
130
+ File.delete(hackpath)
131
+ else
132
+ zf.extract(e, fpath)
133
+ end
134
+ end
135
+ end
136
+ rescue StandardError => e
137
+ if(retries < 3)
138
+ puts ">> [ZIP ERROR ENCOUNTERED] trying again with: #{dir}"
139
+ FileUtils.rm_rf(dir)
140
+ FileUtils.makedirs(dir)
141
+ retry
142
+ end
143
+ raise e
144
+ end
145
+ end
146
+ end
147
+
148
+ def unpack_targz(tgz_file, dir)
149
+ if(!File.exists?(dir))
150
+ FileUtils.makedirs(dir)
151
+ end
152
+ tar = Zlib::GzipReader.new(File.open(tgz_file, 'rb'))
153
+ Minitar.unpack(tar, dir)
154
+
155
+ # Recurse and unpack gzipped children (Adobe did this double
156
+ # gzip with the Linux FlashPlayer for some reason)
157
+ Dir.glob("#{dir}/**/*.tar.gz").each do |child|
158
+ if(child != tgz_file)
159
+ unpack_targz(child, File.dirname(child))
160
+ end
161
+ end
162
+
163
+ end
164
+
165
+ # This is actually not unpacking the FlashPlayer
166
+ # Binary file as expected...
167
+ # OSX is treated the player binary as if it is
168
+ # a regular text file, but if it is copied manually,
169
+ # the command works fine!?
170
+ def unpack_dmg(dmg_file, dir)
171
+ # 1) Mount the dmg in place
172
+ # 2) Recursively Copy it's contents to asproject_home
173
+ # 3) Unmount the dmg
174
+ if(mounted_path.nil?)
175
+ raise StandardError.new('DMG file downloaded, but the RemoteFileTask needs a mounted_path in order to mount it')
176
+ end
177
+
178
+ if(!File.exists?(full_mounted_path))
179
+ system("hdiutil mount #{dmg_file}")
180
+ end
181
+
182
+ begin
183
+ mounted_target = File.join(full_mounted_path, extracted_file)
184
+
185
+ # Copy the DMG contents using system copy rather than ruby utils
186
+ # Because OS X does something special with .app files that the
187
+ # Ruby FileUtils and File classes break...
188
+ from = mounted_target
189
+ # from = File.join(full_mounted_path, extracted_file)
190
+ to = File.join(@user.downloads, @name.to_s, extracted_file)
191
+ FileUtils.makedirs(File.dirname(to))
192
+
193
+ if(File.exists?(from))
194
+ `ditto '#{from}' '#{to}'`
195
+ end
196
+ rescue
197
+ if(File.exists?(full_mounted_path))
198
+ system("hdiutil unmount -force \"#{full_mounted_path}\"")
199
+ end
200
+ end
201
+ end
202
+
203
+ def is_exe?(file)
204
+ return (file.split('.').pop == 'exe')
205
+ end
206
+
207
+ def is_zip?(file)
208
+ return (file.split('.').pop == 'zip')
209
+ end
210
+
211
+ def is_targz?(file)
212
+ parts = file.split('.')
213
+ part = parts.pop
214
+ return (part == 'tgz' || part == 'gz' && parts.pop == 'tar')
215
+ end
216
+
217
+ def is_gzip?(file)
218
+ return (file.split('.').pop == 'gz')
219
+ end
220
+
221
+ def is_swc?(file)
222
+ return (file.split('.').pop == 'swc')
223
+ end
224
+
225
+ def is_rb?(file)
226
+ return (file.split('.').pop == 'rb')
227
+ end
228
+
229
+ def is_dmg?(file)
230
+ return (file.split('.').pop == 'dmg')
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,96 @@
1
+
2
+ module Sprout
3
+ class RemoteFileTargetError < StandardError #:nodoc:
4
+ end
5
+
6
+ class RemoteFileTarget # :nodoc:
7
+
8
+ attr_writer :archive_path
9
+
10
+ # The user path where this gem will download and install files
11
+ # This value is set by the Sprout::Builder that creates this RemoteFileTarget
12
+ attr_accessor :install_path
13
+
14
+ # Optional md5 hash, usually set in the sprout.spec for each RemoteFileTarget
15
+ # If this value is set, the downloaded archive will be hashed, the hashes will
16
+ # be compared and if they differ, the installation process will break.
17
+ attr_accessor :md5
18
+
19
+ # Used for dmg archives. Absolute path to the mounted dmg (essentially it's name)
20
+ attr_accessor :mount_path
21
+
22
+ # Which platform will this RemoteFileTarget support.
23
+ # Supported options are:
24
+ # * universal
25
+ # * macosx
26
+ # * win32
27
+ # * linux
28
+ attr_accessor :platform
29
+
30
+ # URL where Sprouts can go to download the RemoteFileTarget archive
31
+ attr_accessor :url
32
+
33
+ # Relative path within the archive to the executable or binary of interest
34
+ def archive_path
35
+ @archive_path ||= ''
36
+ end
37
+
38
+ # Resolve this RemoteFileTarget now. This method is called by the Sprout::Builder
39
+ # and will download, install and unpack the described archive
40
+ def resolve(update=false)
41
+ if(url)
42
+ @loader = RemoteFileLoader.new
43
+ if(url && (update || !File.exists?(downloaded_path)))
44
+ download(url, downloaded_path, update)
45
+ end
46
+
47
+ if(!File.exists?(installed_path) || !File.exists?(File.join(installed_path, archive_path) ))
48
+ archive_root = File.join(install_path, 'archive')
49
+ install(downloaded_path, archive_root)
50
+ end
51
+ end
52
+ end
53
+
54
+ # Return the basename of the executable that this RemoteFileTarget refers to
55
+ def executable
56
+ return File.basename(archive_path)
57
+ end
58
+
59
+ # The root path to the unpacked archive files. This is the base path that will be added to any
60
+ # +archive_path+ relative paths
61
+ def installed_path
62
+ @installed_path ||= File.join(install_path, 'archive')
63
+ return @installed_path
64
+ end
65
+
66
+ # Parent directory where archives are downloaded
67
+ # can be something like: ~/Library/Sprouts/cache/0.7/sprout-somesprout-tool.x.x.x/
68
+ def downloaded_path
69
+ @downloaded_path ||= File.join(install_path, file_name)
70
+ return @downloaded_path
71
+ end
72
+
73
+ # Base file name represented by the provided +url+
74
+ # Will strip off any ? arguments and trailing slashes. May not play nice with Rails URLS,
75
+ # We expect archive file name suffixes like, zip, gzip, tar.gz, dmg, etc.
76
+ def file_name
77
+ if(url.split('').last == '/')
78
+ return name
79
+ end
80
+ file = url.split('/').pop
81
+ file = file.split('?').shift
82
+ return file
83
+ end
84
+
85
+ private
86
+ def download(url, path, update=false)
87
+ @loader = RemoteFileLoader.new
88
+ @loader.get_remote_file(url, path, update, md5)
89
+ end
90
+
91
+ def install(from, to)
92
+ @loader.unpack_downloaded_file(from, to)
93
+ end
94
+
95
+ end
96
+ end