ocran 1.3.14 → 1.3.15

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="