-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
130 lines (119 loc) · 3.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// jbash - v1.69.0
// https://github.com/bradymholt/jbash#readme
global.options = global.options || {};
global.options.errexit = (typeof global.options.errexit === 'undefined') ? false : global.options.errexit;
global.options.xtrace = (typeof global.options.xtrace === 'undefined') ? false : global.options.xtrace;
global.set = (opt) => {
if (!opt.match(/^(-|\+)/)) {
throw new Error("Invalid set value");
}
let val = opt[0] == "-";
switch (opt[1]) {
case "x":
global.options.xtrace = val;
case "e":
global.options.errexit = val;
}
};
// Aliases
global.args = process.argv.slice(global.shebangInvoked ? 3 : 2);
// Current filename aliased as $0
const path = require("path");
if (global.scriptName) {
// global.scriptName is set by ./bin scripts and used when jBash is used via npx
global[`$0`] = global.scriptName;
} else if (!!module.parent) {
global[`$0`] = path.basename(module.parent.filename);
} else {
global[`$0`] = path.basename(process.argv[0]);
}
// Arguments aliased as $1, $2, etc.
// $1 through $10, at a minimum, will be declared and have argument value or be set to undefined if not specified
for (let i = 1; i <= Math.max(10, args.length); i++) {
if (args.length >= i) {
global[`$${i}`] = args[i - 1];
} else {
global[`$${i}`] = undefined;
}
}
global.cd = process.chdir;
global.exit = process.exit;
global.env = process.env;
// Environmental variables prefixed with $
for (let p in env) {
global[`$${p}`] = env[p];
}
// File access
const fs = require("fs");
global.readFile = (path, encoding = "utf-8") => {
return fs.readFileSync(path, { encoding });
};
global.writeFile = (path, contents, encoding = "utf-8") => {
fs.writeFileSync(path, contents, { encoding });
};
global.cat = global.readFile;
global.printf = (contents) => {
process.stdout.write(contents);
};
global.echo = (contents, outPath, encoding) => {
if (outPath === undefined) {
global.printf(contents + "\n");
} else {
global.writeFile(outPath, contents, encoding);
}
};
global.dirExists = (path) => {
return fs.existsSync(path) && fs.statSync(path).isDirectory();
};
global.mkdir = (path) => {
if (!fs.existsSync(path)) {
fs.mkdirSync(path);
}
};
global.rmdir = (path) => {
if (fs.existsSync(path)) {
fs.rmdirSync(path);
}
};
// Command execution
global["$"] = (cmd, stream) => {
if (global["options"].xtrace) {
global.echo(cmd);
}
let result = require("child_process").spawnSync(cmd, [], {
stdio: [0, stream ? "inherit" : "pipe", stream ? "inherit" : "pipe"],
shell: "/bin/bash",
});
if (result.status != 0) {
let stderr = result.stderr ? result.stderr.toString().replace("/bin/sh: ", "") : null;
let msg = stderr || `Error running: ${cmd}`;
if (global.options.errexit) {
err = new Error(msg);
err.status = result.status;
err.stderr = stderr;
err.output = result.output;
throw err;
} else {
process.stderr.write(msg + "\n");
}
return !stream ? msg : null;
}
return !!result.stdout ? result.stdout.toString().replace(/^\n|\n$/g, "") : null;
};
global.eval = (cmd) => {
return $(cmd, true);
};
global.exec = eval;
// Error handling
const handleUnhandledError = (err) => {
if (global.options.errexit) {
// Since errexit is on, error message was not printed when error was thrown.
// But, now we know the error was not handled so print the error (on stderr) before we exit.
process.stderr.write(err.message + "\n");
exit(err.status || 1);
} else {
throw err;
}
};
process.on("unhandledRejection", handleUnhandledError);
process.on("uncaughtException", handleUnhandledError);