appengine-tools 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'date'
5
5
  require 'spec/rake/spectask'
6
6
 
7
7
  GEM = "appengine-tools"
8
- GEM_VERSION = "0.0.2"
8
+ GEM_VERSION = "0.0.3"
9
9
  AUTHOR = "Ryan Brown"
10
10
  EMAIL = "ribrdb@gmail.com"
11
11
  HOMEPAGE = "http://code.google.com/p/appengine-jruby"
@@ -17,6 +17,7 @@
17
17
  require 'appengine-sdk'
18
18
  require 'appengine-tools/boot'
19
19
  require 'appengine-tools/bundler'
20
+ require 'appengine-tools/update_check'
20
21
  require 'yaml'
21
22
 
22
23
  module AppEngine
@@ -26,6 +27,9 @@ module AppEngine
26
27
  import Java.ComGoogleAppengineToolsAdmin.AppAdminFactory
27
28
  import Java.ComGoogleAppengineToolsAdmin.AppVersionUpload
28
29
  import Java.ComGoogleAppengineToolsUtil.Logging
30
+ import java.io.FileOutputStream
31
+ import java.util.jar.JarOutputStream
32
+ import java.util.zip.ZipEntry
29
33
 
30
34
  class JRubyAppVersionUpload < AppVersionUpload
31
35
  def initialize(connection, app)
@@ -88,12 +92,16 @@ EOF
88
92
  return
89
93
  end
90
94
  if command && ! NO_XML_COMMANDS.include?(command)
91
- AppEngine::Admin.bundle_app(parsed_args[0])
92
- end
93
- if !RUBY_COMMANDS.include?(command)
94
- puts "running AppCfg"
95
- run_appcfg(args)
95
+ path = parsed_args[0]
96
+ AppEngine::Admin.bundle_app(path)
97
+ AppEngine::Development.boot_jruby
98
+ updater = AppEngine::Admin::UpdateCheck.new(path)
99
+ updater.nag
100
+ else
101
+ AppEngine::Development.boot_jruby
96
102
  end
103
+ puts "running AppCfg"
104
+ run_appcfg(args)
97
105
  end
98
106
 
99
107
  def run_appcfg(args)
@@ -119,27 +127,33 @@ EOF
119
127
  end
120
128
 
121
129
  def gem(*args)
130
+ AppEngine::Admin.bundle_deps('.')
122
131
  AppEngine::Development.boot_jruby
132
+ puts "=> Running RubyGems"
123
133
  require 'rubygems'
124
134
  require 'rubygems/command_manager'
125
135
  Gem.configuration = Gem::ConfigFile.new(args)
126
136
  Gem.use_paths('.gems')
127
137
  Gem::Command.add_specific_extra_args(
128
138
  'install', %w(--no-rdoc --no-ri))
139
+ saved_gems = all_gem_specs
129
140
  begin
130
141
  Gem::CommandManager.instance.run(Gem.configuration.args)
131
142
  rescue Gem::SystemExitException => e
132
143
  exit e.exit_code unless e.exit_code == 0
133
144
  end
134
- unless Dir.glob('.gems/specifications/*.gemspec').empty?
145
+ unless ((all_gem_specs == saved_gems) &&
146
+ File.exist?('WEB-INF/lib/gems.jar'))
135
147
  Dir.mkdir 'WEB-INF' unless File.exists? 'WEB-INF'
136
148
  Dir.mkdir 'WEB-INF/lib' unless File.exists? 'WEB-INF/lib'
137
149
  Dir.chdir '.gems'
138
- command = %w(jar cf ../WEB-INF/lib/gems.jar gems specifications)
139
- if !system(*command)
140
- puts 'Error running jar command.'
141
- exit $?
150
+ puts '=> Packaging gems'
151
+ write_jar('../WEB-INF/lib/gems.jar') do |jar|
152
+ add_to_jar('gems', jar)
153
+ add_to_jar('specifications', jar)
142
154
  end
155
+ puts 'If you upgraded any gems, please run `appcfg.rb gem cleanup`'
156
+ puts 'to remove the old versions.'
143
157
  end
144
158
  end
145
159
 
@@ -154,7 +168,45 @@ Must be run from the application directory.
154
168
  EOF
155
169
  end
156
170
 
171
+ def all_gem_specs
172
+ Gem.source_index.map do |_, spec|
173
+ spec
174
+ end
175
+ end
176
+
177
+ def write_jar(filename)
178
+ filename = File.expand_path(filename)
179
+ jar = JarOutputStream.new(FileOutputStream.new(filename))
180
+ begin
181
+ yield jar
182
+ ensure
183
+ jar.close
184
+ end
185
+ end
186
+
187
+ def add_to_jar(path, jar)
188
+ directory = File.directory?(path)
189
+ if directory
190
+ path << '/'
191
+ end
192
+ entry = ZipEntry.new(path)
193
+ jar.put_next_entry(entry)
194
+ unless directory
195
+ data = IO.read(path)
196
+ jar.write(data.to_java_bytes, 0, data.size)
197
+ end
198
+ jar.close_entry
199
+ if directory
200
+ Dir.entries(path).each do |filename|
201
+ unless ['.', '..'].include?(filename)
202
+ add_to_jar(path + filename, jar)
203
+ end
204
+ end
205
+ end
206
+ end
207
+
157
208
  def run(*args)
209
+ AppEngine::Admin.bundle_deps('.')
158
210
  AppEngine::Development.boot_app('.', args)
159
211
  end
160
212
 
@@ -20,7 +20,7 @@ module AppEngine
20
20
  module Development
21
21
 
22
22
  class << self
23
- def boot_jruby(root=nil)
23
+ def boot_jruby(root=nil, options={})
24
24
  unless defined?(JRUBY_VERSION)
25
25
  require 'rubygems'
26
26
  require 'appengine-jruby-jars'
@@ -31,8 +31,19 @@ module AppEngine
31
31
  AppEngine::SDK::TOOLS_JAR,
32
32
  ]
33
33
 
34
+ args = options[:args] || ARGV
35
+ should_exec = options[:exec]
36
+ should_exec ||= should_exec.nil?
37
+
34
38
  ENV['GEM_HOME'] = Gem.dir
35
- exec_jruby(root, jars, [$0] + ARGV)
39
+ ENV['GEM_PATH'] = Gem.path.compact.join(File::SEPARATOR)
40
+ appcfg = [File.expand_path(File.join(File.dirname($0),
41
+ 'appcfg.rb'))]
42
+ if should_exec
43
+ exec_jruby(root, jars, appcfg + args)
44
+ else
45
+ run_jruby(root, jars, appcfg + args)
46
+ end
36
47
  end
37
48
  end
38
49
 
@@ -48,16 +59,28 @@ module AppEngine
48
59
  exec_jruby(root, jars, jruby_args)
49
60
  end
50
61
 
51
- def exec_jruby(root, jars, args)
62
+ def build_command(root, jars, args)
52
63
  app_jars = root ? Dir.glob("#{root}/WEB-INF/lib/*.jar") : []
53
64
  classpath = (app_jars + jars).join(File::PATH_SEPARATOR)
54
65
  utf = "-Dfile.encoding=UTF-8"
55
- java_command = %W(java #{utf} -cp #{classpath} org.jruby.Main) + args
66
+ command = %W(java #{utf} -cp #{classpath} org.jruby.Main) + args
56
67
  if ENV['VERBOSE']
57
- puts java_command.map {|a| a.inspect}.join(' ')
68
+ puts command.map {|a| a.inspect}.join(' ')
58
69
  end
70
+ command
71
+ end
72
+
73
+ def exec_jruby(root, jars, args)
74
+ java_command = build_command(root, jars, args)
59
75
  exec *java_command
60
76
  end
77
+
78
+ def run_jruby(root, jars, args)
79
+ java_command = build_command(root, jars, args)
80
+ if !system(*java_command)
81
+ puts 'Error executing jruby'
82
+ end
83
+ end
61
84
  end
62
85
  end
63
86
  end
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
 
18
18
  require 'appengine-rack'
19
+ require 'appengine-tools/boot'
19
20
  require 'appengine-tools/web-xml'
20
21
  require 'appengine-tools/xml-formatter'
21
22
  require 'fileutils'
@@ -78,10 +79,10 @@ module AppEngine
78
79
  end
79
80
 
80
81
  class AppBundler
81
- EXISTING_JRUBY = /^appengine-jruby-.*jar$/
82
+ EXISTING_JRUBY = /^(jruby-abridged|appengine-jruby)-.*jar$/
82
83
  EXISTING_RACK = /jruby-rack.*jar$/
83
84
  EXISTING_APIS = /^appengine-api.*jar$/
84
- JRUBY_RACK = 'jruby-rack-0.9.4.jar'
85
+ JRUBY_RACK = 'jruby-rack-0.9.5.jar'
85
86
  JRUBY_RACK_URL = 'http://kenai.com/projects/jruby-rack/' +
86
87
  "downloads/download/#{JRUBY_RACK}"
87
88
  RACKUP = %q{Dir.chdir('..') if Dir.pwd =~ /WEB-INF$/;} +
@@ -92,11 +93,15 @@ module AppEngine
92
93
  end
93
94
 
94
95
  def bundle
96
+ bundle_deps
97
+ convert_config_ru
98
+ end
99
+
100
+ def bundle_deps
95
101
  create_webinf
96
102
  copy_jruby
97
103
  copy_rack
98
104
  copy_sdk
99
- convert_config_ru
100
105
  end
101
106
 
102
107
  def app
@@ -117,7 +122,6 @@ module AppEngine
117
122
  end
118
123
 
119
124
  def convert_config_ru
120
- AppEngine::Development.boot_jruby(app.root)
121
125
  if !File.exists?(app.config_ru)
122
126
  if File.exists?(app.web_xml)
123
127
  unless File.exists?(app.aeweb_xml)
@@ -137,22 +141,14 @@ module AppEngine
137
141
  end
138
142
 
139
143
  def copy_jruby
140
- current_jruby = find_jars(EXISTING_JRUBY)
141
- if current_jruby.empty?
142
- puts "=> Installing JRuby"
143
- require 'appengine-jruby-jars'
144
- FileUtils.cp([AppEngine::JRubyJars.jruby_jar,
145
- AppEngine::JRubyJars.rubygems_jar],
146
- app.webinf_lib)
147
- end
148
- # TODO else warn if out of date
144
+ require 'appengine-jruby-jars'
145
+ update_jars(
146
+ "JRuby", EXISTING_JRUBY, [AppEngine::JRubyJars.jruby_jar],
147
+ /rubygems/, [AppEngine::JRubyJars.rubygems_jar])
149
148
  end
150
149
 
151
150
  def copy_rack
152
- current_rack = find_jars(EXISTING_RACK)
153
- if current_rack.empty?
154
- # TODO cache this somewhere
155
- puts "=> Retrieving jruby-rack"
151
+ update_jars('jruby-rack', EXISTING_RACK, [JRUBY_RACK]) do
156
152
  require 'open-uri'
157
153
  open(JRUBY_RACK_URL) do |src|
158
154
  open(File.join(app.webinf_lib, JRUBY_RACK), 'wb') do |dest|
@@ -163,15 +159,10 @@ module AppEngine
163
159
  end
164
160
 
165
161
  def copy_sdk
166
- current_apis = find_jars(EXISTING_APIS)
167
- if current_apis.empty?
168
- puts "=> Installing appengine-sdk"
169
- require 'appengine-sdk'
170
- jars = Dir.glob(
171
- "#{AppEngine::SDK::SDK_ROOT}/lib/user/appengine-api*.jar")
172
- # TODO if there's more than 1 we need to check the api version.
173
- FileUtils.cp(jars[0], app.webinf_lib)
174
- end
162
+ require 'appengine-sdk'
163
+ glob = "appengine-api-1.0-sdk-*.jar"
164
+ jars = Dir.glob("#{AppEngine::SDK::SDK_ROOT}/lib/user/#{glob}")
165
+ update_jars('appengine-sdk', EXISTING_APIS, jars)
175
166
  end
176
167
 
177
168
  private
@@ -180,6 +171,40 @@ module AppEngine
180
171
  Dir.entries(app.webinf_lib).grep(regex) rescue []
181
172
  end
182
173
 
174
+ def update_jars(name, regex, jars, opt_regex=nil, opt_jars=[])
175
+ existing = find_jars(regex)
176
+ if existing.empty?
177
+ message = "Installing #{name}"
178
+ jars_to_install = jars + opt_jars
179
+ else
180
+ has_optional_jars = existing.any? {|j| j =~ opt_regex}
181
+ expected_jars = jars
182
+ expected_jars.concat(opt_jars) if has_optional_jars
183
+ expected = expected_jars.map {|path| File.basename(path)}
184
+ if existing.size != expected.size ||
185
+ (expected & existing) != expected
186
+ message = "Updating #{name}"
187
+ jars_to_install = expected_jars
188
+ end
189
+ end
190
+ if jars_to_install
191
+ puts message
192
+ remove_jars(existing)
193
+ if block_given?
194
+ yield
195
+ else
196
+ FileUtils.cp(jars_to_install, app.webinf_lib)
197
+ end
198
+ end
199
+ end
200
+
201
+ def remove_jars(jars)
202
+ paths = jars.map do |jar|
203
+ "#{app.webinf_lib}/#{jar}"
204
+ end
205
+ FileUtils.rm_f(paths)
206
+ end
207
+
183
208
  def valid_build
184
209
  return false unless File.exists? app.build_status
185
210
  return false unless File.exists? app.web_xml
@@ -193,41 +218,51 @@ module AppEngine
193
218
  end
194
219
 
195
220
  def generate_xml
196
- return if valid_build
197
- puts "=> Generating configuration files"
198
- Dir.glob("#{app.webinf_lib}/*.jar").each do |path|
199
- $: << path
200
- end
201
- app_root = app.root
202
- builder = WebXmlBuilder.new do
203
- # First configure the basic jruby-rack settings.
204
- add_jruby_rack_defaults(RACKUP)
221
+ return if valid_build
222
+ if defined? JRUBY_VERSION
223
+ puts "=> Generating configuration files"
224
+ Dir.glob("#{app.webinf_lib}/*.jar").each do |path|
225
+ $: << path
226
+ end
227
+ app_root = app.root
228
+ builder = WebXmlBuilder.new do
229
+ # First configure the basic jruby-rack settings.
230
+ add_jruby_rack_defaults(RACKUP)
205
231
 
206
- # Now read the user's rackup file
207
- # TODO generate a skeleton if it's missing
208
- Dir.chdir(app_root) do
209
- eval IO.read('config.ru'), nil, 'config.ru', 1
232
+ # Now read the user's rackup file
233
+ # TODO generate a skeleton if it's missing
234
+ Dir.chdir(app_root) do
235
+ eval IO.read('config.ru'), nil, 'config.ru', 1
236
+ end
210
237
  end
238
+ open(app.web_xml, 'w') do |webxml|
239
+ xml = AppEngine::Rack::XmlFormatter.format(builder.to_xml)
240
+ webxml.write(xml)
241
+ end
242
+ open(app.aeweb_xml, 'w') do |aeweb|
243
+ xml = AppEngine::Rack::XmlFormatter.format(app.rack_app.to_xml)
244
+ aeweb.write(xml)
245
+ end
246
+ yaml = {
247
+ :config_ru => File.stat(app.config_ru).mtime,
248
+ :aeweb_xml => File.stat(app.aeweb_xml).mtime,
249
+ :web_xml => File.stat(app.web_xml).mtime }
250
+ open(app.build_status, 'w') { |f| YAML.dump(yaml, f) }
251
+ else
252
+ AppEngine::Development.boot_jruby(app.root,
253
+ :args => ['bundle', app.root],
254
+ :exec => false)
211
255
  end
212
- open(app.web_xml, 'w') do |webxml|
213
- xml = AppEngine::Rack::XmlFormatter.format(builder.to_xml)
214
- webxml.write(xml)
215
- end
216
- open(app.aeweb_xml, 'w') do |aeweb|
217
- xml = AppEngine::Rack::XmlFormatter.format(app.rack_app.to_xml)
218
- aeweb.write(xml)
219
- end
220
- yaml = {
221
- :config_ru => File.stat(app.config_ru).mtime,
222
- :aeweb_xml => File.stat(app.aeweb_xml).mtime,
223
- :web_xml => File.stat(app.web_xml).mtime }
224
- open(app.build_status, 'w') { |f| YAML.dump(yaml, f) }
225
256
  end
226
257
  end
227
258
 
228
259
  def self.bundle_app(root_path)
229
260
  AppBundler.new(root_path).bundle
230
261
  end
262
+
263
+ def self.bundle_deps(root_path)
264
+ AppBundler.new(root_path).bundle_deps
265
+ end
231
266
 
232
267
  end
233
268
  end
@@ -17,29 +17,65 @@
17
17
  require 'appengine-sdk'
18
18
  require 'appengine-tools/boot'
19
19
  require 'appengine-tools/bundler'
20
+ require 'appengine-tools/update_check'
20
21
 
21
22
  module AppEngine
22
23
  module Development
23
- DEV_APPSERVER = 'com.google.appengine.tools.development.DevAppServerMain'
24
+ DEV_APPSERVER = ['com.google.appengine.tools.development.DevAppServerMain']
24
25
  class JRubyDevAppserver
25
26
  class << self
26
27
  def run(args)
27
- path = args[-1] || '.'
28
- if args.length > 0 and File::directory?(args[-1])
29
- unless ENV['BOOTING_DEVAPPSERVER']
30
- puts "=> Booting DevAppServer"
31
- puts "=> Press Ctrl-C to shutdown server"
32
- ENV['BOOTING_DEVAPPSERVER'] = 'true'
33
- end
28
+ path, java_args, server_args = parse_argv(ARGV)
29
+ if path and File::directory?(path)
30
+ puts "=> Booting DevAppServer"
31
+ puts "=> Press Ctrl-C to shutdown server"
34
32
  AppEngine::Admin.bundle_app(path)
33
+ updater = AppEngine::Admin::UpdateCheck.new(path)
34
+ updater.nag if updater.can_nag?
35
+ end
36
+ start_java(path, java_args, server_args)
37
+ end
38
+
39
+ def parse_argv(argv)
40
+ java_args = []
41
+ server_args = ['--disable_update_check']
42
+ start_on_first_thread = false
43
+ if RUBY_PLATFORM =~ /darwin/ ||
44
+ (RUBY_PLATFORM == 'java' &&
45
+ java.lang.System.getProperty("os.name").downcase == "mac os x")
46
+ start_on_first_thread = true
47
+ end
48
+ argv.each do |arg|
49
+ if arg =~ /^--jvm_flag=(.+)/
50
+ java_args << $1
51
+ elsif arg =~ /--startOnFirstThread=(true|false)/
52
+ start_on_first_thread = ($1 == "true")
53
+ else
54
+ server_args << arg
55
+ end
56
+ end
57
+ if start_on_first_thread
58
+ java_args << '-XstartOnFirstThread'
59
+ end
60
+ return server_args[-1], java_args, server_args
61
+ end
62
+
63
+ def start_java(path, java_args, server_args)
64
+ if path
65
+ jruby_home = get_jruby_home(path)
66
+ java_args << "-Djruby.home=#{jruby_home}" if jruby_home
67
+ server_args[-1] = File.expand_path(path)
68
+ Dir.chdir(path)
35
69
  end
36
- AppEngine::Development.boot_jruby
37
- args.unshift(DEV_APPSERVER)
38
- jruby_home = get_jruby_home(args[-1])
39
- if jruby_home
40
- args.unshift("--jvm_flag=-Djruby.home=#{jruby_home}")
70
+ ENV.delete 'GEM_HOME'
71
+ ENV.delete 'GEM_PATH'
72
+ java_args << '-classpath'
73
+ java_args << AppEngine::SDK::TOOLS_JAR
74
+ command = ['java'] + java_args + DEV_APPSERVER + server_args
75
+ if ENV['VERBOSE']
76
+ puts "exec #{command.map{|x| x.inspect}.join(' ')}"
41
77
  end
42
- AppEngine::SDK.load_kickstart.main(args.to_java(:string))
78
+ exec(*command)
43
79
  end
44
80
 
45
81
  def get_jruby_home(path)
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/ruby1.8 -w
2
+ #
3
+ # Copyright:: Copyright 2009 Google Inc.
4
+ # Original Author:: Ryan Brown (mailto:ribrdb@google.com)
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'yaml'
19
+ require 'open-uri'
20
+ begin
21
+ require 'google-appengine'
22
+ rescue LoadError
23
+ end
24
+ require 'rubygems/version'
25
+
26
+ module AppEngine
27
+ module Admin
28
+ class UpdateCheck
29
+ NAG_FILE = "~/.appcfg_rb_nag"
30
+ MAX_NAG_FREQUENCY = 60 * 60 * 24 * 7
31
+ DEFAULT_URL = 'http://appengine-jruby.googlecode.com/hg/updatecheck'
32
+
33
+ def initialize(approot, url=nil, nag_file=nil)
34
+ @url = url || DEFAULT_URL
35
+ @approot = approot
36
+ @nag_file = nag_file || File.expand_path(NAG_FILE)
37
+ end
38
+
39
+ def local_versions
40
+ sdk_version = Gem::Version.new(AppEngine::VERSION) rescue nil
41
+ {
42
+ 'google-appengine' => sdk_version,
43
+ 'appengine-apis' => find_gem_version('appengine-apis'),
44
+ 'dm-appengine' => find_gem_version('dm-appengine'),
45
+ }
46
+ end
47
+
48
+ def find_gem_version(name)
49
+ specs = Dir.glob("#{@approot}/.gems/specifications/#{name}-*.gemspec")
50
+ versions = specs.map do |filename|
51
+ if filename =~ /-(\w+\.\w+.\w+).gemspec$/
52
+ Gem::Version.new($1)
53
+ end
54
+ end
55
+ versions.sort[-1]
56
+ end
57
+
58
+ def remote_versions
59
+ versions = YAML.load(open(@url).read)
60
+ versions.inject({}) do |versions, (name, version)|
61
+ versions[name] = Gem::Version.new(version)
62
+ versions
63
+ end
64
+ end
65
+
66
+ def check_for_updates
67
+ local = local_versions
68
+ unless local['google-appengine']
69
+ puts 'Skipping update check'
70
+ return
71
+ end
72
+ latest = remote_versions
73
+ local.each do |name, version|
74
+ current = latest[name]
75
+ if version && version < current
76
+ prefix = if name == 'google-appengine'
77
+ "sudo"
78
+ else
79
+ "appcfg.rb"
80
+ end
81
+ puts "There is a new version of #{name}: #{current} " +
82
+ "(You have #{version})"
83
+ puts "Please run #{prefix} gem update #{name}."
84
+ end
85
+ end
86
+ end
87
+
88
+ def parse_nag_file
89
+ @nag ||= if File.exist?(@nag_file)
90
+ YAML.load_file(@nag_file)
91
+ else
92
+ {'opt_in' => true, 'timestamp' => 0}
93
+ end
94
+ end
95
+
96
+ def write_nag_file(options)
97
+ open(@nag_file, 'w') do |file|
98
+ file.write(YAML.dump(options))
99
+ end
100
+ end
101
+
102
+ def nag
103
+ nag = parse_nag_file
104
+ return if Time.now.to_i - nag['timestamp'] < MAX_NAG_FREQUENCY
105
+ check_for_updates
106
+ nag['timestamp'] = Time.now.to_i
107
+ write_nag_file(nag)
108
+ rescue OpenURI::HTTPError, Errno::ENOENT
109
+ # check_for_updates will raise an error if we're not online
110
+ # just ignore it, and don't update the nag timestamp.
111
+ end
112
+
113
+ def can_nag?
114
+ parse_nag_file['opt_in']
115
+ end
116
+ end
117
+ end
118
+ end
@@ -2,11 +2,18 @@
2
2
  <application>tools-test</application>
3
3
  <version>foo</version>
4
4
  <public-root>/public</public-root>
5
- <static-files/>
5
+ <static-files>
6
+ <include expiration='365d' path='/public/images/**'/>
7
+ <include path='/public/**'/>
8
+ </static-files>
6
9
  <resource-files/>
7
10
  <system-properties>
8
11
  <property name='os.arch' value=''/>
9
12
  <property name='jruby.management.enabled' value='false'/>
13
+ <property name='jruby.rack.input.rewindable' value='false'/>
10
14
  </system-properties>
11
15
  <ssl-enabled>true</ssl-enabled>
16
+ <inbound-services>
17
+ <service>xmpp_message</service>
18
+ </inbound-services>
12
19
  </appengine-web-app>
data/spec/config.ru CHANGED
@@ -2,6 +2,9 @@ require 'appengine-rack'
2
2
 
3
3
  AppEngine::Rack.configure_app(
4
4
  :application => 'tools-test', :version => 'foo', :ssl_enabled => true)
5
+ AppEngine::Rack.app.inbound_services << :xmpp_message
6
+ AppEngine::Rack.app.static_files.include('/public/images/**', '365d')
7
+ AppEngine::Rack.app.static_files.include('/public/**')
5
8
 
6
9
  ruby_app = lambda {|env| [200, {}, "Hello Rack!"]}
7
10
 
@@ -0,0 +1,176 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'appengine-tools/update_check'
3
+ require 'stringio'
4
+
5
+ module AppEngine
6
+ VERSION = "3.2.1"
7
+ end
8
+
9
+ describe AppEngine::Admin::UpdateCheck do
10
+ before :each do
11
+ @update_check = AppEngine::Admin::UpdateCheck.new('approot', 'url', 'nag')
12
+ end
13
+
14
+ def versions(sdk, apis, dm)
15
+ keys = ['google-appengine', 'appengine-apis', 'dm-appengine']
16
+ hash = {}
17
+ keys.zip([sdk, apis, dm]) do |key, value|
18
+ hash[key] = value && Gem::Version.new(value)
19
+ end
20
+ hash
21
+ end
22
+
23
+ it 'should expand path' do
24
+ File.should_receive(:expand_path).with(
25
+ AppEngine::Admin::UpdateCheck::NAG_FILE)
26
+ uc = AppEngine::Admin::UpdateCheck.new('/')
27
+ end
28
+
29
+ it 'should support local_versions' do
30
+ expected = versions('3.2.1', '1.2.3', nil)
31
+ @update_check.should_receive(:find_gem_version).twice.and_return(
32
+ Gem::Version.new("1.2.3"), nil)
33
+ @update_check.local_versions.should == expected
34
+ end
35
+
36
+ it 'should support find_gem_version' do
37
+ Dir.should_receive(:glob).and_return(
38
+ ['appengine-apis-0.0.20.gemspec','appengine-apis-0.0.3.gemspec'])
39
+ @update_check.find_gem_version("appengine-apis").should ==
40
+ Gem::Version.new('0.0.20')
41
+ end
42
+
43
+ it 'should support remote_versions' do
44
+ expected = versions('3.2.2', '1.2.4', '2.3.4')
45
+ io = StringIO.new(YAML.dump(expected))
46
+ @update_check.stub!(:open)
47
+ @update_check.should_receive(:open).with("url").and_return(io)
48
+ @update_check.remote_versions.should == expected
49
+ end
50
+
51
+ describe 'check_for_updates' do
52
+ before :each do
53
+ @update_check.stub!(:puts)
54
+ end
55
+
56
+
57
+ def expect_puts(*messages)
58
+ length = messages.length
59
+ @update_check.should_receive(:puts) do |arg|
60
+ arg.should == messages.shift
61
+ end.exactly(length).times
62
+ end
63
+
64
+ it 'should skip check if no sdk version' do
65
+ @update_check.should_receive(:local_versions).and_return(
66
+ versions(nil, nil, nil))
67
+ expect_puts("Skipping update check")
68
+ @update_check.check_for_updates
69
+ end
70
+
71
+ it 'should warn about old sdk' do
72
+ @update_check.should_receive(:local_versions).and_return(
73
+ versions('0.0.1', nil, nil))
74
+ @update_check.should_receive(:remote_versions).and_return(
75
+ versions('0.0.2', '0.0.2', '0.0.2'))
76
+ expect_puts(
77
+ "There is a new version of google-appengine: 0.0.2 (You have 0.0.1)",
78
+ "Please run sudo gem update google-appengine."
79
+ )
80
+ @update_check.check_for_updates
81
+ end
82
+
83
+ it 'should warn about old apis' do
84
+ @update_check.should_receive(:local_versions).and_return(
85
+ versions('0.0.2', '0.0.2', '0.0.2'))
86
+ @update_check.should_receive(:remote_versions).and_return(
87
+ versions('0.0.2', '0.0.4', '0.0.2'))
88
+ expect_puts(
89
+ "There is a new version of appengine-apis: 0.0.4 (You have 0.0.2)",
90
+ "Please run appcfg.rb gem update appengine-apis."
91
+ )
92
+ @update_check.check_for_updates
93
+ end
94
+
95
+ it 'should warn about old dm adapter' do
96
+ @update_check.should_receive(:local_versions).and_return(
97
+ versions('0.0.2', '0.0.2', '0.0.2'))
98
+ @update_check.should_receive(:remote_versions).and_return(
99
+ versions('0.0.2', '0.0.2', '0.0.3'))
100
+ expect_puts(
101
+ "There is a new version of dm-appengine: 0.0.3 (You have 0.0.2)",
102
+ "Please run appcfg.rb gem update dm-appengine."
103
+ )
104
+ @update_check.check_for_updates
105
+ end
106
+
107
+
108
+ it 'should warn about multiple old gems' do
109
+ @update_check.should_receive(:local_versions).and_return(
110
+ versions('0.0.1', '0.0.3', '0.0.5'))
111
+ @update_check.should_receive(:remote_versions).and_return(
112
+ versions('0.0.2', '0.0.4', '0.0.5'))
113
+ expect_puts(
114
+ "There is a new version of google-appengine: 0.0.2 (You have 0.0.1)",
115
+ "Please run sudo gem update google-appengine.",
116
+ "There is a new version of appengine-apis: 0.0.4 (You have 0.0.3)",
117
+ "Please run appcfg.rb gem update appengine-apis."
118
+ )
119
+ @update_check.check_for_updates
120
+ end
121
+ end
122
+
123
+ describe 'parse_nag_file' do
124
+ it 'should support missing file' do
125
+ File.should_receive(:exist?).with('nag').and_return(false)
126
+ @update_check.parse_nag_file.should == {
127
+ 'opt_in' => true,
128
+ 'timestamp' => 0
129
+ }
130
+ end
131
+
132
+ it 'should parse existing file' do
133
+ File.should_receive(:exist?).with('nag').and_return(true)
134
+ YAML.should_receive(:load_file).with('nag').and_return("parsed_yaml")
135
+ @update_check.parse_nag_file.should == "parsed_yaml"
136
+ end
137
+ end
138
+
139
+ describe 'nag' do
140
+ it 'should nag if old timestamp' do
141
+ @update_check.should_receive(:parse_nag_file).and_return({
142
+ 'opt_in' => true,
143
+ 'timestamp' => Time.now.to_i - (60 * 60 * 24 * 8)
144
+ })
145
+ @update_check.should_receive(:check_for_updates)
146
+ @update_check.should_receive(:write_nag_file)
147
+ @update_check.nag
148
+ end
149
+
150
+ it 'should not nag if new timestamp' do
151
+ @update_check.should_receive(:parse_nag_file).and_return({
152
+ 'opt_in' => true,
153
+ 'timestamp' => Time.now.to_i - (60 * 60 * 24 * 6)
154
+ })
155
+ @update_check.nag
156
+ end
157
+ end
158
+
159
+ describe 'can_nag?' do
160
+ it 'should return true of opted in' do
161
+ @update_check.should_receive(:parse_nag_file).and_return({
162
+ 'opt_in' => true,
163
+ 'timestamp' => Time.now.to_i
164
+ })
165
+ @update_check.can_nag?.should == true
166
+ end
167
+
168
+ it 'should return false of opted out' do
169
+ @update_check.should_receive(:parse_nag_file).and_return({
170
+ 'opt_in' => false,
171
+ 'timestamp' => Time.now.to_i
172
+ })
173
+ @update_check.can_nag?.should == false
174
+ end
175
+ end
176
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appengine-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Brown
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-13 00:00:00 -07:00
12
+ date: 2009-09-03 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -60,6 +60,7 @@ files:
60
60
  - lib/appengine-tools/boot.rb
61
61
  - lib/appengine-tools/bundler.rb
62
62
  - lib/appengine-tools/dev_appserver.rb
63
+ - lib/appengine-tools/update_check.rb
63
64
  - lib/appengine-tools/web-xml.rb
64
65
  - lib/appengine-tools/xml-formatter.rb
65
66
  - spec/appengine-web.xml
@@ -67,6 +68,7 @@ files:
67
68
  - spec/rack_spec.rb
68
69
  - spec/spec.opts
69
70
  - spec/spec_helper.rb
71
+ - spec/update_check_spec.rb
70
72
  - spec/web-xml_spec.rb
71
73
  - spec/web.xml
72
74
  has_rdoc: true