authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-06-01 19:59:08 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-06-01 19:59:28 -07:00
logff3bc553c65894e1dce033a7c0b89acdb97696fc
tree2f9dcf4c304841005854db6f575f74dfb83a51db
parentca018b40db988497fa08f7cb7ab4f91aab93d8ab
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

cmd/install: add 0.11 support


2 files changed, 413 insertions(+), 0 deletions(-)

src/cmd/fetch.0.11.zig created+412
......@@ -0,0 +1,412 @@
1// Adapted from https://github.com/nektro/zigmod/blob/r89/src/cmd/fetch.zig
2
3const std = @import("std");
4const string = []const u8;
5const ansi = @import("ansi");
6const extras = @import("extras");
7const nfs = @import("nfs");
8
9const zigmod = @import("../lib.zig");
10const u = @import("./../util/funcs.zig");
11const common = @import("./../common.zig");
12const license = @import("./license.zig");
13
14pub fn create_depszig(alloc: std.mem.Allocator, cachepath: string, dir: nfs.Dir, top_module: zigmod.Module, list: *std.array_list.Managed(zigmod.Module)) !void {
15 const f = try dir.createFile("deps.zig", .{});
16 defer f.close();
17
18 const w = f;
19 try w.writeAll("// zig fmt: off\n");
20 try w.writeAll("const std = @import(\"std\");\n");
21 try w.writeAll("const builtin = @import(\"builtin\");\n");
22 try w.writeAll("const string = []const u8;\n");
23 try w.writeAll("const ModuleDependency = std.build.ModuleDependency;\n");
24 try w.writeAll("\n");
25 try w.print("pub const cache = \"{}\";\n", .{u.altStringEscape(cachepath)});
26 try w.writeAll("\n");
27 try w.writeAll(
28 \\pub fn addAllTo(exe: *std.build.LibExeObjStep) void {
29 \\ checkMinZig(builtin.zig_version, exe);
30 \\ const b = exe.step.owner;
31 \\ @setEvalBranchQuota(1_000_000);
32 \\ for (packages) |pkg| {
33 \\ const moddep = pkg.zp(b);
34 \\ exe.addModule(moddep.name, moddep.module);
35 \\ }
36 \\ addAllLibrariesTo(exe);
37 \\}
38 \\
39 \\pub fn addAllLibrariesTo(exe: *std.build.LibExeObjStep) void {
40 \\ const b = exe.step.owner;
41 \\ var llc = false;
42 \\ inline for (comptime std.meta.declarations(package_data)) |decl| {
43 \\ const pkg = @as(Package, @field(package_data, decl.name));
44 \\ for (pkg.system_libs) |item| {
45 \\ exe.linkSystemLibrary(item);
46 \\ llc = true;
47 \\ }
48 \\ for (pkg.frameworks) |item| {
49 \\ if (!builtin.target.isDarwin()) @panic(b.fmt("a dependency is attempting to link to the framework {s}, which is only possible under Darwin", .{item}));
50 \\ exe.linkFramework(item);
51 \\ llc = true;
52 \\ }
53 \\ for (pkg.c_include_dirs) |item| {
54 \\ exe.addIncludePath(.{.path = b.fmt("{s}/{s}", .{ @field(dirs, decl.name), item })});
55 \\ llc = true;
56 \\ }
57 \\ for (pkg.c_source_files) |item| {
58 \\ exe.addCSourceFile(.{ .file = .{ .path = b.fmt("{s}/{s}", .{ @field(dirs, decl.name), item }) }, .flags = pkg.c_source_flags });
59 \\ llc = true;
60 \\ }
61 \\ }
62 \\ if (llc) exe.linkLibC();
63 \\}
64 \\
65 \\pub const Package = struct {
66 \\ directory: string,
67 \\ pkg: ?Pkg = null,
68 \\ c_include_dirs: []const string = &.{},
69 \\ c_source_files: []const string = &.{},
70 \\ c_source_flags: []const string = &.{},
71 \\ system_libs: []const string = &.{},
72 \\ frameworks: []const string = &.{},
73 \\ module: ?ModuleDependency = null,
74 \\
75 \\ pub fn zp(self: *Package, b: *std.build.Builder) ModuleDependency {
76 \\ var temp: [100]ModuleDependency = undefined;
77 \\ const pkg = self.pkg.?;
78 \\ for (pkg.dependencies, 0..) |item, i| {
79 \\ temp[i] = item.zp(b);
80 \\ }
81 \\ if (self.module) |mod| {
82 \\ return mod;
83 \\ }
84 \\ const result = ModuleDependency{
85 \\ .name = pkg.name,
86 \\ .module = b.createModule(.{
87 \\ .source_file = pkg.source,
88 \\ .dependencies = b.allocator.dupe(ModuleDependency, temp[0..pkg.dependencies.len]) catch @panic("oom"),
89 \\ }),
90 \\ };
91 \\ self.module = result;
92 \\ return result;
93 \\ }
94 \\};
95 \\
96 \\pub const Pkg = struct {
97 \\ name: string,
98 \\ source: std.build.FileSource,
99 \\ dependencies: []const *Package,
100 \\};
101 \\
102 \\
103 );
104
105 try w.print(
106 \\fn checkMinZig(current: std.SemanticVersion, exe: *std.build.LibExeObjStep) void {{
107 \\ const min = std.SemanticVersion.parse("{?}") catch return;
108 \\ if (current.order(min).compare(.lt)) @panic(exe.step.owner.fmt("Your Zig version v{{}} does not meet the minimum build requirement of v{{}}", .{{current, min}}));
109 \\}}
110 \\
111 \\
112 , .{if (top_module.minZigVersion()) |sv| u.altSemanticVersion(sv) else null});
113
114 try w.writeAll("pub const dirs = struct {\n");
115 try print_dirs(w, list.items);
116 try w.writeAll("};\n\n");
117
118 try w.writeAll("pub const package_data = struct {\n");
119 var duped = std.array_list.Managed(zigmod.Module).init(alloc);
120 var done = std.array_list.Managed(zigmod.Module).init(alloc);
121 for (list.items) |mod| {
122 if (mod.type == .system_lib or mod.type == .framework) {
123 continue;
124 }
125 try duped.append(mod);
126 }
127 try print_pkg_data_to(w, &duped, &done);
128 try w.writeAll("};\n\n");
129
130 try w.writeAll("pub const packages = ");
131 try print_deps(w, top_module);
132 try w.writeAll(";\n\n");
133
134 try w.writeAll("pub const pkgs = ");
135 try print_pkgs(alloc, w, top_module);
136 try w.writeAll(";\n\n");
137
138 try w.writeAll("pub const imports = struct {\n");
139 try print_imports(alloc, w, top_module, cachepath);
140 try w.writeAll("};\n");
141}
142
143fn create_lockfile(alloc: std.mem.Allocator, list: *std.array_list.Managed(zigmod.Module), path: string, dir: nfs.Dir) !void {
144 const fl = try dir.createFile("zigmod.lock", .{});
145 defer fl.close();
146
147 std.mem.sort(zigmod.Module, list.items, {}, zigmod.Module.lessThan);
148
149 const wl = fl.writer();
150 try wl.writeAll("2\n");
151 for (list.items) |m| {
152 if (m.dep) |md| {
153 if (md.type.isLocal()) continue;
154 const mpath = try std.fs.path.join(alloc, &.{ path, m.clean_path });
155 const version = try md.exact_version(alloc, mpath);
156 try wl.print("{s} {s} {s}\n", .{ @tagName(md.type), md.path, version });
157 }
158 }
159}
160
161const DiffChange = struct {
162 from: string,
163 to: string,
164};
165
166fn diff_lockfile(alloc: std.mem.Allocator) !void {
167 const max = std.math.maxInt(usize);
168
169 if (try u.does_folder_exist(".git")) {
170 const result = try u.run_cmd_raw(alloc, null, &.{ "git", "diff", "zigmod.lock" });
171 var stdout = std.io.fixedBufferStream(result.stdout);
172 const r = stdout.reader();
173 while (try r.readUntilDelimiterOrEofAlloc(alloc, '\n', max)) |line| {
174 if (std.mem.startsWith(u8, line, "@@")) break;
175 }
176
177 var rems = std.array_list.Managed(string).init(alloc);
178 var adds = std.array_list.Managed(string).init(alloc);
179 while (try r.readUntilDelimiterOrEofAlloc(alloc, '\n', max)) |line| {
180 if (line[0] == ' ') continue;
181 if (line[0] == '-') try rems.append(line[1..]);
182 if (line[0] == '+') if (line[1] == '2') continue else try adds.append(line[1..]);
183 }
184
185 var changes = std.StringHashMap(DiffChange).init(alloc);
186
187 var didbreak = false;
188 var i: usize = 0;
189 while (i < rems.items.len) {
190 const it = rems.items[i];
191 const sni = u.indexOfN(it, ' ', 2).?;
192
193 var j: usize = 0;
194 while (j < adds.items.len) {
195 const jt = adds.items[j];
196 const snj = u.indexOfN(jt, ' ', 2).?;
197
198 if (std.mem.eql(u8, it[0..sni], jt[0..snj])) {
199 try changes.put(it[0..sni], .{
200 .from = it[u.indexOfAfter(it, '-', sni).? + 1 .. it.len],
201 .to = jt[u.indexOfAfter(jt, '-', snj).? + 1 .. jt.len],
202 });
203 _ = rems.orderedRemove(i);
204 _ = adds.orderedRemove(j);
205 didbreak = true;
206 break;
207 }
208 if (!didbreak) j += 1;
209 }
210 if (!didbreak) i += 1;
211 if (didbreak) didbreak = false;
212 }
213
214 if (adds.items.len > 0) {
215 std.debug.print(comptime ansi.color.Faint("Newly added packages:\n"), .{});
216 defer std.debug.print("\n", .{});
217
218 for (adds.items) |it| {
219 std.debug.print("- {s}\n", .{it});
220 }
221 }
222
223 if (rems.items.len > 0) {
224 std.debug.print(comptime ansi.color.Faint("Removed packages:\n"), .{});
225 defer std.debug.print("\n", .{});
226
227 for (rems.items) |it| {
228 std.debug.print("- {s}\n", .{it});
229 }
230 }
231
232 if (changes.unmanaged.size > 0) std.debug.print(comptime ansi.color.Faint("Updated packages:\n"), .{});
233 var iter = changes.iterator();
234 while (iter.next()) |it| {
235 if (diff_printchange("git https://github.com", "- {s}/compare/{s}...{s}\n", it)) continue;
236 if (diff_printchange("git https://gitlab.com", "- {s}/-/compare/{s}...{s}\n", it)) continue;
237 if (diff_printchange("git https://gitea.com", "- {s}/compare/{s}...{s}\n", it)) continue;
238
239 std.debug.print("- {s}\n", .{it.key_ptr.*});
240 std.debug.print(" - {s} ... {s}\n", .{ it.value_ptr.from, it.value_ptr.to });
241 }
242 }
243}
244
245fn diff_printchange(comptime testt: string, comptime replacement: string, item: std.StringHashMap(DiffChange).Entry) bool {
246 if (std.mem.startsWith(u8, item.key_ptr.*, testt)) {
247 if (std.mem.eql(u8, item.value_ptr.from, item.value_ptr.to)) return true;
248 std.debug.print(replacement, .{ item.key_ptr.*[4..], item.value_ptr.from, item.value_ptr.to });
249 return true;
250 }
251 return false;
252}
253
254fn print_dirs(w: nfs.File, list: []const zigmod.Module) !void {
255 for (list) |mod| {
256 if (mod.type == .system_lib or mod.type == .framework) continue;
257 if (std.mem.eql(u8, &mod.id, "root")) {
258 try w.writeAll(" pub const _root = \"\";\n");
259 continue;
260 }
261 try w.print(" pub const _{s} = cache ++ \"/{}\";\n", .{ mod.short_id(), u.altStringEscape(mod.clean_path) });
262 }
263}
264
265fn print_deps(w: nfs.File, m: zigmod.Module) !void {
266 try w.writeAll("&[_]*Package{\n");
267 for (m.deps) |d| {
268 if (d.main.len == 0) {
269 continue;
270 }
271 if (d.for_build) {
272 continue;
273 }
274 try w.print(" &package_data._{s},\n", .{d.id[0..12]});
275 }
276 try w.writeAll("}");
277}
278
279fn print_pkg_data_to(w: nfs.File, notdone: *std.array_list.Managed(zigmod.Module), done: *std.array_list.Managed(zigmod.Module)) !void {
280 var len: usize = notdone.items.len;
281 while (notdone.items.len > 0) {
282 for (notdone.items, 0..) |mod, i| {
283 if (contains_all(mod.deps, done.items)) {
284 try w.print(
285 \\ pub var _{s} = Package{{
286 \\ .directory = dirs._{s},
287 \\
288 , .{
289 mod.short_id(),
290 mod.short_id(),
291 });
292 if (mod.main.len > 0 and !std.mem.eql(u8, &mod.id, "root")) {
293 try w.print(
294 \\ .pkg = Pkg{{ .name = "{s}", .source = .{{ .path = dirs._{s} ++ "/{s}" }}, .dependencies =
295 , .{
296 mod.name,
297 mod.short_id(),
298 mod.main,
299 });
300 if (mod.has_no_zig_deps()) {
301 try w.writeAll(" &.{} },\n");
302 } else {
303 try w.writeAll(" &.{");
304 for (mod.deps, 0..) |moddep, j| {
305 if (moddep.main.len == 0) continue;
306 try w.print(" &_{s}", .{moddep.id[0..12]});
307 if (j != mod.deps.len - 1) try w.writeAll(",");
308 }
309 try w.writeAll(" } },\n");
310 }
311 }
312 if (mod.c_include_dirs.len > 0) {
313 try w.writeAll(" .c_include_dirs = &.{");
314 for (mod.c_include_dirs, 0..) |item, j| {
315 try w.print(" \"{}\"", .{u.altStringEscape(item)});
316 if (j != mod.c_include_dirs.len - 1) try w.writeAll(",");
317 }
318 try w.writeAll(" },\n");
319 }
320 if (mod.c_source_files.len > 0) {
321 try w.writeAll(" .c_source_files = &.{");
322 for (mod.c_source_files, 0..) |item, j| {
323 try w.print(" \"{}\"", .{u.altStringEscape(item)});
324 if (j != mod.c_source_files.len - 1) try w.writeAll(",");
325 }
326 try w.writeAll(" },\n");
327 }
328 if (mod.c_source_flags.len > 0) {
329 try w.writeAll(" .c_source_flags = &.{");
330 for (mod.c_source_flags, 0..) |item, j| {
331 try w.print(" \"{}\"", .{u.altStringEscape(item)});
332 if (j != mod.c_source_flags.len - 1) try w.writeAll(",");
333 }
334 try w.writeAll(" },\n");
335 }
336 if (mod.has_syslib_deps()) {
337 try w.writeAll(" .system_libs = &.{");
338 for (mod.deps, 0..) |item, j| {
339 if (!(item.type == .system_lib)) continue;
340 try w.print(" \"{}\"", .{u.altStringEscape(item.name)});
341 if (j != mod.deps.len - 1) try w.writeAll(",");
342 }
343 try w.writeAll(" },\n");
344 }
345 if (mod.has_framework_deps()) {
346 try w.writeAll(" .frameworks = &.{");
347 for (mod.deps, 0..) |item, j| {
348 if (!(item.type == .system_lib)) continue;
349 try w.print(" \"{}\"", .{u.altStringEscape(item.name)});
350 if (j != mod.deps.len - 1) try w.writeAll(",");
351 }
352 try w.writeAll(" },\n");
353 }
354 try w.writeAll(" };\n");
355
356 try done.append(mod);
357 _ = notdone.orderedRemove(i);
358 break;
359 }
360 }
361 if (notdone.items.len == len) {
362 u.fail("notdone still has {d} items", .{len});
363 }
364 len = notdone.items.len;
365 }
366}
367
368/// returns if all of the zig modules in needles are in haystack
369fn contains_all(needles: []zigmod.Module, haystack: []const zigmod.Module) bool {
370 for (needles) |item| {
371 if (item.main.len > 0 and !extras.containsAggregate(zigmod.Module, haystack, item)) {
372 return false;
373 }
374 }
375 return true;
376}
377
378fn print_pkgs(alloc: std.mem.Allocator, w: nfs.File, m: zigmod.Module) !void {
379 try w.writeAll("struct {\n");
380 for (m.deps) |d| {
381 if (d.main.len == 0) {
382 continue;
383 }
384 if (d.for_build) {
385 continue;
386 }
387 const ident = try zig_name_from_pkg_name(alloc, d.name);
388 try w.print(" pub const {s} = &package_data._{s};\n", .{ ident, d.id[0..12] });
389 }
390 try w.writeAll("}");
391}
392
393fn print_imports(alloc: std.mem.Allocator, w: nfs.File, m: zigmod.Module, path: string) !void {
394 for (m.deps) |d| {
395 if (d.main.len == 0) {
396 continue;
397 }
398 if (!d.for_build) {
399 continue;
400 }
401 const ident = try zig_name_from_pkg_name(alloc, d.name);
402 try w.print(" pub const {s} = @import(\"{}/{}/{s}\");\n", .{ ident, u.altStringEscape(path), u.altStringEscape(d.clean_path), d.main });
403 }
404}
405
406fn zig_name_from_pkg_name(alloc: std.mem.Allocator, name: string) !string {
407 var legal = name;
408 legal = try std.mem.replaceOwned(u8, alloc, legal, "-", "_");
409 legal = try std.mem.replaceOwned(u8, alloc, legal, "/", "_");
410 legal = try std.mem.replaceOwned(u8, alloc, legal, ".", "_");
411 return legal;
412}
src/cmd/install.zig+1
......@@ -82,6 +82,7 @@ pub fn execute(self_name: []const u8, args: [][:0]u8) !void {
8282 const version_sct: V = .{ .major = @intCast(zigversion_sv.major), .minor = @intCast(zigversion_sv.minor) };
8383 const version_int: u32 = (version_sct.major << 2) | version_sct.minor;
8484 switch (version_int) {
85 0x0000_000b => try @import("./fetch.0.11.zig").create_depszig(gpa, cachepath, moddir, fetch_top_module, &fetch_list),
8586 0x0000_000c => try @import("./fetch.0.12.zig").create_depszig(gpa, cachepath, moddir, fetch_top_module, &fetch_list),
8687 0x0000_000d => try @import("./fetch.0.13.zig").create_depszig(gpa, cachepath, moddir, fetch_top_module, &fetch_list),
8788 0x0000_000e => try @import("./fetch.0.14.zig").create_depszig(gpa, cachepath, moddir, fetch_top_module, &fetch_list),