vae 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NzZhNTk3MTc0OTgyZDcwMDU1NDRiY2QxNTAxNzUwMTUwMjljODgzYQ==
5
+ data.tar.gz: !binary |-
6
+ Mzg1MTNhZDJhZTBhNGY0ZTU2NjQ5NzVkNjc1YjI5ODE3ZTk5M2NmMQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MjQ5YTY0MTQ2MTc4MmU2NDgxYmVlNjBhZGU2MThjZWUxMmRjYmQ5NjEyMmM4
10
+ MTM4OTEyZDQzMTYyNjM5ZmY3NDZmZTM1MzEzMGJiZDZiYTVlZjE3YTgwYzgx
11
+ YjQxYzNjOTBkN2UwOGJjODkzYTc1ZmYzY2JhZGY2YjhhNmM2ZTE=
12
+ data.tar.gz: !binary |-
13
+ MjY0ZGYxZDY0NTA0NjQxMTdjZWYwNDFiOWM0ZjVmZDA3Yjg2MDQzNGM2ZjA3
14
+ NDVkN2Y3MzY2MzljODYxZDI0MjE4ZDRiMTA3YWM0MDBkMzdiMjg3ODA2YWQ5
15
+ ZmIyNDgzMDFhOWY1NDNiYTE0MDRlMTk2MTQ4ZTkzOGRiYzBlMmU=
data/bin/vae ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby -W0
2
+
3
+ THIS_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
4
+ $:.unshift File.dirname(THIS_FILE) + '/../lib'
5
+
6
+ require 'vae'
7
+
8
+ VaeLocal.run_trapping_exceptions!
data/lib/logging.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'logger'
2
+
3
+ module Logging
4
+ def self.logger
5
+ @logger ||= new_logger
6
+ end
7
+
8
+ private
9
+
10
+ def self.new_logger
11
+ logger = Logger.new(STDOUT)
12
+ logger.level = Logger::Severity::WARN
13
+ logger
14
+ end
15
+ end
data/lib/servlet.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Servlet < Mongrel::HttpHandler
2
+
3
+ def process(request, response)
4
+ response.start do |head,out|
5
+ head["Content-Type"] = "text/html"
6
+ out << "Servlet"
7
+ end
8
+ end
9
+
10
+ end
11
+
12
+ class FileNotFound < ArgumentError
13
+ end
data/lib/site.rb ADDED
@@ -0,0 +1,35 @@
1
+ class Site
2
+ attr_accessor :password, :root, :session_id, :subdomain, :username
3
+
4
+ def fetch_from_server(req)
5
+ http = Net::HTTP.new("#{subdomain}.vaesite.com")
6
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
7
+ http.start { |http|
8
+ http.read_timeout = 120
9
+ http.request(req)
10
+ }
11
+ end
12
+
13
+ def initialize(options)
14
+ @root = options[:root] if options[:root]
15
+ @subdomain = options[:subdomain] if options[:subdomain]
16
+ @username = options[:username] if options[:username]
17
+ @password = options[:password] if options[:password]
18
+ @session_id = Digest::MD5.hexdigest(rand.to_s)
19
+ login_to_server
20
+ end
21
+
22
+ def login_to_server
23
+ req = Net::HTTP::Post.new("/?__vae_local=#{session_id}")
24
+ req.body = "__local_username=#{CGI.escape(username)}&__local_password=#{CGI.escape(password)}&__local_version=#{VER}"
25
+ res = fetch_from_server(req)
26
+ if res.body == "BAD"
27
+ raise VaeError, "Invalid password or insufficient permissions."
28
+ elsif res.body =~ /MSG/
29
+ puts res.body.gsub(/MSG/, "")
30
+ elsif res.body != "GOOD"
31
+ raise VaeError, "Could not connect to Vae servers. Please check your Internet connection."
32
+ end
33
+ end
34
+
35
+ end
data/lib/vae.rb ADDED
@@ -0,0 +1,180 @@
1
+ require 'rubygems'
2
+
3
+ require 'cgi'
4
+ require 'digest/md5'
5
+ require 'mongrel'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'optparse'
9
+ require 'thread'
10
+ require 'webrick'
11
+ require 'yaml'
12
+
13
+ require 'directory_watcher'
14
+ require 'highline/import'
15
+ require 'compass'
16
+ require 'haml'
17
+
18
+ require 'logging'
19
+ require 'servlet'
20
+ require 'site'
21
+ require 'vae_error'
22
+ require 'vae_site_servlet'
23
+ require 'vae_local_servlet'
24
+ require 'version'
25
+
26
+ SERVER_PARSED = [ ".html", ".haml", ".php", ".xml", ".rss", ".pdf.haml", ".pdf.haml.php", ".haml.php" ]
27
+ SERVER_PARSED_GLOB = [ "**/*.html", "**/*.haml", "**/*.php", "**/*.xml", "**/*.rss", "**/*.pdf.haml", "**/*.pdf.haml.php", "**/*.haml.php" ]
28
+ BANNER = "Vae local preview server, version #{VER}"
29
+
30
+ class VaeLocal
31
+
32
+ def fetch_from_vaeplatform(site, req)
33
+ http = Net::HTTP.new("#{site}.vaeplatform.com", 443)
34
+ http.use_ssl = true
35
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
36
+ http.start { |http|
37
+ http.read_timeout = 120
38
+ http.request(req)
39
+ }
40
+ end
41
+
42
+ def get_svn_credentials(site)
43
+ home = Dir.chdir { Dir.pwd }
44
+ Dir.glob("#{home}/.subversion/auth/svn.simple/*").each do |file|
45
+ params = parse_svn_auth_file(file)
46
+ if params["svn:realmstring"] =~ /<http:\/\/svn(\.|_)#{site}.(vae|verb)site.com/ or params["svn:realmstring"] =~ /<http:\/\/#{site}(\.|_)svn.(vae|verb)site.com/
47
+ return params
48
+ end
49
+ end
50
+ {}
51
+ end
52
+
53
+ def parse_svn_auth_file(file)
54
+ key = nil
55
+ mode = nil
56
+ params = {}
57
+ File.read(file).each_line do |line|
58
+ line.strip!
59
+ if mode == :key
60
+ key = line
61
+ mode = nil
62
+ elsif mode == :value
63
+ params[key] = line
64
+ mode = nil
65
+ else
66
+ if line[0,1] == "K"
67
+ mode = :key
68
+ elsif line[0, 1] == "V"
69
+ mode = :value
70
+ end
71
+ end
72
+ end
73
+ params
74
+ end
75
+
76
+ def run!
77
+ options = { :port => 9999 }
78
+ ARGV.options do |opts|
79
+ opts.banner = BANNER + "\n\nUsage: vae [options]\n starts a local development server\n vae [options] deploy\n promotes the source in Subversion repository to the FTP\n\n If you are using the Vae Production environment features:\n vae [options] stage\n promotes the source in Subversion repository to the staging environment\n vae [options] stagerelease\n promotes the source in Subversion repository to the staging environment\n and releases it to the production environment\n vae [options] release\n releases the current staging environment to the production environment\n vae [options] rollback\n rolls back the production environment to a previous release\n\nAvailable Options:"
80
+ opts.on("-u","--username <username>","Your Vae username") { |o| options[:username] = o }
81
+ opts.on("-p","--port <port number>","Start server on this port") { |o| options[:port] = o }
82
+ opts.on("-r","--root <path to site root>","Path to the root of the local copy of your Vae site.") { |o| options[:site_root] = o }
83
+ opts.on("-s","--site <subdomain>","Vae subdomain for this site") { |o| options[:site] = o }
84
+ opts.on_tail("-h","--help", "Show this help message") { puts opts; exit }
85
+ opts.parse!
86
+ end
87
+ options[:site_root] = Dir.pwd if options[:site_root].nil? and (File.exists?("#{Dir.pwd}/__vae.yml") or File.exists?("#{Dir.pwd}/__verb.yml"))
88
+ if options[:site_root]
89
+ [ "verb", "vae" ].each do |name|
90
+ if File.exists?("#{options[:site_root]}/__#{name}.yml")
91
+ site_conf_file = File.read("#{options[:site_root]}/__#{name}.yml")
92
+ site_conf = YAML.load(site_conf_file)
93
+ options[:site] = site_conf[name]["site"] if site_conf[name] and site_conf[name]["site"]
94
+ end
95
+ end
96
+ end
97
+ raise VaeError, "We could not determine the Vae subdomain for this site. Please specify it manually by using the --site option or create a __vae.yml file within the site root." if options[:site].nil?
98
+ unless options[:username]
99
+ svn_credentials = get_svn_credentials(options[:site])
100
+ options[:username] = svn_credentials["username"]
101
+ options[:password] = svn_credentials["password"]
102
+ end
103
+ raise VaeError, "We could not determine the Vae username that you use. Please specify it manually by using the --username option." if options[:username].nil?
104
+ if options[:password].nil?
105
+ options[:password] = ask("Please enter the Vae password for username #{options[:username]}:") {|q| q.echo = false}
106
+ end
107
+ if [ "deploy", "release", "rollback", "stage", "stagerelease" ].include?(ARGV.last)
108
+ stagerelease(ARGV.last, options[:site], options[:username], options[:password])
109
+ exit
110
+ end
111
+ raise VaeError, "You did not specify the path to the root of the local copy of your Vae site. Please specify it manually by using the --root option or cd to the site root (and make sure it contains a __vae.yml file)." unless options[:site_root]
112
+ raise VaeError, "You specified an invalid path to the local copy of your Vae site." unless File.exists?(options[:site_root])
113
+
114
+ $biglock = Mutex.new
115
+ dw = DirectoryWatcher.new options[:site_root], :interval => 1.0, :glob => SERVER_PARSED_GLOB, :pre_load => true
116
+ dw.add_observer { |*args|
117
+ args.each { |event|
118
+ path = event.path.gsub($site.root, "")
119
+ $biglock.synchronize {
120
+ $changed[path] = event.type
121
+ }
122
+ }
123
+ }
124
+ dw.start
125
+
126
+ Dir.chdir File.dirname(__FILE__)
127
+ puts BANNER
128
+ puts "Vae is in action at http://localhost:#{options[:port]}/"
129
+ puts " (hit Control+C to exit)"
130
+ $site = Site.new(:subdomain => options[:site], :root => options[:site_root], :username => options[:username], :password => options[:password])
131
+ $cache = {}
132
+ $changed = {}
133
+ $server = Mongrel::Configurator.new :host => "0.0.0.0", :port => options[:port] do
134
+ listener do
135
+ uri "/", :handler => VaeSiteServlet.new
136
+ #uri "/__welcome/", :handler => VaeLocalServlet.new
137
+ end
138
+ trap("INT") { raise Mongrel::StopServer }
139
+ run
140
+ end
141
+
142
+ begin
143
+ $server.join
144
+ rescue Mongrel::StopServer
145
+ puts "Thanks for using Vae!"
146
+ end
147
+ end
148
+
149
+ def stagerelease(action, site, username, password)
150
+ if action == "deploy"
151
+ action = "stage"
152
+ elsif action == "stagerelease"
153
+ stagerelease("stage", site, username, password)
154
+ stagerelease("release", site, username, password)
155
+ return
156
+ end
157
+ req = Net::HTTP::Post.new("/subversion/#{action}")
158
+ req.body = "username=#{CGI.escape(username)}&password=#{CGI.escape(password)}"
159
+ res = fetch_from_vaeplatform(site, req)
160
+ if res.is_a?(Net::HTTPFound)
161
+ raise VaeError, "Invalid username/password or insufficient permissions."
162
+ else
163
+ puts res.body
164
+ end
165
+ end
166
+
167
+ def self.run_trapping_exceptions!
168
+ begin
169
+ v = VaeLocal.new
170
+ v.run!
171
+ rescue VaeError => e
172
+ cmd = $0
173
+ cmd = "vae" if cmd =~ /\.\.\/vae_local/
174
+ puts "** Error:"
175
+ puts " " + e.to_s
176
+ puts "Type #{cmd} --help for help."
177
+ end
178
+ end
179
+
180
+ end
data/lib/vae_error.rb ADDED
@@ -0,0 +1,2 @@
1
+ class VaeError < StandardError
2
+ end
@@ -0,0 +1,3 @@
1
+ class VaeLocalServlet < Servlet
2
+ end
3
+
@@ -0,0 +1,185 @@
1
+ class VaeSiteServlet < Servlet
2
+
3
+ def bundle_changed_source_files(source_files)
4
+ source_files ||= []
5
+ changed = nil
6
+ $biglock.synchronize {
7
+ changed = $changed
8
+ $changed = {}
9
+ }
10
+ source_files.concat(changed.map { |filename,action|
11
+ get_source_file(filename, (action == :deleted))
12
+ }).reject { |src| src.nil? }
13
+ end
14
+
15
+ def get_source_file(path, optional = false)
16
+ full_path = nil
17
+ if File.exists?($site.root + path)
18
+ full_path = path
19
+ else
20
+ SERVER_PARSED.each do |ext|
21
+ if full_path.nil? and File.exists?($site.root + path + ext)
22
+ full_path = path + ext
23
+ end
24
+ end
25
+ end
26
+ if full_path.nil? and !optional
27
+ raise FileNotFound
28
+ elsif full_path
29
+ begin
30
+ file = File.read($site.root + full_path)
31
+ md5 = Digest::MD5.hexdigest(file)
32
+ rescue Errno::EISDIR
33
+ return nil
34
+ end
35
+ else
36
+ full_path = path
37
+ md5 = ""
38
+ file = ""
39
+ end
40
+ if $cache[full_path] != md5
41
+ $cache[full_path] = md5
42
+ [ full_path, file ]
43
+ else
44
+ nil
45
+ end
46
+ end
47
+
48
+ def fetch_from_vae(wb_req, method, source_files = nil)
49
+ uri = wb_req.params["REQUEST_URI"] + ((wb_req.params["REQUEST_URI"] =~ /\?/) ? "&" : "?") + "__vae_local=#{$site.session_id}"
50
+ source_files = bundle_changed_source_files(source_files)
51
+ if method == "GET"
52
+ if source_files.is_a?(Array) and source_files.size > 0
53
+ req = Net::HTTP::Post.new(uri)
54
+ source_files.map { |src| puts "sending #{src[0]}" }
55
+ req.body = source_files.collect { |src| "__vae_local_files[#{src[0]}]=#{CGI.escape(src[1])}" }.join("&")
56
+ else
57
+ req = Net::HTTP::Get.new(uri)
58
+ end
59
+ else
60
+ if source_files.is_a?(Array) and source_files.size > 0
61
+ fetch_from_vae(wb_req, "GET", source_files)
62
+ end
63
+ req = Net::HTTP::Post.new(uri)
64
+ req.body = wb_req.body.read
65
+ end
66
+ req['cookie'] = wb_req.params["HTTP_COOKIE"]
67
+ if wb_req.params['HTTP_X_REQUESTED_WITH']
68
+ req['X-Requested-With'] = wb_req.params['HTTP_X_REQUESTED_WITH']
69
+ end
70
+ res = $site.fetch_from_server(req)
71
+ if res.body =~ /__vae_local_needs=(.*)/
72
+ begin
73
+ return fetch_from_vae(wb_req, method, [ get_source_file($1) ])
74
+ rescue FileNotFound
75
+ puts "*\n* Could not find #{$1} -- giving up!\n*"
76
+ return $site.fetch_from_server(Net::HTTP::Get.new("/error_pages/not_found.html"))
77
+ end
78
+ end
79
+ res
80
+ end
81
+
82
+ def fetch_from_vae_and_include_source_of_current_page(req, method)
83
+ fetch_from_vae(req, method, [ find_source_file_from_path(req.params["REQUEST_URI"]), get_source_file("/__vae.php", true), get_source_file("/__verb.php", true) ])
84
+ end
85
+
86
+ def find_source_file_from_path(path)
87
+ path_parts = path.split("/").reject { |part| part.length < 1 }
88
+ local_path = ""
89
+ loop do
90
+ gotit = false
91
+ if part = path_parts.shift
92
+ new_local_path = local_path + "/" + part
93
+ (SERVER_PARSED + [ "" ]).each do |ext|
94
+ if File.exists?($site.root + new_local_path + ext)
95
+ gotit = true
96
+ local_path = new_local_path + ext
97
+ end
98
+ end
99
+ end
100
+ break unless gotit
101
+ end
102
+ return nil unless local_path.length > 0
103
+ get_source_file(local_path)
104
+ end
105
+
106
+ def not_modified?(req, res, mtime, etag)
107
+ return true if (ims = req.params['IF_MODIFIED_SINCE']) && Time.parse(ims) >= mtime
108
+ return true if (inm = req.params['IF_NONE_MATCH']) && WEBrick::HTTPUtils::split_header_value(inm).member?(etag)
109
+ false
110
+ end
111
+
112
+ def render_sass(local_path)
113
+ begin
114
+ options = Compass.sass_engine_options
115
+ options[:load_paths] << File.dirname(local_path)
116
+ engine = Sass::Engine.new(open(local_path, "rb").read, options)
117
+ engine.render
118
+ rescue Sass::SyntaxError => e
119
+ e.message
120
+ end
121
+ end
122
+
123
+ def process(request, response)
124
+ serve(request, response)
125
+ response.finished
126
+ end
127
+
128
+ def serve(req, res)
129
+ res.status = 200
130
+ local_path = ($site.root+req.params["REQUEST_URI"] || "/").split("?").first
131
+ if File.exists?(local_path) and !File.directory?(local_path) and !server_parsed?(local_path)
132
+ st = File::stat(local_path)
133
+ mtime = st.mtime
134
+ etag = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
135
+ res.header['etag'] = etag
136
+ if not_modified?(req, res, mtime, etag)
137
+ puts "#{req.params["REQUEST_URI"]} not modified"
138
+ res.status = 304
139
+ else
140
+ mtype = WEBrick::HTTPUtils::mime_type(local_path, WEBrick::HTTPUtils::DefaultMimeTypes)
141
+ res.header['last-modified'] = mtime.httpdate
142
+ if req.params["REQUEST_URI"] =~ /.sass$/
143
+ res.header['Content-Type'] = "text/css"
144
+ res.body << render_sass(local_path)
145
+ else
146
+ res.header['Content-Type'] = mtype
147
+ res.body << open(local_path, "rb").read
148
+ end
149
+ puts "#{req.params["REQUEST_URI"]} local asset"
150
+ end
151
+ else
152
+ if req.params["REQUEST_URI"] =~ /^\/__data\// or req.params["REQUEST_URI"] =~ /^\/__assets\//
153
+ from_vae = { 'location' => "http://#{$site.subdomain}.vaesite.com#{req.params["REQUEST_URI"]}"}
154
+ puts "#{req.params["REQUEST_URI"]} static asset"
155
+ else
156
+ from_vae = fetch_from_vae_and_include_source_of_current_page(req, req.params["REQUEST_METHOD"])
157
+ if from_vae['location']
158
+ puts "#{req.params["REQUEST_URI"]} redirecting to #{from_vae['location']}"
159
+ end
160
+ end
161
+ if from_vae['location']
162
+ res.body << "<p>Redirecting to <a href=\"#{from_vae['location']}\">#{from_vae['location']}</a>"
163
+ res.status = 302
164
+ res.header['Location'] = from_vae['location']
165
+ else
166
+ res.header['Etag'] = from_vae['etag']
167
+ res.header['Last-Modified'] = from_vae['last-modified']
168
+ res.header['Content-Type'] = from_vae['content-type']
169
+ res.header['Content-Disposition'] = from_vae['content-disposition']
170
+ res.header['Set-Cookie'] = from_vae['set-cookie']
171
+ puts "#{req.params["REQUEST_URI"]} rendering"
172
+ res.body << from_vae.body
173
+ end
174
+ end
175
+ end
176
+
177
+ def server_parsed?(path)
178
+ SERVER_PARSED.each do |ext|
179
+ return true if Regexp.new("#{ext}$").match(path)
180
+ end
181
+ false
182
+ end
183
+
184
+ end
185
+
data/lib/version.rb ADDED
@@ -0,0 +1 @@
1
+ VER = "0.6.0"
data/test/vae_test.rb ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/lib'
4
+ require 'test/unit'
5
+ require 'vae'
6
+
7
+ class VaeTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ end
11
+
12
+ def test_server_parsed
13
+ servlet = VaeSiteServlet.new({})
14
+ assert servlet.server_parsed?("cow.html")
15
+ assert servlet.server_parsed?("cow.pdf.html")
16
+ assert servlet.server_parsed?("cow.haml")
17
+ assert servlet.server_parsed?("cow.xml")
18
+ assert servlet.server_parsed?("cow.rss")
19
+ assert servlet.server_parsed?("cow.php")
20
+ assert servlet.server_parsed?("cow.haml.php")
21
+ assert !servlet.server_parsed?("cow.sass")
22
+ assert !servlet.server_parsed?("cow.gif")
23
+ assert !servlet.server_parsed?("cow.html.gif")
24
+ assert !servlet.server_parsed?("cow")
25
+ assert !servlet.server_parsed?("cow.haml.php.jpg")
26
+ end
27
+
28
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vae
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Action Verb, LLC
8
+ - Kevin Bombino
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-09-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: av-redis-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 0.2.2
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 0.2.2
28
+ - !ruby/object:Gem::Dependency
29
+ name: chunky_png
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: compass
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '='
47
+ - !ruby/object:Gem::Version
48
+ version: 0.11.5
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 0.11.5
56
+ - !ruby/object:Gem::Dependency
57
+ name: directory_watcher
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: haml
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '='
75
+ - !ruby/object:Gem::Version
76
+ version: 3.1.2
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '='
82
+ - !ruby/object:Gem::Version
83
+ version: 3.1.2
84
+ - !ruby/object:Gem::Dependency
85
+ name: highline
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: mongrel
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '='
103
+ - !ruby/object:Gem::Version
104
+ version: 1.2.0.pre2
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '='
110
+ - !ruby/object:Gem::Version
111
+ version: 1.2.0.pre2
112
+ - !ruby/object:Gem::Dependency
113
+ name: sass
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '='
117
+ - !ruby/object:Gem::Version
118
+ version: 3.1.4
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 3.1.4
126
+ description: Supports local development for Vae Platform (http://vaeplatform.com/)
127
+ email: support@actionverb.com
128
+ executables:
129
+ - vae
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - bin/vae
134
+ - lib/logging.rb
135
+ - lib/servlet.rb
136
+ - lib/site.rb
137
+ - lib/vae.rb
138
+ - lib/vae_error.rb
139
+ - lib/vae_local_servlet.rb
140
+ - lib/vae_site_servlet.rb
141
+ - lib/version.rb
142
+ - test/vae_test.rb
143
+ homepage: http://vaeplatform.com/vae_local
144
+ licenses:
145
+ - GPL
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.0.3
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: This gem allows for local development for sites on Vae Platform (http://vaeplatform.com/)
167
+ test_files: []
168
+ has_rdoc: