@elixir-playground/git 0.0.0-stage → 1.0.0

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.
Files changed (43) hide show
  1. package/NOTICE.md +15 -0
  2. package/fs/bundles/0.tar +0 -0
  3. package/fs/manifest.json +1 -0
  4. package/git.wasm +0 -0
  5. package/index.d.ts +4 -0
  6. package/index.js +34 -0
  7. package/licenses/git-2.56.0/COPYING +360 -0
  8. package/licenses/git-2.56.0/LGPL-2.1 +511 -0
  9. package/licenses/index.json +51 -0
  10. package/licenses/wasi-compat-playground/LICENSE +18 -0
  11. package/licenses/wasi-libc-2e6fb9d8ee0c/LICENSE +17 -0
  12. package/licenses/wasi-libc-2e6fb9d8ee0c/LICENSE-APACHE +201 -0
  13. package/licenses/wasi-libc-2e6fb9d8ee0c/LICENSE-APACHE-LLVM +220 -0
  14. package/licenses/wasi-libc-2e6fb9d8ee0c/LICENSE-MIT +23 -0
  15. package/licenses/wasi-libc-2e6fb9d8ee0c/cloudlibc-LICENSE +22 -0
  16. package/licenses/wasi-libc-2e6fb9d8ee0c/musl-COPYRIGHT +193 -0
  17. package/licenses/wasi-libc-2e6fb9d8ee0c/musl-fts-COPYING +26 -0
  18. package/licenses/zlib-1.3.2/LICENSE +22 -0
  19. package/package.json +44 -4
  20. package/source/git/README.md +17 -0
  21. package/source/git/git-2.56.0.tar.xz +0 -0
  22. package/source/git/tools/git/build.py +168 -0
  23. package/source/git/tools/git/config.mak +42 -0
  24. package/source/git/tools/git/patches/0001-wasi-spawn.patch +76 -0
  25. package/source/git/tools/git/patches/0002-wasi-async.patch +124 -0
  26. package/source/git/tools/wasi-compat/LICENSE +18 -0
  27. package/source/git/tools/wasi-compat/autoconf.py +158 -0
  28. package/source/git/tools/wasi-compat/config.site +31 -0
  29. package/source/git/tools/wasi-compat/include/grp.h +6 -0
  30. package/source/git/tools/wasi-compat/include/mntent.h +10 -0
  31. package/source/git/tools/wasi-compat/include/netdb.h +7 -0
  32. package/source/git/tools/wasi-compat/include/paths.h +2 -0
  33. package/source/git/tools/wasi-compat/include/pwd.h +5 -0
  34. package/source/git/tools/wasi-compat/include/setjmp.h +17 -0
  35. package/source/git/tools/wasi-compat/include/sys/wait.h +8 -0
  36. package/source/git/tools/wasi-compat/include/syslog.h +7 -0
  37. package/source/git/tools/wasi-compat/include/termios.h +10 -0
  38. package/source/git/tools/wasi-compat/include/wasi-compat.h +38 -0
  39. package/source/git/tools/wasi-compat/include/wasi-posix.h +79 -0
  40. package/source/git/tools/wasi-compat/stubs.c +326 -0
  41. package/source/git/tools/wasi-compat/wrap.c +54 -0
  42. package/source/git/zlib-1.3.2.tar.gz +0 -0
  43. package/README.md +0 -3
@@ -0,0 +1,326 @@
1
+ /* What WASI preview 1 lacks and the C tools (git, sed, …) link against:
2
+ processes, users, modes, terminals and sockets. Processes are the
3
+ playground's host's (its `processes` imports:
4
+ app/src/runtime/processes.ts); the rest says so (ENOSYS) or answers as
5
+ a single user would. Built with wasi-compat.h forced in, as git's files
6
+ are; a tool links what it uses (wasm-ld drops the rest, and with it
7
+ imports nothing calls). */
8
+ #include <errno.h>
9
+ #include <fcntl.h>
10
+ #include <netdb.h>
11
+ #include <pwd.h>
12
+ #include <grp.h>
13
+ #include <stdio.h>
14
+ #include <stdlib.h>
15
+ #include <string.h>
16
+ #include <sys/stat.h>
17
+ #include <sys/wait.h>
18
+ #include <termios.h>
19
+ #include <unistd.h>
20
+ #include <wasi/api.h>
21
+
22
+ #define NOSYS(...) { errno = ENOSYS; return __VA_ARGS__; }
23
+
24
+ /* The calls themselves (wasi-compat.h renames them), and the permission
25
+ bits a POSIX system would have given. */
26
+ #undef stat
27
+ #undef lstat
28
+ #undef fstat
29
+ int stat(const char *, struct stat *);
30
+ int lstat(const char *, struct stat *);
31
+ int fstat(int, struct stat *);
32
+ static int moded(int result, struct stat *st) {
33
+ if (result == 0) {
34
+ if (S_ISDIR(st->st_mode)) st->st_mode |= 0755;
35
+ else if (S_ISLNK(st->st_mode)) st->st_mode |= 0777;
36
+ else st->st_mode |= 0644;
37
+ }
38
+ return result;
39
+ }
40
+ int wasi_stat(const char *path, struct stat *st) { return moded(stat(path, st), st); }
41
+ int wasi_lstat(const char *path, struct stat *st) { return moded(lstat(path, st), st); }
42
+ int wasi_fstat(int fd, struct stat *st) { return moded(fstat(fd, st), st); }
43
+
44
+ #define HOST(name) __attribute__((import_module("processes"), import_name(#name)))
45
+ HOST(pipe) int host_pipe(int *fds);
46
+ HOST(spawn) int host_spawn(const char *request, size_t length, int in, int out, int err, int *pid);
47
+ HOST(wait) int host_wait(int pid, int *status, int nohang);
48
+ HOST(kill) int host_kill(int pid, int signal);
49
+ HOST(dup) int host_dup(int fd, int *opened);
50
+ HOST(dup2) int host_dup2(int fd, int to);
51
+ HOST(async_start) int host_async_start(void *async, void *top, int *pid);
52
+ HOST(async_current) void *host_async_current(void);
53
+ HOST(async_exit) _Noreturn void host_async_exit(int code);
54
+
55
+ static int answer(int error) {
56
+ if (!error) return 0;
57
+ errno = error;
58
+ return -1;
59
+ }
60
+
61
+ int pipe(int fds[2]) { return answer(host_pipe(fds)); }
62
+ int dup(int fd) {
63
+ int opened;
64
+ return answer(host_dup(fd, &opened)) ? -1 : opened;
65
+ }
66
+ int dup2(int fd, int to) { return answer(host_dup2(fd, to)) ? -1 : to; }
67
+ int kill(pid_t pid, int signal) { return answer(host_kill(pid, signal)); }
68
+ pid_t waitpid(pid_t pid, int *status, int options) {
69
+ int got = 0;
70
+ int error = host_wait(pid, &got, options & WNOHANG);
71
+ if (error == EAGAIN) return 0;
72
+ if (answer(error)) return -1;
73
+ if (status) *status = got;
74
+ return pid;
75
+ }
76
+
77
+ /* An async's C stack: what sideband_demux and its kind need (git's own
78
+ is 1 MiB, config.mak). */
79
+ #define ASYNC_STACK (512 << 10)
80
+
81
+ pid_t wasi_async_start(void *async, void **stack) {
82
+ int pid;
83
+ char *base = malloc(ASYNC_STACK);
84
+ *stack = base;
85
+ if (!base) return answer(ENOMEM);
86
+ if (answer(host_async_start(async, base + ASYNC_STACK, &pid))) {
87
+ free(base);
88
+ *stack = NULL;
89
+ return -1;
90
+ }
91
+ return pid;
92
+ }
93
+ void *wasi_async_current(void) { return host_async_current(); }
94
+ _Noreturn void wasi_async_exit(int code) { host_async_exit(code); }
95
+
96
+ /* The host runs argv[0] (by name, as the shell finds it) in `dir` (else
97
+ here), with `env` as its environment and our in, out and err as its
98
+ standard streams: its pid, or -1 (ENOENT: no such program). */
99
+ pid_t wasi_spawn(const char **argv, char **env, const char *dir, int in, int out, int err) {
100
+ char here[4096];
101
+ static char joined[8192];
102
+ if (!dir) dir = getcwd(here, sizeof here) ? here : "/";
103
+ else if (dir[0] != '/') {
104
+ snprintf(joined, sizeof joined, "%s/%s", getcwd(here, sizeof here) ? here : "", dir);
105
+ dir = joined;
106
+ }
107
+ /* NUL-separated: program, directory, argc, arguments, envc, environment. */
108
+ size_t argc = 0, envc = 0;
109
+ while (argv[argc]) argc++;
110
+ while (env && env[envc]) envc++;
111
+ char args[24], envs[24];
112
+ snprintf(args, sizeof args, "%zu", argc - 1);
113
+ snprintf(envs, sizeof envs, "%zu", envc);
114
+ size_t length = strlen(dir) + strlen(args) + strlen(envs) + 3;
115
+ for (size_t i = 0; i < argc; i++) length += strlen(argv[i]) + 1;
116
+ for (size_t i = 0; i < envc; i++) length += strlen(env[i]) + 1;
117
+ char *request = malloc(length), *at = request;
118
+ at = stpcpy(at, argv[0]) + 1;
119
+ at = stpcpy(at, dir) + 1;
120
+ at = stpcpy(at, args) + 1;
121
+ for (size_t i = 1; i < argc; i++) at = stpcpy(at, argv[i]) + 1;
122
+ at = stpcpy(at, envs) + 1;
123
+ for (size_t i = 0; i < envc; i++) at = stpcpy(at, env[i]) + 1;
124
+ int pid = -1;
125
+ int error = host_spawn(request, at - request, in, out, err, &pid);
126
+ free(request);
127
+ return answer(error) ? -1 : pid;
128
+ }
129
+
130
+ /* popen and system: `sh -c COMMAND` (the host's sh, brush), its output
131
+ or input a pipe of ours. */
132
+ static struct { FILE *file; pid_t pid; } opened[16];
133
+ FILE *popen(const char *command, const char *mode) {
134
+ int reading = mode[0] == 'r', fds[2], slot = 0;
135
+ while (slot < 16 && opened[slot].file) slot++;
136
+ if (slot == 16) { errno = EMFILE; return NULL; }
137
+ if ((mode[0] != 'r' && mode[0] != 'w') || pipe(fds)) {
138
+ if (mode[0] != 'r' && mode[0] != 'w') errno = EINVAL;
139
+ return NULL;
140
+ }
141
+ const char *argv[] = {"sh", "-c", command, NULL};
142
+ extern char **environ;
143
+ pid_t pid = reading ? wasi_spawn(argv, environ, NULL, 0, fds[1], 2)
144
+ : wasi_spawn(argv, environ, NULL, fds[0], 1, 2);
145
+ close(fds[reading]);
146
+ FILE *file = pid < 0 ? NULL : fdopen(fds[!reading], mode);
147
+ if (!file) {
148
+ close(fds[!reading]);
149
+ if (pid >= 0) waitpid(pid, NULL, 0);
150
+ return NULL;
151
+ }
152
+ opened[slot].file = file;
153
+ opened[slot].pid = pid;
154
+ return file;
155
+ }
156
+ int pclose(FILE *file) {
157
+ int slot = 0, status;
158
+ while (slot < 16 && opened[slot].file != file) slot++;
159
+ if (slot == 16) { errno = ECHILD; return -1; }
160
+ pid_t pid = opened[slot].pid;
161
+ opened[slot].file = NULL;
162
+ fclose(file);
163
+ return waitpid(pid, &status, 0) < 0 ? -1 : status;
164
+ }
165
+ int system(const char *command) {
166
+ if (!command) return 1;
167
+ const char *argv[] = {"sh", "-c", command, NULL};
168
+ extern char **environ;
169
+ int status;
170
+ pid_t pid = wasi_spawn(argv, environ, NULL, 0, 1, 2);
171
+ if (pid < 0) return -1;
172
+ return waitpid(pid, &status, 0) < 0 ? -1 : status;
173
+ }
174
+
175
+ pid_t fork(void) NOSYS(-1)
176
+ int execv(const char *p, char *const a[]) NOSYS(-1)
177
+ int execvp(const char *p, char *const a[]) NOSYS(-1)
178
+ int execve(const char *p, char *const a[], char *const e[]) NOSYS(-1)
179
+ int execl(const char *p, const char *a, ...) NOSYS(-1)
180
+ int execlp(const char *p, const char *a, ...) NOSYS(-1)
181
+ unsigned alarm(unsigned s) { return 0; }
182
+ /* No rlimits: as many descriptors as a POSIX system's default. */
183
+ int getdtablesize(void) { return 1024; }
184
+ pid_t getppid(void) { return 1; }
185
+ pid_t getpgid(pid_t p) NOSYS(-1)
186
+ /* One process group, init's. */
187
+ pid_t getpgrp(void) { return 1; }
188
+ pid_t tcgetpgrp(int fd) NOSYS(-1)
189
+ pid_t setsid(void) NOSYS(-1)
190
+ int tcgetattr(int fd, struct termios *t) { errno = ENOTTY; return -1; }
191
+ int tcsetattr(int fd, int a, const struct termios *t) { errno = ENOTTY; return -1; }
192
+ char *getpass(const char *prompt) NOSYS(NULL)
193
+
194
+ int sigaction(int n, const struct sigaction *act, struct sigaction *old) {
195
+ void (*was)(int) = act ? signal(n, act->sa_handler) : SIG_DFL;
196
+ if (old) { old->sa_handler = was; old->sa_mask = 0; old->sa_flags = 0; }
197
+ return 0;
198
+ }
199
+ static int member(int n, sigset_t *bit) {
200
+ if (n <= 0 || n > 64) { errno = EINVAL; return -1; }
201
+ *bit = 1ULL << (n - 1);
202
+ return 0;
203
+ }
204
+ int sigemptyset(sigset_t *s) { *s = 0; return 0; }
205
+ int sigfillset(sigset_t *s) { *s = ~0ULL; return 0; }
206
+ int sigaddset(sigset_t *s, int n) { sigset_t bit; if (member(n, &bit)) return -1; *s |= bit; return 0; }
207
+ int sigdelset(sigset_t *s, int n) { sigset_t bit; if (member(n, &bit)) return -1; *s &= ~bit; return 0; }
208
+ int sigismember(const sigset_t *s, int n) { sigset_t bit; if (member(n, &bit)) return -1; return (*s & bit) != 0; }
209
+ static sigset_t blocked;
210
+ int sigprocmask(int how, const sigset_t *set, sigset_t *old) {
211
+ if (old) *old = blocked;
212
+ if (!set) return 0;
213
+ if (how == SIG_BLOCK) blocked |= *set;
214
+ else if (how == SIG_UNBLOCK) blocked &= ~*set;
215
+ else if (how == SIG_SETMASK) blocked = *set;
216
+ else { errno = EINVAL; return -1; }
217
+ return 0;
218
+ }
219
+
220
+ /* One user, uid 0, who owns every file (WASI's st_uid is 0). */
221
+ uid_t getuid(void) { return 0; }
222
+ uid_t geteuid(void) { return 0; }
223
+ gid_t getgid(void) { return 0; }
224
+ gid_t getegid(void) { return 0; }
225
+ static struct passwd user;
226
+ struct passwd *getpwuid(uid_t uid) {
227
+ user.pw_name = "user";
228
+ user.pw_passwd = "";
229
+ user.pw_gecos = "";
230
+ user.pw_dir = getenv("HOME") ? getenv("HOME") : "/";
231
+ user.pw_shell = "/bin/sh";
232
+ return &user;
233
+ }
234
+ struct passwd *getpwnam(const char *name) { return getpwuid(0); }
235
+ struct group *getgrgid(gid_t gid) { return NULL; }
236
+ struct group *getgrnam(const char *name) { return NULL; }
237
+ int initgroups(const char *u, gid_t g) { return 0; }
238
+ int getgroups(int n, gid_t *groups) { return 0; }
239
+ int chown(const char *p, uid_t u, gid_t g) { return 0; }
240
+ int fchown(int fd, uid_t u, gid_t g) { return 0; }
241
+
242
+ /* No mount table to list (mntent.h): an empty one. */
243
+ #include <mntent.h>
244
+ FILE *setmntent(const char *path, const char *mode) { return fopen("/dev/null", "r"); }
245
+ struct mntent *getmntent(FILE *file) { return NULL; }
246
+ int endmntent(FILE *file) { if (file) fclose(file); return 1; }
247
+ char *hasmntopt(const struct mntent *entry, const char *option) { return NULL; }
248
+
249
+ /* No time zones: UTC. */
250
+ void tzset(void) {}
251
+
252
+ /* No umask (wasi-libc has chmod, which fails). */
253
+ mode_t umask(mode_t m) { return 022; }
254
+
255
+
256
+ static void fill(char *x) {
257
+ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
258
+ unsigned char bytes[6];
259
+ arc4random_buf(bytes, sizeof bytes);
260
+ for (int i = 0; i < 6; i++) x[i] = letters[bytes[i] % (sizeof letters - 1)];
261
+ }
262
+ static char *xxxxxx(char *template) {
263
+ size_t n = strlen(template);
264
+ if (n < 6 || strcmp(template + n - 6, "XXXXXX")) { errno = EINVAL; return NULL; }
265
+ return template + n - 6;
266
+ }
267
+ char *mkdtemp(char *template) {
268
+ char *x = xxxxxx(template);
269
+ if (!x) return NULL;
270
+ for (int tries = 0; tries < 100; tries++) {
271
+ fill(x);
272
+ if (!mkdir(template, 0700)) return template;
273
+ if (errno != EEXIST) return NULL;
274
+ }
275
+ return NULL;
276
+ }
277
+ int mkstemp(char *template) {
278
+ char *x = xxxxxx(template);
279
+ if (!x) return -1;
280
+ for (int tries = 0; tries < 100; tries++) {
281
+ fill(x);
282
+ int fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
283
+ if (fd >= 0 || errno != EEXIST) return fd;
284
+ }
285
+ return -1;
286
+ }
287
+
288
+ /* No sockets. */
289
+ int h_errno;
290
+ const char *hstrerror(int e) { return "no network on WASI"; }
291
+ struct hostent *gethostbyname(const char *n) { h_errno = 1; return NULL; }
292
+ struct servent *getservbyname(const char *n, const char *p) { return NULL; }
293
+ int socket(int d, int t, int p) NOSYS(-1)
294
+ int connect(int s, const struct sockaddr *a, socklen_t l) NOSYS(-1)
295
+ int setsockopt(int s, int l, int n, const void *v, socklen_t len) NOSYS(-1)
296
+
297
+ /* No modes: chmod succeeds and changes nothing (wasi-libc's fails). */
298
+ #undef chmod
299
+ #undef fchmod
300
+ int wasi_chmod(const char *p, mode_t m) { return 0; }
301
+ int wasi_fchmod(int fd, mode_t m) { return 0; }
302
+
303
+ /* The program's name (program_invocation_name, gnulib's getprogname and
304
+ error()), which wasi-libc has and never sets: argv[0], as musl's start
305
+ sets it. */
306
+ extern char *__progname, *__progname_full;
307
+ __attribute__((constructor)) static void program_name(void) {
308
+ __wasi_size_t argc, size;
309
+ if (__wasi_args_sizes_get(&argc, &size) || !argc) return;
310
+ char **argv = malloc(argc * sizeof *argv), *strings = malloc(size);
311
+ if (argv && strings && !__wasi_args_get((uint8_t **)argv, (uint8_t *)strings)) {
312
+ char *slash = strrchr(argv[0], '/');
313
+ __progname_full = argv[0];
314
+ __progname = slash ? slash + 1 : argv[0];
315
+ strings = NULL;
316
+ }
317
+ free(argv);
318
+ free(strings);
319
+ }
320
+
321
+ /* WASI has no working directory: the host's PWD is it (wasi-libc keeps
322
+ one for chdir, relative to the preopen). */
323
+ __attribute__((constructor)) static void working_directory(void) {
324
+ const char *pwd = getenv("PWD");
325
+ if (pwd && *pwd) chdir(pwd);
326
+ }
@@ -0,0 +1,54 @@
1
+ /* What wasi-libc does and the autoconf tools need otherwise, over its own
2
+ calls: linked with -Wl,--wrap=NAME for each (tools/wasi-compat/autoconf.py),
3
+ so that gnulib's replacements, which call the system's, get these.
4
+
5
+ fcntl's F_DUPFD and F_DUPFD_CLOEXEC, which wasi-libc's refuses (EINVAL):
6
+ dup, the host's (stubs.c), until the descriptor is at least the one
7
+ asked for (gnulib's fts duplicates its directories' descriptors so).
8
+
9
+ stat, lstat, fstat and fstatat with a mode's permission bits, which
10
+ WASI's lack: as git's (stubs.c wasi_stat), rw-r--r-- for a file,
11
+ rwxr-xr-x for a directory, rwxrwxrwx for a link (find -perm). */
12
+ #include <errno.h>
13
+ #include <fcntl.h>
14
+ #include <stdarg.h>
15
+ #include <sys/stat.h>
16
+ #include <unistd.h>
17
+
18
+ int __real_fcntl(int, int, ...);
19
+
20
+ int __wrap_fcntl(int fd, int cmd, ...) {
21
+ va_list ap;
22
+ va_start(ap, cmd);
23
+ int arg = va_arg(ap, int);
24
+ va_end(ap);
25
+ if (cmd != F_DUPFD && cmd != F_DUPFD_CLOEXEC) return __real_fcntl(fd, cmd, arg);
26
+ if (arg < 0) { errno = EINVAL; return -1; }
27
+ int below[64], count = 0, result;
28
+ while ((result = dup(fd)) >= 0 && result < arg && count < 64) below[count++] = result;
29
+ int saved = errno;
30
+ while (count) close(below[--count]);
31
+ if (result >= 0 && result < arg) { close(result); errno = EMFILE; return -1; }
32
+ errno = saved;
33
+ return result;
34
+ }
35
+
36
+ int __real_stat(const char *, struct stat *);
37
+ int __real_lstat(const char *, struct stat *);
38
+ int __real_fstat(int, struct stat *);
39
+ int __real_fstatat(int, const char *, struct stat *, int);
40
+
41
+ static int moded(int result, struct stat *st) {
42
+ if (result == 0 && !(st->st_mode & 07777)) {
43
+ if (S_ISDIR(st->st_mode)) st->st_mode |= 0755;
44
+ else if (S_ISLNK(st->st_mode)) st->st_mode |= 0777;
45
+ else st->st_mode |= 0644;
46
+ }
47
+ return result;
48
+ }
49
+ int __wrap_stat(const char *path, struct stat *st) { return moded(__real_stat(path, st), st); }
50
+ int __wrap_lstat(const char *path, struct stat *st) { return moded(__real_lstat(path, st), st); }
51
+ int __wrap_fstat(int fd, struct stat *st) { return moded(__real_fstat(fd, st), st); }
52
+ int __wrap_fstatat(int fd, const char *path, struct stat *st, int flag) {
53
+ return moded(__real_fstatat(fd, path, st, flag), st);
54
+ }
Binary file
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.