sprout 0.7.220-x86-darwin-10
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/MIT-LICENSE +20 -0
- data/TODO +12 -0
- data/bin/sprout +128 -0
- data/doc/Bundle +14 -0
- data/doc/Generator +35 -0
- data/doc/Library +63 -0
- data/doc/Task +21 -0
- data/doc/Tool +20 -0
- data/lib/platform.rb +109 -0
- data/lib/progress_bar.rb +354 -0
- data/lib/sprout/archive_unpacker.rb +225 -0
- data/lib/sprout/builder.rb +44 -0
- data/lib/sprout/commands/generate.rb +9 -0
- data/lib/sprout/dynamic_accessors.rb +34 -0
- data/lib/sprout/general_tasks.rb +6 -0
- data/lib/sprout/generator/base_mixins.rb +186 -0
- data/lib/sprout/generator/named_base.rb +227 -0
- data/lib/sprout/generator.rb +7 -0
- data/lib/sprout/log.rb +46 -0
- data/lib/sprout/process_runner.rb +111 -0
- data/lib/sprout/project_model.rb +278 -0
- data/lib/sprout/remote_file_loader.rb +71 -0
- data/lib/sprout/remote_file_target.rb +151 -0
- data/lib/sprout/simple_resolver.rb +88 -0
- data/lib/sprout/tasks/erb_resolver.rb +118 -0
- data/lib/sprout/tasks/gem_wrap_task.rb +200 -0
- data/lib/sprout/tasks/git_task.rb +134 -0
- data/lib/sprout/tasks/library_task.rb +118 -0
- data/lib/sprout/tasks/sftp_task.rb +248 -0
- data/lib/sprout/tasks/ssh_task.rb +153 -0
- data/lib/sprout/tasks/tool_task.rb +793 -0
- data/lib/sprout/tasks/zip_task.rb +158 -0
- data/lib/sprout/template_resolver.rb +207 -0
- data/lib/sprout/user.rb +383 -0
- data/lib/sprout/version.rb +12 -0
- data/lib/sprout/version_file.rb +89 -0
- data/lib/sprout/zip_util.rb +61 -0
- data/lib/sprout.rb +496 -0
- data/rakefile.rb +150 -0
- data/samples/gem_wrap/rakefile.rb +17 -0
- metadata +174 -0
data/lib/progress_bar.rb
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
#
|
2
|
+
# Ruby/ProgressBar - a text progress bar library
|
3
|
+
#
|
4
|
+
# Copyright (C) 2001-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms
|
9
|
+
# of Ruby's license.
|
10
|
+
#
|
11
|
+
# Modified by Luke Bayes to support progress display on
|
12
|
+
# multiple simultaneous connections
|
13
|
+
|
14
|
+
require 'singleton'
|
15
|
+
|
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
|
+
# Used instead of $stderr when Log.debug == true
|
269
|
+
# This helps keep us from junking up unit test
|
270
|
+
# output with download status messages
|
271
|
+
class MockOutput # :nodoc:[all]
|
272
|
+
def print(str)
|
273
|
+
end
|
274
|
+
|
275
|
+
def puts(str)
|
276
|
+
end
|
277
|
+
|
278
|
+
def flush
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
class ReversedProgressBar < ProgressBar # :nodoc:[all]
|
283
|
+
def do_percentage
|
284
|
+
100 - super
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class ProgressBarOutputStream # :nodoc:[all]
|
289
|
+
attr_reader :title
|
290
|
+
|
291
|
+
def initialize(mgr)
|
292
|
+
@mgr = mgr
|
293
|
+
@msg = ''
|
294
|
+
end
|
295
|
+
|
296
|
+
def print(msg)
|
297
|
+
@msg = msg
|
298
|
+
end
|
299
|
+
|
300
|
+
def flush
|
301
|
+
@mgr.flush
|
302
|
+
end
|
303
|
+
|
304
|
+
def to_s
|
305
|
+
return @msg.clone.split("\n").join("").split("\r").join("")
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
class ProgressBarManager # :nodoc:[all]
|
311
|
+
include Singleton
|
312
|
+
|
313
|
+
def initialize
|
314
|
+
@finished = {}
|
315
|
+
@bars = {}
|
316
|
+
@outs = {}
|
317
|
+
end
|
318
|
+
|
319
|
+
def add(title, total1)
|
320
|
+
# if(@bars[title])
|
321
|
+
# raise StandardError.new
|
322
|
+
# end
|
323
|
+
@outs[title] = ProgressBarOutputStream.new(self)
|
324
|
+
@bars[title] = ProgressBarImpl.new(title, total1, @outs[title])
|
325
|
+
end
|
326
|
+
|
327
|
+
def print(title)
|
328
|
+
str = ''
|
329
|
+
str += @outs[title].to_s
|
330
|
+
str += "\r"
|
331
|
+
outio.print "\r"
|
332
|
+
outio.print str
|
333
|
+
end
|
334
|
+
|
335
|
+
def outio
|
336
|
+
ProgressBar.outio
|
337
|
+
end
|
338
|
+
|
339
|
+
def flush
|
340
|
+
@bars.keys.each do |title|
|
341
|
+
print(title)
|
342
|
+
end
|
343
|
+
|
344
|
+
@bars.values.each do |bar|
|
345
|
+
if(bar.finished?)
|
346
|
+
print(bar.title)
|
347
|
+
outio.print "\n"
|
348
|
+
@outs.delete(bar.title)
|
349
|
+
@bars.delete(bar.title)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
|
2
|
+
module Sprout
|
3
|
+
class ArchiveUnpackerError < StandardError #:nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
# Unpack downloaded files from a variety of common archive types.
|
7
|
+
# This library should efficiently extract archived files
|
8
|
+
# on OS X, Win XP, Vista, DOS, Cygwin, and Linux.
|
9
|
+
#
|
10
|
+
# It will attempt to infer the archive type by standard mime-type file
|
11
|
+
# extensions, but if there is a file with no extension, the unpack_archive
|
12
|
+
# method can be provided with an @archive_type symbol argument that is one
|
13
|
+
# of the following values:
|
14
|
+
# :exe
|
15
|
+
# :zip
|
16
|
+
# :targz
|
17
|
+
# :gzip
|
18
|
+
# :swc
|
19
|
+
# :rb
|
20
|
+
# :dmg
|
21
|
+
class ArchiveUnpacker #:nodoc:
|
22
|
+
include Archive::Tar
|
23
|
+
|
24
|
+
def unpack_archive(file_name, dir, force=false, archive_type=nil)
|
25
|
+
archive_type ||= inferred_archive_type(file_name)
|
26
|
+
suffix = suffix_for_archive_type(archive_type)
|
27
|
+
|
28
|
+
unpacked = unpacked_file_name(file_name, dir, suffix)
|
29
|
+
if(File.exists?(unpacked) && force)
|
30
|
+
FileUtils.rm_rf(unpacked)
|
31
|
+
end
|
32
|
+
|
33
|
+
if(!File.exists?(unpacked))
|
34
|
+
case archive_type.to_s
|
35
|
+
when 'zip'
|
36
|
+
unpack_zip(file_name, dir)
|
37
|
+
when 'targz'
|
38
|
+
unpack_targz(file_name, dir)
|
39
|
+
when 'dmg'
|
40
|
+
unpack_dmg(file_name, dir)
|
41
|
+
when 'exe'
|
42
|
+
FileUtils.mkdir_p(dir)
|
43
|
+
File.mv(file_name, dir)
|
44
|
+
when 'swc' || 'rb'
|
45
|
+
return
|
46
|
+
else
|
47
|
+
raise ArchiveUnpackerError.new("ArchiveUnpacker does not know how to unpack files of type: #{archive_type} for file_name: #{file_name}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def unpack_zip(zip_file, dir)
|
53
|
+
# Avoid the rubyzip Segmentation Fault bug
|
54
|
+
# at least on os x...
|
55
|
+
if(RUBY_PLATFORM =~ /darwin/)
|
56
|
+
# Unzipping on OS X
|
57
|
+
FileUtils.makedirs(dir)
|
58
|
+
zip_dir = File.expand_path(File.dirname(zip_file))
|
59
|
+
zip_name = File.basename(zip_file)
|
60
|
+
output = File.expand_path(dir)
|
61
|
+
# puts ">> zip_dir: #{zip_dir} zip_name: #{zip_name} output: #{output}"
|
62
|
+
%x(cd #{zip_dir};unzip #{zip_name} -d #{output})
|
63
|
+
else
|
64
|
+
retries = 0
|
65
|
+
begin
|
66
|
+
retries += 1
|
67
|
+
Zip::ZipFile::open(zip_file) do |zf|
|
68
|
+
zf.each do |e|
|
69
|
+
fpath = File.join(dir, e.name)
|
70
|
+
FileUtils.mkdir_p(File.dirname(fpath))
|
71
|
+
# Disgusting, Gross Hack to fix DOS/Ruby Bug
|
72
|
+
# That makes the zip library throw a ZipDestinationFileExistsError
|
73
|
+
# When the zip archive includes two files whose names
|
74
|
+
# differ only by extension.
|
75
|
+
# This bug actually appears in the File.exists? implementation
|
76
|
+
# throwing false positives!
|
77
|
+
# If you're going to use this code, be sure you extract
|
78
|
+
# into a new, empty directory as existing files will be
|
79
|
+
# clobbered...
|
80
|
+
begin
|
81
|
+
if(File.exists?(fpath) && !File.directory?(fpath))
|
82
|
+
hackpath = fpath + 'hack'
|
83
|
+
zf.extract(e, hackpath)
|
84
|
+
File.copy(hackpath, fpath)
|
85
|
+
File.delete(hackpath)
|
86
|
+
else
|
87
|
+
zf.extract(e, fpath)
|
88
|
+
end
|
89
|
+
rescue NotImplementedError => ni_err
|
90
|
+
puts "[WARNING] #{ni_err} for: #{e}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
rescue StandardError => err
|
95
|
+
FileUtils.rm_rf(dir)
|
96
|
+
if(retries < 3)
|
97
|
+
FileUtils.makedirs(dir)
|
98
|
+
retry
|
99
|
+
end
|
100
|
+
raise err
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def unpacked_file_name(file, dir, suffix=nil)
|
106
|
+
basename = File.basename(file, suffix)
|
107
|
+
path = File.expand_path(dir)
|
108
|
+
return File.join(path, basename)
|
109
|
+
end
|
110
|
+
|
111
|
+
def unpack_targz(tgz_file, dir)
|
112
|
+
if(!File.exists?(dir))
|
113
|
+
FileUtils.makedirs(dir)
|
114
|
+
end
|
115
|
+
tar = Zlib::GzipReader.new(File.open(tgz_file, 'rb'))
|
116
|
+
Minitar.unpack(tar, dir)
|
117
|
+
|
118
|
+
# Recurse and unpack gzipped children (Adobe did this double
|
119
|
+
# gzip with the Linux FlashPlayer for some reason)
|
120
|
+
Dir.glob("#{dir}/**/*.tar.gz").each do |child|
|
121
|
+
if(child != tgz_file)
|
122
|
+
unpack_targz(child, File.dirname(child))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# This is actually not unpacking the FlashPlayer
|
129
|
+
# Binary file as expected...
|
130
|
+
# OSX is treated the player binary as if it is
|
131
|
+
# a regular text file, but if it is copied manually,
|
132
|
+
# the command works fine!?
|
133
|
+
def unpack_dmg(dmg_file, dir)
|
134
|
+
# 1) Mount the dmg in place
|
135
|
+
# 2) Recursively Copy its contents to asproject_home
|
136
|
+
# 3) Unmount the dmg
|
137
|
+
if(mounted_path.nil?)
|
138
|
+
raise StandardError.new('DMG file downloaded, but the RemoteFileTask needs a mounted_path in order to mount it')
|
139
|
+
end
|
140
|
+
|
141
|
+
if(!File.exists?(full_mounted_path))
|
142
|
+
system("hdiutil mount #{dmg_file}")
|
143
|
+
end
|
144
|
+
|
145
|
+
begin
|
146
|
+
mounted_target = File.join(full_mounted_path, extracted_file)
|
147
|
+
|
148
|
+
# Copy the DMG contents using system copy rather than ruby utils
|
149
|
+
# Because OS X does something special with .app files that the
|
150
|
+
# Ruby FileUtils and File classes break...
|
151
|
+
from = mounted_target
|
152
|
+
# from = File.join(full_mounted_path, extracted_file)
|
153
|
+
to = File.join(@user.downloads, @name.to_s, extracted_file)
|
154
|
+
FileUtils.makedirs(File.dirname(to))
|
155
|
+
|
156
|
+
if(File.exists?(from))
|
157
|
+
`ditto '#{from}' '#{to}'`
|
158
|
+
end
|
159
|
+
rescue StandardError => e
|
160
|
+
if(File.exists?(full_mounted_path))
|
161
|
+
system("hdiutil unmount -force \"#{full_mounted_path}\"")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def suffix_for_archive_type(type)
|
167
|
+
if(type == :targz)
|
168
|
+
return '.tar.gz'
|
169
|
+
else
|
170
|
+
return ".#{type.to_s}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def inferred_archive_type(file_name)
|
175
|
+
if is_zip?(file_name)
|
176
|
+
return :zip
|
177
|
+
elsif is_targz?(file_name)
|
178
|
+
return :targz
|
179
|
+
elsif is_gzip?(file_name)
|
180
|
+
return :gz
|
181
|
+
elsif is_swc?(file_name)
|
182
|
+
return :swc
|
183
|
+
elsif is_rb?(file_name)
|
184
|
+
return :rb
|
185
|
+
elsif is_dmg?(file_name)
|
186
|
+
return :dmg
|
187
|
+
elsif is_exe?(file_name)
|
188
|
+
return :exe
|
189
|
+
else
|
190
|
+
return nil
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
def is_zip?(file)
|
196
|
+
return (file.split('.').pop == 'zip')
|
197
|
+
end
|
198
|
+
|
199
|
+
def is_targz?(file)
|
200
|
+
parts = file.split('.')
|
201
|
+
part = parts.pop
|
202
|
+
return (part == 'tgz' || part == 'gz' && parts.pop == 'tar')
|
203
|
+
end
|
204
|
+
|
205
|
+
def is_gzip?(file)
|
206
|
+
return (file.split('.').pop == 'gz')
|
207
|
+
end
|
208
|
+
|
209
|
+
def is_swc?(file)
|
210
|
+
return (file.split('.').pop == 'swc')
|
211
|
+
end
|
212
|
+
|
213
|
+
def is_rb?(file)
|
214
|
+
return (file.split('.').pop == 'rb')
|
215
|
+
end
|
216
|
+
|
217
|
+
def is_dmg?(file)
|
218
|
+
return (file.split('.').pop == 'dmg')
|
219
|
+
end
|
220
|
+
|
221
|
+
def is_exe?(file)
|
222
|
+
return (file.split('.').pop == 'exe')
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Sprout
|
3
|
+
|
4
|
+
class BuilderError < StandardError #:nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
# accepts a destination path and a sprout specification
|
8
|
+
# and will download and unpack the platform-specific
|
9
|
+
# archives that are identified in the spec
|
10
|
+
class Builder # :nodoc:
|
11
|
+
|
12
|
+
def self.build(file_targets_yaml, destination)
|
13
|
+
data = nil
|
14
|
+
|
15
|
+
File.open(file_targets_yaml, 'r') do |f|
|
16
|
+
data = f.read
|
17
|
+
end
|
18
|
+
|
19
|
+
targets = YAML.load(data)
|
20
|
+
targets.each do |target|
|
21
|
+
# iterate over the provided RemoteFileTargets until we
|
22
|
+
# encounter one that is appropriate for our platform,
|
23
|
+
# or one that claims to be universal.
|
24
|
+
# When authoring a sprout.spec for libraries or tools,
|
25
|
+
# put the most specific RemoteFileTargets first, then
|
26
|
+
# universals to catch unexpected platforms.
|
27
|
+
if(target.platform == platform || target.platform == 'universal')
|
28
|
+
target.install_path = FileUtils.mkdir_p(destination)
|
29
|
+
target.resolve
|
30
|
+
return target
|
31
|
+
end
|
32
|
+
end
|
33
|
+
raise BuilderError.new("Sprout::Builder.build failed, unsupported platform or unexpected yaml")
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def self.platform
|
39
|
+
@@platform ||= User.new.platform.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
# DynamicAccessors provides support for
|
3
|
+
# simply setting and getting values of any kind from
|
4
|
+
# any object that includes it.
|
5
|
+
#
|
6
|
+
# require 'dynamic_accessors'
|
7
|
+
#
|
8
|
+
# class Foo
|
9
|
+
# include DynamicAccessors
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# foo = Foo.new
|
13
|
+
# foo.bar = "Hello World"
|
14
|
+
# foo.friends = ['a', 'b', 'c']
|
15
|
+
# puts "foo.bar: #{foo.bar}"
|
16
|
+
# puts "foo.friends: #{foo.friends.join(', ')}"
|
17
|
+
|
18
|
+
module DynamicAccessors
|
19
|
+
|
20
|
+
def initialize(*params)
|
21
|
+
super
|
22
|
+
@missing_params_hash = Hash.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *params, &block)
|
26
|
+
if(method.to_s.match(/=$/))
|
27
|
+
method = method.to_s.gsub('=', '').to_sym
|
28
|
+
return @missing_params_hash[method] = params.shift
|
29
|
+
else
|
30
|
+
return @missing_params_hash[method] if @missing_params_hash.keys.collect(&:to_sym).include?(method)
|
31
|
+
end
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|