sprout 0.3.35
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.txt +20 -0
- data/Manifest.txt +9 -0
- data/bin/sprout +167 -0
- data/lib/command.rb +29 -0
- data/lib/file_target.rb +8 -0
- data/lib/generate.rb +37 -0
- data/lib/library.rb +18 -0
- data/lib/log.rb +46 -0
- data/lib/platform.rb +110 -0
- data/lib/progress_bar.rb +314 -0
- data/lib/project.rb +10 -0
- data/lib/project_model.rb +59 -0
- data/lib/remote_file_loader.rb +186 -0
- data/lib/remote_file_target.rb +44 -0
- data/lib/sprout.rb +340 -0
- data/lib/sprout/version.rb +9 -0
- data/lib/task.rb +20 -0
- data/lib/template.rb +37 -0
- data/lib/template_resolver.rb +204 -0
- data/lib/tool.rb +18 -0
- data/lib/user.rb +234 -0
- data/rakefile.rb +146 -0
- data/setup.rb +1585 -0
- metadata +105 -0
@@ -0,0 +1,204 @@
|
|
1
|
+
|
2
|
+
module PatternPark
|
3
|
+
#######################################
|
4
|
+
# TemplateResolver
|
5
|
+
class TemplateResolver < Hash
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
attr_accessor :replace_all, :ignore_all
|
9
|
+
@@SPROUT_FILE_NAME = 'Sprout'
|
10
|
+
@@RENDER_IGNORE_FILES = ['asclass_config.rb', 'SWFMillTemplate.erb']
|
11
|
+
@@BINARY_EXTENSIONS = ['.jpg', '.png', '.gif', '.doc', '.xls', '.exe', '.swf', 'fla', '.psd']
|
12
|
+
@@LOG_PREFIX = ">> Created file: "
|
13
|
+
@@DELETE_PREFIX = ">> DELETED file: "
|
14
|
+
def initialize
|
15
|
+
@replace_all = false
|
16
|
+
@ignore_all = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def copy_files(from, to, render=false)
|
20
|
+
created_files = Array.new
|
21
|
+
if(!File.exists? from)
|
22
|
+
raise UsageError.new('TemplateResolver attempted to copy files from (' + from + ') but it does not exist...')
|
23
|
+
end
|
24
|
+
if(File.directory? from)
|
25
|
+
Dir.open(from).each do |filename|
|
26
|
+
if(!Sprout.ignore_file? filename)
|
27
|
+
fullname = File.join(from, filename)
|
28
|
+
new_fullname = File.join(to, filename)
|
29
|
+
cleaned_filename = clean_file_name(filename)
|
30
|
+
cleaned_fullname = File.join(to, cleaned_filename)
|
31
|
+
if(File.directory? fullname)
|
32
|
+
Dir.mkdir(new_fullname) unless File.exists? new_fullname
|
33
|
+
puts new_fullname
|
34
|
+
copy_files(fullname, new_fullname, render)
|
35
|
+
else
|
36
|
+
file = copy_file(fullname, cleaned_fullname, render)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
raise UsageError.new("copy_files called with a file (" + from + ") instead of a directory!")
|
42
|
+
end
|
43
|
+
|
44
|
+
return created_files
|
45
|
+
end
|
46
|
+
|
47
|
+
def puts(file, is_delete=false)
|
48
|
+
prefix = (is_delete) ? @@DELETE_PREFIX : @@LOG_PREFIX
|
49
|
+
Log.puts(prefix + file.gsub(Dir.pwd + '/', ''))
|
50
|
+
end
|
51
|
+
|
52
|
+
def b(path)
|
53
|
+
(is_binary?(path)) ? 'b' : ''
|
54
|
+
end
|
55
|
+
|
56
|
+
def copy_file(from, to, render=false, delegate=nil)
|
57
|
+
if(write_file?(to))
|
58
|
+
content = nil
|
59
|
+
File.open(from, 'r' + b(from)) do |f|
|
60
|
+
content = f.read
|
61
|
+
end
|
62
|
+
if(render && should_render?(from))
|
63
|
+
begin
|
64
|
+
bind = (delegate.nil?) ? binding : delegate.get_binding
|
65
|
+
content = ERB.new(content, nil, '>').result(bind)
|
66
|
+
rescue NameError => e
|
67
|
+
Log.puts '>> Template ' + from + ' references a value that is not defined'
|
68
|
+
raise e
|
69
|
+
end
|
70
|
+
end
|
71
|
+
FileUtils.makedirs(File.dirname(to))
|
72
|
+
File.open(to, 'w' + b(to)) do |f|
|
73
|
+
f.write(content)
|
74
|
+
end
|
75
|
+
puts to
|
76
|
+
return to
|
77
|
+
end
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def should_render?(file)
|
82
|
+
if(is_binary?(file) || @@RENDER_IGNORE_FILES.index(File.basename(file)))
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
return true
|
86
|
+
end
|
87
|
+
|
88
|
+
def write_file?(file)
|
89
|
+
if(!File.exists?(file))
|
90
|
+
return true
|
91
|
+
elsif(@replace_all)
|
92
|
+
puts(file, true)
|
93
|
+
File.delete(file)
|
94
|
+
return true
|
95
|
+
elsif(@ignore_all)
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
relative = file.gsub(Dir.pwd, '')
|
100
|
+
msg = <<EOF
|
101
|
+
|
102
|
+
[WARNING] Sprout Encountered an existing file at [#{relative}], what would you like to do?
|
103
|
+
(r)eplace, (i)gnore, (R)eplace all or (I)gnore all?
|
104
|
+
|
105
|
+
EOF
|
106
|
+
if(Log.debug)
|
107
|
+
return false
|
108
|
+
end
|
109
|
+
|
110
|
+
$stdout.puts msg
|
111
|
+
answer = $stdin.gets.chomp
|
112
|
+
if(answer == 'r')
|
113
|
+
return true
|
114
|
+
elsif(answer == 'i')
|
115
|
+
return false
|
116
|
+
elsif(answer == 'R')
|
117
|
+
msg = <<EOF
|
118
|
+
|
119
|
+
Are you sure you want to replace ALL duplicate files?
|
120
|
+
(y)es or (n)o
|
121
|
+
|
122
|
+
EOF
|
123
|
+
$stdout.puts msg
|
124
|
+
answer = $stdin.gets.chomp
|
125
|
+
if(answer == 'y')
|
126
|
+
@replace_all = true
|
127
|
+
else
|
128
|
+
write_file?(file)
|
129
|
+
end
|
130
|
+
elsif(answer == 'I')
|
131
|
+
@ignore_all = true
|
132
|
+
return false
|
133
|
+
else
|
134
|
+
$stdout.puts "I didn't understand that response... Please choose from the following choices:\n\n"
|
135
|
+
write_file?(file)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def render_file filename
|
140
|
+
file = File.open(filename, 'r')
|
141
|
+
resolved = ERB.new(file.read, nil, '>').result(binding)
|
142
|
+
file.close
|
143
|
+
file = File.open(filename, 'w')
|
144
|
+
file.write(resolved)
|
145
|
+
file.close
|
146
|
+
end
|
147
|
+
|
148
|
+
def clean_file_name name
|
149
|
+
return name.gsub(@@SPROUT_FILE_NAME, project_name)
|
150
|
+
end
|
151
|
+
|
152
|
+
def project_name
|
153
|
+
return Sprout.project_name
|
154
|
+
end
|
155
|
+
|
156
|
+
def instance_name
|
157
|
+
return project_name[0,1].downcase + project_name[1,project_name.size]
|
158
|
+
end
|
159
|
+
|
160
|
+
#TODO: Figure out if the file is plain text or not... Possible?
|
161
|
+
def is_binary? file
|
162
|
+
file_extension = File.extname(file).downcase
|
163
|
+
@@BINARY_EXTENSIONS.each do |ext|
|
164
|
+
if(file_extension == ext)
|
165
|
+
return true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
|
171
|
+
=begin
|
172
|
+
Found this code for binary inspection here:
|
173
|
+
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/44940
|
174
|
+
it's not 100%, but better than what I'm doing with extensions.
|
175
|
+
This should be tested and inserted above
|
176
|
+
if it works.
|
177
|
+
|
178
|
+
NON_ASCII_PRINTABLE = /[^\x20-\x7e\s]/
|
179
|
+
|
180
|
+
def nonbinary?(io, forbidden, size = 1024)
|
181
|
+
while buf = io.read(size)
|
182
|
+
return false if forbidden =~ buf
|
183
|
+
end
|
184
|
+
true
|
185
|
+
end
|
186
|
+
|
187
|
+
# usage: ruby this_script.rb filename ...
|
188
|
+
ARGV.each do |fn|
|
189
|
+
begin
|
190
|
+
open(fn) do |f|
|
191
|
+
if nonbinary?(f, NON_ASCII_PRINTABLE)
|
192
|
+
puts "#{fn}: ascii printable"
|
193
|
+
else
|
194
|
+
puts "#{fn}: binary"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
rescue
|
198
|
+
puts "#$0: #$!"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
=end
|
202
|
+
|
203
|
+
end
|
204
|
+
end
|
data/lib/tool.rb
ADDED
data/lib/user.rb
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
|
2
|
+
module PatternPark
|
3
|
+
|
4
|
+
class ExecutionError < StandardError; end
|
5
|
+
|
6
|
+
#############################
|
7
|
+
# User class
|
8
|
+
class User
|
9
|
+
@@user = nil
|
10
|
+
|
11
|
+
def User.new(os=nil, impl=nil)
|
12
|
+
if(os.nil? && impl.nil? && @@user)
|
13
|
+
return @@user
|
14
|
+
end
|
15
|
+
if(os.nil?)
|
16
|
+
os = Platform::OS
|
17
|
+
end
|
18
|
+
if(impl.nil?)
|
19
|
+
impl = Platform::IMPL
|
20
|
+
end
|
21
|
+
if(os == :win32 && impl == :vista)
|
22
|
+
@@user = VistaUser.new
|
23
|
+
elsif(os == :win32)
|
24
|
+
@@user = WinUser.new
|
25
|
+
elsif(os == :unix && impl == :cygwin)
|
26
|
+
@@user = CygwinUser.new
|
27
|
+
elsif(os == :unix && impl == :macosx)
|
28
|
+
@@user = OSXUser.new
|
29
|
+
elsif(os == :unix && impl == :linux)
|
30
|
+
@@user = UnixUser.new
|
31
|
+
else
|
32
|
+
@@user = UnixUser.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def User.user=(user)
|
37
|
+
@@user = user
|
38
|
+
end
|
39
|
+
|
40
|
+
def User.home=(path)
|
41
|
+
User.new().home = path
|
42
|
+
end
|
43
|
+
|
44
|
+
def User.home
|
45
|
+
User.new().home
|
46
|
+
end
|
47
|
+
|
48
|
+
def User.application_home(name)
|
49
|
+
return User.new().application_home(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def User.library
|
53
|
+
return User.new().library
|
54
|
+
end
|
55
|
+
|
56
|
+
def User.execute(tool, options='')
|
57
|
+
return User.new().execute(tool, options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def User.execute_thread(tool, options='')
|
61
|
+
if(Log.debug)
|
62
|
+
return ThreadMock.new
|
63
|
+
else
|
64
|
+
return User.new().execute_thread(tool, options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def User.clean_path(path)
|
69
|
+
return User.new().clean_path(path)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Called from Sprout.init_values...
|
73
|
+
def User.init_values
|
74
|
+
@@user = nil
|
75
|
+
@@home = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#############################
|
80
|
+
# UnixUser class
|
81
|
+
class UnixUser
|
82
|
+
|
83
|
+
def initialize
|
84
|
+
@home = nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def home=(path)
|
88
|
+
@home = path
|
89
|
+
end
|
90
|
+
|
91
|
+
def home
|
92
|
+
if(@home)
|
93
|
+
return @home
|
94
|
+
end
|
95
|
+
|
96
|
+
["HOME", "USERPROFILE"].each do |homekey|
|
97
|
+
return @home = ENV[homekey] if ENV[homekey]
|
98
|
+
end
|
99
|
+
|
100
|
+
if ENV["HOMEDRIVE"] && ENV["HOMEPATH"]
|
101
|
+
return @home = "#{ENV["HOMEDRIVE"]}:#{ENV["HOMEPATH"]}"
|
102
|
+
end
|
103
|
+
|
104
|
+
begin
|
105
|
+
return @home = File.expand_path("~")
|
106
|
+
rescue StandardError => ex
|
107
|
+
if File::ALT_SEPARATOR
|
108
|
+
return @home = "C:\\"
|
109
|
+
else
|
110
|
+
return @home = "/"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def library
|
116
|
+
return home
|
117
|
+
end
|
118
|
+
|
119
|
+
def platform
|
120
|
+
return Platform::IMPL
|
121
|
+
end
|
122
|
+
|
123
|
+
def execute(tool, options='')
|
124
|
+
tool = Sprout.load(tool)
|
125
|
+
target = tool.archive_path
|
126
|
+
Log.puts(">> Execute: #{File.basename(target)} #{options}")
|
127
|
+
runner = CommandRunner.new("#{clean_path(target)} #{options}")
|
128
|
+
runner.run
|
129
|
+
result = runner.read
|
130
|
+
error = runner.readError.to_s
|
131
|
+
if(result.size > 0)
|
132
|
+
Log.puts result
|
133
|
+
end
|
134
|
+
if(error.size > 0)
|
135
|
+
raise ExecutionError.new("[ERROR] #{error}")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def execute_thread(tool, options='')
|
140
|
+
return Thread.new {
|
141
|
+
execute(tool, options)
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def clean_path(path)
|
146
|
+
if(path.index(' '))
|
147
|
+
return %{'#{path}'}
|
148
|
+
end
|
149
|
+
return path
|
150
|
+
end
|
151
|
+
|
152
|
+
def application_home(name)
|
153
|
+
return File.join(library, format_application_name(name.to_s));
|
154
|
+
end
|
155
|
+
|
156
|
+
def format_application_name(name)
|
157
|
+
if(name.index('.') != 0)
|
158
|
+
name = '.' + name
|
159
|
+
end
|
160
|
+
return name.split(" ").join("_").downcase
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class OSXUser < UnixUser
|
165
|
+
@@LIBRARY = 'Library'
|
166
|
+
|
167
|
+
def library
|
168
|
+
lib = File.join(home, @@LIBRARY)
|
169
|
+
if(File.exists?(lib))
|
170
|
+
return lib
|
171
|
+
else
|
172
|
+
return super
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def format_application_name(name)
|
177
|
+
return name.capitalize
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class WinUser < UnixUser
|
182
|
+
@@LOCAL_SETTINGS = "Local\ Settings"
|
183
|
+
@@APPLICATION_DATA = "Application\ Data"
|
184
|
+
|
185
|
+
def home
|
186
|
+
usr = super
|
187
|
+
if(usr.index "My Documents")
|
188
|
+
usr = File.dirname(usr)
|
189
|
+
end
|
190
|
+
return usr
|
191
|
+
end
|
192
|
+
|
193
|
+
def library
|
194
|
+
# For some reason, my homepath returns inside 'My Documents'...
|
195
|
+
application_data = File.join(home, @@LOCAL_SETTINGS, @@APPLICATION_DATA)
|
196
|
+
if(File.exists?(application_data))
|
197
|
+
return application_data
|
198
|
+
else
|
199
|
+
return super
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def clean_path(path)
|
204
|
+
path = path.split('/').join(File::SEPARATOR)
|
205
|
+
if(path.index(' '))
|
206
|
+
return %{"#{path}"}
|
207
|
+
end
|
208
|
+
return path
|
209
|
+
end
|
210
|
+
|
211
|
+
def format_application_name(name)
|
212
|
+
return name.capitalize
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
class CygwinUser < WinUser
|
217
|
+
end
|
218
|
+
|
219
|
+
class VistaUser < WinUser
|
220
|
+
def home
|
221
|
+
profile = ENV['USERPROFILE']
|
222
|
+
if(profile)
|
223
|
+
return profile
|
224
|
+
end
|
225
|
+
return super
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
class ThreadMock
|
230
|
+
def alive?
|
231
|
+
return false
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|