@@ -22,39 +22,48 @@ pub fn main() !void {
2222 defer config .deinit ();
2323
2424 var zig_version : zigdcore.ZigVersion = v : {
25- const zig_ver = std .fs .cwd ().readFileAlloc (allocator , "zig.ver" , 1 << 21 ) catch | e | switch (e ) {
26- std .fs .File .OpenError .FileNotFound = > {
27- const absolute_cwd = try std .fs .cwd ().realpathAlloc (allocator , "." );
28- defer allocator .free (absolute_cwd );
29-
30- if (config .recursive_search_for_workspace_version (absolute_cwd )) | workspace_version | {
31- break :v zigdcore.ZigVersion {
32- .as_string = workspace_version ,
33- .source = .WorkspaceVer ,
34- };
35- }
36-
37- if (config .default ) | default_version | {
38- break :v zigdcore.ZigVersion {
39- .as_string = default_version ,
40- .source = .DefaultVer ,
41- };
42- }
43-
44- std .log .err ("No default, workspace, or zig.ver version was found." , .{});
45- return ;
46- },
47- else = > return e ,
48- };
25+ if (try utils .existsReadFileCwd (allocator , "zig.ver" )) | zig_ver | {
26+ // Can't error so no need for errdefer in this scope
27+ break :v zigdcore.ZigVersion {
28+ .as_string = zig_ver ,
29+ .source = .Zigver ,
30+ };
31+ }
4932
50- break :v zigdcore.ZigVersion {
51- .as_string = zig_ver ,
52- .source = .Zigver ,
53- };
33+ if (try utils .existsReadFileCwdSentinel (allocator , "build.zig.zon" )) | build_zig_zon | {
34+ defer allocator .free (build_zig_zon );
35+
36+ if (try zon_minimum_version (allocator , build_zig_zon )) | zonver | {
37+ break :v zigdcore.ZigVersion {
38+ .as_string = zonver ,
39+ .source = .Zonver ,
40+ };
41+ }
42+ }
43+
44+ const absolute_cwd = try std .fs .cwd ().realpathAlloc (allocator , "." );
45+ defer allocator .free (absolute_cwd );
46+
47+ if (config .recursive_search_for_workspace_version (absolute_cwd )) | workspace_version | {
48+ break :v zigdcore.ZigVersion {
49+ .as_string = workspace_version ,
50+ .source = .WorkspaceVer ,
51+ };
52+ }
53+
54+ if (config .default ) | default_version | {
55+ break :v zigdcore.ZigVersion {
56+ .as_string = default_version ,
57+ .source = .DefaultVer ,
58+ };
59+ }
60+
61+ std .log .err ("No default, workspace, or zig.ver version was found." , .{});
62+ return ;
5463 };
5564
5665 zig_version = try zigdcore .ZigVersion .parse (allocator , zig_version .as_string , & zig_version .source , true );
57- defer zig_version .deinitIfMasterOrZigver (allocator );
66+ defer zig_version .deinitIfMasterOrZigverOrZonver (allocator );
5867
5968 const zig_binary_path = try std .fs .path .join (allocator , &.{ zigd_path , "versions" , zig_version .as_string , "zig" ++ utils .binary_ext });
6069 defer allocator .free (zig_binary_path );
@@ -176,3 +185,56 @@ const Config = struct {
176185 self .allocator .free (self .contents );
177186 }
178187};
188+
189+ // Caller frees the returned memory
190+ fn zon_minimum_version (allocator : std.mem.Allocator , zon_contents : [:0 ]u8 ) ! ? []const u8 {
191+ var ast = try std .zig .Ast .parse (allocator , zon_contents , .zon );
192+ defer ast .deinit (allocator );
193+
194+ var ast_buf : [2 ]std.zig.Ast.Node.Index = undefined ;
195+ const root = ast .fullStructInit (& ast_buf , ast .nodes .items (.data )[0 ].lhs ) orelse return error .ZonParseError ;
196+
197+ for (root .ast .fields ) | field_idx | {
198+ const field_name = try parseFieldName (allocator , ast , field_idx );
199+ defer allocator .free (field_name );
200+
201+ if (std .mem .eql (u8 , field_name , "minimum_zig_version" )) {
202+ return try parseString (allocator , ast , field_idx );
203+ }
204+ }
205+
206+ return null ;
207+ }
208+
209+ // Caller frees memory
210+ fn parseString (allocator : std.mem.Allocator , ast : std.zig.Ast , idx : std.zig.Ast.Node.Index ) ! []const u8 {
211+ const node_tags = ast .nodes .items (.tag );
212+ const main_tokens = ast .nodes .items (.main_token );
213+ if (node_tags [idx ] != .string_literal ) {
214+ return error .ExpectedStringLiteral ;
215+ }
216+ const str_lit_token = main_tokens [idx ];
217+ const token_bytes = ast .tokenSlice (str_lit_token );
218+ return try parseStrLit (allocator , token_bytes , 0 );
219+ }
220+
221+ // Caller frees memory
222+ inline fn parseStrLit (
223+ allocator : std.mem.Allocator ,
224+ bytes : []const u8 ,
225+ offset : u32 ,
226+ ) ! []u8 {
227+ return try std .zig .string_literal .parseAlloc (allocator , bytes [offset .. ]);
228+ }
229+
230+ fn parseFieldName (
231+ alloc : std.mem.Allocator ,
232+ ast : std.zig.Ast ,
233+ idx : std.zig.Ast.Node.Index ,
234+ ) ! []const u8 {
235+ const name = ast .tokenSlice (ast .firstToken (idx ) - 2 );
236+ return if (name [0 ] == '@' ) // Escaping something, like @"hello bois"
237+ try std .zig .string_literal .parseAlloc (alloc , name [1.. ])
238+ else
239+ try alloc .dupe (u8 , name );
240+ }
0 commit comments