@@ -9,10 +9,16 @@ const VERSIONS_JSON = 'https://ziglang.org/download/index.json';
99const MACH_VERSIONS_JSON = 'https://pkg.machengine.org/zig/index.json' ;
1010const 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
1417const MACH_ZIG_VERSION_REGEX = / \. \s * m a c h _ z i g _ v e r s i o n \s * = \s * " ( .* ?) " / ;
1518const MINIMUM_ZIG_VERSION_REGEX = / \. \s * m i n i m u m _ z i g _ v e r s i o n \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 * \. g l o b a l _ c a c h e _ d i r = " ( .* ) " , $ / m;
1622
1723let _cached_version = null ;
1824async function getVersion ( ) {
@@ -200,15 +206,46 @@ async function getCachePrefix() {
200206}
201207
202208async 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
214251async function getTarballCachePath ( ) {
0 commit comments