ocran 1.3.13 → 1.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7de27881bd34052b90faa5618a30c4da84182ff53a5edc1adfc32db052e2aa1
4
- data.tar.gz: 16f25058a7a72073ade7050625a66bc2d41044db1cb704ad540210dcce1791b0
3
+ metadata.gz: a782f6a9d0c148e6270aa19573c86e5f6518e9511bcfda3aec59de84a1291e41
4
+ data.tar.gz: 4eff772bc2997a4a99d08ea925c9e9d2eb0e8a1da48c687588dbf7c46d3d3453
5
5
  SHA512:
6
- metadata.gz: 1b389b0744a54767cb7ba5187bfa3ce645dc2c71ce25adb6ce85bec94a7afa01f01ed4e055dec6df68818f7718d0418bd4b1bca5a151343bb624ab8126488744
7
- data.tar.gz: 35a2a1197eabcc3a28483101583729c8e905982153c028576a09a605a2e195b8b01949d2e90988e31cd0077a3fc96e469fb121a8e1d1744e8b28e597a3edf5b4
6
+ metadata.gz: 3f94bc970689b64b199584baa2ee27f5f371ba6220b3fd736ef24314ab49644eb21932ba2e9397add861bfc609da6b5e4d0be5e45a6804a8bcf64057a1c51978
7
+ data.tar.gz: b881a6a9f0832490a5875360531e367b0f6efb008b2c8f94c54815fb63885f5350a19c40800f13da70fe714607ee774fd2a4e598373318d2b15a2b4b6fb9fc75
data/bin/ocran CHANGED
@@ -15,6 +15,16 @@ module Ocran
15
15
  a.downcase == b.downcase
16
16
  end
17
17
 
18
+ def Pathname.glob(pattern, flags = 0)
19
+ if block_given?
20
+ Dir.glob(pattern, flags) { |s| yield Pathname.new(s) }
21
+ else
22
+ ary = Dir.glob(pattern, flags)
23
+ ary.map! { |s| Pathname.new(s) }
24
+ ary
25
+ end
26
+ end
27
+
18
28
  attr_reader :path
19
29
  if File::ALT_SEPARATOR.nil?
20
30
  File::ALT_SEPARATOR = "\\"
@@ -23,7 +33,7 @@ module Ocran
23
33
  ABSOLUTE_PAT = /\A([A-Z]:)?#{SEPARATOR_PAT}/i
24
34
 
25
35
  def initialize(path)
26
- @path = path && path.encode("UTF-8")
36
+ @path = path.encode("UTF-8")
27
37
  end
28
38
 
29
39
  def to_native
@@ -39,20 +49,20 @@ module Ocran
39
49
  # be reached from 'src'.
40
50
  def relative_path_from(other)
41
51
  a = @path.split(SEPARATOR_PAT)
42
- b = other.path.split(SEPARATOR_PAT)
52
+ b = other.to_s.split(SEPARATOR_PAT)
43
53
  while a.first && b.first && Pathname.pathequal(a.first, b.first)
44
54
  a.shift
45
55
  b.shift
46
56
  end
47
- return other if Pathname.new(b.first).absolute?
57
+ return other if b.first && Pathname.new(b.first).absolute?
48
58
  b.size.times { a.unshift ".." }
49
- return Pathname.new(a.join("/"))
59
+ Pathname.new(File.join(*a))
50
60
  end
51
61
 
52
62
  # Determines if 'src' is contained in 'tgt' (i.e. it is a subpath of
53
63
  # 'tgt'). Both must be absolute paths and not contain '..'
54
64
  def subpath?(other)
55
- other = Ocran.Pathname(other)
65
+ other = Pathname.new(other)
56
66
  src_normalized = to_posix.downcase
57
67
  tgt_normalized = other.to_posix.downcase
58
68
  src_normalized =~ /^#{Regexp.escape tgt_normalized}#{SEPARATOR_PAT}/i
@@ -62,37 +72,49 @@ module Ocran
62
72
  # is an absolute path. Otherwise, returns the full path of the
63
73
  # left + right.
64
74
  def /(other)
65
- other = Ocran.Pathname(other)
75
+ other = Pathname.new(other)
66
76
  if other.absolute?
67
77
  other
68
78
  else
69
- Ocran.Pathname(@path + "/" + other.path)
79
+ Pathname.new(File.join(@path, other.to_s))
70
80
  end
71
81
  end
72
82
 
73
83
  def append_to_filename!(s)
74
- @path.sub!(/(\.[^.]*?|)$/) { s.to_s + $1 }
84
+ @path = sub(/(\.[^.]*?|)$/) { s.to_s + $1 }
85
+ end
86
+
87
+ def sub(*a, &b)
88
+ Pathname.new(@path.sub(*a, &b))
89
+ end
90
+
91
+ def sub_ext(new_ext)
92
+ sub(/(\.[^.]*?)?$/, new_ext)
93
+ end
94
+
95
+ def extname
96
+ File.extname(@path)
75
97
  end
76
98
 
77
99
  def ext(new_ext = nil)
78
100
  if new_ext
79
- Pathname.new(@path.sub(/(\.[^.]*?)?$/) { new_ext })
101
+ sub_ext(new_ext)
80
102
  else
81
- File.extname(@path)
103
+ extname
82
104
  end
83
105
  end
84
106
 
85
107
  def ext?(expected_ext)
86
- Pathname.pathequal(ext, expected_ext)
108
+ Pathname.pathequal(extname, expected_ext)
87
109
  end
88
110
 
89
111
  def entries
90
- Dir.entries(@path).map { |e| self / e.encode("UTF-8") }
112
+ Dir.entries(@path, encoding: "UTF-8").map { |e| self / e }
91
113
  end
92
114
 
93
115
  # Recursively find all files which match a specified regular
94
116
  # expression.
95
- def find_all_files(re)
117
+ def find_all_files(re = //)
96
118
  entries.map do |pn|
97
119
  if pn.directory?
98
120
  if pn.basename =~ /^\.\.?$/
@@ -111,18 +133,35 @@ module Ocran
111
133
  end
112
134
 
113
135
  def ==(other); to_posix.downcase == other.to_posix.downcase; end
136
+ alias === ==
137
+ alias eql? ==
114
138
  def =~(o); @path =~ o; end
115
- def <=>(other); @path.casecmp(other.path); end
139
+ def <=>(other); @path.casecmp(other.to_s); end
116
140
  def exist?; File.exist?(@path); end
117
141
  def file?; File.file?(@path); end
118
142
  def directory?; File.directory?(@path); end
119
143
  def absolute?; @path =~ ABSOLUTE_PAT; end
120
144
  def dirname; Pathname.new(File.dirname(@path)); end
121
145
  def basename; Pathname.new(File.basename(@path)); end
122
- def expand(dir = nil); Pathname.new(File.expand_path(@path, dir && Ocran.Pathname(dir))); end
146
+
147
+ def expand_path(dir = ".")
148
+ Pathname.new(File.expand_path(@path, dir))
149
+ end
150
+
151
+ def expand(dir = nil); dir ? expand_path(dir) : expand_path; end
123
152
  def size; File.size(@path); end
124
153
  def encode(e); to_posix.encode(e); end # called when creating an installer with innosetup
125
154
 
155
+ def binread(*args)
156
+ File.binread(@path, *args)
157
+ end
158
+
159
+ def parent
160
+ Pathname.new(File.basename(File.dirname(@path)))
161
+ end
162
+
163
+ alias to_path to_posix
164
+
126
165
  alias to_s to_posix
127
166
  alias to_str to_posix
128
167
  end
@@ -187,7 +226,7 @@ module Ocran
187
226
  a.sort.inject([]) { |r, e| r.last == e ? r : r << e }
188
227
  end
189
228
 
190
- VERSION = "1.3.12"
229
+ VERSION = "1.3.15"
191
230
 
192
231
  IGNORE_MODULE_NAMES = /\/(enumerator.so|rational.so|complex.so|fiber.so|thread.rb|ruby2_keywords.rb)$/
193
232
 
@@ -202,7 +241,7 @@ module Ocran
202
241
  # Directories anywhere
203
242
  (^|\/)(\.autotest|\.svn|\.cvs|\.git)(\/|$) |
204
243
  # Unlikely extensions
205
- \.(rdoc|c|cpp|c\+\+|cxx|h|hxx|hpp|obj|o|a)$/
244
+ \.(rdoc|c|cpp|c\+\+|cxx|h|hxx|hpp|obj|o|a)$
206
245
  )}xi
207
246
 
208
247
  GEM_NON_FILE_RE = /(#{GEM_EXTRA_RE}|#{GEM_SCRIPT_RE})/
@@ -230,6 +269,7 @@ module Ocran
230
269
  :force_windows => false,
231
270
  :force_console => false,
232
271
  :icon_filename => nil,
272
+ :rubyopt => nil,
233
273
  :gemfile => nil,
234
274
  :inno_script => nil,
235
275
  :quiet => false,
@@ -269,40 +309,23 @@ module Ocran
269
309
  exit 1
270
310
  end
271
311
 
272
- # Returns a binary blob store embedded in the current Ruby script.
273
- def Ocran.get_next_embedded_image
274
- DATA.read(DATA.readline.to_i).unpack("m")[0]
275
- end
276
-
277
312
  def Ocran.save_environment
278
313
  @load_path_before = $LOAD_PATH.dup
279
314
  @pwd_before = Dir.pwd
280
- @env_before = {}; ENV.each { |key, value| @env_before[key] = value }
315
+ @env_before = ENV.to_hash
281
316
  end
282
317
 
283
318
  def Ocran.restore_environment
284
- @env_before.each { |key, value| ENV[key] = value }
285
- ENV.each_key { |key| ENV.delete(key) unless @env_before.has_key?(key) }
319
+ ENV.clear.update(@env_before)
286
320
  Dir.chdir @pwd_before
287
321
  end
288
322
 
289
323
  def Ocran.find_stubs
290
- if defined?(DATA)
291
- @stubimage = get_next_embedded_image
292
- @stubwimage = get_next_embedded_image
293
- lzmaimage = get_next_embedded_image
294
- @lzmapath = Host.tempdir / "lzma.exe"
295
- File.open(@lzmapath, "wb") { |file| file << lzmaimage }
296
- ediconimage = get_next_embedded_image
297
- @ediconpath = Host.tempdir / "edicon.exe"
298
- File.open(@ediconpath, "wb") { |file| file << ediconimage }
299
- else
300
- ocranpath = Pathname(File.dirname(__FILE__))
301
- @stubimage = File.open(ocranpath / "../share/ocran/stub.exe", "rb") { |file| file.read }
302
- @stubwimage = File.open(ocranpath / "../share/ocran/stubw.exe", "rb") { |file| file.read }
303
- @lzmapath = (ocranpath / "../share/ocran/lzma.exe").expand
304
- @ediconpath = (ocranpath / "../share/ocran/edicon.exe").expand
305
- end
324
+ ocranpath = Pathname(File.dirname(__FILE__))
325
+ @stubimage = (ocranpath / "../share/ocran/stub.exe").binread
326
+ @stubwimage = (ocranpath / "../share/ocran/stubw.exe").binread
327
+ @lzmapath = (ocranpath / "../share/ocran/lzma.exe").expand_path
328
+ @ediconpath = (ocranpath / "../share/ocran/edicon.exe").expand_path
306
329
  end
307
330
 
308
331
  def Ocran.parseargs(argv)
@@ -362,6 +385,7 @@ Executable options:
362
385
  --console Force console application (ruby.exe)
363
386
  --chdir-first When exe starts, change working directory to app dir.
364
387
  --icon <ico> Replace icon with a custom one.
388
+ --rubyopt <str> Set the RUBYOPT environment variable when running the executable
365
389
  --debug Executable will be verbose.
366
390
  --debug-extract Executable will unpack to local dir and not delete after.
367
391
  EOF
@@ -375,9 +399,11 @@ EOF
375
399
  when /\A--add-all-core\z/
376
400
  @options[:add_all_core] = true
377
401
  when /\A--output\z/
378
- @options[:output_override] = Pathname(argv.shift)
402
+ path = argv.shift
403
+ @options[:output_override] = Pathname.new(path) if path
379
404
  when /\A--dll\z/
380
- @options[:extra_dlls] << argv.shift
405
+ path = argv.shift
406
+ @options[:extra_dlls] << path if path
381
407
  when /\A--quiet\z/
382
408
  @options[:quiet] = true
383
409
  when /\A--verbose\z/
@@ -391,14 +417,19 @@ EOF
391
417
  when /\A--chdir-first\z/
392
418
  @options[:chdir_first] = true
393
419
  when /\A--icon\z/
394
- @options[:icon_filename] = Pathname(argv.shift)
395
- Ocran.fatal_error "Icon file #{icon_filename} not found.\n" unless icon_filename.exist?
420
+ path = argv.shift
421
+ Ocran.fatal_error "Icon file #{path} not found.\n" unless path && File.exist?(path)
422
+ @options[:icon_filename] = Pathname.new(path)
423
+ when /\A--rubyopt\z/
424
+ @options[:rubyopt] = argv.shift
396
425
  when /\A--gemfile\z/
397
- @options[:gemfile] = Pathname(argv.shift)
398
- Ocran.fatal_error "Gemfile #{gemfile} not found.\n" unless gemfile.exist?
426
+ path = argv.shift
427
+ Ocran.fatal_error "Gemfile #{path} not found.\n" unless path && File.exist?(path)
428
+ @options[:gemfile] = Pathname.new(path)
399
429
  when /\A--innosetup\z/
400
- @options[:inno_script] = Pathname(argv.shift)
401
- Ocran.fatal_error "Inno Script #{inno_script} not found.\n" unless inno_script.exist?
430
+ path = argv.shift
431
+ Ocran.fatal_error "Inno Script #{path} not found.\n" unless path && File.exist?(path)
432
+ @options[:inno_script] = Pathname.new(path)
402
433
  when /\A--no-autodll\z/
403
434
  @options[:autodll] = false
404
435
  when /\A--version\z/
@@ -417,17 +448,18 @@ EOF
417
448
  @options[:enc] = !$1
418
449
  when /\A--(no-)?gem-(\w+)(?:=(.*))?$/
419
450
  negate, group, list = $1, $2, $3
420
- @options[:gem] ||= []
421
- @options[:gem] << [negate, group.to_sym, list && list.split(",")]
451
+ @options[:gem] << [negate, group.to_sym, list&.split(",")] if group
422
452
  when /\A--help\z/, /\A--./
423
453
  puts usage
424
454
  exit 0
425
455
  else
426
- if __FILE__.respond_to?(:encoding)
427
- @options[:files] << arg.dup.force_encoding(__FILE__.encoding)
428
- else
429
- @options[:files] << arg
456
+ path = arg.dup
457
+
458
+ if !File.exist?(path) || Dir.empty?(path)
459
+ Ocran.fatal_error "#{path} not found!"
430
460
  end
461
+
462
+ @options[:files] << path
431
463
  end
432
464
  end
433
465
 
@@ -449,14 +481,12 @@ EOF
449
481
  end
450
482
 
451
483
  @options[:files].map! { |path|
452
- path = path.encode("UTF-8").tr('\\', "/")
484
+ path = path.encode("UTF-8").tr("\\", "/")
453
485
  if File.directory?(path)
454
486
  # If a directory is passed, we want all files under that directory
455
487
  path = "#{path}/**/*"
456
488
  end
457
- files = Dir[path]
458
- Ocran.fatal_error "#{path} not found!" if files.empty?
459
- files.map { |path| Pathname(path).expand }
489
+ Pathname.glob(path).map!(&:expand_path)
460
490
  }.flatten!
461
491
  end
462
492
 
@@ -482,8 +512,6 @@ EOF
482
512
  modules_to_check.each do |mod|
483
513
  modules_checked[mod] = true
484
514
  mod.constants.each do |const|
485
- # Module::Config causes warning on Ruby 1.9.3 - prevent autoloading
486
- next if Module === mod && const == :Config
487
515
  if mod.autoload?(const)
488
516
  Ocran.msg "Attempting to trigger autoload of #{mod}::#{const}"
489
517
  begin
@@ -505,26 +533,26 @@ EOF
505
533
  def Ocran.find_load_path(loadpaths, feature)
506
534
  if feature.absolute?
507
535
  # Choose those loadpaths which contain the feature
508
- candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.expand) }
536
+ candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.expand_path) }
509
537
  # Guess the require'd feature
510
- feature_pairs = candidate_loadpaths.map { |loadpath| [loadpath, feature.relative_path_from(loadpath.expand)] }
538
+ feature_pairs = candidate_loadpaths.map { |loadpath| [loadpath, feature.relative_path_from(loadpath.expand_path)] }
511
539
  # Select the shortest possible require-path (longest load-path)
512
540
  if feature_pairs.empty?
513
541
  nil
514
542
  else
515
- feature_pairs.sort_by { |loadpath, feature| feature.path.size }.first[0]
543
+ feature_pairs.sort_by { |loadpath, feature| feature.to_s.size }.first[0]
516
544
  end
517
545
  else
518
546
  # Select the loadpaths that contain 'feature' and select the shortest
519
- candidates = loadpaths.select { |loadpath| feature.expand(loadpath).exist? }
520
- candidates.sort_by { |loadpath| loadpath.path.size }.last
547
+ candidates = loadpaths.select { |loadpath| feature.expand_path(loadpath).exist? }
548
+ candidates.sort_by { |loadpath| loadpath.to_s.size }.last
521
549
  end
522
550
  end
523
551
 
524
552
  # Find the root of all files specified on the command line and use
525
553
  # it as the "src" of the output.
526
554
  def Ocran.find_src_root(files)
527
- src_files = files.map { |file| file.expand }
555
+ src_files = files.map { |file| file.expand_path }
528
556
  src_prefix = src_files.inject(src_files.first.dirname) do |srcroot, path|
529
557
  if path.subpath?(Host.exec_prefix)
530
558
  srcroot
@@ -575,18 +603,19 @@ EOF
575
603
  end
576
604
  end
577
605
 
578
- ENV["BUNDLE_GEMFILE"] = Ocran.gemfile
606
+ ENV["BUNDLE_GEMFILE"] = Ocran.gemfile.to_s
579
607
  Bundler.load.specs.each do |spec|
580
608
  Ocran.verbose_msg "From Gemfile, adding gem #{spec.full_name}"
581
609
  gems[spec.name] ||= spec
582
610
  end
583
611
 
612
+ # This code is implemented for compatibility with older Bundler versions (< v1.16.0.pre.1).
584
613
  unless gems.any? { |name, spec| name == "bundler" }
585
614
  # Bundler itself wasn't added for some reason, let's put it in directly
586
615
  Ocran.verbose_msg "From Gemfile, forcing inclusion of bundler gem itself"
587
616
  bundler_spec = Gem.loaded_specs["bundler"]
588
617
  bundler_spec or Ocran.fatal_error "Unable to locate bundler gem"
589
- gems["bundler"] ||= spec
618
+ gems["bundler"] ||= bundler_spec
590
619
  end
591
620
  end
592
621
 
@@ -606,12 +635,12 @@ EOF
606
635
  features_from_gems << feature
607
636
  next
608
637
  end
609
- gempaths = Pathname(Gem.path)
638
+ gempaths = Gem.path
610
639
  gempaths.each do |gempath|
611
640
  geminstallpath = Pathname(gempath) / "gems"
612
641
  if feature.subpath?(geminstallpath)
613
642
  gemlocalpath = feature.relative_path_from(geminstallpath)
614
- fullgemname = gemlocalpath.path.split("/").first
643
+ fullgemname = gemlocalpath.to_s.split("/").first
615
644
  gemspecpath = gempath / "specifications" / "#{fullgemname}.gemspec"
616
645
  if spec = Gem::Specification.load(gemspecpath)
617
646
  gems[spec.name] ||= spec
@@ -678,9 +707,9 @@ EOF
678
707
  Ocran.msg "Detected gem #{spec.full_name} (#{include.join(", ")})"
679
708
 
680
709
  gem_root = Pathname(spec.gem_dir)
681
- gem_extension = (gem_root / ".." / ".." / "extensions").expand
710
+ gem_extension = (gem_root / ".." / ".." / "extensions").expand_path
682
711
  if gem_extension.exist?
683
- build_complete = gem_extension.find_all_files(/gem.build_complete/).select { |p| p.dirname.basename.to_s == spec.full_name }
712
+ build_complete = gem_extension.find_all_files(/gem.build_complete/).select { |p| p.parent.to_s == spec.full_name }
684
713
  else
685
714
  build_complete = nil
686
715
  end
@@ -700,14 +729,14 @@ EOF
700
729
  when :loaded
701
730
  files << features_from_gems.select { |feature| feature.subpath?(gem_root) }
702
731
  when :files
703
- gem_root_files ||= gem_root.find_all_files(//)
732
+ gem_root_files ||= gem_root.find_all_files
704
733
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) !~ GEM_NON_FILE_RE }
705
734
  files << build_complete if build_complete
706
735
  when :extras
707
- gem_root_files ||= gem_root.find_all_files(//)
736
+ gem_root_files ||= gem_root.find_all_files
708
737
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_EXTRA_RE }
709
738
  when :scripts
710
- gem_root_files ||= gem_root.find_all_files(//)
739
+ gem_root_files ||= gem_root.find_all_files
711
740
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_SCRIPT_RE }
712
741
  end
713
742
  end
@@ -719,7 +748,7 @@ EOF
719
748
  Ocran.warn "#{missing_file} was not found"
720
749
  end
721
750
 
722
- total_size = actual_files.inject(0) { |size, path| size + path.size }
751
+ total_size = actual_files.sum(0, &:size)
723
752
  Ocran.msg "\t#{actual_files.size} files, #{total_size} bytes"
724
753
 
725
754
  gem_files += actual_files
@@ -733,9 +762,9 @@ EOF
733
762
  end
734
763
 
735
764
  def Ocran.build_exe
736
- all_load_paths = $LOAD_PATH.map { |loadpath| Pathname(loadpath).expand }
737
- @added_load_paths = ($LOAD_PATH - @load_path_before).map { |loadpath| Pathname(loadpath).expand }
738
- working_directory = Pathname.pwd.expand
765
+ all_load_paths = $LOAD_PATH.map { |loadpath| Pathname(loadpath).expand_path }
766
+ @added_load_paths = ($LOAD_PATH - @load_path_before).map { |loadpath| Pathname(loadpath).expand_path }
767
+ working_directory = Pathname.pwd
739
768
 
740
769
  restore_environment
741
770
 
@@ -780,7 +809,7 @@ EOF
780
809
  encpath = path / "enc"
781
810
  if encpath.exist?
782
811
  encfiles = encpath.find_all_files(/\.so$/)
783
- size = encfiles.inject(0) { |sum, pn| sum + pn.size }
812
+ size = encfiles.sum(0, &:size)
784
813
  Ocran.msg "Including #{encfiles.size} encoding support files (#{size} bytes, use --no-enc to exclude)"
785
814
  features.push(*encfiles)
786
815
  end
@@ -795,13 +824,13 @@ EOF
795
824
  libs = []
796
825
  features.each do |feature|
797
826
  path = find_load_path(all_load_paths, feature)
798
- if path.nil? || path.expand == Pathname.pwd
827
+ if path.nil? || path.expand_path == Pathname.pwd
799
828
  Ocran.files << feature
800
829
  else
801
830
  if feature.absolute?
802
- feature = feature.relative_path_from(path.expand)
831
+ feature = feature.relative_path_from(path.expand_path)
803
832
  end
804
- fullpath = feature.expand(path)
833
+ fullpath = feature.expand_path(path)
805
834
 
806
835
  if fullpath.subpath?(Host.exec_prefix)
807
836
  # Features found in the Ruby installation are put in the
@@ -864,11 +893,10 @@ EOF
864
893
  next unless path.to_posix =~
865
894
  /\/(ruby\/(?:site_ruby\/|vendor_ruby\/)?[0-9.]+)\/?$/i
866
895
  subdir = $1
867
- Dir["#{lp}/**/*"].each do |f|
868
- fpath = Pathname.new(f)
896
+ Pathname.glob("#{lp}/**/*").each do |fpath|
869
897
  next if fpath.directory?
870
898
  tgt = "lib/#{subdir}/#{fpath.relative_path_from(path).to_posix}"
871
- libs << [f, tgt]
899
+ libs << [fpath, tgt]
872
900
  end
873
901
  end
874
902
  end
@@ -877,13 +905,19 @@ EOF
877
905
  dlls = Ocran.autodll ? LibraryDetector.detect_dlls : []
878
906
 
879
907
  # Detect external manifests
880
- manifests = Host.exec_prefix.find_all_files(/\.manifest$/)
908
+ # For RubyInstaller environments supporting Ruby 2.4 and above,
909
+ # a manifest file is required.
910
+ if (manifest = Host.exec_prefix / "bin/ruby_builtin_dlls/ruby_builtin_dlls.manifest").exist?
911
+ manifests = [manifest]
912
+ else
913
+ manifests = []
914
+ end
881
915
 
882
916
  executable = nil
883
917
  if Ocran.output_override
884
918
  executable = Ocran.output_override
885
919
  else
886
- executable = Ocran.files.first.basename.ext(".exe")
920
+ executable = Ocran.files.first.basename.sub_ext(".exe")
887
921
  executable.append_to_filename!("-debug") if Ocran.debug
888
922
  end
889
923
 
@@ -959,8 +993,8 @@ EOF
959
993
  if gemspec.subpath?(Host.exec_prefix)
960
994
  path = gemspec.relative_path_from(Host.exec_prefix)
961
995
  sb.createfile(gemspec, path)
962
- elsif defined?(Gem) and gemhome = Pathname(Gem.path.find { |pth| gemspec.subpath?(pth) })
963
- path = GEMHOMEDIR / gemspec.relative_path_from(gemhome)
996
+ elsif defined?(Gem) and gemhome = Gem.path.find { |pth| gemspec.subpath?(pth) }
997
+ path = GEMHOMEDIR / gemspec.relative_path_from(Pathname(gemhome))
964
998
  sb.createfile(gemspec, path)
965
999
  else
966
1000
  Ocran.fatal_error "Gem spec #{gemspec} does not exist in the Ruby installation. Don't know where to put it."
@@ -975,11 +1009,12 @@ EOF
975
1009
 
976
1010
  # Workaround: RubyInstaller cannot find the msys folder if ../msys64/usr/bin/msys-2.0.dll is not present (since RubyInstaller-2.4.1 rubyinstaller 2 issue 23)
977
1011
  # Add an empty file to /msys64/usr/bin/msys-2.0.dll if the dll was not required otherwise
978
- require 'tempfile'
979
- sb.createfile((Tempfile.new("msys-2.0.dll")).path.to_s, 'msys64/usr/bin/msys-2.0.dll') unless sb.files.keys.any? { |entry| entry.to_s.include?("msys-2.0.dll") }
1012
+ unless sb.files.keys.any? { |entry| entry.to_s.include?("msys-2.0.dll") }
1013
+ sb.createfile(Pathname(File.dirname(__FILE__)) / "../share/ocran/empty-msys-2.0.dll".to_s, 'msys64/usr/bin/msys-2.0.dll')
1014
+ end
980
1015
 
981
1016
  # Set environment variable
982
- sb.setenv("RUBYOPT", ENV["RUBYOPT"] || "")
1017
+ sb.setenv("RUBYOPT", Ocran.rubyopt || ENV["RUBYOPT"] || "")
983
1018
  sb.setenv("RUBYLIB", load_path.map { |path| path.to_native }.uniq.join(";"))
984
1019
 
985
1020
  sb.setenv("GEM_PATH", (TEMPDIR_ROOT / GEMHOMEDIR).to_native)
@@ -998,71 +1033,64 @@ EOF
998
1033
  end
999
1034
 
1000
1035
  module LibraryDetector
1036
+ # Windows API functions for handling files may return long paths,
1037
+ # with a maximum character limit of 32,767.
1038
+ # "\\?\" prefix(4 characters) + long path(32762 characters) + NULL = 32767 characters
1039
+ # https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
1040
+ MAX_PATH = 32767
1041
+
1042
+ # The byte size of the buffer given as an argument to the EnumProcessModules function.
1043
+ # This buffer is used to store the handles of the loaded modules.
1044
+ # If the buffer size is smaller than the number of loaded modules,
1045
+ # it will automatically increase the buffer size and call the EnumProcessModules function again.
1046
+ # Increasing the initial buffer size can reduce the number of iterations required.
1047
+ # https://learn.microsoft.com/en-us/windows/win32/psapi/enumerating-all-modules-for-a-process
1048
+ DEFAULT_HMODULE_BUFFER_SIZE = 1024
1049
+
1001
1050
  def LibraryDetector.init_fiddle
1002
- require "fiddle"
1051
+ require "fiddle/import"
1003
1052
  require "fiddle/types"
1004
- module_eval {
1005
- extend Fiddle::Importer
1006
- dlload "psapi.dll"
1007
- include Fiddle::Win32Types
1008
- extern "BOOL EnumProcessModules(HANDLE, HMODULE*, DWORD, DWORD*)"
1009
- extend Fiddle::Importer
1010
- dlload "kernel32.dll"
1011
- include Fiddle::Win32Types
1012
-
1013
- # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
1014
- # typedef PVOID HANDLE
1015
- # typedef HINSTANCE HMODULE;
1016
-
1017
- typealias "HMODULE", "voidp"
1018
- typealias "HANDLE", "voidp"
1019
- typealias "LPWSTR", "char*"
1020
-
1021
- extern "DWORD GetModuleFileNameW(HMODULE, LPWSTR, DWORD)"
1022
- extern "HANDLE GetCurrentProcess(void)"
1023
- extern "DWORD GetLastError(void)"
1024
- }
1025
- end
1026
1053
 
1027
- def LibraryDetector.loaded_dlls
1028
- require "fiddle"
1029
- psapi = Fiddle.dlopen("psapi")
1030
- enumprocessmodules = Fiddle::Function.new(psapi["EnumProcessModules"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG)
1031
- kernel32 = Fiddle.dlopen("kernel32")
1032
- getcurrentprocess = Fiddle::Function.new(kernel32["GetCurrentProcess"], [], Fiddle::TYPE_LONG)
1033
- getmodulefilename = Fiddle::Function.new(kernel32["GetModuleFileNameW"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG], Fiddle::TYPE_LONG)
1034
- getlasterror = Fiddle::Function.new(kernel32["GetLastError"], [], Fiddle::TYPE_LONG)
1035
-
1036
- # Different packing/unpacking for 64/32 bits systems
1037
- if Fiddle::SIZEOF_VOIDP == 8 then
1038
- f_single = "Q"
1039
- f_array = "Q*"
1040
- else
1041
- f_single = "I"
1042
- f_array = "I*"
1043
- end
1054
+ extend Fiddle::Importer
1055
+ dlload "kernel32.dll", "psapi.dll"
1044
1056
 
1045
- bytes_needed = Fiddle::SIZEOF_VOIDP * 32
1046
- module_handle_buffer = nil
1047
- process_handle = getcurrentprocess.call()
1048
- loop do
1049
- module_handle_buffer = "\x00" * bytes_needed
1050
- bytes_needed_buffer = [0].pack(f_single)
1051
- r = enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
1052
- bytes_needed = bytes_needed_buffer.unpack(f_single)[0]
1053
- break if bytes_needed <= module_handle_buffer.size
1054
- end
1057
+ include Fiddle::Win32Types
1058
+ # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
1059
+ typealias "HINSTANCE", "HANDLE" # for Ruby2.6 only
1060
+ typealias "HMODULE", "HINSTANCE"
1061
+ typealias "LPDWORD", "PDWORD"
1062
+ typealias "LPWSTR", "char*"
1063
+
1064
+ extern "BOOL EnumProcessModules(HANDLE, HMODULE*, DWORD, LPDWORD)"
1065
+ extern "DWORD GetModuleFileNameW(HMODULE, LPWSTR, DWORD)"
1066
+ extern "HANDLE GetCurrentProcess()"
1067
+ extern "DWORD GetLastError()"
1068
+ end
1055
1069
 
1056
- handles = module_handle_buffer.unpack(f_array)
1057
- handles.select { |handle| handle > 0 }.map do |handle|
1058
- str = "\x00\x00" * 256
1059
- modulefilename_length = getmodulefilename.call(handle, str, str.size)
1060
- unless modulefilename_length > 0
1061
- errorcode = getlasterror.call()
1062
- Ocran.fatal_error "LibraryDetector: GetModuleFileNameW failed with error code 0x" + errorcode.to_s(16)
1070
+ def LibraryDetector.loaded_dlls
1071
+ init_fiddle
1072
+
1073
+ dword = "L" # A DWORD is a 32-bit unsigned integer.
1074
+ bytes_needed = [0].pack(dword)
1075
+ bytes = DEFAULT_HMODULE_BUFFER_SIZE
1076
+ process_handle = GetCurrentProcess()
1077
+ handles = while true
1078
+ buffer = "\x00" * bytes
1079
+ if EnumProcessModules(process_handle, buffer, buffer.bytesize, bytes_needed) == 0
1080
+ Ocran.fatal_error "LibraryDetector: EnumProcessModules failed with error code %#010x" % GetLastError()
1081
+ end
1082
+ bytes = bytes_needed.unpack1(dword)
1083
+ if bytes <= buffer.bytesize
1084
+ break buffer.unpack("J#{bytes / Fiddle::SIZEOF_VOIDP}")
1085
+ end
1086
+ end
1087
+ str = "\x00".encode("UTF-16LE") * MAX_PATH
1088
+ handles.map do |handle|
1089
+ length = GetModuleFileNameW(handle, str, str.bytesize)
1090
+ if length == 0
1091
+ Ocran.fatal_error "LibraryDetector: GetModuleFileNameW failed with error code %#010x" % GetLastError()
1063
1092
  end
1064
- modulefilename = str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
1065
- Ocran.Pathname(modulefilename)
1093
+ Ocran.Pathname(str[0, length])
1066
1094
  end
1067
1095
  end
1068
1096
 
@@ -1108,7 +1136,7 @@ EOF
1108
1136
  end
1109
1137
 
1110
1138
  if Ocran.icon_filename
1111
- system Ocran.ediconpath, path, Ocran.icon_filename
1139
+ system Ocran.ediconpath.to_s, path.to_s, Ocran.icon_filename.to_s
1112
1140
  end
1113
1141
 
1114
1142
  opcode_offset = File.size(path)
@@ -1138,7 +1166,7 @@ EOF
1138
1166
  begin
1139
1167
  data_size = File.size(tmpinpath)
1140
1168
  Ocran.msg "Compressing #{data_size} bytes"
1141
- system(Ocran.lzmapath, "e", tmpinpath, tmpoutpath) or fail
1169
+ system(Ocran.lzmapath.to_s, "e", tmpinpath, tmpoutpath) or fail
1142
1170
  compressed_data_size = File.size?(tmpoutpath)
1143
1171
  ocranfile.write([OP_DECOMPRESS_LZMA, compressed_data_size].pack("VV"))
1144
1172
  IO.copy_stream(tmpoutpath, ocranfile)
@@ -1185,7 +1213,7 @@ EOF
1185
1213
  Ocran.msg "Running InnoSetup compiler ISCC"
1186
1214
  result = system(*iscc_cmd)
1187
1215
  if not result
1188
- case $?
1216
+ case $?.exitstatus
1189
1217
  when 0 then raise RuntimeError.new("ISCC reported success, but system reported error?")
1190
1218
  when 1 then raise RuntimeError.new("ISCC reports invalid command line parameters")
1191
1219
  when 2 then raise RuntimeError.new("ISCC reports that compilation failed")
@@ -1202,8 +1230,8 @@ EOF
1202
1230
  end
1203
1231
 
1204
1232
  def mkdir(path)
1205
- return if @paths[path.path.downcase]
1206
- @paths[path.path.downcase] = true
1233
+ return if @paths[path.to_s.downcase]
1234
+ @paths[path.to_posix.downcase] = true
1207
1235
  Ocran.verbose_msg "m #{showtempdir path}"
1208
1236
  unless Ocran.inno_script # The directory will be created by InnoSetup with a [Dirs] statement
1209
1237
  @of << [OP_CREATE_DIRECTORY, path.to_native].pack("VZ*")
@@ -1212,7 +1240,7 @@ EOF
1212
1240
 
1213
1241
  def ensuremkdir(tgt)
1214
1242
  tgt = Ocran.Pathname(tgt)
1215
- return if tgt.path == "."
1243
+ return if tgt.to_s == "."
1216
1244
  if not @paths[tgt.to_posix.downcase]
1217
1245
  ensuremkdir(tgt.dirname)
1218
1246
  mkdir(tgt)
@@ -1230,7 +1258,7 @@ EOF
1230
1258
  @files[tgt] = src
1231
1259
  src, tgt = Ocran.Pathname(src), Ocran.Pathname(tgt)
1232
1260
  ensuremkdir(tgt.dirname)
1233
- str = File.open(src, "rb") { |file| file.read }
1261
+ str = src.binread
1234
1262
  Ocran.verbose_msg "a #{showtempdir tgt}"
1235
1263
  unless Ocran.inno_script # InnoSetup will install the file with a [Files] statement
1236
1264
  @of << [OP_CREATE_FILE, tgt.to_native, str.size].pack("VZ*V")
@@ -1261,7 +1289,7 @@ EOF
1261
1289
  end
1262
1290
 
1263
1291
  def showtempdir(x)
1264
- x.to_s.gsub(TEMPDIR_ROOT, "<tempdir>")
1292
+ x.to_s.gsub(TEMPDIR_ROOT.to_s, "<tempdir>")
1265
1293
  end
1266
1294
  end # class OcranBuilder
1267
1295
  end # module Ocran
@@ -1283,7 +1311,7 @@ if File.basename(__FILE__) == File.basename($0)
1283
1311
 
1284
1312
  if Ocran.run_script
1285
1313
  Ocran.msg "Loading script to check dependencies"
1286
- $0 = Ocran.files.first
1314
+ $0 = Ocran.files.first.to_s
1287
1315
  load Ocran.files.first
1288
1316
  end
1289
1317
  end
data/lib/ocran/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ocran
4
- VERSION = "1.3.13"
5
- end
4
+ VERSION = "1.3.15"
5
+ end
Binary file
File without changes
data/share/ocran/stub.exe CHANGED
Binary file
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ocran
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.13
4
+ version: 1.3.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andi Idogawa
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-05-17 00:00:00.000000000 Z
12
+ date: 2023-11-30 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: "OCRAN (One-Click Ruby Application Next) builds Windows executables from
15
15
  Ruby source code. \n The executable is a self-extracting, self-running executable
@@ -31,6 +31,7 @@ files:
31
31
  - lib/ocran.rb
32
32
  - lib/ocran/version.rb
33
33
  - share/ocran/edicon.exe
34
+ - share/ocran/empty-msys-2.0.dll
34
35
  - share/ocran/lzma.exe
35
36
  - share/ocran/stub.exe
36
37
  - share/ocran/stubw.exe
@@ -40,7 +41,7 @@ licenses:
40
41
  metadata:
41
42
  homepage_uri: https://github.com/largo/ocran
42
43
  source_code_uri: https://github.com/largo/ocran
43
- changelog_uri: https://github.com/largo/ocran/History.txt
44
+ changelog_uri: https://github.com/largo/ocran/CHANGELOG.txt
44
45
  post_install_message:
45
46
  rdoc_options: []
46
47
  require_paths:
@@ -49,14 +50,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
50
  requirements:
50
51
  - - ">="
51
52
  - !ruby/object:Gem::Version
52
- version: 2.0.0
53
+ version: 2.6.0
53
54
  required_rubygems_version: !ruby/object:Gem::Requirement
54
55
  requirements:
55
56
  - - ">="
56
57
  - !ruby/object:Gem::Version
57
58
  version: '0'
58
59
  requirements: []
59
- rubygems_version: 3.4.13
60
+ rubygems_version: 3.4.10
60
61
  signing_key:
61
62
  specification_version: 4
62
63
  summary: OCRAN (One-Click Ruby Application Next) builds Windows executables from Ruby