| 1 | const std = @import("std"); |
| 2 | const string = []const u8; |
| 3 | const yaml = @import("yaml"); |
| 4 | const extras = @import("extras"); |
| 5 | const root = @import("root"); |
| 6 | const build_options = root.build_options; |
| 7 | const nfs = @import("nfs"); |
| 8 | |
| 9 | const zigmod = @import("../lib.zig"); |
| 10 | const u = @import("funcs.zig"); |
| 11 | |
| 12 | // |
| 13 | // |
| 14 | |
| 15 | const gpa = std.heap.c_allocator; |
| 16 | const b = 1; |
| 17 | const kb = b * 1024; |
| 18 | const mb = kb * 1024; |
| 19 | |
| 20 | pub const ModFile = struct { |
| 21 | const Self = @This(); |
| 22 | |
| 23 | id: [48]u8, |
| 24 | name: string, |
| 25 | main: string, |
| 26 | c_include_dirs: []const string, |
| 27 | c_source_flags: []const string, |
| 28 | c_source_files: []const string, |
| 29 | deps: []zigmod.Dep, |
| 30 | yaml: yaml.Mapping, |
| 31 | root_files: []const string, |
| 32 | files: []const string, |
| 33 | rootdeps: []zigmod.Dep, |
| 34 | builddeps: []zigmod.Dep, |
| 35 | min_zig_version: ?std.SemanticVersion, |
| 36 | |
| 37 | pub fn openFile(dir: nfs.Dir, ops: nfs.Dir.OpenFileFlags) !struct { string, nfs.File } { |
| 38 | return .{ "zig.mod", dir.openFile("zig.mod", ops) catch |err| switch (err) { |
| 39 | error.ENOENT => return .{ "zigmod.yml", dir.openFile("zigmod.yml", ops) catch |err2| switch (err2) { |
| 40 | error.ENOENT => return error.ManifestNotFound, |
| 41 | else => |e2| return e2, |
| 42 | } }, |
| 43 | else => |e| return e, |
| 44 | } }; |
| 45 | } |
| 46 | |
| 47 | pub fn init(alloc: std.mem.Allocator) !Self { |
| 48 | return try from_dir(alloc, nfs.cwd(), "."); |
| 49 | } |
| 50 | |
| 51 | pub fn from_dir(alloc: std.mem.Allocator, dir: nfs.Dir, dir_path: string) !Self { |
| 52 | const file_path, const file = try openFile(dir, .{}); |
| 53 | defer file.close(); |
| 54 | const input = try file.readAllAlloc(alloc, mb); |
| 55 | const doc = try yaml.parse(alloc, input); |
| 56 | return from_mapping(alloc, doc.mapping, dir_path, file_path); |
| 57 | } |
| 58 | |
| 59 | pub fn from_mapping(alloc: std.mem.Allocator, mapping: yaml.Mapping, dir_path: string, file_path: string) !Self { |
| 60 | var id = zigmod.Dep.EMPTY; |
| 61 | std.mem.copyForwards(u8, &id, mapping.get_string("id") orelse &u.random_string(48)); |
| 62 | |
| 63 | const name = mapping.get_string("name") orelse ""; |
| 64 | const main = mapping.get_string("main") orelse ""; |
| 65 | |
| 66 | if (std.mem.indexOf(u8, name, "/")) |_| { |
| 67 | u.fail("name may not contain any '/'", .{}); |
| 68 | } |
| 69 | |
| 70 | if (mapping.get_string("min_zigmod_version")) |min_zigmod_version_raw| { |
| 71 | const meets = zigmod.meetsMinimumVersion(min_zigmod_version_raw); |
| 72 | if (meets == null) { |
| 73 | u.fail("invalid min_zigmod_version: {s}", .{min_zigmod_version_raw}); |
| 74 | } |
| 75 | if (meets.? == false) { |
| 76 | u.fail("Your Zigmod version {s} does not meet the minimum of {s} required by {s}{s}{s}", .{ build_options.version, min_zigmod_version_raw, dir_path, std.fs.path.sep_str, file_path }); |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | return Self{ |
| 81 | .id = id, |
| 82 | .name = name, |
| 83 | .main = main, |
| 84 | .c_include_dirs = try mapping.get_string_array(alloc, "c_include_dirs"), |
| 85 | .c_source_flags = try mapping.get_string_array(alloc, "c_source_flags"), |
| 86 | .c_source_files = try mapping.get_string_array(alloc, "c_source_files"), |
| 87 | .deps = try dep_list_by_name(alloc, mapping, &.{"dependencies"}, false), |
| 88 | .yaml = mapping, |
| 89 | .root_files = try mapping.get_string_array(alloc, "root_files"), |
| 90 | .files = try mapping.get_string_array(alloc, "files"), |
| 91 | .rootdeps = try dep_list_by_name(alloc, mapping, &.{ "dev_dependencies", "root_dependencies" }, false), |
| 92 | .builddeps = try dep_list_by_name(alloc, mapping, &.{ "dev_dependencies", "build_dependencies" }, true), |
| 93 | .min_zig_version = std.SemanticVersion.parse(mapping.get_string("min_zig_version") orelse "") catch null, |
| 94 | }; |
| 95 | } |
| 96 | |
| 97 | fn dep_list_by_name(alloc: std.mem.Allocator, mapping: yaml.Mapping, props: []const string, for_build: bool) std.mem.Allocator.Error![]zigmod.Dep { |
| 98 | var dep_list = std.array_list.Managed(zigmod.Dep).init(alloc); |
| 99 | errdefer dep_list.deinit(); |
| 100 | |
| 101 | for (props) |prop| { |
| 102 | if (mapping.get(prop)) |dep_seq| { |
| 103 | if (dep_seq != .sequence) continue; |
| 104 | for (dep_seq.sequence) |item| { |
| 105 | var dtype: string = undefined; |
| 106 | var path: [:0]const u8 = undefined; |
| 107 | var version: ?[:0]const u8 = null; |
| 108 | var main = item.mapping.get_string("main") orelse ""; |
| 109 | |
| 110 | if (item.mapping.get("src")) |val| { |
| 111 | var src_iter = std.mem.tokenizeScalar(u8, val.string, ' '); |
| 112 | dtype = src_iter.next().?; |
| 113 | path = try gpa.dupeZ(u8, src_iter.next().?); |
| 114 | if (src_iter.next()) |dver| { |
| 115 | version = try gpa.dupeZ(u8, dver); |
| 116 | } |
| 117 | } else { |
| 118 | dtype = item.mapping.get("type").?.string; |
| 119 | path = item.mapping.get("path").?.string; |
| 120 | } |
| 121 | if (item.mapping.get("version")) |verv| { |
| 122 | version = verv.string; |
| 123 | } |
| 124 | if (version == null) { |
| 125 | version = ""; |
| 126 | } |
| 127 | const dep_type = std.meta.stringToEnum(zigmod.Dep.Type, dtype).?; |
| 128 | if (dep_type == .local) { |
| 129 | if (version.?.len > 0) { |
| 130 | main = version.?; |
| 131 | version = ""; |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | var id = zigmod.Dep.EMPTY; |
| 136 | std.mem.copyForwards(u8, &id, item.mapping.get_string("id") orelse ""); |
| 137 | |
| 138 | try dep_list.append(zigmod.Dep{ |
| 139 | .type = dep_type, |
| 140 | .path = path, |
| 141 | .id = id, |
| 142 | .name = item.mapping.get_string("name") orelse "", |
| 143 | .main = main, |
| 144 | .version = version.?, |
| 145 | .c_include_dirs = try item.mapping.get_string_array(alloc, "c_include_dirs"), |
| 146 | .c_source_flags = try item.mapping.get_string_array(alloc, "c_source_flags"), |
| 147 | .c_source_files = try item.mapping.get_string_array(alloc, "c_source_files"), |
| 148 | .only_os = try u.list_remove(alloc, try u.split(alloc, item.mapping.get_string("only_os") orelse "", ','), ""), |
| 149 | .except_os = try u.list_remove(alloc, try u.split(alloc, item.mapping.get_string("except_os") orelse "", ','), ""), |
| 150 | .yaml = item.mapping, |
| 151 | .deps = try dep_list_by_name(alloc, item.mapping, &.{"dependencies"}, for_build), |
| 152 | .keep = std.mem.eql(u8, "true", item.mapping.get_string("keep") orelse ""), |
| 153 | .for_build = for_build, |
| 154 | }); |
| 155 | // const d = &dep_list.getLast(); |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | return dep_list.toOwnedSlice(); |
| 160 | } |
| 161 | }; |