as 0.3.18.11
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of as might be problematic. Click here for more details.
- data/LICENSE +24 -0
- data/README.md +105 -0
- data/Rakefile +101 -0
- data/bin/as +6 -0
- data/caldecott_helper/Gemfile +10 -0
- data/caldecott_helper/Gemfile.lock +48 -0
- data/caldecott_helper/server.rb +43 -0
- data/config/clients.yml +17 -0
- data/config/micro/offline.conf +2 -0
- data/config/micro/paths.yml +22 -0
- data/config/micro/refresh_ip.rb +20 -0
- data/lib/cli/commands/admin.rb +80 -0
- data/lib/cli/commands/apps.rb +1208 -0
- data/lib/cli/commands/base.rb +233 -0
- data/lib/cli/commands/manifest.rb +56 -0
- data/lib/cli/commands/micro.rb +115 -0
- data/lib/cli/commands/misc.rb +140 -0
- data/lib/cli/commands/services.rb +217 -0
- data/lib/cli/commands/user.rb +65 -0
- data/lib/cli/config.rb +170 -0
- data/lib/cli/console_helper.rb +163 -0
- data/lib/cli/core_ext.rb +122 -0
- data/lib/cli/errors.rb +19 -0
- data/lib/cli/file_helper.rb +123 -0
- data/lib/cli/frameworks.rb +265 -0
- data/lib/cli/manifest_helper.rb +316 -0
- data/lib/cli/runner.rb +568 -0
- data/lib/cli/services_helper.rb +104 -0
- data/lib/cli/tunnel_helper.rb +336 -0
- data/lib/cli/usage.rb +125 -0
- data/lib/cli/version.rb +7 -0
- data/lib/cli/zip_util.rb +77 -0
- data/lib/cli.rb +48 -0
- data/lib/vmc/client.rb +558 -0
- data/lib/vmc/const.rb +27 -0
- data/lib/vmc/micro/switcher/base.rb +97 -0
- data/lib/vmc/micro/switcher/darwin.rb +19 -0
- data/lib/vmc/micro/switcher/dummy.rb +15 -0
- data/lib/vmc/micro/switcher/linux.rb +16 -0
- data/lib/vmc/micro/switcher/windows.rb +31 -0
- data/lib/vmc/micro/vmrun.rb +158 -0
- data/lib/vmc/micro.rb +56 -0
- data/lib/vmc.rb +3 -0
- metadata +270 -0
data/lib/cli/core_ext.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
module VMCExtensions
|
2
|
+
|
3
|
+
def say(message)
|
4
|
+
VMC::Cli::Config.output.puts(message) if VMC::Cli::Config.output
|
5
|
+
end
|
6
|
+
|
7
|
+
def header(message, filler = '-')
|
8
|
+
say "\n"
|
9
|
+
say message
|
10
|
+
say filler.to_s * message.size
|
11
|
+
end
|
12
|
+
|
13
|
+
def banner(message)
|
14
|
+
say "\n"
|
15
|
+
say message
|
16
|
+
end
|
17
|
+
|
18
|
+
def display(message, nl=true)
|
19
|
+
if nl
|
20
|
+
say message
|
21
|
+
else
|
22
|
+
if VMC::Cli::Config.output
|
23
|
+
VMC::Cli::Config.output.print(message)
|
24
|
+
VMC::Cli::Config.output.flush
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear(size=80)
|
30
|
+
return unless VMC::Cli::Config.output
|
31
|
+
VMC::Cli::Config.output.print("\r")
|
32
|
+
VMC::Cli::Config.output.print(" " * size)
|
33
|
+
VMC::Cli::Config.output.print("\r")
|
34
|
+
#VMC::Cli::Config.output.flush
|
35
|
+
end
|
36
|
+
|
37
|
+
def err(message, prefix='Error: ')
|
38
|
+
raise VMC::Cli::CliExit, "#{prefix}#{message}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def warn(msg)
|
42
|
+
say "#{"[WARNING]".yellow} #{msg}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def quit(message = nil)
|
46
|
+
raise VMC::Cli::GracefulExit, message
|
47
|
+
end
|
48
|
+
|
49
|
+
def blank?
|
50
|
+
self.to_s.blank?
|
51
|
+
end
|
52
|
+
|
53
|
+
def uptime_string(delta)
|
54
|
+
num_seconds = delta.to_i
|
55
|
+
days = num_seconds / (60 * 60 * 24);
|
56
|
+
num_seconds -= days * (60 * 60 * 24);
|
57
|
+
hours = num_seconds / (60 * 60);
|
58
|
+
num_seconds -= hours * (60 * 60);
|
59
|
+
minutes = num_seconds / 60;
|
60
|
+
num_seconds -= minutes * 60;
|
61
|
+
"#{days}d:#{hours}h:#{minutes}m:#{num_seconds}s"
|
62
|
+
end
|
63
|
+
|
64
|
+
def pretty_size(size, prec=1)
|
65
|
+
return 'NA' unless size
|
66
|
+
return "#{size}B" if size < 1024
|
67
|
+
return sprintf("%.#{prec}fK", size/1024.0) if size < (1024*1024)
|
68
|
+
return sprintf("%.#{prec}fM", size/(1024.0*1024.0)) if size < (1024*1024*1024)
|
69
|
+
return sprintf("%.#{prec}fG", size/(1024.0*1024.0*1024.0))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module VMCStringExtensions
|
74
|
+
|
75
|
+
def red
|
76
|
+
colorize("\e[0m\e[31m")
|
77
|
+
end
|
78
|
+
|
79
|
+
def green
|
80
|
+
colorize("\e[0m\e[32m")
|
81
|
+
end
|
82
|
+
|
83
|
+
def yellow
|
84
|
+
colorize("\e[0m\e[33m")
|
85
|
+
end
|
86
|
+
|
87
|
+
def bold
|
88
|
+
colorize("\e[0m\e[1m")
|
89
|
+
end
|
90
|
+
|
91
|
+
def colorize(color_code)
|
92
|
+
if VMC::Cli::Config.colorize
|
93
|
+
"#{color_code}#{self}\e[0m"
|
94
|
+
else
|
95
|
+
self
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def blank?
|
100
|
+
self =~ /^\s*$/
|
101
|
+
end
|
102
|
+
|
103
|
+
def truncate(limit = 30)
|
104
|
+
return "" if self.blank?
|
105
|
+
etc = "..."
|
106
|
+
stripped = self.strip[0..limit]
|
107
|
+
if stripped.length > limit
|
108
|
+
stripped.gsub(/\s+?(\S+)?$/, "") + etc
|
109
|
+
else
|
110
|
+
stripped
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class Object
|
117
|
+
include VMCExtensions
|
118
|
+
end
|
119
|
+
|
120
|
+
class String
|
121
|
+
include VMCStringExtensions
|
122
|
+
end
|
data/lib/cli/errors.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module VMC::Cli
|
2
|
+
|
3
|
+
class CliError < StandardError
|
4
|
+
def self.error_code(code = nil)
|
5
|
+
define_method(:error_code) { code }
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class UnknownCommand < CliError; error_code(100); end
|
10
|
+
class TargetMissing < CliError; error_code(102); end
|
11
|
+
class TargetInaccessible < CliError; error_code(103); end
|
12
|
+
|
13
|
+
class TargetError < CliError; error_code(201); end
|
14
|
+
class AuthError < TargetError; error_code(202); end
|
15
|
+
|
16
|
+
class CliExit < CliError; error_code(400); end
|
17
|
+
class GracefulExit < CliExit; error_code(401); end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module VMC::Cli
|
2
|
+
module FileHelper
|
3
|
+
|
4
|
+
class AppFogIgnore
|
5
|
+
|
6
|
+
def initialize(patterns,project_root = "")
|
7
|
+
@patterns = patterns + [ ".git/" ]
|
8
|
+
@project_root = project_root
|
9
|
+
end
|
10
|
+
|
11
|
+
def included_files(filenames)
|
12
|
+
exclude_dots_only(filenames).reject do |filename|
|
13
|
+
exclude = false
|
14
|
+
@patterns.each do |pattern|
|
15
|
+
if is_negative_pattern?(pattern)
|
16
|
+
exclude = false if negative_match(pattern,filename)
|
17
|
+
else
|
18
|
+
exclude ||= match(pattern,filename)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
exclude
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def exclude_dots_only(filenames)
|
26
|
+
filenames.reject do |filename|
|
27
|
+
base = File.basename(filename)
|
28
|
+
base == "." || base == ".."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
def excluded_files(filenames)
|
35
|
+
filenames - included_files(filenames)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_file(project_root)
|
39
|
+
f = "#{project_root}/.asignore"
|
40
|
+
if File.exists?(f)
|
41
|
+
contents = File.read(f).split("\n")
|
42
|
+
AppFogIgnore.new(contents,project_root)
|
43
|
+
else
|
44
|
+
AppFogIgnore.new([],project_root)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def match(pattern,filename)
|
49
|
+
|
50
|
+
filename = filename.sub(/^#{@project_root}\//,'') # remove any project directory prefix
|
51
|
+
|
52
|
+
return false if pattern =~ /^\s*$/ # ignore blank lines
|
53
|
+
|
54
|
+
return false if pattern =~ /^#/ # lines starting with # are comments
|
55
|
+
|
56
|
+
return false if pattern =~ /^!/ # lines starting with ! are negated
|
57
|
+
|
58
|
+
if pattern =~ /\/$/
|
59
|
+
# pattern ending in a slash should ignore directory and all its children
|
60
|
+
dirname = pattern.sub(/\/$/,'')
|
61
|
+
return filename == dirname || filename =~ /^#{dirname}\/.*$/
|
62
|
+
end
|
63
|
+
|
64
|
+
if pattern =~ /^\//
|
65
|
+
parts = filename.split('/')
|
66
|
+
return File.fnmatch(pattern.sub(/^\//,''),parts[0])
|
67
|
+
end
|
68
|
+
|
69
|
+
if pattern.include? '/'
|
70
|
+
return File.fnmatch(pattern,filename)
|
71
|
+
end
|
72
|
+
|
73
|
+
File.fnmatch(pattern,filename,File::FNM_PATHNAME)
|
74
|
+
end
|
75
|
+
|
76
|
+
def is_negative_pattern?(pattern)
|
77
|
+
pattern =~ /^!/
|
78
|
+
end
|
79
|
+
|
80
|
+
def negative_match(pattern,filename)
|
81
|
+
return false unless pattern =~ /^!/
|
82
|
+
match(pattern.sub(/^!/,''),filename)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def ignore_sockets(files)
|
88
|
+
files.reject { |f| File.socket? f }
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_unreachable_links(path,files)
|
92
|
+
pwd = Pathname.new(path)
|
93
|
+
abspath = pwd.realpath.to_s
|
94
|
+
unreachable = []
|
95
|
+
files.each do |f|
|
96
|
+
file = Pathname.new(f)
|
97
|
+
#if file.symlink? && !file.realpath.to_s.start_with?(abspath)
|
98
|
+
# unreachable << file.relative_path_from(pwd).to_s
|
99
|
+
#end
|
100
|
+
end
|
101
|
+
|
102
|
+
unless unreachable.empty?
|
103
|
+
root = pwd.relative_path_from(pwd).to_s
|
104
|
+
err "Can't deploy application containing links '#{unreachable.join(",")}' that reach outside its root '#{root}'"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def copy_files(project_root,files,dest_dir)
|
109
|
+
project_root = Pathname.new(project_root)
|
110
|
+
files.each do |f|
|
111
|
+
dest = Pathname.new(f).relative_path_from(project_root)
|
112
|
+
if File.symlink?(f)
|
113
|
+
FileUtils.copy_entry(f,"#{dest_dir}/#{dest}")
|
114
|
+
elsif File.directory?(f)
|
115
|
+
FileUtils.mkdir_p("#{dest_dir}/#{dest}")
|
116
|
+
else
|
117
|
+
FileUtils.cp(f,"#{dest_dir}/#{dest}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
module VMC::Cli
|
2
|
+
|
3
|
+
class Framework
|
4
|
+
|
5
|
+
DEFAULT_FRAMEWORK = "http://b20nine.com/unknown"
|
6
|
+
DEFAULT_MEM = '256M'
|
7
|
+
|
8
|
+
FRAMEWORKS = {
|
9
|
+
'Rails' => ['rails3', { :mem => '256M', :description => 'Rails Application', :console=>true}],
|
10
|
+
'Spring' => ['spring', { :mem => '512M', :description => 'Java SpringSource Spring Application'}],
|
11
|
+
'Grails' => ['grails', { :mem => '512M', :description => 'Java SpringSource Grails Application'}],
|
12
|
+
'Lift' => ['lift', { :mem => '512M', :description => 'Scala Lift Application'}],
|
13
|
+
'JavaWeb' => ['java_web',{ :mem => '512M', :description => 'Java Web Application'}],
|
14
|
+
'Standalone' => ['standalone', { :mem => '64M', :description => 'Standalone Application'}],
|
15
|
+
'Sinatra' => ['sinatra', { :mem => '128M', :description => 'Sinatra Application'}],
|
16
|
+
'Node' => ['node', { :mem => '64M', :description => 'Node.js Application'}],
|
17
|
+
'PHP' => ['php', { :mem => '128M', :description => 'PHP Application'}],
|
18
|
+
'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}],
|
19
|
+
'WSGI' => ['wsgi', { :mem => '64M', :description => 'Python WSGI Application'}],
|
20
|
+
'Django' => ['django', { :mem => '128M', :description => 'Python Django Application'}],
|
21
|
+
'dotNet' => ['dotNet', { :mem => '128M', :description => '.Net Web Application'}],
|
22
|
+
'Rack' => ['rack', { :mem => '128M', :description => 'Rack Application'}],
|
23
|
+
'Play' => ['play', { :mem => '256M', :description => 'Play Framework Application'}]
|
24
|
+
}
|
25
|
+
|
26
|
+
class << self
|
27
|
+
|
28
|
+
def known_frameworks(available_frameworks)
|
29
|
+
frameworks = []
|
30
|
+
FRAMEWORKS.each do |key,fw|
|
31
|
+
frameworks << key if available_frameworks.include? [fw[0]]
|
32
|
+
end
|
33
|
+
frameworks
|
34
|
+
end
|
35
|
+
|
36
|
+
def lookup(name)
|
37
|
+
return create(*FRAMEWORKS[name])
|
38
|
+
end
|
39
|
+
|
40
|
+
def lookup_by_framework(name)
|
41
|
+
FRAMEWORKS.each do |key,fw|
|
42
|
+
return create(fw[0],fw[1]) if fw[0] == name
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def create(name,opts)
|
47
|
+
if name == "standalone"
|
48
|
+
return StandaloneFramework.new(name, opts)
|
49
|
+
else
|
50
|
+
return Framework.new(name,opts)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def detect(path, available_frameworks)
|
55
|
+
if !File.directory? path
|
56
|
+
if path.end_with?('.war')
|
57
|
+
return detect_framework_from_war path
|
58
|
+
elsif path.end_with?('.zip')
|
59
|
+
return detect_framework_from_zip path, available_frameworks
|
60
|
+
elsif available_frameworks.include?(["standalone"])
|
61
|
+
return Framework.lookup('Standalone')
|
62
|
+
else
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
Dir.chdir(path) do
|
67
|
+
# Rails
|
68
|
+
if File.exist?('config/environment.rb')
|
69
|
+
return Framework.lookup('Rails')
|
70
|
+
|
71
|
+
# Rack
|
72
|
+
elsif File.exist?('config.ru') && available_frameworks.include?(["rack"])
|
73
|
+
return Framework.lookup('Rack')
|
74
|
+
|
75
|
+
# Java Web Apps
|
76
|
+
elsif Dir.glob('*.war').first
|
77
|
+
return detect_framework_from_war(Dir.glob('*.war').first)
|
78
|
+
|
79
|
+
elsif File.exist?('WEB-INF/web.xml')
|
80
|
+
return detect_framework_from_war
|
81
|
+
|
82
|
+
# Simple Ruby Apps
|
83
|
+
elsif !Dir.glob('*.rb').empty?
|
84
|
+
matched_file = nil
|
85
|
+
Dir.glob('*.rb').each do |fname|
|
86
|
+
next if matched_file
|
87
|
+
File.open(fname, 'r') do |f|
|
88
|
+
str = f.read # This might want to be limited
|
89
|
+
matched_file = fname if (str && str.match(/^\s*\#?\s*require\s*\(?\s*['"]sinatra['"]/))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
if matched_file
|
93
|
+
# Sinatra apps
|
94
|
+
f = Framework.lookup('Sinatra')
|
95
|
+
f.exec = "ruby #{matched_file}"
|
96
|
+
return f
|
97
|
+
end
|
98
|
+
|
99
|
+
# PHP
|
100
|
+
elsif !Dir.glob('*.php').empty?
|
101
|
+
return Framework.lookup('PHP')
|
102
|
+
|
103
|
+
# Erlang/OTP using Rebar
|
104
|
+
elsif !Dir.glob('releases/*/*.rel').empty? && !Dir.glob('releases/*/*.boot').empty?
|
105
|
+
return Framework.lookup('Erlang/OTP Rebar')
|
106
|
+
|
107
|
+
# Python Django
|
108
|
+
# XXX: not all django projects keep settings.py in top-level directory
|
109
|
+
elsif File.exist?('manage.py') && File.exist?('settings.py')
|
110
|
+
return Framework.lookup('Django')
|
111
|
+
|
112
|
+
# Python
|
113
|
+
elsif !Dir.glob('wsgi.py').empty?
|
114
|
+
return Framework.lookup('WSGI')
|
115
|
+
|
116
|
+
# .Net
|
117
|
+
elsif !Dir.glob('web.config').empty?
|
118
|
+
return Framework.lookup('dotNet')
|
119
|
+
|
120
|
+
# Node.js
|
121
|
+
elsif !Dir.glob('*.js').empty?
|
122
|
+
if File.exist?('server.js') || File.exist?('app.js') || File.exist?('index.js') || File.exist?('main.js')
|
123
|
+
return Framework.lookup('Node')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Play or Standalone Apps
|
127
|
+
elsif Dir.glob('*.zip').first
|
128
|
+
zip_file = Dir.glob('*.zip').first
|
129
|
+
return detect_framework_from_zip zip_file, available_frameworks
|
130
|
+
end
|
131
|
+
|
132
|
+
# Default to Standalone if no other match was made
|
133
|
+
return Framework.lookup('Standalone') if available_frameworks.include?(["standalone"])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def detect_framework_from_war(war_file=nil)
|
138
|
+
if war_file
|
139
|
+
contents = ZipUtil.entry_lines(war_file)
|
140
|
+
else
|
141
|
+
#assume we are working with current dir
|
142
|
+
contents = Dir['**/*'].join("\n")
|
143
|
+
end
|
144
|
+
|
145
|
+
# Spring/Lift Variations
|
146
|
+
if contents =~ /WEB-INF\/lib\/grails-web.*\.jar/
|
147
|
+
return Framework.lookup('Grails')
|
148
|
+
elsif contents =~ /WEB-INF\/lib\/lift-webkit.*\.jar/
|
149
|
+
return Framework.lookup('Lift')
|
150
|
+
elsif contents =~ /WEB-INF\/classes\/org\/springframework/
|
151
|
+
return Framework.lookup('Spring')
|
152
|
+
elsif contents =~ /WEB-INF\/lib\/spring-core.*\.jar/
|
153
|
+
return Framework.lookup('Spring')
|
154
|
+
elsif contents =~ /WEB-INF\/lib\/org\.springframework\.core.*\.jar/
|
155
|
+
return Framework.lookup('Spring')
|
156
|
+
else
|
157
|
+
return Framework.lookup('JavaWeb')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def detect_framework_from_zip(zip_file, available_frameworks)
|
162
|
+
contents = ZipUtil.entry_lines(zip_file)
|
163
|
+
detect_framework_from_zip_contents(contents, available_frameworks)
|
164
|
+
end
|
165
|
+
|
166
|
+
def detect_framework_from_zip_contents(contents, available_frameworks)
|
167
|
+
if available_frameworks.include?(["play"]) && contents =~ /lib\/play\..*\.jar/
|
168
|
+
return Framework.lookup('Play')
|
169
|
+
elsif available_frameworks.include?(["standalone"])
|
170
|
+
return Framework.lookup('Standalone')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
attr_reader :name, :description, :console
|
176
|
+
attr_accessor :exec
|
177
|
+
|
178
|
+
def initialize(framework=nil, opts={})
|
179
|
+
@name = framework || DEFAULT_FRAMEWORK
|
180
|
+
@memory = opts[:mem] || DEFAULT_MEM
|
181
|
+
@description = opts[:description] || 'Unknown Application Type'
|
182
|
+
@exec = opts[:exec]
|
183
|
+
@console = opts[:console] || false
|
184
|
+
end
|
185
|
+
|
186
|
+
def to_s
|
187
|
+
description
|
188
|
+
end
|
189
|
+
|
190
|
+
def require_url?
|
191
|
+
true
|
192
|
+
end
|
193
|
+
|
194
|
+
def require_start_command?
|
195
|
+
false
|
196
|
+
end
|
197
|
+
|
198
|
+
def prompt_for_runtime?
|
199
|
+
false
|
200
|
+
end
|
201
|
+
|
202
|
+
def default_runtime(path)
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def memory(runtime=nil)
|
207
|
+
@memory
|
208
|
+
end
|
209
|
+
|
210
|
+
alias :mem :memory
|
211
|
+
end
|
212
|
+
|
213
|
+
class StandaloneFramework < Framework
|
214
|
+
def require_url?
|
215
|
+
false
|
216
|
+
end
|
217
|
+
|
218
|
+
def require_start_command?
|
219
|
+
true
|
220
|
+
end
|
221
|
+
|
222
|
+
def prompt_for_runtime?
|
223
|
+
true
|
224
|
+
end
|
225
|
+
|
226
|
+
def default_runtime(path)
|
227
|
+
if !File.directory? path
|
228
|
+
if path =~ /\.(jar|class)$/
|
229
|
+
return "java"
|
230
|
+
elsif path =~ /\.(rb)$/
|
231
|
+
return "ruby18"
|
232
|
+
elsif path =~ /\.(zip)$/
|
233
|
+
return detect_runtime_from_zip path
|
234
|
+
end
|
235
|
+
else
|
236
|
+
Dir.chdir(path) do
|
237
|
+
return "ruby18" if not Dir.glob('**/*.rb').empty?
|
238
|
+
if !Dir.glob('**/*.class').empty? || !Dir.glob('**/*.jar').empty?
|
239
|
+
return "java"
|
240
|
+
elsif Dir.glob('*.zip').first
|
241
|
+
zip_file = Dir.glob('*.zip').first
|
242
|
+
return detect_runtime_from_zip zip_file
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
return nil
|
247
|
+
end
|
248
|
+
|
249
|
+
def memory(runtime=nil)
|
250
|
+
default_mem = @memory
|
251
|
+
default_mem = '128M' if runtime =~ /\Aruby/ || runtime == "php"
|
252
|
+
default_mem = '512M' if runtime == "java" || runtime == "java7"
|
253
|
+
default_mem
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
def detect_runtime_from_zip(zip_file)
|
258
|
+
contents = ZipUtil.entry_lines(zip_file)
|
259
|
+
if contents =~ /\.(jar)$/
|
260
|
+
return "java"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|