ocran 1.3.15 → 1.3.17

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.
data/README.md ADDED
@@ -0,0 +1,531 @@
1
+ # ocran
2
+
3
+ home :: https://github.com/largo/ocran/
4
+
5
+ issues :: http://github.com/largo/ocran/issues
6
+
7
+ ## Description
8
+
9
+ OCRAN (One-Click Ruby Application Next) builds Windows executables from Ruby
10
+ source code. The executable is a self-extracting, self-running
11
+ executable that contains the Ruby interpreter, your source code and
12
+ any additionally needed ruby libraries or DLL.
13
+
14
+ OCRAN is a fork of Ocra (https://github.com/larsch/ocra) in order to
15
+ maintain compatibility with newer Ruby versions after 3.0
16
+
17
+ ## Recommended usage
18
+ Most commonly you will needs this, when you want to ship your program to windows servers / users that don't have Ruby installed.
19
+ By default each time the .exe is opened it will extract the ruby interpeter along with the code to the temp directory.
20
+ Since this process takes time, we recommend using the innosetup edition which will install your program together with the ruby intepreter into
21
+ a directory.
22
+
23
+ ## Features
24
+
25
+ * LZMA Compression (optional, default on)
26
+ * Both windowed/console mode supported
27
+ * Includes gems based on usage, or from a Bundler Gemfile
28
+
29
+ ## Problems & Bug Reporting
30
+
31
+ * Windows support only
32
+
33
+ If you experience problems with OCRAN or have found a bug, please use
34
+ the issue tracker on GitHub (http://github.com/largo/ocran/issues).
35
+
36
+ ## Safety
37
+
38
+ As this gem comes with binaries, we have taken actions to insure your safety.
39
+ The gem releases are built on Github Actions. Feel free verify that it matches the version on rubygems.
40
+ It ships with seb.exe and LZMA.exe in this repository, which come from official sources.
41
+
42
+ ## Installation
43
+
44
+ Gem:
45
+
46
+ gem install ocran
47
+
48
+ Alternatively you can download the gem at either
49
+ http://rubygems.org/gems/ocran or
50
+ https://github.com/largo/ocran/releases/.
51
+
52
+ ## Synopsis
53
+
54
+ ### Building an executable:
55
+
56
+ ocran script.rb
57
+
58
+ Will package `script.rb`, the Ruby interpreter and all
59
+ dependencies (gems and DLLs) into an executable named
60
+ `script.exe`.
61
+
62
+ ### Command line:
63
+
64
+ ocran [options] script.rb [<other files> ...] [-- <script arguments> ...]
65
+
66
+ ### Options:
67
+
68
+ ocran --help
69
+
70
+ Ocran options:
71
+
72
+ --help Display this information.
73
+ --quiet Suppress output while building executable.
74
+ --verbose Show extra output while building executable.
75
+ --version Display version number and exit.
76
+
77
+ Packaging options:
78
+
79
+ --dll dllname Include additional DLLs from the Ruby bindir.
80
+ --add-all-core Add all core ruby libraries to the executable.
81
+ --gemfile <file> Add all gems and dependencies listed in a Bundler Gemfile.
82
+ --no-enc Exclude encoding support files
83
+
84
+ Gem content detection modes:
85
+
86
+ --gem-minimal[=gem1,..] Include only loaded scripts
87
+ --gem-guess=[gem1,...] Include loaded scripts & best guess (DEFAULT)
88
+ --gem-all[=gem1,..] Include all scripts & files
89
+ --gem-full[=gem1,..] Include EVERYTHING
90
+ --gem-spec[=gem1,..] Include files in gemspec (Does not work with Rubygems 1.7+)
91
+
92
+ --[no-]gem-scripts[=..] Other script files than those loaded
93
+ --[no-]gem-files[=..] Other files (e.g. data files)
94
+ --[no-]gem-extras[=..] Extra files (README, etc.)
95
+
96
+ Gem modes:
97
+
98
+ * *minimal*: loaded scripts
99
+ * *guess*: loaded scripts and other files
100
+ * *all*: loaded scripts, other scripts, other files (except extras)
101
+ * *full*: Everything found in the gem directory
102
+
103
+ File groups:
104
+
105
+ * *scripts*: .rb/.rbw files
106
+ * *extras*: C/C++ sources, object files, test, spec, README
107
+ * *files*: all other files
108
+
109
+ Auto-detection options:
110
+
111
+ --no-dep-run Don't run script.rb to check for dependencies.
112
+ --no-autoload Don't load/include script.rb's autoloads.
113
+ --no-autodll Disable detection of runtime DLL dependencies.
114
+
115
+ Output options:
116
+
117
+ --output <file> Name the exe to generate. Defaults to ./<scriptname>.exe.
118
+ --no-lzma Disable LZMA compression of the executable.
119
+ --innosetup <file> Use given Inno Setup script (.iss) to create an installer.
120
+
121
+ Executable options:
122
+
123
+ --windows Force Windows application (rubyw.exe)
124
+ --console Force console application (ruby.exe)
125
+ --chdir-first When exe starts, change working directory to app dir.
126
+ --icon <ico> Replace icon with a custom one.
127
+ --rubyopt <str> Set the RUBYOPT environment variable when running the executable
128
+ --debug Executable will be verbose.
129
+ --debug-extract Executable will unpack to local dir and not delete after.
130
+
131
+
132
+ ### Compilation:
133
+
134
+ * OCRAN will load your script (using `Kernel#load`) and build
135
+ the executable when it exits.
136
+
137
+ * Your program should 'require' all necessary files when invoked without
138
+ arguments, so OCRAN can detect all dependencies.
139
+
140
+ * DLLs are detected automatically but only those located in your Ruby
141
+ installation are included.
142
+
143
+ * .rb files will become console applications. .rbw files will become
144
+ windowed application (without a console window popping
145
+ up). Alternatively, use the `--console` or
146
+ `--windows` options.
147
+
148
+ ### Running your application:
149
+
150
+ * The 'current working directory' is not changed by OCRAN when running
151
+ your application. You must change to the installation or temporary
152
+ directory yourself. See also below.
153
+ * When the application is running, the OCRAN_EXECUTABLE environment
154
+ variable points to the .exe (with full path).
155
+ * The temporary location of the script can be obtained by inspected
156
+ the $0 variable.
157
+ * OCRAN does not set up the include path. Use `$:.unshift
158
+ File.dirname($0)` at the start of your script if you need to
159
+ 'require' additional source files from the same directory as your
160
+ main script.
161
+
162
+ ### Pitfalls:
163
+
164
+ * Avoid modifying load paths at run time. Specify load paths using -I
165
+ or RUBYLIB if you must, but don't expect OCRAN to preserve them for
166
+ runtime. OCRAN may pack sources into other directories than you
167
+ expect.
168
+ * If you use .rbw files or the `--windows` option, then check
169
+ that your application works with rubyw.exe before trying with OCRAN.
170
+ * Avoid absolute paths in your code and when invoking OCRAN.
171
+
172
+ ### Multibyte path and filename support:
173
+
174
+ * OCRAN-built executables can correctly handle multibyte paths and filenames
175
+ (e.g., Japanese or emoji) on Windows. To use this feature, the executable
176
+ must be run on Windows 10 version 1903 or later.
177
+ * When using OCRAN-built executables from the console, we recommend running
178
+ `chcp 65001` to switch the code page to UTF-8. This ensures proper
179
+ input/output of multibyte characters in Command Prompt (CMD) and
180
+ PowerShell.
181
+
182
+ ## REQUIREMENTS:
183
+
184
+ * Windows
185
+ * Working Ruby installation.
186
+ * Ruby Installation with devkit from rubyinstaller (when working with the source code only)
187
+
188
+ ## Development
189
+
190
+ ### Quick start
191
+
192
+ Quickly set up the development environment and run the full test suite:
193
+
194
+ git clone https://github.com/largo/ocran.git
195
+ cd ocran
196
+ bin/setup # install Bundler & all dev gems, generate stub for tests
197
+ bundle exec rake # run the entire Minitest suite
198
+
199
+ ### Developer Utilities (bin/ scripts)
200
+
201
+ All scripts in the `bin/` directory are designed for developers and can be executed in any standard Windows shell, including Command Prompt (CMD), PowerShell, and Git Bash.
202
+
203
+ | Script | Purpose |
204
+ |---------------|--------------------------------------------------------------------------|
205
+ | `bin/setup` | Installs Bundler and all required development gems, then builds stub.exe |
206
+ | `bin/console` | Launches an IRB console with OCRAN preloaded |
207
+
208
+
209
+ ### Rake tasks (Windows compatible)
210
+
211
+ | Task | Purpose |
212
+ |--------------|------------------------------------------------------------------------|
213
+ | `rake build` | Compile stub.exe (requires MSVC or mingw‑w64 + DevKit) |
214
+ | `rake clean` | Remove generated binaries (e.g., stub.exe); temp files are not deleted |
215
+ | `rake test` | Execute all unit & integration tests |
216
+
217
+ ## Technical details
218
+
219
+ OCRAN first runs the target script in order to detect any files that
220
+ are loaded and used at runtime (Using `Kernel#require` and
221
+ `Kernel#load`).
222
+
223
+ OCRAN embeds everything needed to run a Ruby script into a single
224
+ executable file. The file contains the .exe stub which is compiled
225
+ from C-code, and a custom opcode format containing instructions to
226
+ create directories, save files, set environment variables and run
227
+ programs. The OCRAN script generates this executable and the
228
+ instructions to be run when it is launched.
229
+
230
+ When executed, the OCRAN stub extracts the Ruby interpreter and your
231
+ scripts into a temporary directory. The directory will contains the
232
+ same directory layout as your Ruby installlation. The source files for
233
+ your application will be put in the 'src' subdirectory.
234
+
235
+ ### Libraries
236
+
237
+ Any code that is loaded through `Kernel#require` when your
238
+ script is executed will be included in the OCRAN
239
+ executable. Conditionally loaded code will not be loaded and included
240
+ in the executable unless the code is actually run when OCRAN invokes
241
+ your script. Otherwise, OCRAN won't know about it and will not include
242
+ the source files.
243
+
244
+ RubyGems are handled specially. Whenever a file from a Gem is
245
+ detected, OCRAN will attempt to include all the required files from
246
+ that specific Gem, expect some unlikely needed files such as readme's
247
+ and other documentation. This behaviour can be controlled by using the
248
+ --gem-* options. Behaviour can be changed for all gems or specific
249
+ gems using --gem-*=gemname.
250
+
251
+ Libraries found in non-standard path (for example, if you invoke OCRAN
252
+ with "ruby -I some/path") will be placed into the site dir
253
+ (lib/ruby/site_ruby). Avoid changing `$LOAD_PATH` or
254
+ `$:` from your script to include paths outside your source
255
+ tree, since OCRAN may place the files elsewhere when extracted into the
256
+ temporary directory.
257
+
258
+ In case your script (or any of its dependencies) sets up autoloaded
259
+ module using `Kernel#autoload`, OCRAN will automatically try to
260
+ load them to ensure that they are all included in the
261
+ executable. Modules that doesn't exist will be ignored (a warning will
262
+ be logged).
263
+
264
+ Dynamic link libraries (.dll files, for example WxWidgets, or other
265
+ source files) will be detected and included by OCRAN.
266
+
267
+ ### Including libraries non-automatically
268
+
269
+ If an application or framework is complicated enough that it tends
270
+ to confuse Ocran's automatic dependency resolution, then you can
271
+ use other means to specify what needs to be packaged with your app.
272
+
273
+ To disable automatic dependency resolution, use the `--no-dep-run`
274
+ option; with it, Ocran will skip executing your program during the
275
+ build process. This on the other hand requires using `--gem-full` option
276
+ (see more below); otherwise Ocran will not include all the necessary
277
+ files for the gems.
278
+
279
+ You will also probably need to use the `--add-all-core` option to
280
+ include the Ruby core libraries.
281
+
282
+ If your app uses gems, then you can specify them in a
283
+ Bundler (http://gembundler.com) Gemfile, then use the --gemfile
284
+ option to supply it to Ocran. Ocran will automatically include all
285
+ gems specified, and all their dependencies.
286
+
287
+ (Note: This assumes that the gems are installed in your system,
288
+ *not* locally packaged inside the app directory by "bundle package")
289
+
290
+ These options are particularly useful for packaging Rails
291
+ applications. For example, to package a Rails 3 app in the
292
+ directory "someapp" and create an exe named "someapp.exe", without
293
+ actually running the app during the build, you could use the
294
+ following command:
295
+
296
+ ocran someapp/script/rails someapp --output someapp.exe --add-all-core \
297
+ --gemfile someapp/Gemfile --no-dep-run --gem-full --chdir-first -- server
298
+
299
+ Note the space between `--` and `server`! It's important; `server` is
300
+ an argument to be passed to rails when the script is ran.
301
+
302
+ Rails 2 apps can be packaged similarly, though you will have to
303
+ integrate them with Bundler (http://gembundler.com/rails23.html)
304
+ first.
305
+
306
+ ### Gem handling
307
+
308
+ By default, Ocran includes all scripts that are loaded by your script
309
+ when it is run before packaging. Ocran detects which gems are using and
310
+ includes any additional non-script files from those gems, except
311
+ trivial files such as C/C++ source code, object files, READMEs, unit
312
+ tests, specs, etc.
313
+
314
+ This behaviour can be changed by using the --gem-* options. There are
315
+ four possible modes:
316
+
317
+ * *minimal*: Include only loaded scripts
318
+ * *guess*: Include loaded scripts and important files (DEFAULT)
319
+ * *all*: Include all scripts and important files
320
+ * *full*: Include all files
321
+
322
+ If you find that files are missing from the resulting executable, try
323
+ first with --gem-all=gemname for the gem that is missing, and if that
324
+ does not work, try --gem-full=gemname. The paranoid can use --gem-full
325
+ to include all files for all required gems.
326
+
327
+ ### Creating an installer for your application
328
+
329
+ To make your application start up quicker, or to allow it to
330
+ keep files in its application directory between runs, or if
331
+ you just want to make your program seem more like a "regular"
332
+ Windows application, you can have Ocran generate an installer
333
+ for your app with the free Inno Setup software.
334
+
335
+ You will first have to download and install Inno Setup 5 or
336
+ later, and also add its directory to your PATH (so that Ocran
337
+ can find the ISCC compiler program). Once you've done that,
338
+ you can use the `--innosetup` option to Ocran to supply an
339
+ Inno Setup script. Do not add any [Files] or [Dirs] sections
340
+ to the script; Ocran will figure those out itself.
341
+
342
+ To continue the Rails example above, let's package the Rails 3
343
+ app into an installer. Save the following as `someapp.iss`:
344
+
345
+ [Setup]
346
+ AppName=SomeApp
347
+ AppVersion=0.1
348
+ DefaultDirName={pf}\SomeApp
349
+ DefaultGroupName=SomeApp
350
+ OutputBaseFilename=SomeAppInstaller
351
+
352
+ [Icons]
353
+ Name: "{group}\SomeApp"; Filename: "{app}\someapp.bat"; IconFilename: "{app}\someapp.ico"; Flags: runminimized;
354
+ Name: "{group}\Uninstall SomeApp"; Filename: "{uninstallexe}"
355
+
356
+ Then, run Ocran with this command:
357
+
358
+ ocran someapp/script/rails someapp --output someapp.exe --add-all-core \
359
+ --gemfile someapp/Gemfile --no-dep-run --gem-full --chdir-first --no-lzma \
360
+ --icon someapp.ico --innosetup someapp.iss -- server
361
+
362
+ If all goes well, a file named "SomeAppInstaller.exe" will be placed
363
+ into the Output directory.
364
+
365
+ ### Environment variables
366
+
367
+ OCRAN executables clear the RUBYLIB environment variable before your
368
+ script is launched. This is done to ensure that your script does not
369
+ use load paths from the end user's Ruby installation.
370
+
371
+ OCRAN executables set the RUBYOPT environment variable to the value it
372
+ had when you invoked OCRAN. For example, if you had "RUBYOPT=rubygems"
373
+ on your build PC, OCRAN ensures that it is also set on PC's running the
374
+ executables.
375
+
376
+ OCRAN executables set OCRAN_EXECUTABLE to the full path of the
377
+ executable, for example
378
+
379
+ ENV["OCRAN_EXECUTABLE"] # => C:\Program Files\MyApp\MyApp.exe
380
+
381
+ ### Working directory
382
+
383
+ The OCRAN executable does not change the working directory when it is
384
+ launched, unless you use the `--chdir-first` option.
385
+
386
+ You should not assume that the current working directory when invoking
387
+ an executable built with .exe is the location of the source script. It
388
+ can be the directory where the executable is placed (when invoked
389
+ through the Windows Explorer), the users' current working directory
390
+ (when invoking from the Command Prompt), or even
391
+ `C:\\WINDOWS\\SYSTEM32` when the executable is invoked through
392
+ a file association.
393
+
394
+ With the `--chdir-first` option, the working directory will
395
+ always be the common parent directory of your source files. This
396
+ should be fine for most applications. However, if your application
397
+ is designed to run from the command line and take filenames as
398
+ arguments, then you cannot use this option.
399
+
400
+ If you wish to maintain the user's working directory, but need to
401
+ `require` additional Ruby scripts from the source directory, you can
402
+ add the following line to your script:
403
+
404
+ $LOAD_PATH.unshift File.dirname($0)
405
+
406
+ ### Load path mangling
407
+
408
+ Adding paths to `$LOAD_PATH` or `$:` at runtime is not
409
+ recommended. Adding relative load paths depends on the working
410
+ directory being the same as where the script is located (See
411
+ above). If you have additional library files in directories below the
412
+ directory containing your source script you can use this idiom:
413
+
414
+ $LOAD_PATH.unshift File.join(File.dirname($0), 'path/to/script')
415
+
416
+ ### Detecting
417
+
418
+ You can detect whether OCRAN is currently building your script by
419
+ looking for the 'Ocran' constant. If it is defined, OCRAN is currenly
420
+ building the executable from your script. For example, you can use
421
+ this to avoid opening a GUI window when compiling executables:
422
+
423
+ app = MyApp.new
424
+ app.main_loop unless defined?(Ocran)
425
+
426
+ ### Additional files and resources
427
+
428
+ You can add additional files to the OCRAN executable (for example
429
+ images) by appending them to the command line. They should be placed
430
+ in the source directory with your main script (or a subdirectory).
431
+
432
+ ocran mainscript.rb someimage.jpeg docs/document.txt
433
+
434
+ This will create the following layout in the temporary directory when
435
+ your program is executed:
436
+
437
+ src/mainscript.rb
438
+ src/someimage.jpeg
439
+ src/docs/document.txt
440
+
441
+ Both files, directoriess and glob patterns can be specified on the
442
+ command line. Files will be added as-is. If a directory is specified,
443
+ OCRAN will include all files found below that directory. Glob patterns
444
+ (See Dir.glob) can be used to specify a specific set of files, for
445
+ example:
446
+
447
+ ocran script.rb assets/**/*.png
448
+
449
+ ### Command Line Arguments
450
+
451
+ To pass command line argument to your script (both while building and
452
+ when run from the resulting executable), specify them after a
453
+ `--` marker. For example:
454
+
455
+ ocran script.rb -- --some-options=value
456
+
457
+ This will pass `--some-options=value` to the script when
458
+ build and when running the executable. Any extra argument specified by
459
+ the user when invoking the executable will be appended after the
460
+ compile-time arguments.
461
+
462
+ ### Window/Console
463
+
464
+ By default, OCRAN builds console application from .rb-files and
465
+ windowed applications (without console window) from .rbw-files.
466
+
467
+ Ruby on Windows provides two executables: ruby.exe is a console mode
468
+ application and rubyw.exe is a windowed application which does not
469
+ bring up a console window when launched using the Windows Explorer.
470
+ By default, or if the `--console` option is used, OCRAN will
471
+ use the console runtime (ruby.exe). OCRAN will automatically select the
472
+ windowed runtime when your script has the ".rbw" extension, or if you
473
+ specify the `--windows` command line option.
474
+
475
+ If your application works in console mode but not in windowed mode,
476
+ first check if your script works without OCRAN using rubyw.exe. A
477
+ script that prints to standard output (using puts, print etc.) will
478
+ eventually cause an exception when run with rubyw.exe (when the IO
479
+ buffers run full).
480
+
481
+ You can also try wrapping your script in an exception handler that
482
+ logs any errors to a file:
483
+
484
+ begin
485
+ # your script here
486
+ rescue Exception => e
487
+ File.open("except.log") do |f|
488
+ f.puts e.inspect
489
+ f.puts e.backtrace
490
+ end
491
+ end
492
+
493
+ ## CREDITS:
494
+
495
+ Lars Christensen and contributors for the OCRA project which this is forked from.
496
+
497
+ Kevin Walzer of codebykevin, Maxim Samsonov for ocra2, John Mair for codesigining support (to be merged)
498
+
499
+ Thanks for Igor Pavlov for the LZMA compressor and decompressor. The
500
+ source code used was place into Public Domain by Igor Pavlov.
501
+
502
+ Erik Veenstra for rubyscript2exe which provided inspiration.
503
+
504
+ Dice for the default .exe icon (vit-ruby.ico,
505
+ http://ruby.morphball.net/vit-ruby-ico_en.html)
506
+
507
+ ## LICENSE:
508
+
509
+ (The MIT License)
510
+
511
+ Copyright (c) 2009-2020 Lars Christensen
512
+ Copyright (c) 2020-2025 The OCRAN Committers Team
513
+
514
+ Permission is hereby granted, free of charge, to any person obtaining
515
+ a copy of this software and associated documentation files (the
516
+ 'Software'), to deal in the Software without restriction, including
517
+ without limitation the rights to use, copy, modify, merge, publish,
518
+ distribute, sublicense, and/or sell copies of the Software, and to
519
+ permit persons to whom the Software is furnished to do so, subject to
520
+ the following conditions:
521
+
522
+ The above copyright notice and this permission notice shall be
523
+ included in all copies or substantial portions of the Software.
524
+
525
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
526
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
527
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
528
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
529
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
530
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
531
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/exe/ocran ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ load File.expand_path("../lib/ocran/runner.rb", __dir__)
5
+ load Ocran::Runner.new.run
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ocran
4
+ module BuildConstants
5
+ # Alias for the temporary directory where files are extracted.
6
+ EXTRACT_ROOT = Pathname.new("|")
7
+ # Directory for source files in temporary directory.
8
+ SRCDIR = Pathname.new("src")
9
+ # Directory for Ruby binaries in temporary directory.
10
+ BINDIR = Pathname.new("bin")
11
+ # Directory for gem files in temporary directory.
12
+ GEMDIR = Pathname.new("gems")
13
+ # Directory for Ruby library in temporary directory.
14
+ LIBDIR = Pathname.new("lib")
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ocran
4
+ class BuildFacade
5
+ def initialize(filer, launcher)
6
+ @filer, @launcher = filer, launcher
7
+ end
8
+
9
+ def mkdir(...) = @filer.__send__(__method__, ...)
10
+
11
+ def cp(...) = @filer.__send__(__method__, ...)
12
+
13
+ def export(...) = @launcher.__send__(__method__, ...)
14
+
15
+ def exec(...) = @launcher.__send__(__method__, ...)
16
+ end
17
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ require "pathname"
3
+ require_relative "refine_pathname"
4
+ require_relative "command_output"
5
+ require_relative "build_constants"
6
+
7
+ module Ocran
8
+ module BuildHelper
9
+ using RefinePathname
10
+
11
+ include BuildConstants, CommandOutput
12
+
13
+ EMPTY_SOURCE = File.expand_path("empty_source", __dir__).freeze
14
+
15
+ def mkdir(target)
16
+ verbose "mkdir #{target}"
17
+ super
18
+ end
19
+
20
+ def cp(source, target)
21
+ verbose "cp #{source} #{target}"
22
+ super
23
+ end
24
+
25
+ def exec(image, script, *argv)
26
+ args = argv.map { |s| replace_placeholder(s) }.join(" ")
27
+ verbose "exec #{image} #{script} #{args}"
28
+ super
29
+ end
30
+
31
+ def export(name, value)
32
+ verbose "export #{name}=#{replace_placeholder(value)}"
33
+ super
34
+ end
35
+
36
+ def replace_placeholder(s)
37
+ s.to_s.gsub(EXTRACT_ROOT.to_s, "<tempdir>")
38
+ end
39
+ private :replace_placeholder
40
+
41
+ def copy_to_bin(source, target)
42
+ cp(source, BINDIR / target)
43
+ end
44
+
45
+ def copy_to_gem(source, target)
46
+ cp(source, GEMDIR / target)
47
+ end
48
+
49
+ def copy_to_lib(source, target)
50
+ cp(source, LIBDIR / target)
51
+ end
52
+
53
+ def duplicate_to_exec_prefix(source)
54
+ cp(source, Pathname(source).relative_path_from(HostConfigHelper.exec_prefix))
55
+ end
56
+
57
+ def duplicate_to_gem_home(source, gem_path)
58
+ copy_to_gem(source, Pathname(source).relative_path_from(gem_path))
59
+ end
60
+
61
+ def resolve_source_path(source, root_prefix)
62
+ source = Pathname(source)
63
+
64
+ if source.subpath?(HostConfigHelper.exec_prefix)
65
+ source.relative_path_from(HostConfigHelper.exec_prefix)
66
+ elsif source.subpath?(root_prefix)
67
+ SRCDIR / source.relative_path_from(root_prefix)
68
+ else
69
+ SRCDIR / source.basename
70
+ end
71
+ end
72
+
73
+ # Sets an environment variable with a joined path value.
74
+ # This method processes an array of path strings or Pathname objects, accepts
75
+ # absolute paths as is, and appends a placeholder to relative paths to convert
76
+ # them into absolute paths. The converted paths are then joined into a single
77
+ # string using the system's path separator.
78
+ #
79
+ # @param name [String] the name of the environment variable to set.
80
+ # @param paths [Array<String, Pathname>] an array of path arguments which can
81
+ # be either absolute or relative.
82
+ #
83
+ # Example:
84
+ # set_env_path("RUBYLIB", "lib", "ext", "vendor/lib")
85
+ # # This sets RUBYLIB to a string such as "C:/ProjectRoot/lib;C:/ProjectRoot/ext;C:/ProjectRoot/vendor/lib"
86
+ # # assuming each path is correctly converted to an absolute path through a placeholder.
87
+ #
88
+ def set_env_path(name, *paths)
89
+ value = paths.map { |path|
90
+ if File.absolute_path?(path)
91
+ path
92
+ else
93
+ File.join(EXTRACT_ROOT, path)
94
+ end
95
+ }.join(File::PATH_SEPARATOR)
96
+
97
+ export(name, value)
98
+ end
99
+
100
+ def touch(target)
101
+ verbose "touch #{target}"
102
+ cp(EMPTY_SOURCE, target)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ load File.expand_path("../ocran.rb", __dir__)
3
+
4
+ module Ocran
5
+ module CommandOutput
6
+ def say(s)
7
+ puts "=== #{s}" unless Ocran.option&.quiet?
8
+ end
9
+
10
+ def verbose(s)
11
+ puts s if Ocran.option&.verbose?
12
+ end
13
+
14
+ def warning(s)
15
+ STDERR.puts "WARNING: #{s}" if Ocran.option&.warning?
16
+ end
17
+
18
+ def error(s)
19
+ STDERR.puts "ERROR: #{s}"
20
+ end
21
+ end
22
+ end