ocran 1.3.14 → 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: 449194532d3384d90405c64c563178872353c0174ac273f6d139b5af97b74098
4
- data.tar.gz: fd72ceea04583f1023000765017a70f12d87b517f847119b722d1af2810028ea
3
+ metadata.gz: a782f6a9d0c148e6270aa19573c86e5f6518e9511bcfda3aec59de84a1291e41
4
+ data.tar.gz: 4eff772bc2997a4a99d08ea925c9e9d2eb0e8a1da48c687588dbf7c46d3d3453
5
5
  SHA512:
6
- metadata.gz: e3f49d0fddb65df9b88ce81b21aecd8c27350afc8018c2899629830058e7f6e35fe03431d6448cd4a5343b2967d512d376a712a87939ffa847ce7913836188fb
7
- data.tar.gz: f83fbb8cf6768d4f32e220a83ecb1f77468c27b4735f7a14f4a3fe3680e50587ad79ac0ba5c9c4912498ea9171bfd5c6aeb041b7f49bf5908d5b522dd1ea0051
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.14"
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})/
@@ -270,40 +309,23 @@ module Ocran
270
309
  exit 1
271
310
  end
272
311
 
273
- # Returns a binary blob store embedded in the current Ruby script.
274
- def Ocran.get_next_embedded_image
275
- DATA.read(DATA.readline.to_i).unpack("m")[0]
276
- end
277
-
278
312
  def Ocran.save_environment
279
313
  @load_path_before = $LOAD_PATH.dup
280
314
  @pwd_before = Dir.pwd
281
- @env_before = {}; ENV.each { |key, value| @env_before[key] = value }
315
+ @env_before = ENV.to_hash
282
316
  end
283
317
 
284
318
  def Ocran.restore_environment
285
- @env_before.each { |key, value| ENV[key] = value }
286
- ENV.each_key { |key| ENV.delete(key) unless @env_before.has_key?(key) }
319
+ ENV.clear.update(@env_before)
287
320
  Dir.chdir @pwd_before
288
321
  end
289
322
 
290
323
  def Ocran.find_stubs
291
- if defined?(DATA)
292
- @stubimage = get_next_embedded_image
293
- @stubwimage = get_next_embedded_image
294
- lzmaimage = get_next_embedded_image
295
- @lzmapath = Host.tempdir / "lzma.exe"
296
- File.open(@lzmapath, "wb") { |file| file << lzmaimage }
297
- ediconimage = get_next_embedded_image
298
- @ediconpath = Host.tempdir / "edicon.exe"
299
- File.open(@ediconpath, "wb") { |file| file << ediconimage }
300
- else
301
- ocranpath = Pathname(File.dirname(__FILE__))
302
- @stubimage = File.open(ocranpath / "../share/ocran/stub.exe", "rb") { |file| file.read }
303
- @stubwimage = File.open(ocranpath / "../share/ocran/stubw.exe", "rb") { |file| file.read }
304
- @lzmapath = (ocranpath / "../share/ocran/lzma.exe").expand
305
- @ediconpath = (ocranpath / "../share/ocran/edicon.exe").expand
306
- 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
307
329
  end
308
330
 
309
331
  def Ocran.parseargs(argv)
@@ -377,9 +399,11 @@ EOF
377
399
  when /\A--add-all-core\z/
378
400
  @options[:add_all_core] = true
379
401
  when /\A--output\z/
380
- @options[:output_override] = Pathname(argv.shift)
402
+ path = argv.shift
403
+ @options[:output_override] = Pathname.new(path) if path
381
404
  when /\A--dll\z/
382
- @options[:extra_dlls] << argv.shift
405
+ path = argv.shift
406
+ @options[:extra_dlls] << path if path
383
407
  when /\A--quiet\z/
384
408
  @options[:quiet] = true
385
409
  when /\A--verbose\z/
@@ -393,16 +417,19 @@ EOF
393
417
  when /\A--chdir-first\z/
394
418
  @options[:chdir_first] = true
395
419
  when /\A--icon\z/
396
- @options[:icon_filename] = Pathname(argv.shift)
397
- 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)
398
423
  when /\A--rubyopt\z/
399
424
  @options[:rubyopt] = argv.shift
400
425
  when /\A--gemfile\z/
401
- @options[:gemfile] = Pathname(argv.shift)
402
- 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)
403
429
  when /\A--innosetup\z/
404
- @options[:inno_script] = Pathname(argv.shift)
405
- 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)
406
433
  when /\A--no-autodll\z/
407
434
  @options[:autodll] = false
408
435
  when /\A--version\z/
@@ -421,17 +448,18 @@ EOF
421
448
  @options[:enc] = !$1
422
449
  when /\A--(no-)?gem-(\w+)(?:=(.*))?$/
423
450
  negate, group, list = $1, $2, $3
424
- @options[:gem] ||= []
425
- @options[:gem] << [negate, group.to_sym, list && list.split(",")]
451
+ @options[:gem] << [negate, group.to_sym, list&.split(",")] if group
426
452
  when /\A--help\z/, /\A--./
427
453
  puts usage
428
454
  exit 0
429
455
  else
430
- if __FILE__.respond_to?(:encoding)
431
- @options[:files] << arg.dup.force_encoding(__FILE__.encoding)
432
- else
433
- @options[:files] << arg
456
+ path = arg.dup
457
+
458
+ if !File.exist?(path) || Dir.empty?(path)
459
+ Ocran.fatal_error "#{path} not found!"
434
460
  end
461
+
462
+ @options[:files] << path
435
463
  end
436
464
  end
437
465
 
@@ -453,14 +481,12 @@ EOF
453
481
  end
454
482
 
455
483
  @options[:files].map! { |path|
456
- path = path.encode("UTF-8").tr('\\', "/")
484
+ path = path.encode("UTF-8").tr("\\", "/")
457
485
  if File.directory?(path)
458
486
  # If a directory is passed, we want all files under that directory
459
487
  path = "#{path}/**/*"
460
488
  end
461
- files = Dir[path]
462
- Ocran.fatal_error "#{path} not found!" if files.empty?
463
- files.map { |path| Pathname(path).expand }
489
+ Pathname.glob(path).map!(&:expand_path)
464
490
  }.flatten!
465
491
  end
466
492
 
@@ -486,8 +512,6 @@ EOF
486
512
  modules_to_check.each do |mod|
487
513
  modules_checked[mod] = true
488
514
  mod.constants.each do |const|
489
- # Module::Config causes warning on Ruby 1.9.3 - prevent autoloading
490
- next if Module === mod && const == :Config
491
515
  if mod.autoload?(const)
492
516
  Ocran.msg "Attempting to trigger autoload of #{mod}::#{const}"
493
517
  begin
@@ -509,26 +533,26 @@ EOF
509
533
  def Ocran.find_load_path(loadpaths, feature)
510
534
  if feature.absolute?
511
535
  # Choose those loadpaths which contain the feature
512
- candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.expand) }
536
+ candidate_loadpaths = loadpaths.select { |loadpath| feature.subpath?(loadpath.expand_path) }
513
537
  # Guess the require'd feature
514
- 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)] }
515
539
  # Select the shortest possible require-path (longest load-path)
516
540
  if feature_pairs.empty?
517
541
  nil
518
542
  else
519
- feature_pairs.sort_by { |loadpath, feature| feature.path.size }.first[0]
543
+ feature_pairs.sort_by { |loadpath, feature| feature.to_s.size }.first[0]
520
544
  end
521
545
  else
522
546
  # Select the loadpaths that contain 'feature' and select the shortest
523
- candidates = loadpaths.select { |loadpath| feature.expand(loadpath).exist? }
524
- 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
525
549
  end
526
550
  end
527
551
 
528
552
  # Find the root of all files specified on the command line and use
529
553
  # it as the "src" of the output.
530
554
  def Ocran.find_src_root(files)
531
- src_files = files.map { |file| file.expand }
555
+ src_files = files.map { |file| file.expand_path }
532
556
  src_prefix = src_files.inject(src_files.first.dirname) do |srcroot, path|
533
557
  if path.subpath?(Host.exec_prefix)
534
558
  srcroot
@@ -579,18 +603,19 @@ EOF
579
603
  end
580
604
  end
581
605
 
582
- ENV["BUNDLE_GEMFILE"] = Ocran.gemfile
606
+ ENV["BUNDLE_GEMFILE"] = Ocran.gemfile.to_s
583
607
  Bundler.load.specs.each do |spec|
584
608
  Ocran.verbose_msg "From Gemfile, adding gem #{spec.full_name}"
585
609
  gems[spec.name] ||= spec
586
610
  end
587
611
 
612
+ # This code is implemented for compatibility with older Bundler versions (< v1.16.0.pre.1).
588
613
  unless gems.any? { |name, spec| name == "bundler" }
589
614
  # Bundler itself wasn't added for some reason, let's put it in directly
590
615
  Ocran.verbose_msg "From Gemfile, forcing inclusion of bundler gem itself"
591
616
  bundler_spec = Gem.loaded_specs["bundler"]
592
617
  bundler_spec or Ocran.fatal_error "Unable to locate bundler gem"
593
- gems["bundler"] ||= spec
618
+ gems["bundler"] ||= bundler_spec
594
619
  end
595
620
  end
596
621
 
@@ -610,12 +635,12 @@ EOF
610
635
  features_from_gems << feature
611
636
  next
612
637
  end
613
- gempaths = Pathname(Gem.path)
638
+ gempaths = Gem.path
614
639
  gempaths.each do |gempath|
615
640
  geminstallpath = Pathname(gempath) / "gems"
616
641
  if feature.subpath?(geminstallpath)
617
642
  gemlocalpath = feature.relative_path_from(geminstallpath)
618
- fullgemname = gemlocalpath.path.split("/").first
643
+ fullgemname = gemlocalpath.to_s.split("/").first
619
644
  gemspecpath = gempath / "specifications" / "#{fullgemname}.gemspec"
620
645
  if spec = Gem::Specification.load(gemspecpath)
621
646
  gems[spec.name] ||= spec
@@ -682,9 +707,9 @@ EOF
682
707
  Ocran.msg "Detected gem #{spec.full_name} (#{include.join(", ")})"
683
708
 
684
709
  gem_root = Pathname(spec.gem_dir)
685
- gem_extension = (gem_root / ".." / ".." / "extensions").expand
710
+ gem_extension = (gem_root / ".." / ".." / "extensions").expand_path
686
711
  if gem_extension.exist?
687
- 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 }
688
713
  else
689
714
  build_complete = nil
690
715
  end
@@ -704,14 +729,14 @@ EOF
704
729
  when :loaded
705
730
  files << features_from_gems.select { |feature| feature.subpath?(gem_root) }
706
731
  when :files
707
- gem_root_files ||= gem_root.find_all_files(//)
732
+ gem_root_files ||= gem_root.find_all_files
708
733
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) !~ GEM_NON_FILE_RE }
709
734
  files << build_complete if build_complete
710
735
  when :extras
711
- gem_root_files ||= gem_root.find_all_files(//)
736
+ gem_root_files ||= gem_root.find_all_files
712
737
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_EXTRA_RE }
713
738
  when :scripts
714
- gem_root_files ||= gem_root.find_all_files(//)
739
+ gem_root_files ||= gem_root.find_all_files
715
740
  files << gem_root_files.select { |path| path.relative_path_from(gem_root) =~ GEM_SCRIPT_RE }
716
741
  end
717
742
  end
@@ -723,7 +748,7 @@ EOF
723
748
  Ocran.warn "#{missing_file} was not found"
724
749
  end
725
750
 
726
- total_size = actual_files.inject(0) { |size, path| size + path.size }
751
+ total_size = actual_files.sum(0, &:size)
727
752
  Ocran.msg "\t#{actual_files.size} files, #{total_size} bytes"
728
753
 
729
754
  gem_files += actual_files
@@ -737,9 +762,9 @@ EOF
737
762
  end
738
763
 
739
764
  def Ocran.build_exe
740
- all_load_paths = $LOAD_PATH.map { |loadpath| Pathname(loadpath).expand }
741
- @added_load_paths = ($LOAD_PATH - @load_path_before).map { |loadpath| Pathname(loadpath).expand }
742
- 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
743
768
 
744
769
  restore_environment
745
770
 
@@ -784,7 +809,7 @@ EOF
784
809
  encpath = path / "enc"
785
810
  if encpath.exist?
786
811
  encfiles = encpath.find_all_files(/\.so$/)
787
- size = encfiles.inject(0) { |sum, pn| sum + pn.size }
812
+ size = encfiles.sum(0, &:size)
788
813
  Ocran.msg "Including #{encfiles.size} encoding support files (#{size} bytes, use --no-enc to exclude)"
789
814
  features.push(*encfiles)
790
815
  end
@@ -799,13 +824,13 @@ EOF
799
824
  libs = []
800
825
  features.each do |feature|
801
826
  path = find_load_path(all_load_paths, feature)
802
- if path.nil? || path.expand == Pathname.pwd
827
+ if path.nil? || path.expand_path == Pathname.pwd
803
828
  Ocran.files << feature
804
829
  else
805
830
  if feature.absolute?
806
- feature = feature.relative_path_from(path.expand)
831
+ feature = feature.relative_path_from(path.expand_path)
807
832
  end
808
- fullpath = feature.expand(path)
833
+ fullpath = feature.expand_path(path)
809
834
 
810
835
  if fullpath.subpath?(Host.exec_prefix)
811
836
  # Features found in the Ruby installation are put in the
@@ -868,11 +893,10 @@ EOF
868
893
  next unless path.to_posix =~
869
894
  /\/(ruby\/(?:site_ruby\/|vendor_ruby\/)?[0-9.]+)\/?$/i
870
895
  subdir = $1
871
- Dir["#{lp}/**/*"].each do |f|
872
- fpath = Pathname.new(f)
896
+ Pathname.glob("#{lp}/**/*").each do |fpath|
873
897
  next if fpath.directory?
874
898
  tgt = "lib/#{subdir}/#{fpath.relative_path_from(path).to_posix}"
875
- libs << [f, tgt]
899
+ libs << [fpath, tgt]
876
900
  end
877
901
  end
878
902
  end
@@ -881,13 +905,19 @@ EOF
881
905
  dlls = Ocran.autodll ? LibraryDetector.detect_dlls : []
882
906
 
883
907
  # Detect external manifests
884
- 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
885
915
 
886
916
  executable = nil
887
917
  if Ocran.output_override
888
918
  executable = Ocran.output_override
889
919
  else
890
- executable = Ocran.files.first.basename.ext(".exe")
920
+ executable = Ocran.files.first.basename.sub_ext(".exe")
891
921
  executable.append_to_filename!("-debug") if Ocran.debug
892
922
  end
893
923
 
@@ -963,8 +993,8 @@ EOF
963
993
  if gemspec.subpath?(Host.exec_prefix)
964
994
  path = gemspec.relative_path_from(Host.exec_prefix)
965
995
  sb.createfile(gemspec, path)
966
- elsif defined?(Gem) and gemhome = Pathname(Gem.path.find { |pth| gemspec.subpath?(pth) })
967
- 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))
968
998
  sb.createfile(gemspec, path)
969
999
  else
970
1000
  Ocran.fatal_error "Gem spec #{gemspec} does not exist in the Ruby installation. Don't know where to put it."
@@ -979,8 +1009,9 @@ EOF
979
1009
 
980
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)
981
1011
  # Add an empty file to /msys64/usr/bin/msys-2.0.dll if the dll was not required otherwise
982
- require 'tempfile'
983
- 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
984
1015
 
985
1016
  # Set environment variable
986
1017
  sb.setenv("RUBYOPT", Ocran.rubyopt || ENV["RUBYOPT"] || "")
@@ -1002,71 +1033,64 @@ EOF
1002
1033
  end
1003
1034
 
1004
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
+
1005
1050
  def LibraryDetector.init_fiddle
1006
- require "fiddle"
1051
+ require "fiddle/import"
1007
1052
  require "fiddle/types"
1008
- module_eval {
1009
- extend Fiddle::Importer
1010
- dlload "psapi.dll"
1011
- include Fiddle::Win32Types
1012
- extern "BOOL EnumProcessModules(HANDLE, HMODULE*, DWORD, DWORD*)"
1013
- extend Fiddle::Importer
1014
- dlload "kernel32.dll"
1015
- include Fiddle::Win32Types
1016
-
1017
- # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
1018
- # typedef PVOID HANDLE
1019
- # typedef HINSTANCE HMODULE;
1020
-
1021
- typealias "HMODULE", "voidp"
1022
- typealias "HANDLE", "voidp"
1023
- typealias "LPWSTR", "char*"
1024
-
1025
- extern "DWORD GetModuleFileNameW(HMODULE, LPWSTR, DWORD)"
1026
- extern "HANDLE GetCurrentProcess(void)"
1027
- extern "DWORD GetLastError(void)"
1028
- }
1029
- end
1030
1053
 
1031
- def LibraryDetector.loaded_dlls
1032
- require "fiddle"
1033
- psapi = Fiddle.dlopen("psapi")
1034
- enumprocessmodules = Fiddle::Function.new(psapi["EnumProcessModules"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG)
1035
- kernel32 = Fiddle.dlopen("kernel32")
1036
- getcurrentprocess = Fiddle::Function.new(kernel32["GetCurrentProcess"], [], Fiddle::TYPE_LONG)
1037
- getmodulefilename = Fiddle::Function.new(kernel32["GetModuleFileNameW"], [Fiddle::TYPE_UINTPTR_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG], Fiddle::TYPE_LONG)
1038
- getlasterror = Fiddle::Function.new(kernel32["GetLastError"], [], Fiddle::TYPE_LONG)
1039
-
1040
- # Different packing/unpacking for 64/32 bits systems
1041
- if Fiddle::SIZEOF_VOIDP == 8 then
1042
- f_single = "Q"
1043
- f_array = "Q*"
1044
- else
1045
- f_single = "I"
1046
- f_array = "I*"
1047
- end
1054
+ extend Fiddle::Importer
1055
+ dlload "kernel32.dll", "psapi.dll"
1048
1056
 
1049
- bytes_needed = Fiddle::SIZEOF_VOIDP * 32
1050
- module_handle_buffer = nil
1051
- process_handle = getcurrentprocess.call()
1052
- loop do
1053
- module_handle_buffer = "\x00" * bytes_needed
1054
- bytes_needed_buffer = [0].pack(f_single)
1055
- r = enumprocessmodules.call(process_handle, module_handle_buffer, module_handle_buffer.size, bytes_needed_buffer)
1056
- bytes_needed = bytes_needed_buffer.unpack(f_single)[0]
1057
- break if bytes_needed <= module_handle_buffer.size
1058
- 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
1059
1069
 
1060
- handles = module_handle_buffer.unpack(f_array)
1061
- handles.select { |handle| handle > 0 }.map do |handle|
1062
- str = "\x00\x00" * 256
1063
- modulefilename_length = getmodulefilename.call(handle, str, str.size)
1064
- unless modulefilename_length > 0
1065
- errorcode = getlasterror.call()
1066
- 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()
1067
1092
  end
1068
- modulefilename = str[0, modulefilename_length * 2].force_encoding("UTF-16LE").encode("UTF-8")
1069
- Ocran.Pathname(modulefilename)
1093
+ Ocran.Pathname(str[0, length])
1070
1094
  end
1071
1095
  end
1072
1096
 
@@ -1112,7 +1136,7 @@ EOF
1112
1136
  end
1113
1137
 
1114
1138
  if Ocran.icon_filename
1115
- system Ocran.ediconpath, path, Ocran.icon_filename
1139
+ system Ocran.ediconpath.to_s, path.to_s, Ocran.icon_filename.to_s
1116
1140
  end
1117
1141
 
1118
1142
  opcode_offset = File.size(path)
@@ -1142,7 +1166,7 @@ EOF
1142
1166
  begin
1143
1167
  data_size = File.size(tmpinpath)
1144
1168
  Ocran.msg "Compressing #{data_size} bytes"
1145
- system(Ocran.lzmapath, "e", tmpinpath, tmpoutpath) or fail
1169
+ system(Ocran.lzmapath.to_s, "e", tmpinpath, tmpoutpath) or fail
1146
1170
  compressed_data_size = File.size?(tmpoutpath)
1147
1171
  ocranfile.write([OP_DECOMPRESS_LZMA, compressed_data_size].pack("VV"))
1148
1172
  IO.copy_stream(tmpoutpath, ocranfile)
@@ -1189,7 +1213,7 @@ EOF
1189
1213
  Ocran.msg "Running InnoSetup compiler ISCC"
1190
1214
  result = system(*iscc_cmd)
1191
1215
  if not result
1192
- case $?
1216
+ case $?.exitstatus
1193
1217
  when 0 then raise RuntimeError.new("ISCC reported success, but system reported error?")
1194
1218
  when 1 then raise RuntimeError.new("ISCC reports invalid command line parameters")
1195
1219
  when 2 then raise RuntimeError.new("ISCC reports that compilation failed")
@@ -1206,8 +1230,8 @@ EOF
1206
1230
  end
1207
1231
 
1208
1232
  def mkdir(path)
1209
- return if @paths[path.path.downcase]
1210
- @paths[path.path.downcase] = true
1233
+ return if @paths[path.to_s.downcase]
1234
+ @paths[path.to_posix.downcase] = true
1211
1235
  Ocran.verbose_msg "m #{showtempdir path}"
1212
1236
  unless Ocran.inno_script # The directory will be created by InnoSetup with a [Dirs] statement
1213
1237
  @of << [OP_CREATE_DIRECTORY, path.to_native].pack("VZ*")
@@ -1216,7 +1240,7 @@ EOF
1216
1240
 
1217
1241
  def ensuremkdir(tgt)
1218
1242
  tgt = Ocran.Pathname(tgt)
1219
- return if tgt.path == "."
1243
+ return if tgt.to_s == "."
1220
1244
  if not @paths[tgt.to_posix.downcase]
1221
1245
  ensuremkdir(tgt.dirname)
1222
1246
  mkdir(tgt)
@@ -1234,7 +1258,7 @@ EOF
1234
1258
  @files[tgt] = src
1235
1259
  src, tgt = Ocran.Pathname(src), Ocran.Pathname(tgt)
1236
1260
  ensuremkdir(tgt.dirname)
1237
- str = File.open(src, "rb") { |file| file.read }
1261
+ str = src.binread
1238
1262
  Ocran.verbose_msg "a #{showtempdir tgt}"
1239
1263
  unless Ocran.inno_script # InnoSetup will install the file with a [Files] statement
1240
1264
  @of << [OP_CREATE_FILE, tgt.to_native, str.size].pack("VZ*V")
@@ -1265,7 +1289,7 @@ EOF
1265
1289
  end
1266
1290
 
1267
1291
  def showtempdir(x)
1268
- x.to_s.gsub(TEMPDIR_ROOT, "<tempdir>")
1292
+ x.to_s.gsub(TEMPDIR_ROOT.to_s, "<tempdir>")
1269
1293
  end
1270
1294
  end # class OcranBuilder
1271
1295
  end # module Ocran
@@ -1287,7 +1311,7 @@ if File.basename(__FILE__) == File.basename($0)
1287
1311
 
1288
1312
  if Ocran.run_script
1289
1313
  Ocran.msg "Loading script to check dependencies"
1290
- $0 = Ocran.files.first
1314
+ $0 = Ocran.files.first.to_s
1291
1315
  load Ocran.files.first
1292
1316
  end
1293
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.14"
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.14
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-09-08 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
@@ -49,7 +50,7 @@ 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
  - - ">="