ruboto 0.10.1 → 0.10.2.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/Rakefile +110 -34
- data/assets/rakelib/ruboto.rake +181 -76
- data/assets/src/org/ruboto/JRubyAdapter.java +7 -3
- data/assets/src/org/ruboto/ScriptLoader.java +12 -4
- data/assets/src/ruboto/widget.rb +43 -34
- data/bin/ruboto +9 -4
- data/lib/ruboto/sdk_versions.rb +11 -2
- data/lib/ruboto/util/build.rb +1 -1
- data/lib/ruboto/util/update.rb +104 -32
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/call_super_activity.rb +2 -3
- data/test/activity/dir_and_file_activity.rb +18 -0
- data/test/activity/dir_and_file_activity_test.rb +20 -0
- data/test/activity/image_button_and_button_activity.rb +4 -5
- data/test/activity/json_activity.rb +21 -0
- data/test/activity/json_activity_test.rb +17 -0
- data/test/activity/location_activity.rb +30 -0
- data/test/activity/location_activity_test.rb +17 -0
- data/test/activity/margins_activity.rb +0 -1
- data/test/activity/option_menu_activity.rb +0 -1
- data/test/activity/psych_activity.rb +8 -2
- data/test/activity/ssl_activity.rb +31 -0
- data/test/activity/ssl_activity_test.rb +22 -0
- data/test/activity/stack_activity.rb +0 -1
- data/test/activity/stack_activity_test.rb +4 -5
- data/test/activity/subclass_activity.rb +0 -1
- data/test/activity/view_constants_activity.rb +0 -1
- data/test/app_test_methods.rb +19 -6
- data/test/minimal_app_test.rb +10 -10
- data/test/rake_test.rb +8 -8
- data/test/ruboto_gen_test.rb +18 -12
- data/test/ruboto_update_test.rb +16 -10
- data/test/test_helper.rb +16 -35
- metadata +21 -9
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ PLATFORM_PROJECT = File.expand_path('tmp/RubotoCore', File.dirname(__FILE__))
|
|
11
11
|
PLATFORM_DEBUG_APK = "#{PLATFORM_PROJECT}/bin/RubotoCore-debug.apk"
|
12
12
|
PLATFORM_DEBUG_APK_BAK = "#{PLATFORM_PROJECT}/bin/RubotoCore-debug.apk.bak"
|
13
13
|
PLATFORM_RELEASE_APK = "#{PLATFORM_PROJECT}/bin/RubotoCore-release.apk"
|
14
|
-
PLATFORM_CURRENT_RELEASE_APK =
|
14
|
+
PLATFORM_CURRENT_RELEASE_APK = File.expand_path('tmp/RubotoCore-release.apk', File.dirname(__FILE__))
|
15
15
|
MANIFEST_FILE = "AndroidManifest.xml"
|
16
16
|
GEM_FILE = "ruboto-#{Ruboto::VERSION}.gem"
|
17
17
|
GEM_SPEC_FILE = 'ruboto.gemspec'
|
@@ -87,8 +87,8 @@ task :release_docs do
|
|
87
87
|
user = ask('login : ') { |q| q.echo = true }
|
88
88
|
pass = ask('password: ') { |q| q.echo = '*' }
|
89
89
|
rescue
|
90
|
-
print 'user name: '
|
91
|
-
print ' password: '
|
90
|
+
print 'user name: '; user = STDIN.gets.chomp
|
91
|
+
print ' password: '; pass = STDIN.gets.chomp
|
92
92
|
end
|
93
93
|
require 'uri'
|
94
94
|
require 'net/http'
|
@@ -106,12 +106,12 @@ task :release_docs do
|
|
106
106
|
req.basic_auth(user, pass)
|
107
107
|
res = https.start { |http| http.request(req) }
|
108
108
|
milestones = YAML.load(res.body).sort_by { |i| Date.parse(i['due_on']) }
|
109
|
-
puts milestones.map{|m| "#{'%2d' % m['number']} #{m['title']}"}.join("\n")
|
109
|
+
puts milestones.map { |m| "#{'%2d' % m['number']} #{m['title']}" }.join("\n")
|
110
110
|
|
111
111
|
if defined? ask
|
112
112
|
milestone = ask('milestone: ', Integer) { |q| q.echo = true }
|
113
113
|
else
|
114
|
-
print 'milestone: '
|
114
|
+
print 'milestone: '; milestone = STDIN.gets.chomp
|
115
115
|
end
|
116
116
|
|
117
117
|
uri = URI("#{base_uri}/issues?milestone=#{milestone}&state=closed&per_page=1000")
|
@@ -123,9 +123,9 @@ task :release_docs do
|
|
123
123
|
milestone_description = issues[0] ? issues[0]['milestone']['description'] : "No issues for milestone #{milestone}"
|
124
124
|
categories = {'Features' => 'feature', 'Bugfixes' => 'bug', 'Internal' => 'internal', 'Support' => 'support', 'Documentation' => 'documentation', 'Pull requests' => nil, 'Other' => nil}
|
125
125
|
grouped_issues = issues.group_by do |i|
|
126
|
-
labels = i['labels'].map { |l| l['name']}
|
126
|
+
labels = i['labels'].map { |l| l['name'] }
|
127
127
|
cat = nil
|
128
|
-
categories.each do |k,v|
|
128
|
+
categories.each do |k, v|
|
129
129
|
if labels.include? v
|
130
130
|
cat = k
|
131
131
|
break
|
@@ -198,7 +198,7 @@ task :stats do
|
|
198
198
|
https.use_ssl = true
|
199
199
|
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
200
200
|
|
201
|
-
counts_per_month = Hash.new{|h, k| h[k] = Hash.new{|mh,mk| mh[mk] = 0 }}
|
201
|
+
counts_per_month = Hash.new { |h, k| h[k] = Hash.new { |mh, mk| mh[mk] = 0 } }
|
202
202
|
total = 0
|
203
203
|
|
204
204
|
%w{ruboto-core ruboto}.each do |gem|
|
@@ -213,20 +213,20 @@ task :stats do
|
|
213
213
|
req = Net::HTTP::Get.new(downloads_uri.request_uri)
|
214
214
|
res = https.start { |http| http.request(req) }
|
215
215
|
counts = YAML.load(res.body)
|
216
|
-
counts.delete_if{|date_str,count| count == 0}
|
216
|
+
counts.delete_if { |date_str, count| count == 0 }
|
217
217
|
counts.each do |date_str, count|
|
218
218
|
date = Date.parse(date_str)
|
219
219
|
counts_per_month[date.year][date.month] += count
|
220
220
|
total += count
|
221
221
|
end
|
222
|
-
print '.'
|
222
|
+
print '.'; STDOUT.flush
|
223
223
|
end
|
224
224
|
puts
|
225
225
|
end
|
226
226
|
|
227
227
|
puts "\nDownloads statistics per month:"
|
228
228
|
years = counts_per_month.keys
|
229
|
-
puts "\n #{years.map{|year| '%6s:' % year}.join(' ')}"
|
229
|
+
puts "\n #{years.map { |year| '%6s:' % year }.join(' ')}"
|
230
230
|
(1..12).each do |month|
|
231
231
|
print "#{'%2d' % month}:"
|
232
232
|
years.each do |year|
|
@@ -240,7 +240,7 @@ task :stats do
|
|
240
240
|
|
241
241
|
puts "\nRubyGems download statistics per month:"
|
242
242
|
years = counts_per_month.keys
|
243
|
-
puts ' ' + years.map{|year| '%-12s' % year}.join
|
243
|
+
puts ' ' + years.map { |year| '%-12s' % year }.join
|
244
244
|
(0..20).each do |l|
|
245
245
|
print (l % 10 == 0) ? '%4d' % ((20-l) * 100) : ' '
|
246
246
|
years.each do |year|
|
@@ -254,7 +254,7 @@ task :stats do
|
|
254
254
|
end
|
255
255
|
puts
|
256
256
|
end
|
257
|
-
puts ' ' + years.map{|year| '%-12s' % year}.join
|
257
|
+
puts ' ' + years.map { |year| '%-12s' % year }.join
|
258
258
|
|
259
259
|
puts "\nTotal: #{total}\n\n"
|
260
260
|
end
|
@@ -275,11 +275,15 @@ task :release => [:clean, :gem] do
|
|
275
275
|
sh "git push"
|
276
276
|
end
|
277
277
|
|
278
|
-
desc "Run the tests"
|
278
|
+
desc "Run the tests. Select which test files to load with 'rake test TEST=test_file_pattern'"
|
279
279
|
task :test do
|
280
280
|
FileUtils.rm_rf Dir['tmp/RubotoTestApp_template*']
|
281
|
-
|
282
|
-
|
281
|
+
test_pattern = ARGV.grep(/^TEST=.*$/)
|
282
|
+
ARGV.delete_if { |a| test_pattern.include? a }
|
283
|
+
test_pattern.map! { |t| t[5..-1] }
|
284
|
+
$: << File.expand_path('test', File.dirname(__FILE__))
|
285
|
+
(test_pattern.any? ? test_pattern : ['test/*_test.rb']).map { |d| Dir[d] }.flatten.each do |f|
|
286
|
+
require f.chomp('.rb')[5..-1]
|
283
287
|
end
|
284
288
|
end
|
285
289
|
|
@@ -305,13 +309,10 @@ namespace :platform do
|
|
305
309
|
task PLATFORM_DEBUG_APK do
|
306
310
|
Rake::Task[PLATFORM_PROJECT].invoke
|
307
311
|
Dir.chdir(PLATFORM_PROJECT) do
|
308
|
-
if File.exists?(
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
else
|
313
|
-
FileUtils.rm PLATFORM_DEBUG_APK
|
314
|
-
end
|
312
|
+
if File.exists?(PLATFORM_DEBUG_APK_BAK)
|
313
|
+
FileUtils.cp PLATFORM_DEBUG_APK_BAK, PLATFORM_DEBUG_APK
|
314
|
+
else
|
315
|
+
FileUtils.rm PLATFORM_DEBUG_APK
|
315
316
|
end
|
316
317
|
sh 'rake debug'
|
317
318
|
end
|
@@ -342,14 +343,9 @@ namespace :platform do
|
|
342
343
|
end
|
343
344
|
end
|
344
345
|
|
345
|
-
desc '
|
346
|
-
task :current =>
|
347
|
-
|
348
|
-
if File.size(PLATFORM_CURRENT_RELEASE_APK) != File.size(PLATFORM_DEBUG_APK)
|
349
|
-
FileUtils.cp PLATFORM_DEBUG_APK, PLATFORM_DEBUG_APK_BAK
|
350
|
-
FileUtils.cp PLATFORM_CURRENT_RELEASE_APK, PLATFORM_DEBUG_APK
|
351
|
-
end
|
352
|
-
end
|
346
|
+
desc 'Install the current RubotoCore platform release apk'
|
347
|
+
task :current => PLATFORM_CURRENT_RELEASE_APK do
|
348
|
+
install_apk
|
353
349
|
end
|
354
350
|
|
355
351
|
desc 'Install the Ruboto Core platform debug apk'
|
@@ -360,9 +356,89 @@ namespace :platform do
|
|
360
356
|
end
|
361
357
|
|
362
358
|
desc 'Uninstall the Ruboto Core platform debug apk'
|
363
|
-
task :uninstall
|
364
|
-
|
365
|
-
|
359
|
+
task :uninstall do
|
360
|
+
uninstall_apk
|
361
|
+
end
|
362
|
+
|
363
|
+
private
|
364
|
+
|
365
|
+
def package
|
366
|
+
'org.ruboto.core'
|
367
|
+
end
|
368
|
+
|
369
|
+
def install_apk
|
370
|
+
failure_pattern = /^Failure \[(.*)\]/
|
371
|
+
success_pattern = /^Success/
|
372
|
+
case package_installed?
|
373
|
+
when true
|
374
|
+
puts "Package #{package} already installed."
|
375
|
+
return
|
376
|
+
when false
|
377
|
+
puts "Package #{package} already installed, but of different size. Replacing package."
|
378
|
+
output = `adb install -r #{PLATFORM_CURRENT_RELEASE_APK} 2>&1`
|
379
|
+
if $? == 0 && output !~ failure_pattern && output =~ success_pattern
|
380
|
+
clear_update
|
381
|
+
return
|
382
|
+
end
|
383
|
+
case $1
|
384
|
+
when 'INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES'
|
385
|
+
puts 'Found package signed with different certificate. Uninstalling it and retrying install.'
|
386
|
+
else
|
387
|
+
puts "'adb install' returned an unknown error: (#$?) #{$1 ? "[#$1}]" : output}."
|
388
|
+
puts "Uninstalling #{package} and retrying install."
|
389
|
+
end
|
390
|
+
uninstall_apk
|
391
|
+
end
|
392
|
+
puts "Installing package #{package}"
|
393
|
+
begin
|
394
|
+
output = nil
|
395
|
+
timeout 180 do
|
396
|
+
output = `adb install #{PLATFORM_CURRENT_RELEASE_APK} 2>&1`
|
397
|
+
end
|
398
|
+
rescue TimeoutError
|
399
|
+
puts 'Install of current RubotoCore timed out. Retrying.'
|
400
|
+
retry
|
401
|
+
end
|
402
|
+
puts output
|
403
|
+
raise "Install failed (#{$?}) #{$1 ? "[#$1}]" : output}" if $? != 0 || output =~ failure_pattern || output !~ success_pattern
|
404
|
+
end
|
405
|
+
|
406
|
+
def uninstall_apk
|
407
|
+
return if package_installed?.nil?
|
408
|
+
puts "Uninstalling package #{package}"
|
409
|
+
system "adb uninstall #{package}"
|
410
|
+
if $? != 0 && package_installed?
|
411
|
+
puts "Uninstall failed exit code #{$?}"
|
412
|
+
exit $?
|
366
413
|
end
|
367
414
|
end
|
415
|
+
|
416
|
+
def package_installed?
|
417
|
+
package_name = package
|
418
|
+
['', '-0', '-1', '-2'].each do |i|
|
419
|
+
path = "/data/app/#{package_name}#{i}.apk"
|
420
|
+
o = `adb shell ls -l #{path}`.chomp
|
421
|
+
if o =~ /^-rw-r--r-- system\s+system\s+(\d+) \d{4}-\d{2}-\d{2} \d{2}:\d{2} #{File.basename(path)}$/
|
422
|
+
apk_file = PLATFORM_CURRENT_RELEASE_APK
|
423
|
+
if !File.exists?(apk_file) || $1.to_i == File.size(apk_file)
|
424
|
+
return true
|
425
|
+
else
|
426
|
+
return false
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
sdcard_path = "/mnt/asec/#{package_name}#{i}/pkg.apk"
|
431
|
+
o = `adb shell ls -l #{sdcard_path}`.chomp
|
432
|
+
if o =~ /^-r-xr-xr-x system\s+root\s+(\d+) \d{4}-\d{2}-\d{2} \d{2}:\d{2} #{File.basename(sdcard_path)}$/
|
433
|
+
apk_file = PLATFORM_CURRENT_RELEASE_APK
|
434
|
+
if !File.exists?(apk_file) || $1.to_i == File.size(apk_file)
|
435
|
+
return true
|
436
|
+
else
|
437
|
+
return false
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
return nil
|
442
|
+
end
|
443
|
+
|
368
444
|
end
|
data/assets/rakelib/ruboto.rake
CHANGED
@@ -3,8 +3,11 @@ require 'rubygems'
|
|
3
3
|
require 'time'
|
4
4
|
require 'rake/clean'
|
5
5
|
require 'rexml/document'
|
6
|
+
require 'timeout'
|
6
7
|
|
7
|
-
|
8
|
+
ON_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i)
|
9
|
+
|
10
|
+
ANT_CMD = ON_WINDOWS ? 'ant.bat' : 'ant'
|
8
11
|
|
9
12
|
if `#{ANT_CMD} -version` !~ /version (\d+)\.(\d+)\.(\d+)/ || $1.to_i < 1 || ($1.to_i == 1 && $2.to_i < 8)
|
10
13
|
puts "ANT version 1.8.0 or later required. Version found: #{$1}.#{$2}.#{$3}"
|
@@ -12,48 +15,64 @@ if `#{ANT_CMD} -version` !~ /version (\d+)\.(\d+)\.(\d+)/ || $1.to_i < 1 || ($1.
|
|
12
15
|
end
|
13
16
|
|
14
17
|
adb_version_str = `adb version`
|
15
|
-
(puts
|
16
|
-
(puts "Unrecognized adb version: #$1";exit 1) unless adb_version_str =~ /Android Debug Bridge version (\d+\.\d+\.\d+)/
|
17
|
-
(puts "adb version 1.0.31 or later required. Version found: #$1";exit 1) unless Gem::Version.new($1) >= Gem::Version.new('1.0.31')
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
18
|
+
(puts 'Android SDK platform tools not in PATH (adb command not found).'; exit 1) unless $? == 0
|
19
|
+
(puts "Unrecognized adb version: #$1"; exit 1) unless adb_version_str =~ /Android Debug Bridge version (\d+\.\d+\.\d+)/
|
20
|
+
(puts "adb version 1.0.31 or later required. Version found: #$1"; exit 1) unless Gem::Version.new($1) >= Gem::Version.new('1.0.31')
|
21
|
+
unless ENV['ANDROID_HOME']
|
22
|
+
unless ON_WINDOWS
|
23
|
+
begin
|
24
|
+
adb_path = `which adb`
|
25
|
+
ENV['ANDROID_HOME'] = File.dirname(File.dirname(adb_path)) if $? == 0
|
26
|
+
rescue Errno::ENOENT
|
27
|
+
puts "Unable to detect adb location: #$!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
(puts 'You need to set the ANDROID_HOME environment variable.'; exit 1) unless ENV['ANDROID_HOME']
|
32
|
+
|
33
|
+
# FIXME(uwe): On windows the file is called dx.bat
|
34
|
+
dx_filename = File.join(ENV['ANDROID_HOME'], 'platform-tools', ON_WINDOWS ? 'dx.bat' : 'dx')
|
35
|
+
unless File.exists? dx_filename
|
36
|
+
puts 'You need to install the Android SDK Platform-tools!'
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
new_dx_content = File.read(dx_filename).dup
|
40
|
+
# set defaultXmx=-Xmx1024M
|
41
|
+
xmx_pattern = /^defaultMx="-Xmx(\d+)(M|m|G|g|T|t)"/
|
42
|
+
if new_dx_content =~ xmx_pattern &&
|
43
|
+
($1.to_i * 1024 ** {'M' => 2, 'G' => 3, 'T' => 4}[$2.upcase]) < 2560*1024**2
|
44
|
+
puts "Increasing max heap space from #$1#$2 to 2560M in #{dx_filename}"
|
45
|
+
new_dx_content.sub!(xmx_pattern, 'defaultMx="-Xmx2560M"')
|
46
|
+
File.open(dx_filename, 'w') { |f| f << new_dx_content } rescue puts "\n!!! Unable to increase dx heap size !!!\n\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
def manifest; @manifest ||= REXML::Document.new(File.read(MANIFEST_FILE)) end
|
50
|
+
def package; manifest.root.attribute('package') end
|
51
|
+
def build_project_name; @build_project_name ||= REXML::Document.new(File.read('build.xml')).elements['project'].attribute(:name).value end
|
52
|
+
def scripts_path; @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files/scripts" end
|
53
|
+
def app_files_path; @app_files_path ||= "/data/data/#{package}/files" end
|
54
|
+
|
55
|
+
PROJECT_DIR = File.expand_path('..', File.dirname(__FILE__))
|
37
56
|
UPDATE_MARKER_FILE = File.join(PROJECT_DIR, 'bin', 'LAST_UPDATE')
|
38
|
-
BUNDLE_JAR
|
39
|
-
BUNDLE_PATH
|
40
|
-
MANIFEST_FILE
|
57
|
+
BUNDLE_JAR = File.expand_path 'libs/bundle.jar'
|
58
|
+
BUNDLE_PATH = File.expand_path 'bin/bundle'
|
59
|
+
MANIFEST_FILE = File.expand_path 'AndroidManifest.xml'
|
41
60
|
PROJECT_PROPS_FILE = File.expand_path 'project.properties'
|
42
61
|
RUBOTO_CONFIG_FILE = File.expand_path 'ruboto.yml'
|
43
|
-
GEM_FILE
|
44
|
-
GEM_LOCK_FILE
|
45
|
-
RELEASE_APK_FILE
|
46
|
-
APK_FILE
|
47
|
-
TEST_APK_FILE
|
48
|
-
JRUBY_JARS
|
49
|
-
RESOURCE_FILES
|
50
|
-
JAVA_SOURCE_FILES
|
51
|
-
RUBY_SOURCE_FILES
|
52
|
-
APK_DEPENDENCIES
|
53
|
-
KEYSTORE_FILE
|
54
|
-
KEYSTORE_ALIAS
|
55
|
-
|
56
|
-
CLEAN.include('bin', 'gen')
|
62
|
+
GEM_FILE = File.expand_path 'Gemfile.apk'
|
63
|
+
GEM_LOCK_FILE = File.expand_path 'Gemfile.apk.lock'
|
64
|
+
RELEASE_APK_FILE = File.expand_path "bin/#{build_project_name}-release.apk"
|
65
|
+
APK_FILE = File.expand_path "bin/#{build_project_name}-debug.apk"
|
66
|
+
TEST_APK_FILE = File.expand_path "test/bin/#{build_project_name}Test-debug.apk"
|
67
|
+
JRUBY_JARS = Dir[File.expand_path 'libs/jruby-*.jar']
|
68
|
+
RESOURCE_FILES = Dir[File.expand_path 'res/**/*']
|
69
|
+
JAVA_SOURCE_FILES = Dir[File.expand_path 'src/**/*.java']
|
70
|
+
RUBY_SOURCE_FILES = Dir[File.expand_path 'src/**/*.rb']
|
71
|
+
APK_DEPENDENCIES = [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES + RUBY_SOURCE_FILES
|
72
|
+
KEYSTORE_FILE = (key_store = File.readlines('ant.properties').grep(/^key.store=/).first) ? File.expand_path(key_store.chomp.sub(/^key.store=/, '').sub('${user.home}', '~')) : "#{build_project_name}.keystore"
|
73
|
+
KEYSTORE_ALIAS = (key_alias = File.readlines('ant.properties').grep(/^key.alias=/).first) ? key_alias.chomp.sub(/^key.alias=/, '') : build_project_name
|
74
|
+
|
75
|
+
CLEAN.include('bin', 'gen', 'test/bin', 'test/gen')
|
57
76
|
|
58
77
|
task :default => :debug
|
59
78
|
|
@@ -84,7 +103,7 @@ namespace :debug do
|
|
84
103
|
end
|
85
104
|
end
|
86
105
|
|
87
|
-
desc
|
106
|
+
desc 'build package and install it on the emulator or device'
|
88
107
|
task :install => APK_FILE do
|
89
108
|
install_apk
|
90
109
|
end
|
@@ -117,10 +136,10 @@ task :keystore => KEYSTORE_FILE
|
|
117
136
|
|
118
137
|
file KEYSTORE_FILE do
|
119
138
|
unless File.read('ant.properties') =~ /^key.store=/
|
120
|
-
File.open('ant.properties', 'a'){|f| f << "\nkey.store=#{KEYSTORE_FILE}\n"}
|
139
|
+
File.open('ant.properties', 'a') { |f| f << "\nkey.store=#{KEYSTORE_FILE}\n" }
|
121
140
|
end
|
122
141
|
unless File.read('ant.properties') =~ /^key.alias=/
|
123
|
-
File.open('ant.properties', 'a'){|f| f << "\nkey.alias=#{KEYSTORE_ALIAS}\n"}
|
142
|
+
File.open('ant.properties', 'a') { |f| f << "\nkey.alias=#{KEYSTORE_ALIAS}\n" }
|
124
143
|
end
|
125
144
|
sh "keytool -genkey -v -keystore #{KEYSTORE_FILE} -alias #{KEYSTORE_ALIAS} -keyalg RSA -keysize 2048 -validity 10000"
|
126
145
|
end
|
@@ -129,14 +148,14 @@ desc 'Tag this working copy with the current version'
|
|
129
148
|
task :tag do
|
130
149
|
next unless File.exists?('.git') && `git --version` =~ /git version /
|
131
150
|
unless `git branch` =~ /^\* master$/
|
132
|
-
puts
|
151
|
+
puts 'You must be on the master branch to release!'
|
133
152
|
exit!
|
134
153
|
end
|
135
154
|
# sh "git commit --allow-empty -a -m 'Release #{version}'"
|
136
155
|
output = `git status --porcelain`
|
137
156
|
raise "\nWorkspace not clean!\n#{output}" unless output.empty?
|
138
157
|
sh "git tag #{version}"
|
139
|
-
sh
|
158
|
+
sh 'git push origin master --tags'
|
140
159
|
end
|
141
160
|
|
142
161
|
desc 'Start the emulator with larger disk'
|
@@ -151,7 +170,7 @@ end
|
|
151
170
|
|
152
171
|
desc 'Stop the application on the device/emulator (requires emulator or rooted device).'
|
153
172
|
task :stop do
|
154
|
-
raise
|
173
|
+
raise 'Unable to stop app. Only available on emulator.' unless stop_app
|
155
174
|
end
|
156
175
|
|
157
176
|
desc 'Restart the application'
|
@@ -166,9 +185,9 @@ file MANIFEST_FILE => PROJECT_PROPS_FILE do
|
|
166
185
|
sdk_level = File.read(PROJECT_PROPS_FILE).scan(/(?:target=android-)(\d+)/)[0][0].to_i
|
167
186
|
old_manifest = File.read(MANIFEST_FILE)
|
168
187
|
manifest = old_manifest.dup
|
169
|
-
manifest.sub!(/(android:minSdkVersion=').*?(')/){
|
170
|
-
manifest.sub!(/(android:targetSdkVersion=').*?(')/){
|
171
|
-
File.open(MANIFEST_FILE, 'w'){|f| f << manifest} if manifest != old_manifest
|
188
|
+
manifest.sub!(/(android:minSdkVersion=').*?(')/) { "#$1#{sdk_level}#$2" }
|
189
|
+
manifest.sub!(/(android:targetSdkVersion=').*?(')/) { "#$1#{sdk_level}#$2" }
|
190
|
+
File.open(MANIFEST_FILE, 'w') { |f| f << manifest } if manifest != old_manifest
|
172
191
|
end
|
173
192
|
|
174
193
|
file RUBOTO_CONFIG_FILE
|
@@ -178,7 +197,7 @@ file APK_FILE => APK_DEPENDENCIES do |t|
|
|
178
197
|
end
|
179
198
|
|
180
199
|
desc 'Copy scripts to emulator or device'
|
181
|
-
task :update_scripts =>
|
200
|
+
task :update_scripts => %w(install:quick) do
|
182
201
|
update_scripts
|
183
202
|
end
|
184
203
|
|
@@ -206,7 +225,23 @@ namespace :test do
|
|
206
225
|
task :quick => :update_scripts do
|
207
226
|
Dir.chdir('test') do
|
208
227
|
puts 'Running quick tests'
|
209
|
-
sh "#{ANT_CMD} instrument
|
228
|
+
sh "#{ANT_CMD} instrument"
|
229
|
+
install_retry_count = 0
|
230
|
+
begin
|
231
|
+
timeout 120 do
|
232
|
+
sh "#{ANT_CMD} installi"
|
233
|
+
end
|
234
|
+
rescue TimeoutError
|
235
|
+
puts 'Installing package timed out.'
|
236
|
+
install_retry_count += 1
|
237
|
+
if install_retry_count > 3
|
238
|
+
puts 'Retrying install...'
|
239
|
+
retry
|
240
|
+
end
|
241
|
+
puts 'Trying one final time to install the package:'
|
242
|
+
sh "#{ANT_CMD} installi"
|
243
|
+
end
|
244
|
+
sh "#{ANT_CMD} run-tests-quick"
|
210
245
|
end
|
211
246
|
end
|
212
247
|
end
|
@@ -221,11 +256,26 @@ file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
|
|
221
256
|
next unless File.exists? GEM_FILE
|
222
257
|
puts "Generating #{BUNDLE_JAR}"
|
223
258
|
|
224
|
-
|
225
|
-
|
259
|
+
# Override RUBY_ENGINE (we can bundle from MRI for JRuby)
|
260
|
+
platforms = Gem.platforms
|
261
|
+
ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
262
|
+
Gem.platforms = [Gem::Platform::RUBY, Gem::Platform.new('universal-java')]
|
263
|
+
Object.const_set('RUBY_ENGINE', 'jruby')
|
264
|
+
|
265
|
+
ENV['BUNDLE_GEMFILE'] = GEM_FILE
|
266
|
+
require 'bundler'
|
267
|
+
Bundler.bundle_path = Pathname.new BUNDLE_PATH
|
268
|
+
|
269
|
+
definition = Bundler.definition
|
270
|
+
definition.validate_ruby!
|
271
|
+
Bundler::Installer.install(Bundler.root, definition)
|
272
|
+
|
273
|
+
# Restore RUBY_ENGINE (limit the scope of this hack)
|
274
|
+
Object.const_set('RUBY_ENGINE', ruby_engine) if ruby_engine
|
275
|
+
Gem.platforms = platforms
|
226
276
|
|
227
|
-
gem_paths = Dir["#{BUNDLE_PATH}/
|
228
|
-
raise
|
277
|
+
gem_paths = Dir["#{BUNDLE_PATH}/gems"]
|
278
|
+
raise 'Gem path not found' if gem_paths.empty?
|
229
279
|
raise "Found multiple gem paths: #{gem_paths}" if gem_paths.size > 1
|
230
280
|
gem_path = gem_paths[0]
|
231
281
|
puts "Found gems in #{gem_path}"
|
@@ -257,11 +307,11 @@ file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
|
|
257
307
|
Dir.chdir gem_path do
|
258
308
|
scanned_files = []
|
259
309
|
source_files = RUBY_SOURCE_FILES.map { |f| f.gsub("#{PROJECT_DIR}/src/", '') }
|
260
|
-
Dir[
|
310
|
+
Dir['*/lib/**/*'].each do |f|
|
261
311
|
next if File.directory? f
|
262
|
-
raise
|
312
|
+
raise 'Malformed file name' unless f =~ %r{^(.*?)/lib/(.*)$}
|
263
313
|
gem_name, lib_file = $1, $2
|
264
|
-
if existing_file = scanned_files.find { |sf| sf =~ %r{(.*?)/lib/#{lib_file}} }
|
314
|
+
if (existing_file = scanned_files.find { |sf| sf =~ %r{(.*?)/lib/#{lib_file}} })
|
265
315
|
puts "Overwriting duplicate file #{lib_file} in gem #{$1} with file in #{gem_name}"
|
266
316
|
FileUtils.rm existing_file
|
267
317
|
scanned_files.delete existing_file
|
@@ -300,6 +350,20 @@ puts 'Starting JRuby OpenSSL Service'
|
|
300
350
|
public
|
301
351
|
Java::JopensslService.new.basicLoad(JRuby.runtime)
|
302
352
|
END_CODE
|
353
|
+
elsif jar =~ %r{json/ext/generator.jar$}
|
354
|
+
jar_load_code = <<-END_CODE
|
355
|
+
require 'jruby'
|
356
|
+
puts 'Starting JSON Generator Service'
|
357
|
+
public
|
358
|
+
Java::json.ext.GeneratorService.new.basicLoad(JRuby.runtime)
|
359
|
+
END_CODE
|
360
|
+
elsif jar =~ %r{json/ext/parser.jar$}
|
361
|
+
jar_load_code = <<-END_CODE
|
362
|
+
require 'jruby'
|
363
|
+
puts 'Starting JSON Parser Service'
|
364
|
+
public
|
365
|
+
Java::json.ext.ParserService.new.basicLoad(JRuby.runtime)
|
366
|
+
END_CODE
|
303
367
|
else
|
304
368
|
jar_load_code = ''
|
305
369
|
end
|
@@ -345,7 +409,7 @@ def strings(name)
|
|
345
409
|
end
|
346
410
|
|
347
411
|
def version
|
348
|
-
|
412
|
+
manifest.root.attribute('versionName')
|
349
413
|
end
|
350
414
|
|
351
415
|
def app_name
|
@@ -358,18 +422,24 @@ end
|
|
358
422
|
|
359
423
|
def device_path_exists?(path)
|
360
424
|
path_output =`adb shell ls #{path}`
|
361
|
-
|
362
|
-
result
|
425
|
+
path_output.chomp !~ /No such file or directory|opendir failed, Permission denied/
|
363
426
|
end
|
364
427
|
|
365
|
-
|
428
|
+
# Determine if the package is installed.
|
429
|
+
# Return true if the package is installed and is identical to the local package.
|
430
|
+
# Return false if the package is installed, but differs from the local package.
|
431
|
+
# Return nil if the package is not installed.
|
432
|
+
def package_installed?(test = false)
|
366
433
|
package_name = "#{package}#{'.tests' if test}"
|
367
|
-
|
434
|
+
%w( -0 -1 -2).each do |i|
|
368
435
|
path = "/data/app/#{package_name}#{i}.apk"
|
369
436
|
o = `adb shell ls -l #{path}`.chomp
|
370
|
-
if o =~ /^-rw-r--r-- system\s+system\s+(\d+)
|
437
|
+
if o =~ /^-rw-r--r-- system\s+system\s+(\d+)\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2})\s+#{File.basename(path)}$/
|
438
|
+
installed_apk_size = $1.to_i
|
439
|
+
installed_timestamp = Time.parse($2)
|
371
440
|
apk_file = test ? TEST_APK_FILE : APK_FILE
|
372
|
-
if !File.exists?(apk_file) ||
|
441
|
+
if !File.exists?(apk_file) || (installed_apk_size == File.size(apk_file) &&
|
442
|
+
installed_timestamp >= File.mtime(apk_file))
|
373
443
|
return true
|
374
444
|
else
|
375
445
|
return false
|
@@ -378,16 +448,19 @@ def package_installed? test = false
|
|
378
448
|
|
379
449
|
sdcard_path = "/mnt/asec/#{package_name}#{i}/pkg.apk"
|
380
450
|
o = `adb shell ls -l #{sdcard_path}`.chomp
|
381
|
-
if o =~ /^-r-xr-xr-x system\s+root\s+(\d+)
|
451
|
+
if o =~ /^-r-xr-xr-x system\s+root\s+(\d+)\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2})\s+#{File.basename(sdcard_path)}$/
|
452
|
+
installed_apk_size = $1.to_i
|
453
|
+
installed_timestamp = Time.parse($2)
|
382
454
|
apk_file = test ? TEST_APK_FILE : APK_FILE
|
383
|
-
if !File.exists?(apk_file) ||
|
455
|
+
if !File.exists?(apk_file) || (installed_apk_size == File.size(apk_file) &&
|
456
|
+
installed_timestamp >= File.mtime(apk_file))
|
384
457
|
return true
|
385
458
|
else
|
386
459
|
return false
|
387
460
|
end
|
388
461
|
end
|
389
462
|
end
|
390
|
-
|
463
|
+
nil
|
391
464
|
end
|
392
465
|
|
393
466
|
def replace_faulty_code(faulty_file, faulty_code)
|
@@ -420,7 +493,7 @@ def build_apk(t, release)
|
|
420
493
|
else
|
421
494
|
sh "#{ANT_CMD} debug"
|
422
495
|
end
|
423
|
-
|
496
|
+
true
|
424
497
|
end
|
425
498
|
|
426
499
|
def install_apk
|
@@ -431,23 +504,55 @@ def install_apk
|
|
431
504
|
puts "Package #{package} already installed."
|
432
505
|
return
|
433
506
|
when false
|
434
|
-
puts "Package #{package} already installed, but of different size. Replacing package."
|
435
|
-
output =
|
507
|
+
puts "Package #{package} already installed, but of different size or timestamp. Replacing package."
|
508
|
+
output = nil
|
509
|
+
install_retry_count = 0
|
510
|
+
begin
|
511
|
+
timeout 120 do
|
512
|
+
output = `adb install -r #{APK_FILE} 2>&1`
|
513
|
+
end
|
514
|
+
rescue Timeout::Error
|
515
|
+
puts "Installing package #{package} timed out."
|
516
|
+
install_retry_count += 1
|
517
|
+
if install_retry_count > 3
|
518
|
+
puts 'Retrying install...'
|
519
|
+
retry
|
520
|
+
end
|
521
|
+
puts 'Trying one final time to install the package:'
|
522
|
+
output = `adb install -r #{APK_FILE} 2>&1`
|
523
|
+
end
|
436
524
|
if $? == 0 && output !~ failure_pattern && output =~ success_pattern
|
437
525
|
clear_update
|
438
526
|
return
|
439
527
|
end
|
440
528
|
case $1
|
441
529
|
when 'INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES'
|
442
|
-
puts
|
530
|
+
puts 'Found package signed with different certificate. Uninstalling it and retrying install.'
|
443
531
|
else
|
444
532
|
puts "'adb install' returned an unknown error: (#$?) #{$1 ? "[#$1}]" : output}."
|
445
533
|
puts "Uninstalling #{package} and retrying install."
|
446
534
|
end
|
447
535
|
uninstall_apk
|
536
|
+
else
|
537
|
+
# Package not installed.
|
448
538
|
end
|
449
539
|
puts "Installing package #{package}"
|
450
|
-
output =
|
540
|
+
output = nil
|
541
|
+
install_retry_count = 0
|
542
|
+
begin
|
543
|
+
timeout 120 do
|
544
|
+
output = `adb install #{APK_FILE} 2>&1`
|
545
|
+
end
|
546
|
+
rescue Timeout::Error
|
547
|
+
puts "Installing package #{package} timed out."
|
548
|
+
install_retry_count += 1
|
549
|
+
if install_retry_count > 3
|
550
|
+
puts 'Retrying install...'
|
551
|
+
retry
|
552
|
+
end
|
553
|
+
puts 'Trying one final time to install the package:'
|
554
|
+
output = `adb install #{APK_FILE} 2>&1`
|
555
|
+
end
|
451
556
|
puts output
|
452
557
|
raise "Install failed (#{$?}) #{$1 ? "[#$1}]" : output}" if $? != 0 || output =~ failure_pattern || output !~ success_pattern
|
453
558
|
clear_update
|
@@ -465,10 +570,10 @@ end
|
|
465
570
|
|
466
571
|
def update_scripts
|
467
572
|
`adb shell mkdir -p #{scripts_path}` if !device_path_exists?(scripts_path)
|
468
|
-
puts
|
573
|
+
puts 'Pushing files to apk public file area.'
|
469
574
|
last_update = File.exists?(UPDATE_MARKER_FILE) ? Time.parse(File.read(UPDATE_MARKER_FILE)) : Time.parse('1970-01-01T00:00:00')
|
470
575
|
Dir.chdir('src') do
|
471
|
-
Dir[
|
576
|
+
Dir['**/*.rb'].each do |script_file|
|
472
577
|
next if File.directory? script_file
|
473
578
|
next if File.mtime(script_file) < last_update
|
474
579
|
next if script_file =~ /~$/
|
@@ -485,5 +590,5 @@ end
|
|
485
590
|
|
486
591
|
def stop_app
|
487
592
|
output = `adb shell ps | grep #{package} | awk '{print $2}' | xargs adb shell kill`
|
488
|
-
|
593
|
+
output !~ /Operation not permitted/
|
489
594
|
end
|