authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-07-05 17:41:40 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-07-05 17:41:40 -07:00
log13793e258c36d9a49f1c79db6e0188fe87a624de
tree11b11d638175423789e00a6b8b3c490b6b35b561
parent1b963fe00dbd657b570c8a6a099d8c8feb91f2ff

add the `ci` command. similar to `fetch` but only reads from `zigmod.lock`


8 files changed, 87 insertions(+), 39 deletions(-)

docs/commands/ci.md created+7
......@@ -0,0 +1,7 @@
1## `ci` command
2```
3zigmod ci
4```
5
6- This command takes no parameters and will do almost exactly the same thing as the [`fetch`](./fetch.md) command, except it will read version strings from your `zigmod.lock` file instead of from dependencies' `zig.mod` definitions.
7- Inspired by the [`npm ci`](https://docs.npmjs.com/cli/ci.html) command.
docs/commands/fetch.md+1
......@@ -5,6 +5,7 @@ zigmod fetch
55
66- This command takes no parameters and will generate a `deps.zig` in the root of your project. This is the file that you will then import into your `build.zig` to automatically add all the necessary packages and (any) C code that may be in your dependencies.
77- `deps.zig` is not typically checked into your source control.
8- This command will also produce a `zigmod.lock` which you can use to easily generate [reproducible builds](https://reproducible-builds.org/) using the [`ci`](./ci.md) command.
89
910For a full reference on the fields available in `deps.zig` you can check [here](../deps.zig.md).
1011
src/cmd/ci.zig created+25
......@@ -0,0 +1,25 @@
1const std = @import("std");
2const gpa = std.heap.c_allocator;
3
4const u = @import("./../util/index.zig");
5const common = @import("./../common.zig");
6
7// Inspired by:
8// https://docs.npmjs.com/cli/v7/commands/npm-ci
9
10pub fn execute(args: [][]u8) !void {
11 _ = args;
12
13 const dir = try std.fs.path.join(gpa, &.{ ".zigmod", "deps" });
14
15 const top_module = try common.collect_deps_deep(dir, "zig.mod", .{
16 .log = true,
17 .update = false,
18 .lock = try common.parse_lockfile("zigmod.lock"),
19 });
20
21 const list = &std.ArrayList(u.Module).init(gpa);
22 try common.collect_pkgs(top_module, list);
23
24 try @import("./fetch.zig").create_depszig(dir, top_module, list);
25}
src/common.zig+37-24
......@@ -10,6 +10,7 @@ const yaml = @import("./util/yaml.zig");
1010pub const CollectOptions = struct {
1111 log: bool,
1212 update: bool,
13 lock: ?[]const [4][]const u8 = null,
1314};
1415
1516pub fn collect_deps_deep(dir: []const u8, mpath: []const u8, options: CollectOptions) !u.Module {
......@@ -21,7 +22,7 @@ pub fn collect_deps_deep(dir: []const u8, mpath: []const u8, options: CollectOpt
2122 try moduledeps.append(try add_files_package("root", m.root_files, m.name));
2223 }
2324 try moduledeps.append(try collect_deps(dir, mpath, options));
24 for (m.devdeps) |d| {
25 for (m.devdeps) |*d| {
2526 if (try get_module_from_dep(d, dir, m.name, options)) |founddep| {
2627 try moduledeps.append(founddep);
2728 }
......@@ -31,13 +32,8 @@ pub fn collect_deps_deep(dir: []const u8, mpath: []const u8, options: CollectOpt
3132 .id = "root",
3233 .name = "root",
3334 .main = m.main,
34 .c_include_dirs = &.{},
35 .c_source_flags = &.{},
36 .c_source_files = &.{},
3735 .deps = moduledeps.toOwnedSlice(),
3836 .clean_path = "",
39 .only_os = &.{},
40 .except_os = &.{},
4137 .yaml = m.yaml,
4238 .dep = null,
4339 };
......@@ -50,7 +46,7 @@ pub fn collect_deps(dir: []const u8, mpath: []const u8, options: CollectOptions)
5046 if (m.files.len > 0) {
5147 try moduledeps.append(try add_files_package(m.id, m.files, m.name));
5248 }
53 for (m.deps) |d| {
49 for (m.deps) |*d| {
5450 if (try get_module_from_dep(d, dir, m.name, options)) |founddep| {
5551 try moduledeps.append(founddep);
5652 }
......@@ -65,8 +61,6 @@ pub fn collect_deps(dir: []const u8, mpath: []const u8, options: CollectOptions)
6561 .c_source_files = m.c_source_files,
6662 .deps = moduledeps.toOwnedSlice(),
6763 .clean_path = "../..",
68 .only_os = &.{},
69 .except_os = &.{},
7064 .yaml = m.yaml,
7165 .dep = null,
7266 };
......@@ -180,8 +174,18 @@ fn get_moddir(basedir: []const u8, d: u.Dep, parent_name: []const u8, options: C
180174 }
181175}
182176
183pub fn get_module_from_dep(d: u.Dep, dir: []const u8, parent_name: []const u8, options: CollectOptions) anyerror!?u.Module {
184 const moddir = try get_moddir(dir, d, parent_name, options);
177pub fn get_module_from_dep(d: *u.Dep, dir: []const u8, parent_name: []const u8, options: CollectOptions) anyerror!?u.Module {
178 if (options.lock) |lock| {
179 for (lock) |item| {
180 if (std.mem.eql(u8, item[0], try d.clean_path())) {
181 d.type = std.meta.stringToEnum(u.DepType, item[1]).?;
182 d.path = item[2];
183 d.version = item[3];
184 break;
185 }
186 }
187 }
188 const moddir = try get_moddir(dir, d.*, parent_name, options);
185189 switch (d.type) {
186190 .system_lib => {
187191 return u.Module{
......@@ -191,20 +195,17 @@ pub fn get_module_from_dep(d: u.Dep, dir: []const u8, parent_name: []const u8, o
191195 .only_os = d.only_os,
192196 .except_os = d.except_os,
193197 .main = "",
194 .c_include_dirs = &.{},
195 .c_source_flags = &.{},
196 .c_source_files = &.{},
197198 .deps = &[_]u.Module{},
198199 .clean_path = d.path,
199200 .yaml = null,
200 .dep = d,
201 .dep = d.*,
201202 };
202203 },
203204 else => {
204205 var dd = try collect_deps(dir, try u.concat(&.{ moddir, "/zig.mod" }), options) catch |e| switch (e) {
205206 error.FileNotFound => {
206207 if (d.main.len > 0 or d.c_include_dirs.len > 0 or d.c_source_files.len > 0) {
207 var mod_from = try u.Module.from(d, dir, options);
208 var mod_from = try u.Module.from(d.*, dir, options);
208209 if (d.type != .local) mod_from.clean_path = u.trim_prefix(moddir, dir)[1..];
209210 if (mod_from.is_for_this()) return mod_from;
210211 return null;
......@@ -213,7 +214,7 @@ pub fn get_module_from_dep(d: u.Dep, dir: []const u8, parent_name: []const u8, o
213214 },
214215 else => e,
215216 };
216 dd.dep = d;
217 dd.dep = d.*;
217218 const save = dd;
218219 if (d.type != .local) dd.clean_path = u.trim_prefix(moddir, dir)[1..];
219220 if (dd.id.len == 0) dd.id = try u.random_string(48);
......@@ -274,23 +275,35 @@ fn add_files_package(pkg_name: []const u8, dirs: []const []const u8, parent_name
274275 \\
275276 );
276277
277 const d: u.Dep = .{
278 var d: u.Dep = .{
278279 .type = .local,
279280 .path = "files",
280281 .id = "",
281282 .name = "self/files",
282283 .main = fname,
283284 .version = "absolute",
284 .c_include_dirs = &.{},
285 .c_source_flags = &.{},
286 .c_source_files = &.{},
287 .only_os = &.{},
288 .except_os = &.{},
289285 .yaml = null,
290286 .deps = &.{},
291287 };
292 return (try get_module_from_dep(d, destination, parent_name, .{
288 return (try get_module_from_dep(&d, destination, parent_name, .{
293289 .log = false,
294290 .update = false,
295291 })).?;
296292}
293
294pub fn parse_lockfile(path: []const u8) ![]const [4][]const u8 {
295 const list = &std.ArrayList([4][]const u8).init(gpa);
296 const max = std.math.maxInt(usize);
297 const f = try std.fs.cwd().openFile(path, .{});
298 const r = f.reader();
299 while (try r.readUntilDelimiterOrEofAlloc(gpa, '\n', max)) |line| {
300 var iter = std.mem.split(line, " ");
301 try list.append([4][]const u8{
302 iter.next().?,
303 iter.next().?,
304 iter.next().?,
305 iter.next().?,
306 });
307 }
308 return list.toOwnedSlice();
309}
src/lib.zig+2
......@@ -1,10 +1,12 @@
11pub const commands_to_bootstrap = struct {
22 pub const fetch = @import("./cmd/fetch.zig");
3 pub const ci = @import("./cmd/ci.zig");
34};
45
56pub const commands = struct {
67 pub const init = @import("./cmd/init.zig");
78 pub const fetch = @import("./cmd/fetch.zig");
9 pub const ci = @import("./cmd/ci.zig");
810 pub const sum = @import("./cmd/sum.zig");
911 pub const zpm = @import("./cmd/zpm.zig");
1012 pub const license = @import("./cmd/license.zig");
src/util/dep.zig+6-6
......@@ -18,13 +18,13 @@ pub const Dep = struct {
1818 name: []const u8,
1919 main: []const u8,
2020 version: []const u8,
21 c_include_dirs: []const []const u8,
22 c_source_flags: []const []const u8,
23 c_source_files: []const []const u8,
24 only_os: []const []const u8,
25 except_os: []const []const u8,
21 c_include_dirs: []const []const u8 = &.{},
22 c_source_flags: []const []const u8 = &.{},
23 c_source_files: []const []const u8 = &.{},
24 only_os: []const []const u8 = &.{},
25 except_os: []const []const u8 = &.{},
2626 yaml: ?yaml.Mapping,
27 deps: []const u.Dep,
27 deps: []u.Dep,
2828
2929 pub fn clean_path(self: Dep) ![]const u8 {
3030 if (self.type == .local) {
src/util/modfile.zig+3-3
......@@ -20,9 +20,9 @@ pub const ModFile = struct {
2020 c_include_dirs: []const []const u8,
2121 c_source_flags: []const []const u8,
2222 c_source_files: []const []const u8,
23 deps: []const u.Dep,
23 deps: []u.Dep,
2424 yaml: yaml.Mapping,
25 devdeps: []const u.Dep,
25 devdeps: []u.Dep,
2626 root_files: []const []const u8,
2727 files: []const []const u8,
2828
......@@ -61,7 +61,7 @@ pub const ModFile = struct {
6161 };
6262 }
6363
64 fn dep_list_by_name(alloc: *std.mem.Allocator, mapping: yaml.Mapping, prop: []const u8) anyerror![]const u.Dep {
64 fn dep_list_by_name(alloc: *std.mem.Allocator, mapping: yaml.Mapping, prop: []const u8) anyerror![]u.Dep {
6565 const dep_list = &std.ArrayList(u.Dep).init(alloc);
6666 if (mapping.get(prop)) |dep_seq| {
6767 if (dep_seq == .sequence) {
src/util/module.zig+6-6
......@@ -14,11 +14,11 @@ pub const Module = struct {
1414 id: []const u8,
1515 name: []const u8,
1616 main: []const u8,
17 c_include_dirs: []const []const u8,
18 c_source_flags: []const []const u8,
19 c_source_files: []const []const u8,
20 only_os: []const []const u8,
21 except_os: []const []const u8,
17 c_include_dirs: []const []const u8 = &.{},
18 c_source_flags: []const []const u8 = &.{},
19 c_source_files: []const []const u8 = &.{},
20 only_os: []const []const u8 = &.{},
21 except_os: []const []const u8 = &.{},
2222 yaml: ?yaml.Mapping,
2323 deps: []Module,
2424 clean_path: []const u8,
......@@ -27,7 +27,7 @@ pub const Module = struct {
2727 pub fn from(dep: u.Dep, dir: []const u8, options: common.CollectOptions) !Module {
2828 const moddeps = &std.ArrayList(Module).init(gpa);
2929 defer moddeps.deinit();
30 for (dep.deps) |d| {
30 for (dep.deps) |*d| {
3131 if (try common.get_module_from_dep(d, dir, dep.name, options)) |founddep| {
3232 try moddeps.append(founddep);
3333 }