appengine-tools 0.0.2 → 0.0.3

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.
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