ocra 1.1.5.pre2 → 1.1.5.pre3

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,6 +17,16 @@
17
17
  include all files listed in the Gem specification (Thanks to Jorge
18
18
  L. Cangas for patch & ideas).
19
19
 
20
+ * NameErrors are now rescued when attempting to load autoloadable
21
+ constants. Hopefully resolves issues with ActiveRecord [#28488].
22
+
23
+ * Now works if the script changes environment or working directory
24
+ while running.
25
+
26
+ * Fixed a regression in 1.1.4 when resource files are specified;
27
+ directory layout would not be maintained, e.g. when running "ocra
28
+ bin/script share/data.dat".
29
+
20
30
  === 1.1.4
21
31
 
22
32
  * The tempdir marker is now pretty-printed as "<tempdir>" in the
data/README.txt CHANGED
@@ -23,11 +23,6 @@ the tracker on the RubyForge project page
23
23
  http://rubyforge.org/projects/ocra/. You are welcome to ask questions
24
24
  in the forums there aswell.
25
25
 
26
- == TODO:
27
-
28
- * Support for packaging gems that need extra non-ruby files
29
- (e.g. mime-types, prawn).
30
-
31
26
  == SYNOPSIS:
32
27
 
33
28
  ocra [option] script.rb
@@ -80,7 +75,6 @@ in the forums there aswell.
80
75
 
81
76
  * Avoid absolute paths in your code and when invoking OCRA.
82
77
 
83
-
84
78
  == REQUIREMENTS:
85
79
 
86
80
  * Windows
@@ -119,7 +113,18 @@ your application will be put in the 'src' subdirectory.
119
113
 
120
114
  === Libraries
121
115
 
122
- Rubygems will be automatically included in the OCRA executable.
116
+ Any code that is loaded through Kernel#require when your script is
117
+ executed will be included in the OCRA executable. Conditionally loaded
118
+ code will not be loaded and included in the executable unless the code
119
+ is actually run when OCRA invokes your script. Otherwise, OCRA won't
120
+ know about it and will not include the source files.
121
+
122
+ RubyGems are handled specially. Whenever a file from a Gem is
123
+ detected, OCRA will attempt to include all the files from that
124
+ specific Gem (all files listed in the manifest), expect some unlikely
125
+ needed files such as readme's and other documentation. This can be
126
+ overruled using the '--no-gem-filter' which will make OCRA include
127
+ every file that is listed in the Gem's manifest.
123
128
 
124
129
  Libraries found in non-standard path (for example, if you invoke OCRA
125
130
  with "ruby -I some/path") will be placed into the site dir
@@ -128,13 +133,13 @@ with "ruby -I some/path") will be placed into the site dir
128
133
  tree, since OCRA may place the files elsewhere when extracted into the
129
134
  temporary directory.
130
135
 
131
- Autoloaded libraries (Kernel#autoload) will be attempted loaded when
132
- building the executable. Modules that doesn't exist will be ignore
133
- (but a warning will be logged).
136
+ In case your script (or any of its dependencies) sets up autoloaded
137
+ module using Kernel#autoload, OCRA will automatically try to load them
138
+ to ensure that they are all included in the executable. Modules that
139
+ doesn't exist will be ignored (a warning will be logged).
134
140
 
135
- Conditionally loaded code will not be loaded and included in the
136
- executable unless the code is actually run when OCRA invokes your
137
- script.
141
+ Dynamic link libraries (.dll files, for example WxWidgets, or other
142
+ source files) will be detected and included by OCRA.
138
143
 
139
144
  === Environment variables
140
145
 
@@ -154,13 +159,16 @@ executable, for example
154
159
 
155
160
  === Working directory
156
161
 
162
+ The OCRA executable does not change the working directory when it is
163
+ launched.
164
+
157
165
  You should not assume that the current working directory when invoking
158
166
  an executable built with .exe is the location of the source script. It
159
167
  can be the directory where the executable is placed (when invoked
160
168
  through the Windows Explorer), the users' current working directory
161
- (when invoking from the Command Prompt), or even <tt>C:\\WINDOWS\\SYSTEM32</tt>
162
- when the executable is invoked through a file association. You can
163
- optionally change the directory yourself:
169
+ (when invoking from the Command Prompt), or even
170
+ <tt>C:\\WINDOWS\\SYSTEM32</tt> when the executable is invoked through
171
+ a file association. You can optionally change the directory yourself:
164
172
 
165
173
  Dir.chdir File.dirname($0)
166
174
 
@@ -214,6 +222,9 @@ of files, for example
214
222
 
215
223
  === Window/Console
216
224
 
225
+ By default, OCRA builds console application from .rb-files and
226
+ windowed applications (without console window) from .rbw-files.
227
+
217
228
  Ruby on Windows provides two executables: ruby.exe is a console mode
218
229
  application and rubyw.exe is a windowed application which does not
219
230
  bring up a console window when launched using the Windows Explorer.
data/bin/ocra CHANGED
@@ -11,7 +11,7 @@ module Ocra
11
11
  OP_SETENV = 5
12
12
  OP_POST_CREATE_PROCESS = 6
13
13
 
14
- VERSION = "1.1.5.pre2"
14
+ VERSION = "1.1.5.pre3"
15
15
 
16
16
  IGNORE_MODULES = /^enumerator.so$/
17
17
 
@@ -32,63 +32,76 @@ module Ocra
32
32
 
33
33
  TEMPDIR_MARKER = "\xFF"
34
34
 
35
+ @options = {
36
+ :lzma_mode => true,
37
+ :extra_dlls => [],
38
+ :files => [],
39
+ :load_autoload => true,
40
+ :force_windows => false,
41
+ :force_console => false,
42
+ :icon_filename => nil,
43
+ :quiet => false,
44
+ :autodll => true,
45
+ :show_warnings => true,
46
+ :gem_filter => true
47
+ }
48
+
49
+ @options.each_key { |opt| eval("def self.#{opt}; @options[:#{opt}]; end") }
50
+
35
51
  class << self
36
- attr_accessor :lzma_mode
37
- attr_accessor :extra_dlls
38
- attr_accessor :files
39
- attr_accessor :load_autoload
40
- attr_accessor :force_windows
41
- attr_accessor :force_console
42
- attr_accessor :icon_filename
43
- attr_accessor :quiet
44
- attr_accessor :autodll
45
- attr_accessor :show_warnings
46
- attr_accessor :gem_filter
47
-
48
52
  attr_reader :lzmapath
49
53
  attr_reader :ediconpath
50
54
  attr_reader :stubimage
51
55
  attr_reader :stubwimage
52
-
53
- def get_next_embedded_image
54
- DATA.read(DATA.readline.to_i).unpack("m")[0]
55
- end
56
56
  end
57
57
 
58
- def Ocra.initialize_ocra
58
+ # Returns a binary blob store embedded in the current Ruby script.
59
+ def get_next_embedded_image
60
+ DATA.read(DATA.readline.to_i).unpack("m")[0]
61
+ end
62
+
63
+ def Ocra.dospath(path)
64
+ path.tr('/','\\')
65
+ end
66
+
67
+ def Ocra.posixpath(path)
68
+ path.tr('\\','/')
69
+ end
70
+
71
+ def Ocra.save_environment
59
72
  @load_path_before = $LOAD_PATH.dup
60
-
73
+ @pwd_before = Dir.pwd
74
+ @env_before = {}; ENV.each { |key, value| @env_before[key] = value }
75
+ end
76
+
77
+ def Ocra.restore_environment
78
+ @env_before.each { |key, value| ENV[key] = value }
79
+ ENV.each_key { |key| ENV.delete(key) unless @env_before.has_key?(key) }
80
+ Dir.chdir @pwd_before
81
+ end
82
+
83
+ def Ocra.find_stubs
61
84
  if defined?(DATA)
62
85
  @stubimage = get_next_embedded_image
63
86
  @stubwimage = get_next_embedded_image
64
87
  lzmaimage = get_next_embedded_image
65
- @lzmapath = File.join(ENV['TEMP'], 'lzma.exe').tr('/','\\')
88
+ @lzmapath = File.join(ENV['TEMP'], 'lzma.exe')
66
89
  File.open(@lzmapath, "wb") { |file| file << lzmaimage }
67
90
  ediconimage = get_next_embedded_image
68
- @ediconpath = File.join(ENV['TEMP'], 'edicon.exe').tr('/','\\')
91
+ @ediconpath = File.join(ENV['TEMP'], 'edicon.exe')
69
92
  File.open(@ediconpath, "wb") { |file| file << ediconimage }
70
93
  else
71
94
  ocrapath = File.dirname(__FILE__)
72
95
  @stubimage = File.open(File.join(ocrapath, '../share/ocra/stub.exe'), "rb") { |file| file.read }
73
96
  @stubwimage = File.open(File.join(ocrapath, '../share/ocra/stubw.exe'), "rb") { |file| file.read }
74
- @lzmapath = File.expand_path('../share/ocra/lzma.exe', ocrapath).tr('/','\\')
75
- @ediconpath = File.expand_path('../share/ocra/edicon.exe', ocrapath).tr('/','\\')
97
+ @lzmapath = File.expand_path('../share/ocra/lzma.exe', ocrapath)
98
+ @ediconpath = File.expand_path('../share/ocra/edicon.exe', ocrapath)
76
99
  end
100
+ @lzmapath = Ocra.dospath(@lzmapath)
101
+ @ediconpath = Ocra.dospath(@ediconpath)
77
102
  end
78
103
 
79
104
  def Ocra.parseargs(argv)
80
- lzma_mode = true
81
- extra_dlls = []
82
- files = []
83
- load_autoload = true
84
- force_windows = false
85
- force_console = false
86
- icon_filename = nil
87
- quiet = false
88
- autodll = true
89
- show_warnings = true
90
- gem_filter = true
91
-
92
105
  usage = <<EOF
93
106
  ocra [options] script.rb
94
107
 
@@ -107,34 +120,34 @@ EOF
107
120
  while arg = argv.shift
108
121
  case arg
109
122
  when /\A--(no-)?lzma\z/
110
- lzma_mode = !$1
123
+ @options[:lzma_mode] = !$1
111
124
  when /\A--dll\z/
112
- extra_dlls << argv.shift
125
+ @options[:extra_dlls] << argv.shift
113
126
  when /\A--quiet\z/
114
- quiet = true
127
+ @options[:quiet] = true
115
128
  when /\A--windows\z/
116
- force_windows = true
129
+ @options[:force_windows] = true
117
130
  when /\A--console\z/
118
- force_console = true
131
+ @options[:force_console] = true
119
132
  when /\A--no-autoload\z/
120
- load_autoload = false
133
+ @options[:load_autoload] = false
121
134
  when /\A--icon\z/
122
- icon_filename = argv.shift
135
+ @options[:icon_filename] = argv.shift
123
136
  raise "Icon file #{icon_filename} not found.\n" unless File.exist?(icon_filename)
124
137
  when /\A--no-autodll\z/
125
- autodll = false
138
+ @options[:autodll] = false
126
139
  when /\A--version\z/
127
140
  puts "Ocra #{VERSION}"
128
141
  exit
129
142
  when /\A--no-warnings\z/
130
- show_warnings = false
143
+ @options[:show_warnings] = false
131
144
  when /\A--no-gem-filter\z/
132
- gem_filter = false
145
+ @options[:gem_filter] = false
133
146
  when /\A--help\z/, /\A--/
134
147
  puts usage
135
148
  exit
136
149
  else
137
- files << arg
150
+ @options[:files] << arg
138
151
  end
139
152
  end
140
153
 
@@ -142,23 +155,12 @@ EOF
142
155
  puts usage
143
156
  exit
144
157
  end
145
-
146
- @lzma_mode = lzma_mode
147
- @extra_dlls = extra_dlls
148
- @quiet = quiet
149
- @force_windows = force_windows
150
- @force_console = force_console
151
- @load_autoload = load_autoload
152
- @icon_filename = icon_filename
153
- @autodll = autodll
154
- @files = files
155
- @show_warnings = show_warnings
156
- @gem_filter = gem_filter
157
158
  end
158
159
 
159
160
  def Ocra.init(argv)
161
+ save_environment
160
162
  parseargs(argv)
161
- initialize_ocra
163
+ find_stubs
162
164
  end
163
165
 
164
166
  # Force loading autoloaded constants. Searches through all modules
@@ -178,6 +180,8 @@ EOF
178
180
  if mod.autoload?(const)
179
181
  begin
180
182
  mod.const_get(const)
183
+ rescue NameError
184
+ puts "=== WARNING: #{mod}::#{const} was defined autoloadable, but caused NameError" if Ocra.show_warnings
181
185
  rescue LoadError
182
186
  puts "=== WARNING: #{mod}::#{const} was not loadable" if Ocra.show_warnings
183
187
  end
@@ -187,6 +191,9 @@ EOF
187
191
  end
188
192
  end
189
193
 
194
+ # Compute the relative path from the 'src' path (directory) to 'tgt'
195
+ # (directory or file). Return the absolute path to 'tgt' if it can't
196
+ # be reached from 'src'.
190
197
  def Ocra.relative_path(src, tgt)
191
198
  a = src.split('/')
192
199
  b = tgt.split('/')
@@ -202,11 +209,14 @@ EOF
202
209
  # Determines if 'src' is contained in 'tgt' (i.e. it is a subpath of
203
210
  # 'tgt'). Both must be absolute paths and not contain '..'
204
211
  def Ocra.subpath?(src, tgt)
205
- src_normalized = src.tr('/','\\')
206
- tgt_normalized = tgt.tr('/','\\')
212
+ src_normalized = Ocra.dospath(src).downcase
213
+ tgt_normalized = Ocra.dospath(tgt).downcase
207
214
  src_normalized =~ /^#{Regexp.escape tgt_normalized}[\/\\]/i
208
215
  end
209
216
 
217
+ # Guess the load path (from 'paths') that was used to load
218
+ # 'path'. This is primarily relevant on Ruby 1.8 which stores
219
+ # "unqualified" paths in $LOADED_FEATURES.
210
220
  def Ocra.find_load_path(paths, path)
211
221
  if path[1,1] == ":"
212
222
  rps = paths.map {|p| relative_path(File.expand_path(p), path) }
@@ -219,6 +229,8 @@ EOF
219
229
 
220
230
  def Ocra.build_exe
221
231
  @added_load_paths = $LOAD_PATH - @load_path_before
232
+
233
+ restore_environment
222
234
 
223
235
  # Attempt to autoload libraries before doing anything else.
224
236
  attempt_load_autoload if Ocra.load_autoload
@@ -236,12 +248,38 @@ EOF
236
248
 
237
249
  require 'rbconfig'
238
250
  exec_prefix = RbConfig::CONFIG['exec_prefix']
239
- src_prefix = File.expand_path(File.dirname(Ocra.files[0]))
251
+ src_prefix = Dir.pwd
240
252
  sitelibdir = RbConfig::CONFIG['sitelibdir']
241
253
  bindir = RbConfig::CONFIG['bindir']
242
254
  libruby_so = RbConfig::CONFIG['LIBRUBY_SO']
243
255
 
244
- instsitelibdir = sitelibdir[exec_prefix.size+1..-1]
256
+ # Find the root of all files specified on the command line and use
257
+ # it as the "src" of the output. Adjust 'Ocra.files' to be
258
+ # relative to the resulting root.
259
+ files = Ocra.files.map { |file| Dir[Ocra.posixpath(file)] }.flatten
260
+ files = files.map { |file| File.expand_path(file) }
261
+ src_prefix = files.inject(File.dirname(files[0])) do |srcroot, path|
262
+ if subpath?(path, exec_prefix)
263
+ srcroot
264
+ else
265
+ loop do
266
+ relpath = relative_path(srcroot, path)
267
+ if relpath =~ /^[A-Z]:$/i
268
+ puts "ERROR: No common directory contains all specified files"
269
+ end
270
+ if relpath =~ /^\.\.\//
271
+ srcroot = File.dirname(srcroot)
272
+ else
273
+ break
274
+ end
275
+ end
276
+ srcroot
277
+ end
278
+ end
279
+ files = files.map { |file| relative_path(src_prefix, file) }
280
+ Ocra.files.replace(files)
281
+
282
+ instsitelibdir = relative_path(exec_prefix, sitelibdir)
245
283
 
246
284
  load_path = []
247
285
 
@@ -260,7 +298,7 @@ EOF
260
298
  Gem.path.each do |gempath|
261
299
  geminstallpath = File.join(gempath, "gems")
262
300
  if subpath?(filename, geminstallpath)
263
- gemlocalpath = filename[geminstallpath.size+1..-1]
301
+ gemlocalpath = relative_path(geminstallpath, filename)
264
302
  fullgemname = gemlocalpath.split('/')[0]
265
303
  gems << [gempath, fullgemname]
266
304
  features_from_gems << filename
@@ -304,9 +342,9 @@ EOF
304
342
  end
305
343
  fullpath = File.expand_path(filename, path)
306
344
  if subpath?(fullpath, exec_prefix)
307
- libs << [ fullpath, fullpath[exec_prefix.size+1..-1] ]
345
+ libs << [ fullpath, relative_path(exec_prefix, fullpath) ]
308
346
  elsif subpath?(fullpath, src_prefix)
309
- targetpath = "src/" + fullpath[src_prefix.size+1..-1]
347
+ targetpath = File.join("src", relative_path(src_prefix, fullpath))
310
348
  libs << [ fullpath, targetpath ]
311
349
  if not @added_load_paths.include?(path) and not load_path.include?(path)
312
350
  load_path << File.join(TEMPDIR_MARKER, File.dirname(targetpath))
@@ -344,8 +382,8 @@ EOF
344
382
  puts "=== Building #{executable}" unless Ocra.quiet
345
383
  OcraBuilder.new(executable, windowed) do |sb|
346
384
  # Add explicitly mentioned files
347
- Ocra.files.each do |file|
348
- file = File.expand_path(file)
385
+ files.each do |file|
386
+ file = File.join(src_prefix, file)
349
387
 
350
388
  if subpath?(file, exec_prefix)
351
389
  target = relative_path(exec_prefix, file)
@@ -355,8 +393,6 @@ EOF
355
393
  target = File.join('src', File.basename(file))
356
394
  end
357
395
 
358
- target.tr!('/','\\')
359
-
360
396
  if File.directory?(file)
361
397
  sb.ensuremkdir(target)
362
398
  else
@@ -370,15 +406,15 @@ EOF
370
406
  else
371
407
  rubyexe = (RbConfig::CONFIG['ruby_install_name'] || "ruby") + ".exe"
372
408
  end
373
- sb.createfile(File.join(bindir, rubyexe), "bin\\" + rubyexe)
409
+ sb.createfile(File.join(bindir, rubyexe), File.join("bin", rubyexe))
374
410
  if libruby_so
375
- sb.createfile(File.join(bindir, libruby_so), "bin\\#{libruby_so}")
411
+ sb.createfile(File.join(bindir, libruby_so), File.join("bin", libruby_so))
376
412
  end
377
413
 
378
414
  # Add detected DLLs
379
415
  dlls.each do |dll|
380
- if subpath?(dll.tr('\\','/'), exec_prefix)
381
- target = dll[exec_prefix.size+1..-1]
416
+ if subpath?(dll, exec_prefix)
417
+ target = relative_path(exec_prefix, dll)
382
418
  else
383
419
  target = File.join('bin', File.basename(dll))
384
420
  end
@@ -387,17 +423,17 @@ EOF
387
423
 
388
424
  # Add extra DLLs
389
425
  Ocra.extra_dlls.each do |dll|
390
- sb.createfile(File.join(bindir, dll), File.join("bin", dll).tr('/','\\'))
426
+ sb.createfile(File.join(bindir, dll), File.join("bin", dll))
391
427
  end
392
428
 
393
429
  # Add gemspec files
394
430
  gemspecs.each do |gemspec|
395
431
  if subpath?(gemspec, exec_prefix)
396
- path = gemspec[exec_prefix.size+1..-1]
397
- sb.createfile(gemspec, path.tr('/','\\'))
432
+ path = relative_path(exec_prefix, gemspec)
433
+ sb.createfile(gemspec, path)
398
434
  elsif defined?(Gem) and gemhome = Gem.path.find { |pth| subpath?(gemspec, pth) }
399
435
  path = File.join('gemhome', relative_path(gemhome, gemspec))
400
- sb.createfile(gemspec, path.tr('/','\\'))
436
+ sb.createfile(gemspec, path)
401
437
  else
402
438
  raise "#{gemspec} does not exist in the Ruby installation. Don't know where to put it."
403
439
  end
@@ -405,7 +441,7 @@ EOF
405
441
 
406
442
  # Add loaded libraries
407
443
  libs.each do |path, target|
408
- sb.createfile(path, target.tr('/', '\\'))
444
+ sb.createfile(path, target)
409
445
  end
410
446
 
411
447
  # Set environment variable
@@ -414,7 +450,7 @@ EOF
414
450
  sb.setenv('GEM_PATH', "#{TEMPDIR_MARKER}\\gemhome")
415
451
 
416
452
  # Launch the script
417
- sb.postcreateprocess(TEMPDIR_MARKER + "\\bin\\" + rubyexe, "#{rubyexe} \"\xff\\src\\" + File.basename(Ocra.files[0]) + "\"")
453
+ sb.postcreateprocess(TEMPDIR_MARKER + "\\bin\\" + rubyexe, "#{rubyexe} \"\xff\\src\\" + Ocra.dospath(Ocra.files[0]) + "\"")
418
454
 
419
455
  puts "=== Compressing" unless Ocra.quiet or not Ocra.lzma_mode
420
456
  end
@@ -452,13 +488,16 @@ EOF
452
488
  loaded = loaded_dlls
453
489
  exec_prefix = RbConfig::CONFIG['exec_prefix']
454
490
  loaded.select do |path|
455
- Ocra.subpath?(path.tr('\\','/'), exec_prefix) and
491
+ Ocra.subpath?(path, exec_prefix) and
456
492
  File.basename(path) =~ /\.dll$/i and
457
493
  File.basename(path).downcase != RbConfig::CONFIG['LIBRUBY_SO'].downcase
458
494
  end
459
495
  end
460
496
  end
461
-
497
+
498
+ # Utility class that produces the actual executable. Opcodes
499
+ # (createfile, mkdir etc) are added by invoking methods on an
500
+ # instance of OcraBuilder.
462
501
  class OcraBuilder
463
502
  def initialize(path, windowed)
464
503
  @paths = {}
@@ -507,36 +546,43 @@ EOF
507
546
  ocrafile.write(Signature.pack("C*"))
508
547
  end
509
548
  end
549
+
510
550
  def mkdir(path)
511
551
  @paths[path.downcase] = true
512
552
  puts "m #{showtempdir path}" unless Ocra.quiet
513
- @of << [OP_CREATE_DIRECTORY, path].pack("VZ*")
553
+ @of << [OP_CREATE_DIRECTORY, Ocra.dospath(path)].pack("VZ*")
514
554
  end
555
+
515
556
  def ensuremkdir(tgt)
516
557
  return if tgt == "."
517
- if not @paths[tgt.downcase]
558
+ if not @paths[Ocra.posixpath(tgt.downcase)]
518
559
  ensuremkdir(File.dirname(tgt))
519
560
  mkdir(tgt)
520
561
  end
521
562
  end
563
+
522
564
  def createfile(src, tgt)
523
565
  ensuremkdir(File.dirname(tgt))
524
566
  str = File.open(src, "rb") { |file| file.read }
525
567
  puts "a #{showtempdir tgt}" unless Ocra.quiet
526
- @of << [OP_CREATE_FILE, tgt, str.size, str].pack("VZ*VA*")
568
+ @of << [OP_CREATE_FILE, Ocra.dospath(tgt), str.size, str].pack("VZ*VA*")
527
569
  end
570
+
528
571
  def createprocess(image, cmdline)
529
572
  puts "l #{showtempdir image} #{showtempdir cmdline}" unless Ocra.quiet
530
- @of << [OP_CREATE_PROCESS, image, cmdline].pack("VZ*Z*")
573
+ @of << [OP_CREATE_PROCESS, Ocra.dospath(image), cmdline].pack("VZ*Z*")
531
574
  end
575
+
532
576
  def postcreateprocess(image, cmdline)
533
577
  puts "p #{showtempdir image} #{showtempdir cmdline}" unless Ocra.quiet
534
- @of << [OP_POST_CREATE_PROCESS, image, cmdline].pack("VZ*Z*")
578
+ @of << [OP_POST_CREATE_PROCESS, Ocra.dospath(image), cmdline].pack("VZ*Z*")
535
579
  end
580
+
536
581
  def setenv(name, value)
537
582
  puts "e #{name} #{showtempdir value}" unless Ocra.quiet
538
583
  @of << [OP_SETENV, name, value].pack("VZ*Z*")
539
584
  end
585
+
540
586
  def close
541
587
  @of.close
542
588
  end
@@ -552,6 +598,11 @@ end # module Ocra
552
598
  if File.basename(__FILE__) == File.basename($0)
553
599
  Ocra.init(ARGV)
554
600
  ARGV.clear
601
+
602
+ if !File.exist?(Ocra.files[0])
603
+ puts "ERROR: #{Ocra.files[0]} was not found!"
604
+ exit
605
+ end
555
606
 
556
607
  at_exit do
557
608
  if $!.nil? or $!.kind_of?(SystemExit)
@@ -1,3 +1,3 @@
1
1
  class Ocra
2
- VERSION = '1.1.5.pre2'
2
+ VERSION = '1.1.5.pre3'
3
3
  end
Binary file
Binary file
Binary file
@@ -34,6 +34,17 @@ class TestOcra < Test::Unit::TestCase
34
34
  # Path to test fixtures.
35
35
  FixturePath = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures'))
36
36
 
37
+ # Create a pristine environment to test built executables. Files are
38
+ # copied and the PATH environment is set to the minimal. Yields to
39
+ # the block, then cleans up.
40
+ def pristine_env(*files)
41
+ with_tmpdir files do
42
+ with_env "PATH" => ENV["SystemRoot"] + ";" + ENV["SystemRoot"] + "\\SYSTEM32" do
43
+ yield
44
+ end
45
+ end
46
+ end
47
+
37
48
  attr_reader :ocra
38
49
 
39
50
  def initialize(*args)
@@ -48,13 +59,11 @@ class TestOcra < Test::Unit::TestCase
48
59
  # files located in test/fixtures.
49
60
  def with_fixture(name)
50
61
  path = File.join(FixturePath, name)
51
- cp_r path, '.'
52
- begin
62
+ with_tmpdir do
63
+ cp_r path, '.'
53
64
  cd name do
54
65
  yield
55
66
  end
56
- ensure
57
- rm_rf name
58
67
  end
59
68
  end
60
69
 
@@ -76,10 +85,11 @@ class TestOcra < Test::Unit::TestCase
76
85
  end
77
86
  end
78
87
 
79
- def with_tmpdir
88
+ def with_tmpdir(files = [])
80
89
  tempdirname = File.join(ENV['TEMP'], ".ocratest-#{$$}-#{rand 2**32}").tr('\\','/')
81
90
  Dir.mkdir tempdirname
82
91
  begin
92
+ cp files, tempdirname
83
93
  FileUtils.cd tempdirname do
84
94
  yield
85
95
  end
@@ -88,35 +98,14 @@ class TestOcra < Test::Unit::TestCase
88
98
  end
89
99
  end
90
100
 
91
- def with_exe(name)
92
- orig_exe = File.expand_path(name)
93
- with_tmpdir do
94
- cp orig_exe, File.join('.', File.basename(name))
95
- yield
96
- end
97
- end
98
-
99
- # Test setup method. Creates a tempory directory to work in and
100
- # changes to it.
101
- def setup
102
- @testnum += 1
103
- @tempdirname = ".ocratest-#{$$}-#{@testnum}"
104
- Dir.mkdir @tempdirname
105
- Dir.chdir @tempdirname
106
- end
107
-
108
- # Test cleanup method. Exits the temporary directory and deletes it.
109
- def teardown
110
- Dir.chdir '..'
111
- FileUtils.rm_rf @tempdirname
112
- end
113
-
114
101
  # Hello world test. Test that we can build and run executables.
115
102
  def test_helloworld
116
103
  with_fixture 'helloworld' do
117
104
  assert system("ruby", ocra, "helloworld.rb", *DefaultArgs)
118
105
  assert File.exist?("helloworld.exe")
119
- assert system("helloworld.exe")
106
+ pristine_env "helloworld.exe" do
107
+ assert system("helloworld.exe")
108
+ end
120
109
  end
121
110
  end
122
111
 
@@ -125,7 +114,9 @@ class TestOcra < Test::Unit::TestCase
125
114
  with_fixture 'helloworld' do
126
115
  assert system("ruby", ocra, "helloworld.rb", "--quiet", "--lzma")
127
116
  assert File.exist?("helloworld.exe")
128
- assert system("helloworld.exe")
117
+ pristine_env "helloworld.exe" do
118
+ assert system("helloworld.exe")
119
+ end
129
120
  end
130
121
  end
131
122
 
@@ -134,10 +125,12 @@ class TestOcra < Test::Unit::TestCase
134
125
  def test_writefile
135
126
  with_fixture 'writefile' do
136
127
  assert system("ruby", ocra, "writefile.rb", *DefaultArgs)
137
- assert File.exist?("writefile.exe")
138
- assert system("writefile.exe")
139
- assert File.exist?("output.txt")
140
- assert "output", File.read("output.txt")
128
+ pristine_env "writefile.exe" do
129
+ assert File.exist?("writefile.exe")
130
+ assert system("writefile.exe")
131
+ assert File.exist?("output.txt")
132
+ assert "output", File.read("output.txt")
133
+ end
141
134
  end
142
135
  end
143
136
 
@@ -145,8 +138,10 @@ class TestOcra < Test::Unit::TestCase
145
138
  def test_exitstatus
146
139
  with_fixture 'exitstatus' do
147
140
  assert system("ruby", ocra, "exitstatus.rb", *DefaultArgs)
148
- system("exitstatus.exe")
149
- assert_equal 167, $?.exitstatus
141
+ pristine_env "exitstatus.exe" do
142
+ system("exitstatus.exe")
143
+ assert_equal 167, $?.exitstatus
144
+ end
150
145
  end
151
146
  end
152
147
 
@@ -155,8 +150,10 @@ class TestOcra < Test::Unit::TestCase
155
150
  with_fixture 'arguments' do
156
151
  assert system("ruby", ocra, "arguments.rb", *DefaultArgs)
157
152
  assert File.exist?("arguments.exe")
158
- system("arguments.exe foo \"bar baz\"")
159
- assert_equal 5, $?.exitstatus
153
+ pristine_env "arguments.exe" do
154
+ system("arguments.exe foo \"bar baz\"")
155
+ assert_equal 5, $?.exitstatus
156
+ end
160
157
  end
161
158
  end
162
159
 
@@ -166,9 +163,11 @@ class TestOcra < Test::Unit::TestCase
166
163
  with_fixture 'stdoutredir' do
167
164
  assert system("ruby", ocra, "stdoutredir.rb", *DefaultArgs)
168
165
  assert File.exist?("stdoutredir.exe")
169
- system("stdoutredir.exe > output.txt")
170
- assert File.exist?("output.txt")
171
- assert_equal "Hello, World!\n", File.read("output.txt")
166
+ pristine_env "stdoutredir.exe" do
167
+ system("stdoutredir.exe > output.txt")
168
+ assert File.exist?("output.txt")
169
+ assert_equal "Hello, World!\n", File.read("output.txt")
170
+ end
172
171
  end
173
172
  end
174
173
 
@@ -178,8 +177,11 @@ class TestOcra < Test::Unit::TestCase
178
177
  with_fixture 'stdinredir' do
179
178
  assert system("ruby", ocra, "stdinredir.rb", *DefaultArgs)
180
179
  assert File.exist?("stdinredir.exe")
181
- system("stdinredir.exe < input.txt")
182
- assert 104, $?.exitstatus
180
+ # Kernel.system("ruby -e \"system 'stdinredir.exe<input.txt';p $?\"")
181
+ pristine_env "stdinredir.exe", "input.txt" do
182
+ system("stdinredir.exe < input.txt")
183
+ end
184
+ assert_equal 104, $?.exitstatus
183
185
  end
184
186
  end
185
187
 
@@ -197,8 +199,10 @@ class TestOcra < Test::Unit::TestCase
197
199
  with_fixture 'gdbmdll' do
198
200
  assert system("ruby", ocra, "gdbmdll.rb", *args)
199
201
  with_env 'PATH' => '.' do
200
- system("gdbmdll.exe")
201
- assert_equal 104, $?.exitstatus
202
+ pristine_env "gdbmdll.exe" do
203
+ system("gdbmdll.exe")
204
+ assert_equal 104, $?.exitstatus
205
+ end
202
206
  end
203
207
  end
204
208
  end
@@ -210,8 +214,10 @@ class TestOcra < Test::Unit::TestCase
210
214
  with_fixture 'relativerequire' do
211
215
  assert system("ruby", ocra, "relativerequire.rb", *DefaultArgs)
212
216
  assert File.exist?("relativerequire.exe")
213
- system("relativerequire.exe")
214
- assert_equal 160, $?.exitstatus
217
+ pristine_env "relativerequire.exe" do
218
+ system("relativerequire.exe")
219
+ assert_equal 160, $?.exitstatus
220
+ end
215
221
  end
216
222
  end
217
223
 
@@ -222,8 +228,9 @@ class TestOcra < Test::Unit::TestCase
222
228
  with_fixture 'autoload' do
223
229
  assert system("ruby", ocra, "autoload.rb", *DefaultArgs)
224
230
  assert File.exist?("autoload.exe")
225
- File.unlink('foo.rb')
226
- assert system("autoload.exe")
231
+ pristine_env "autoload.exe" do
232
+ assert system("autoload.exe")
233
+ end
227
234
  end
228
235
  end
229
236
 
@@ -235,7 +242,9 @@ class TestOcra < Test::Unit::TestCase
235
242
  args.push '--no-warnings'
236
243
  assert system("ruby", ocra, "autoloadmissing.rb", *args)
237
244
  assert File.exist?("autoloadmissing.exe")
238
- assert system("autoloadmissing.exe")
245
+ pristine_env "autoloadmissing.exe" do
246
+ assert system("autoloadmissing.exe")
247
+ end
239
248
  end
240
249
  end
241
250
 
@@ -244,8 +253,9 @@ class TestOcra < Test::Unit::TestCase
244
253
  with_fixture 'autoloadnested' do
245
254
  assert system("ruby", ocra, "autoloadnested.rb", *DefaultArgs)
246
255
  assert File.exist?("autoloadnested.exe")
247
- File.unlink('foo.rb')
248
- assert system("autoloadnested.exe")
256
+ pristine_env "autoloadnested.exe" do
257
+ assert system("autoloadnested.exe")
258
+ end
249
259
  end
250
260
  end
251
261
 
@@ -256,7 +266,9 @@ class TestOcra < Test::Unit::TestCase
256
266
  with_fixture 'relloadpath1' do
257
267
  assert system('ruby', '-I', 'lib', ocra, 'relloadpath1.rb', *DefaultArgs)
258
268
  assert File.exist?('relloadpath1.exe')
259
- assert system('relloadpath1.exe')
269
+ pristine_env "relloadpath1.exe" do
270
+ assert system('relloadpath1.exe')
271
+ end
260
272
  end
261
273
  end
262
274
 
@@ -265,7 +277,9 @@ class TestOcra < Test::Unit::TestCase
265
277
  with_fixture 'relloadpath1' do
266
278
  assert system('ruby', '-I', './lib', ocra, 'relloadpath1.rb', *DefaultArgs)
267
279
  assert File.exist?('relloadpath1.exe')
268
- assert system('relloadpath1.exe')
280
+ pristine_env "relloadpath1.exe" do
281
+ assert system('relloadpath1.exe')
282
+ end
269
283
  end
270
284
  end
271
285
 
@@ -277,7 +291,9 @@ class TestOcra < Test::Unit::TestCase
277
291
  with_env 'RUBYLIB' => 'lib' do
278
292
  assert system('ruby', ocra, 'relloadpath1.rb', *DefaultArgs)
279
293
  assert File.exist?('relloadpath1.exe')
280
- assert system('relloadpath1.exe')
294
+ pristine_env "relloadpath1.exe" do
295
+ assert system('relloadpath1.exe')
296
+ end
281
297
  end
282
298
  end
283
299
  end
@@ -288,7 +304,9 @@ class TestOcra < Test::Unit::TestCase
288
304
  with_env 'RUBYLIB' => './lib' do
289
305
  assert system('ruby', ocra, 'relloadpath1.rb', *DefaultArgs)
290
306
  assert File.exist?('relloadpath1.exe')
291
- assert system('relloadpath1.exe')
307
+ pristine_env "relloadpath1.exe" do
308
+ assert system('relloadpath1.exe')
309
+ end
292
310
  end
293
311
  end
294
312
  end
@@ -299,7 +317,9 @@ class TestOcra < Test::Unit::TestCase
299
317
  cd 'src' do
300
318
  assert system('ruby', '-I', '../lib', ocra, 'relloadpath2.rb', *DefaultArgs)
301
319
  assert File.exist?('relloadpath2.exe')
302
- assert system('relloadpath2.exe')
320
+ pristine_env "relloadpath2.exe" do
321
+ assert system('relloadpath2.exe')
322
+ end
303
323
  end
304
324
  end
305
325
  end
@@ -310,7 +330,9 @@ class TestOcra < Test::Unit::TestCase
310
330
  with_fixture 'relloadpath3' do
311
331
  assert system('ruby', ocra, 'relloadpath3.rb', *DefaultArgs)
312
332
  assert File.exist?('relloadpath3.exe')
313
- assert system('relloadpath3.exe')
333
+ pristine_env "relloadpath3.exe" do
334
+ assert system('relloadpath3.exe')
335
+ end
314
336
  end
315
337
  end
316
338
 
@@ -321,14 +343,16 @@ class TestOcra < Test::Unit::TestCase
321
343
  cd 'src' do
322
344
  assert system('ruby', ocra, 'relloadpath4.rb', *DefaultArgs)
323
345
  assert File.exist?('relloadpath4.exe')
324
- assert system('relloadpath4.exe')
346
+ pristine_env "relloadpath4.exe" do
347
+ assert system('relloadpath4.exe')
348
+ end
325
349
  end
326
350
  end
327
351
  end
328
352
 
329
353
  # Test that ocra.rb accepts --version and outputs the version number.
330
354
  def test_version
331
- assert_match(/^Ocra \d+(\.\d)+$/, `ruby \"#{ocra}\" --version`)
355
+ assert_match(/^Ocra \d+(\.\d)+(.pre\d+)?$/, `ruby \"#{ocra}\" --version`)
332
356
  end
333
357
 
334
358
  # Test that ocra.rb accepts --icon.
@@ -337,7 +361,9 @@ class TestOcra < Test::Unit::TestCase
337
361
  icofile = File.join(OcraRoot, 'src', 'vit-ruby.ico')
338
362
  assert system("ruby", ocra, '--icon', icofile, "helloworld.rb", *DefaultArgs)
339
363
  assert File.exist?("helloworld.exe")
340
- assert system("helloworld.exe")
364
+ pristine_env "helloworld.exe" do
365
+ assert system("helloworld.exe")
366
+ end
341
367
  end
342
368
  end
343
369
 
@@ -347,7 +373,9 @@ class TestOcra < Test::Unit::TestCase
347
373
  with_fixture 'resource' do
348
374
  assert system("ruby", ocra, "resource.rb", "resource.txt", "res/resource.txt", *DefaultArgs)
349
375
  assert File.exist?("resource.exe")
350
- assert system("resource.exe")
376
+ pristine_env "resource.exe" do
377
+ assert system("resource.exe")
378
+ end
351
379
  end
352
380
  end
353
381
 
@@ -365,9 +393,11 @@ class TestOcra < Test::Unit::TestCase
365
393
  with_fixture 'environment' do
366
394
  with_env "RUBYOPT" => "-rtime" do
367
395
  assert system("ruby", ocra, "environment.rb", *DefaultArgs)
368
- assert system("environment.exe")
369
- env = Marshal.load(File.open("environment", "rb") { |f| f.read })
370
- assert_equal "-rtime", env['RUBYOPT']
396
+ pristine_env "environment.exe" do
397
+ assert system("environment.exe")
398
+ env = Marshal.load(File.open("environment", "rb") { |f| f.read })
399
+ assert_equal "-rtime", env['RUBYOPT']
400
+ end
371
401
  end
372
402
  end
373
403
  end
@@ -375,25 +405,29 @@ class TestOcra < Test::Unit::TestCase
375
405
  def test_exit
376
406
  with_fixture 'exit' do
377
407
  assert system("ruby", ocra, "exit.rb", *DefaultArgs)
378
- assert File.exist?("exit.exe")
379
- assert system("exit.exe")
408
+ pristine_env "exit.exe" do
409
+ assert File.exist?("exit.exe")
410
+ assert system("exit.exe")
411
+ end
380
412
  end
381
413
  end
382
414
 
383
415
  def test_ocra_executable_env
384
416
  with_fixture 'environment' do
385
417
  assert system("ruby", ocra, "environment.rb", *DefaultArgs)
386
- assert system("environment.exe")
387
- env = Marshal.load(File.open("environment", "rb") { |f| f.read })
388
- expected_path = File.expand_path("environment.exe").tr('/','\\')
389
- assert_equal expected_path, env['OCRA_EXECUTABLE']
418
+ pristine_env "environment.exe" do
419
+ assert system("environment.exe")
420
+ env = Marshal.load(File.open("environment", "rb") { |f| f.read })
421
+ expected_path = File.expand_path("environment.exe").tr('/','\\')
422
+ assert_equal expected_path, env['OCRA_EXECUTABLE']
423
+ end
390
424
  end
391
425
  end
392
426
 
393
427
  def test_hierarchy
394
428
  with_fixture 'hierarchy' do
395
429
  assert system("ruby", ocra, "hierarchy.rb", "assets/**/*", *DefaultArgs)
396
- with_exe "hierarchy.exe" do
430
+ pristine_env "hierarchy.exe" do
397
431
  assert system("hierarchy.exe")
398
432
  end
399
433
  end
@@ -404,7 +438,7 @@ class TestOcra < Test::Unit::TestCase
404
438
  assert system("ruby", ocra, "helloworld.rb", *DefaultArgs)
405
439
  tempdir = File.expand_path("temporary directory")
406
440
  mkdir_p tempdir
407
- with_exe "helloworld.exe" do
441
+ pristine_env "helloworld.exe" do
408
442
  with_env "TMP" => tempdir.tr('/','\\') do
409
443
  assert system("helloworld.exe")
410
444
  end
@@ -412,11 +446,18 @@ class TestOcra < Test::Unit::TestCase
412
446
  end
413
447
  end
414
448
 
449
+ # Should be able to build executable when specifying absolute path
450
+ # to the script from somewhere else.
415
451
  def test_abspath
416
452
  with_fixture "helloworld" do
417
- assert system("ruby", ocra, File.expand_path("helloworld.rb"), *DefaultArgs)
418
- assert File.exist?("helloworld.exe")
419
- assert system("helloworld.exe")
453
+ script_path = File.expand_path("helloworld.rb")
454
+ with_tmpdir do
455
+ assert system("ruby", ocra, script_path, *DefaultArgs)
456
+ assert File.exist?("helloworld.exe")
457
+ pristine_env "helloworld.exe" do
458
+ assert system("helloworld.exe")
459
+ end
460
+ end
420
461
  end
421
462
  end
422
463
 
@@ -426,7 +467,9 @@ class TestOcra < Test::Unit::TestCase
426
467
  cd "build" do
427
468
  assert system("ruby", ocra, File.expand_path("../helloworld.rb"), *DefaultArgs)
428
469
  assert File.exist?("helloworld.exe")
429
- assert system("helloworld.exe")
470
+ pristine_env "helloworld.exe" do
471
+ assert system("helloworld.exe")
472
+ end
430
473
  end
431
474
  end
432
475
  end
@@ -435,7 +478,9 @@ class TestOcra < Test::Unit::TestCase
435
478
  with_fixture "helloworld" do
436
479
  assert system("ruby", ocra, "./helloworld.rb", *DefaultArgs)
437
480
  assert File.exist?("helloworld.exe")
438
- assert system("helloworld.exe")
481
+ pristine_env "helloworld.exe" do
482
+ assert system("helloworld.exe")
483
+ end
439
484
  end
440
485
  end
441
486
 
@@ -445,10 +490,39 @@ class TestOcra < Test::Unit::TestCase
445
490
  cd "build" do
446
491
  assert system("ruby", ocra, "../helloworld.rb", *DefaultArgs)
447
492
  assert File.exist?("helloworld.exe")
448
- assert system("helloworld.exe")
493
+ pristine_env "helloworld.exe" do
494
+ assert system("helloworld.exe")
495
+ end
449
496
  end
450
497
  end
451
498
  end
452
499
 
500
+ # Should accept hierachical source code layout
501
+ def test_srcroot
502
+ with_fixture "srcroot" do
503
+ assert system("ruby", ocra, "bin/srcroot.rb", "share/data.txt", *DefaultArgs)
504
+ assert File.exist?("srcroot.exe")
505
+ pristine_env "srcroot.exe" do
506
+ exe = File.expand_path("srcroot.exe")
507
+ cd ENV["SystemRoot"] do
508
+ assert system(exe)
509
+ end
510
+ end
511
+ end
512
+ end
513
+
514
+ # Should be able to build executables when script changes directory.
515
+ def test_chdir
516
+ with_fixture "chdir" do
517
+ assert system("ruby", ocra, "chdir.rb", *DefaultArgs)
518
+ assert File.exist?("chdir.exe")
519
+ pristine_env "chdir.exe" do
520
+ exe = File.expand_path("chdir.exe")
521
+ cd ENV["SystemRoot"] do
522
+ assert system(exe)
523
+ end
524
+ end
525
+ end
526
+ end
453
527
 
454
528
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ocra
3
3
  version: !ruby/object:Gem::Version
4
- hash: 270495469
4
+ hash: -671420158
5
5
  prerelease: true
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
9
  - 5
10
- - pre2
11
- version: 1.1.5.pre2
10
+ - pre3
11
+ version: 1.1.5.pre3
12
12
  platform: ruby
13
13
  authors:
14
14
  - Lars Christensen
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-08-17 00:00:00 +02:00
19
+ date: 2010-08-20 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency