sprout 0.7.153-darwin

Sign up to get free protection for your applications and to get access to all the features.
@@ -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