ocran 1.4.3 → 1.4.5
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 +4 -4
- data/CHANGELOG.txt +37 -0
- data/README.md +539 -31
- data/lib/ocran/build_facade.rb +2 -0
- data/lib/ocran/cosmo_toolchain.rb +383 -0
- data/lib/ocran/dir_builder.rb +3 -0
- data/lib/ocran/direction.rb +819 -64
- data/lib/ocran/gem_spec_queryable.rb +24 -3
- data/lib/ocran/inno_setup_script_builder.rb +15 -1
- data/lib/ocran/launcher_event_recorder.rb +29 -0
- data/lib/ocran/option.rb +172 -3
- data/lib/ocran/rubyopt_processor.rb +95 -0
- data/lib/ocran/runner.rb +84 -2
- data/lib/ocran/runtime_environment.rb +19 -1
- data/lib/ocran/stub_builder.rb +38 -6
- data/lib/ocran/version.rb +1 -1
- data/lib/ocran/zip_payload_builder.rb +282 -0
- data/lib/ocran/zip_writer.rb +287 -0
- data/src/Makefile +9 -0
- data/src/inst_dir.c +44 -2
- data/src/inst_dir.h +14 -0
- data/src/script_info.c +15 -2
- data/src/script_info.h +15 -1
- data/src/stub.c +70 -9
- data/src/system_utils.c +26 -0
- data/src/system_utils.h +14 -0
- data/src/system_utils_posix.c +46 -0
- data/src/unpack.c +8 -0
- data/src/unpack.h +19 -0
- metadata +15 -24
data/src/inst_dir.c
CHANGED
|
@@ -98,8 +98,50 @@ const char *CreateInstDir(bool is_extract_to_exe_dir)
|
|
|
98
98
|
return NULL;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
/* Normalize 8.3 short names (e.g. a TEMP under C:\Users\RUNNER~1) so all
|
|
102
|
+
paths derived from the extraction dir use one consistent spelling. */
|
|
103
|
+
char *long_dir = ToLongPath(inst_dir);
|
|
104
|
+
free(inst_dir);
|
|
105
|
+
if (!long_dir) {
|
|
106
|
+
return NULL;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
InstDir = long_dir;
|
|
110
|
+
return InstDir;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Sets the installation directory to the executable's own directory
|
|
114
|
+
// (installer/wrapper mode, RUN_IN_EXE_DIR). No directory is created and
|
|
115
|
+
// the directory must never be deleted by the stub.
|
|
116
|
+
const char *SetInstDirToExeDir(void)
|
|
117
|
+
{
|
|
118
|
+
if (InstDir != NULL) {
|
|
119
|
+
APP_ERROR("Installation directory has already been set");
|
|
120
|
+
return NULL;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
char *image_path = GetImagePath();
|
|
124
|
+
if (!image_path) {
|
|
125
|
+
APP_ERROR("Failed to get executable name");
|
|
126
|
+
return NULL;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
char *image_dir = GetParentPath(image_path);
|
|
130
|
+
free(image_path);
|
|
131
|
+
if (!image_dir) {
|
|
132
|
+
APP_ERROR("Failed to obtain the directory path of the executable file");
|
|
133
|
+
return NULL;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Normalize 8.3 short names for a consistent spelling (see CreateInstDir) */
|
|
137
|
+
char *long_dir = ToLongPath(image_dir);
|
|
138
|
+
free(image_dir);
|
|
139
|
+
if (!long_dir) {
|
|
140
|
+
return NULL;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
InstDir = long_dir;
|
|
144
|
+
return InstDir;
|
|
103
145
|
}
|
|
104
146
|
|
|
105
147
|
// Frees the allocated memory for the installation directory path.
|
data/src/inst_dir.h
CHANGED
|
@@ -20,6 +20,20 @@
|
|
|
20
20
|
*/
|
|
21
21
|
const char *CreateInstDir(bool is_extract_to_exe_dir);
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @brief Sets the installation directory to the executable's own directory.
|
|
25
|
+
*
|
|
26
|
+
* Unlike CreateInstDir, no new directory is created: the stub runs the
|
|
27
|
+
* application directly from the directory the executable resides in
|
|
28
|
+
* (installer/wrapper mode, RUN_IN_EXE_DIR). The directory must never be
|
|
29
|
+
* deleted by the stub.
|
|
30
|
+
*
|
|
31
|
+
* @return
|
|
32
|
+
* A pointer to the directory path if successful, NULL if an error
|
|
33
|
+
* occurred. The returned path should not be freed by the caller.
|
|
34
|
+
*/
|
|
35
|
+
const char *SetInstDirToExeDir(void);
|
|
36
|
+
|
|
23
37
|
/**
|
|
24
38
|
* @brief Free the allocated installation directory path
|
|
25
39
|
* and reset the internal pointer to NULL.
|
data/src/script_info.c
CHANGED
|
@@ -163,7 +163,8 @@ static char **shallow_merge_argv(char *argv1[], char *argv2[])
|
|
|
163
163
|
return outv;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
bool RunScript(char *argv[], bool is_chdir_to_script_dir,
|
|
166
|
+
bool RunScript(char *argv[], bool is_chdir_to_script_dir,
|
|
167
|
+
const char *chdir_dir, int *exit_code)
|
|
167
168
|
{
|
|
168
169
|
if (!IsScriptInfoSet()) {
|
|
169
170
|
APP_ERROR("Script info is not initialized");
|
|
@@ -202,6 +203,7 @@ bool RunScript(char *argv[], bool is_chdir_to_script_dir, int *exit_code)
|
|
|
202
203
|
goto cleanup;
|
|
203
204
|
}
|
|
204
205
|
|
|
206
|
+
const char *target_dir = NULL;
|
|
205
207
|
if (is_chdir_to_script_dir) {
|
|
206
208
|
script_dir = GetParentPath(script_name);
|
|
207
209
|
if (!script_dir) {
|
|
@@ -213,8 +215,19 @@ bool RunScript(char *argv[], bool is_chdir_to_script_dir, int *exit_code)
|
|
|
213
215
|
"Changing working directory to script directory '%s'",
|
|
214
216
|
script_dir
|
|
215
217
|
);
|
|
218
|
+
target_dir = script_dir;
|
|
219
|
+
} else if (chdir_dir) {
|
|
220
|
+
DEBUG(
|
|
221
|
+
"Changing working directory to '%s'",
|
|
222
|
+
chdir_dir
|
|
223
|
+
);
|
|
224
|
+
target_dir = chdir_dir;
|
|
225
|
+
}
|
|
216
226
|
|
|
217
|
-
|
|
227
|
+
if (target_dir) {
|
|
228
|
+
char *ruby_optv[5] = {
|
|
229
|
+
script_info[0], "-C", (char *)target_dir, "--", NULL
|
|
230
|
+
};
|
|
218
231
|
char **new_argv = shallow_merge_argv(ruby_optv, merged_argv + 1);
|
|
219
232
|
if (!new_argv) {
|
|
220
233
|
APP_ERROR("Failed to merge script arguments with extra arguments");
|
data/src/script_info.h
CHANGED
|
@@ -4,4 +4,18 @@
|
|
|
4
4
|
char **GetScriptInfo(void);
|
|
5
5
|
bool SetScriptInfo(const char *info, size_t info_size);
|
|
6
6
|
void FreeScriptInfo(void);
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Launches the packaged script.
|
|
9
|
+
*
|
|
10
|
+
* @param argv Original argv of the stub; elements after
|
|
11
|
+
* argv[0] are appended to the script arguments.
|
|
12
|
+
* @param is_chdir_to_script_dir When true, the script starts with its working
|
|
13
|
+
* directory set to the extracted script's
|
|
14
|
+
* directory (--chdir-first).
|
|
15
|
+
* @param chdir_dir When non-NULL (and is_chdir_to_script_dir is
|
|
16
|
+
* false), the script starts with its working
|
|
17
|
+
* directory set to this path (--chdir-exe-dir).
|
|
18
|
+
* @param exit_code Receives the script's exit code.
|
|
19
|
+
*/
|
|
20
|
+
bool RunScript(char *argv[], bool is_chdir_to_script_dir,
|
|
21
|
+
const char *chdir_dir, int *exit_code);
|
data/src/stub.c
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
#include <stdio.h>
|
|
9
9
|
#include <stdbool.h>
|
|
10
10
|
#include <stdlib.h>
|
|
11
|
+
#ifdef __COSMOPOLITAN__
|
|
12
|
+
#include <cosmo.h> /* IsWindows() */
|
|
13
|
+
#include <libc/nt/runtime.h> /* ExitProcess() */
|
|
14
|
+
#endif
|
|
11
15
|
#include "error.h"
|
|
12
16
|
#include "system_utils.h"
|
|
13
17
|
#include "inst_dir.h"
|
|
@@ -21,6 +25,7 @@ int main(int argc, char *argv[])
|
|
|
21
25
|
OperationModes op_modes = 0;
|
|
22
26
|
const char *extract_dir = NULL;
|
|
23
27
|
char *image_path = NULL;
|
|
28
|
+
char *exe_dir = NULL;
|
|
24
29
|
|
|
25
30
|
/*
|
|
26
31
|
Initialize signal and control handling so the parent process remains
|
|
@@ -57,15 +62,24 @@ int main(int argc, char *argv[])
|
|
|
57
62
|
DEBUG("Ocran stub running in debug mode");
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
/* Create extraction directory
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
/* Create extraction directory, or run in place next to the executable
|
|
66
|
+
(installer/wrapper mode, see RUN_IN_EXE_DIR) */
|
|
67
|
+
if (IsRunInExeDir(op_modes)) {
|
|
68
|
+
extract_dir = SetInstDirToExeDir();
|
|
69
|
+
if (!extract_dir) {
|
|
70
|
+
FATAL("Failed to resolve the executable directory");
|
|
71
|
+
goto cleanup;
|
|
72
|
+
}
|
|
73
|
+
DEBUG("Running in executable directory: %s", extract_dir);
|
|
74
|
+
} else {
|
|
75
|
+
extract_dir = CreateInstDir(IsExtractToExeDir(op_modes));
|
|
76
|
+
if (!extract_dir) {
|
|
77
|
+
FATAL("Failed to create extraction directory");
|
|
78
|
+
goto cleanup;
|
|
79
|
+
}
|
|
80
|
+
DEBUG("Created extraction directory: %s", extract_dir);
|
|
65
81
|
}
|
|
66
82
|
|
|
67
|
-
DEBUG("Created extraction directory: %s", extract_dir);
|
|
68
|
-
|
|
69
83
|
/* Unpacking process */
|
|
70
84
|
if (!ProcessImage(unpack_ctx)) {
|
|
71
85
|
FATAL("Failed to unpack image due to invalid or corrupted data");
|
|
@@ -87,12 +101,41 @@ int main(int argc, char *argv[])
|
|
|
87
101
|
goto cleanup;
|
|
88
102
|
}
|
|
89
103
|
|
|
104
|
+
/* Resolve the executable's directory when the script should start
|
|
105
|
+
with its working directory next to the .exe (--chdir-exe-dir). */
|
|
106
|
+
if (IsChdirToExeDir(op_modes)) {
|
|
107
|
+
exe_dir = GetParentPath(image_path);
|
|
108
|
+
if (!exe_dir) {
|
|
109
|
+
FATAL("Failed to resolve the executable directory");
|
|
110
|
+
goto cleanup;
|
|
111
|
+
}
|
|
112
|
+
DEBUG("Will start script in executable directory: %s", exe_dir);
|
|
113
|
+
}
|
|
114
|
+
#ifdef __COSMOPOLITAN__
|
|
115
|
+
/*
|
|
116
|
+
This stub is itself an APE. It fork/execs the payload interpreter and
|
|
117
|
+
reads the result with WEXITSTATUS() (system_utils_posix.c), so on
|
|
118
|
+
Windows the child must keep Cosmopolitan's wait-status exit encoding
|
|
119
|
+
(status << 8) -- otherwise `exit 3` would come back looking like death
|
|
120
|
+
by signal 3. CosmoRuby reports the plain status by default now, which
|
|
121
|
+
is right for a native parent but wrong for this one; the variable asks
|
|
122
|
+
it for the old encoding. Harmless for interpreters that do not know
|
|
123
|
+
the variable, and a no-op off Windows. This process still reports the
|
|
124
|
+
plain status to ITS native parent, at the end of main().
|
|
125
|
+
*/
|
|
126
|
+
DEBUG("Set 'COSMORUBY_WAIT_STATUS_EXIT' so the payload's status survives waitpid()");
|
|
127
|
+
if (!SetEnvVar("COSMORUBY_WAIT_STATUS_EXIT", "1")) {
|
|
128
|
+
FATAL("The script cannot be launched due to a configuration error");
|
|
129
|
+
goto cleanup;
|
|
130
|
+
}
|
|
131
|
+
#endif
|
|
132
|
+
|
|
90
133
|
/*
|
|
91
134
|
RunScript uses the current value of status as its initial value
|
|
92
135
|
and then overwrites it with the external script’s return code.
|
|
93
136
|
*/
|
|
94
137
|
DEBUG("Run application script");
|
|
95
|
-
if (!RunScript(argv, IsChdirBeforeScript(op_modes), &status)) {
|
|
138
|
+
if (!RunScript(argv, IsChdirBeforeScript(op_modes), exe_dir, &status)) {
|
|
96
139
|
FATAL("Failed to run script");
|
|
97
140
|
goto cleanup;
|
|
98
141
|
}
|
|
@@ -110,6 +153,10 @@ cleanup:
|
|
|
110
153
|
free(image_path);
|
|
111
154
|
}
|
|
112
155
|
|
|
156
|
+
if (exe_dir) {
|
|
157
|
+
free(exe_dir);
|
|
158
|
+
}
|
|
159
|
+
|
|
113
160
|
if (unpack_ctx) {
|
|
114
161
|
ClosePackFile(unpack_ctx);
|
|
115
162
|
unpack_ctx = NULL;
|
|
@@ -120,7 +167,9 @@ cleanup:
|
|
|
120
167
|
/*
|
|
121
168
|
If AUTO_CLEAN_INST_DIR is set, delete the extraction directory.
|
|
122
169
|
*/
|
|
123
|
-
|
|
170
|
+
/* Never delete in RUN_IN_EXE_DIR mode: the "installation directory"
|
|
171
|
+
is the real application directory, not a temporary extraction dir. */
|
|
172
|
+
if (IsAutoCleanInstDir(op_modes) && !IsRunInExeDir(op_modes)) {
|
|
124
173
|
DEBUG("Deleting extraction directory: %s", extract_dir);
|
|
125
174
|
if (!DeleteInstDir()) {
|
|
126
175
|
DEBUG("Failed to delete extraction directory");
|
|
@@ -129,5 +178,17 @@ cleanup:
|
|
|
129
178
|
|
|
130
179
|
FreeInstDir();
|
|
131
180
|
extract_dir = NULL;
|
|
181
|
+
|
|
182
|
+
#ifdef __COSMOPOLITAN__
|
|
183
|
+
/* On Windows, Cosmopolitan Libc's exit path encodes the full wait
|
|
184
|
+
status into the process exit code (code << 8) so that cosmo
|
|
185
|
+
parents can reconstruct it. Native Windows parents (cmd,
|
|
186
|
+
PowerShell, CI runners) expect the plain code, so bypass the
|
|
187
|
+
libc exit path and report the code as-is. */
|
|
188
|
+
if (IsWindows()) {
|
|
189
|
+
fflush(NULL);
|
|
190
|
+
ExitProcess(status);
|
|
191
|
+
}
|
|
192
|
+
#endif
|
|
132
193
|
return status;
|
|
133
194
|
}
|
data/src/system_utils.c
CHANGED
|
@@ -96,6 +96,32 @@ char *JoinPath(const char *p1, const char *p2)
|
|
|
96
96
|
return joined_path;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
char *ToLongPath(const char *path)
|
|
100
|
+
{
|
|
101
|
+
if (!path) {
|
|
102
|
+
return NULL;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
DWORD required = GetLongPathName(path, NULL, 0);
|
|
106
|
+
if (required == 0) {
|
|
107
|
+
return _strdup(path); /* e.g. path does not exist - keep as is */
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
char *buf = malloc(required);
|
|
111
|
+
if (!buf) {
|
|
112
|
+
APP_ERROR("Memory allocation failed for long path");
|
|
113
|
+
return NULL;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
DWORD written = GetLongPathName(path, buf, required);
|
|
117
|
+
if (written == 0 || written >= required) {
|
|
118
|
+
free(buf);
|
|
119
|
+
return _strdup(path);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return buf;
|
|
123
|
+
}
|
|
124
|
+
|
|
99
125
|
char *GetParentPath(const char *path)
|
|
100
126
|
{
|
|
101
127
|
if (!path) {
|
data/src/system_utils.h
CHANGED
|
@@ -102,6 +102,20 @@ char *GetImagePath(void);
|
|
|
102
102
|
*/
|
|
103
103
|
char *GetTempDirectoryPath(void);
|
|
104
104
|
|
|
105
|
+
/**
|
|
106
|
+
* @brief Normalizes a path to its long form.
|
|
107
|
+
*
|
|
108
|
+
* On Windows, converts 8.3 short names (e.g. "C:\\Users\\RUNNER~1") to the
|
|
109
|
+
* full long path via GetLongPathName. Two spellings of the same directory
|
|
110
|
+
* would otherwise defeat Ruby's $LOADED_FEATURES deduplication, causing
|
|
111
|
+
* files to be loaded twice ("already initialized constant" warnings).
|
|
112
|
+
* On POSIX this simply returns a copy of the given path.
|
|
113
|
+
*
|
|
114
|
+
* @return A newly allocated string (caller frees), or NULL on allocation
|
|
115
|
+
* failure. Falls back to a copy of the input if conversion fails.
|
|
116
|
+
*/
|
|
117
|
+
char *ToLongPath(const char *path);
|
|
118
|
+
|
|
105
119
|
/**
|
|
106
120
|
* @brief Writes the contents of a buffer to the specified file path.
|
|
107
121
|
* Creates any missing parent directories and overwrites existing files.
|
data/src/system_utils_posix.c
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#ifdef __APPLE__
|
|
2
2
|
#include <mach-o/dyld.h>
|
|
3
3
|
#endif
|
|
4
|
+
#ifdef __COSMOPOLITAN__
|
|
5
|
+
#include <cosmo.h> /* GetProgramExecutableName() */
|
|
6
|
+
#endif
|
|
4
7
|
#include <unistd.h>
|
|
5
8
|
#include <fcntl.h>
|
|
6
9
|
#include <sys/stat.h>
|
|
@@ -360,6 +363,23 @@ bool ExportFile(const char *path, const void *buffer, size_t buffer_size) {
|
|
|
360
363
|
/* ===== Path utilities ===== */
|
|
361
364
|
|
|
362
365
|
char *GetImagePath(void) {
|
|
366
|
+
#ifdef __COSMOPOLITAN__
|
|
367
|
+
/* Cosmopolitan Libc defines neither __linux__ nor __APPLE__; it resolves
|
|
368
|
+
the executable path itself on every OS the APE binary runs on. */
|
|
369
|
+
const char *exe = GetProgramExecutableName();
|
|
370
|
+
if (!exe || !*exe) {
|
|
371
|
+
FATAL("GetImagePath: GetProgramExecutableName failed");
|
|
372
|
+
return NULL;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
char *result = strdup(exe);
|
|
376
|
+
if (!result) {
|
|
377
|
+
FATAL("GetImagePath: strdup failed");
|
|
378
|
+
return NULL;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return result;
|
|
382
|
+
#else
|
|
363
383
|
static char path_buffer[4096];
|
|
364
384
|
#ifdef __APPLE__
|
|
365
385
|
uint32_t size = sizeof(path_buffer);
|
|
@@ -388,10 +408,30 @@ char *GetImagePath(void) {
|
|
|
388
408
|
|
|
389
409
|
strcpy(result, path_buffer);
|
|
390
410
|
return result;
|
|
411
|
+
#endif /* __COSMOPOLITAN__ */
|
|
391
412
|
}
|
|
392
413
|
|
|
393
414
|
char *GetTempDirectoryPath(void) {
|
|
394
415
|
const char *tmpdir = getenv("TMPDIR");
|
|
416
|
+
#ifdef __COSMOPOLITAN__
|
|
417
|
+
/* On Windows, Cosmopolitan Libc translates the magic "/tmp" prefix to
|
|
418
|
+
a real directory, but WHERE it points differs between cosmo
|
|
419
|
+
releases (%TMP% in some, C:\tmp in others). This stub and the
|
|
420
|
+
packed cosmopolitan Ruby may be built against different cosmo
|
|
421
|
+
versions, so a literal "/tmp/..." extraction path handed to the
|
|
422
|
+
child can resolve to a DIFFERENT directory than the one the stub
|
|
423
|
+
extracted into. TMP/TEMP, by contrast, are presented by cosmo in
|
|
424
|
+
its unambiguous drive-letter form (e.g. /C/Users/x/AppData/Local/
|
|
425
|
+
Temp) that every cosmo runtime resolves identically, so prefer
|
|
426
|
+
them. On POSIX hosts they are normally unset and the usual
|
|
427
|
+
TMPDIR -> /tmp behavior is preserved. */
|
|
428
|
+
if (!tmpdir || !*tmpdir) {
|
|
429
|
+
tmpdir = getenv("TMP");
|
|
430
|
+
}
|
|
431
|
+
if (!tmpdir || !*tmpdir) {
|
|
432
|
+
tmpdir = getenv("TEMP");
|
|
433
|
+
}
|
|
434
|
+
#endif
|
|
395
435
|
if (!tmpdir || !*tmpdir) {
|
|
396
436
|
tmpdir = "/tmp";
|
|
397
437
|
}
|
|
@@ -498,3 +538,9 @@ bool CreateAndWaitForProcess(const char *app_name, char *argv[], int *exit_code)
|
|
|
498
538
|
|
|
499
539
|
return true;
|
|
500
540
|
}
|
|
541
|
+
|
|
542
|
+
/* POSIX has no short-path aliases - return a plain copy. */
|
|
543
|
+
char *ToLongPath(const char *path)
|
|
544
|
+
{
|
|
545
|
+
return path ? strdup(path) : NULL;
|
|
546
|
+
}
|
data/src/unpack.c
CHANGED
|
@@ -536,6 +536,14 @@ bool IsDataCompressed(OperationModes modes) {
|
|
|
536
536
|
return IsMode(modes, DATA_COMPRESSED);
|
|
537
537
|
}
|
|
538
538
|
|
|
539
|
+
bool IsRunInExeDir(OperationModes modes) {
|
|
540
|
+
return IsMode(modes, RUN_IN_EXE_DIR);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
bool IsChdirToExeDir(OperationModes modes) {
|
|
544
|
+
return IsMode(modes, CHDIR_TO_EXE_DIR);
|
|
545
|
+
}
|
|
546
|
+
|
|
539
547
|
bool ProcessImage(const UnpackContext *context)
|
|
540
548
|
{
|
|
541
549
|
if (!context) {
|
data/src/unpack.h
CHANGED
|
@@ -66,6 +66,23 @@ typedef enum {
|
|
|
66
66
|
* required before using the data.
|
|
67
67
|
*/
|
|
68
68
|
DATA_COMPRESSED = 0x10,
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Runs the application directly from the executable's own directory
|
|
72
|
+
* instead of creating an extraction directory. Used by installer builds
|
|
73
|
+
* (e.g. Inno Setup) where the application files are installed next to
|
|
74
|
+
* the stub executable. Restores the pre-1.4 (OCRA) wrapper behavior.
|
|
75
|
+
*/
|
|
76
|
+
RUN_IN_EXE_DIR = 0x20,
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Change the current directory to the directory containing the
|
|
80
|
+
* executable before running the script. This makes relative file
|
|
81
|
+
* access resolve next to the .exe, regardless of how it was invoked
|
|
82
|
+
* (Explorer, command prompt, file association). Opt-in via the
|
|
83
|
+
* --chdir-exe-dir build option.
|
|
84
|
+
*/
|
|
85
|
+
CHDIR_TO_EXE_DIR = 0x40,
|
|
69
86
|
} OperationModes;
|
|
70
87
|
|
|
71
88
|
bool IsDebugMode(OperationModes modes);
|
|
@@ -73,6 +90,8 @@ bool IsExtractToExeDir(OperationModes modes);
|
|
|
73
90
|
bool IsAutoCleanInstDir(OperationModes modes);
|
|
74
91
|
bool IsChdirBeforeScript(OperationModes modes);
|
|
75
92
|
bool IsDataCompressed(OperationModes modes);
|
|
93
|
+
bool IsRunInExeDir(OperationModes modes);
|
|
94
|
+
bool IsChdirToExeDir(OperationModes modes);
|
|
76
95
|
|
|
77
96
|
typedef struct UnpackContext UnpackContext;
|
|
78
97
|
|
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.4.
|
|
4
|
+
version: 1.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andi Idogawa
|
|
@@ -25,27 +25,13 @@ dependencies:
|
|
|
25
25
|
- - "~>"
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
27
|
version: '1.0'
|
|
28
|
-
description:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- Self-extracting executable (.exe on Windows, native binary on Linux/macOS)
|
|
36
|
-
- Directory with a launch script (--output-dir)
|
|
37
|
-
- Zip archive with a launch script (--output-zip)
|
|
38
|
-
|
|
39
|
-
This is a fork of OCRA maintained for Ruby 3.2+ compatibility.
|
|
40
|
-
Migration guide: replace OCRA_EXECUTABLE with OCRAN_EXECUTABLE in your code.
|
|
41
|
-
|
|
42
|
-
Usage:
|
|
43
|
-
ocran helloworld.rb # builds helloworld.exe / helloworld
|
|
44
|
-
ocran --output-dir out/ app.rb
|
|
45
|
-
ocran --output-zip app.zip app.rb
|
|
46
|
-
|
|
47
|
-
See readme at https://github.com/largo/ocran
|
|
48
|
-
Report problems at https://github.com/largo/ocran/issues
|
|
28
|
+
description: 'OCRAN (One-Click Ruby Application Next) packages Ruby applications for
|
|
29
|
+
distribution on Windows, Linux, and macOS. It bundles your script, the Ruby interpreter,
|
|
30
|
+
gems, and native libraries into a self-contained artifact that runs without Ruby
|
|
31
|
+
installed on the target machine: a self-extracting executable (default), a directory
|
|
32
|
+
(--output-dir), a zip archive (--output-zip), or a macOS .app bundle (--macosx-bundle).
|
|
33
|
+
Fork of OCRA maintained for Ruby 3.2+; migrating code should replace OCRA_EXECUTABLE
|
|
34
|
+
with OCRAN_EXECUTABLE.'
|
|
49
35
|
email:
|
|
50
36
|
- andi@idogawa.com
|
|
51
37
|
executables:
|
|
@@ -64,6 +50,7 @@ files:
|
|
|
64
50
|
- lib/ocran/build_facade.rb
|
|
65
51
|
- lib/ocran/build_helper.rb
|
|
66
52
|
- lib/ocran/command_output.rb
|
|
53
|
+
- lib/ocran/cosmo_toolchain.rb
|
|
67
54
|
- lib/ocran/dir_builder.rb
|
|
68
55
|
- lib/ocran/direction.rb
|
|
69
56
|
- lib/ocran/ed_icon.rb
|
|
@@ -73,15 +60,19 @@ files:
|
|
|
73
60
|
- lib/ocran/host_config_helper.rb
|
|
74
61
|
- lib/ocran/inno_setup_script_builder.rb
|
|
75
62
|
- lib/ocran/launcher_batch_builder.rb
|
|
63
|
+
- lib/ocran/launcher_event_recorder.rb
|
|
76
64
|
- lib/ocran/library_detector.rb
|
|
77
65
|
- lib/ocran/library_detector_posix.rb
|
|
78
66
|
- lib/ocran/option.rb
|
|
79
67
|
- lib/ocran/refine_pathname.rb
|
|
68
|
+
- lib/ocran/rubyopt_processor.rb
|
|
80
69
|
- lib/ocran/runner.rb
|
|
81
70
|
- lib/ocran/runtime_environment.rb
|
|
82
71
|
- lib/ocran/stub_builder.rb
|
|
83
72
|
- lib/ocran/version.rb
|
|
84
73
|
- lib/ocran/windows_command_escaping.rb
|
|
74
|
+
- lib/ocran/zip_payload_builder.rb
|
|
75
|
+
- lib/ocran/zip_writer.rb
|
|
85
76
|
- share/ocran/lzma.exe
|
|
86
77
|
- src/Makefile
|
|
87
78
|
- src/error.c
|
|
@@ -110,7 +101,7 @@ licenses:
|
|
|
110
101
|
metadata:
|
|
111
102
|
homepage_uri: https://github.com/largo/ocran
|
|
112
103
|
source_code_uri: https://github.com/largo/ocran
|
|
113
|
-
changelog_uri: https://github.com/largo/ocran/CHANGELOG.txt
|
|
104
|
+
changelog_uri: https://github.com/largo/ocran/blob/master/CHANGELOG.txt
|
|
114
105
|
rdoc_options: []
|
|
115
106
|
require_paths:
|
|
116
107
|
- lib
|
|
@@ -125,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
125
116
|
- !ruby/object:Gem::Version
|
|
126
117
|
version: '0'
|
|
127
118
|
requirements: []
|
|
128
|
-
rubygems_version: 4.0.
|
|
119
|
+
rubygems_version: 4.0.16
|
|
129
120
|
specification_version: 4
|
|
130
121
|
summary: OCRAN (One-Click Ruby Application Next) packages Ruby applications for distribution
|
|
131
122
|
on Windows, Linux, and macOS.
|