Skip to content

Commit 8d6198c

Browse files
committed
Handle zig env being ZON instead of JSON
1 parent 475c97b commit 8d6198c

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

common.js

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ const VERSIONS_JSON = 'https://ziglang.org/download/index.json';
99
const MACH_VERSIONS_JSON = 'https://pkg.machengine.org/zig/index.json';
1010
const CACHE_PREFIX = "setup-zig-global-cache-";
1111

12+
// The following regexes pull specific values out of ZON.
13+
// This is bad and should be replaced with an actual parser -- see #50.
14+
1215
// Mach uses `mach_zig_version` in `build.zig.zon` to signify Mach nominated versions.
1316
// See: https://github.com/marler8997/anyzig?tab=readme-ov-file#mach-versions-and-download-mirror
1417
const MACH_ZIG_VERSION_REGEX = /\.\s*mach_zig_version\s*=\s*"(.*?)"/;
1518
const MINIMUM_ZIG_VERSION_REGEX = /\.\s*minimum_zig_version\s*=\s*"(.*?)"/;
19+
// This is tied quite precisely to the output of `zig env`. It's just a temporary workaround until
20+
// I get around to implementing a ZON parser here.
21+
const ZIG_ENV_CACHE_DIR_REGEX = /^\s*\.global_cache_dir = "(.*)",$/m;
1622

1723
let _cached_version = null;
1824
async function getVersion() {
@@ -200,15 +206,46 @@ async function getCachePrefix() {
200206
}
201207

202208
async function getZigCachePath() {
203-
let env_output = '';
204-
await exec.exec('zig', ['env'], {
205-
listeners: {
206-
stdout: (data) => {
207-
env_output += data.toString();
208-
},
209-
},
210-
});
211-
return JSON.parse(env_output)['global_cache_dir'];
209+
const env_zon = (await exec.getExecOutput('zig', ['env'])).stdout;
210+
if (env_zon[0] !== '.') {
211+
// JSON (legacy)
212+
return JSON.parse(env_zon)['global_cache_dir'];
213+
}
214+
const match = ZIG_ENV_CACHE_DIR_REGEX.exec(env_zon);
215+
if (!match) throw new Error("Failed to parse cache directory from 'zig env' output");
216+
return parseZigString(match[1]);
217+
}
218+
function parseZigString(raw) {
219+
// This function is neither complete (Unicode codepoint literals), nor correct (byte-escapes
220+
// aren't really compatible with JS "strings"). It's just a temporary best-effort implementation
221+
// which can hopefully handle any real-world directory path we encounter.
222+
let result = "";
223+
let i = 0;
224+
while (i < raw.length) {
225+
if (raw[i] != '\\') {
226+
result += raw[i];
227+
i += 1;
228+
continue;
229+
}
230+
i += 2;
231+
switch (raw[i - 1]) {
232+
case 'n': result += '\n'; break;
233+
case 'r': result += '\r'; break;
234+
case '\\': result += '\\'; break;
235+
case 't': result += '\t'; break;
236+
case '\'': result += '\''; break;
237+
case '"': result += '"'; break;
238+
case 'x': {
239+
const byte_val = parseInt(raw.slice(i, i + 2), 16);
240+
result += String.fromCharCode(byte_val);
241+
i += 2;
242+
break;
243+
}
244+
case 'u': throw new Error("unsupported Unicode codepoint literal in string");
245+
default: throw new Error("invalid escape code in string");
246+
}
247+
}
248+
return result;
212249
}
213250

214251
async function getTarballCachePath() {

0 commit comments

Comments
 (0)