| author | |
| committer | |
| log | 13793e258c36d9a49f1c79db6e0188fe87a624de |
| tree | 11b11d638175423789e00a6b8b3c490b6b35b561 |
| parent | 1b963fe00dbd657b570c8a6a099d8c8feb91f2ff |
8 files changed, 87 insertions(+), 39 deletions(-)
docs/commands/ci.md created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | ## `ci` command | |
| 2 | ``` | |
| 3 | zigmod 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 |
| 5 | 5 | |
| 6 | 6 | - 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. |
| 7 | 7 | - `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. | |
| 8 | 9 | |
| 9 | 10 | For a full reference on the fields available in `deps.zig` you can check [here](../deps.zig.md). |
| 10 | 11 |
src/cmd/ci.zig created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | const std = @import("std"); | |
| 2 | const gpa = std.heap.c_allocator; | |
| 3 | ||
| 4 | const u = @import("./../util/index.zig"); | |
| 5 | const common = @import("./../common.zig"); | |
| 6 | ||
| 7 | // Inspired by: | |
| 8 | // https://docs.npmjs.com/cli/v7/commands/npm-ci | |
| 9 | ||
| 10 | pub 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"); |
| 10 | 10 | pub const CollectOptions = struct { |
| 11 | 11 | log: bool, |
| 12 | 12 | update: bool, |
| 13 | lock: ?[]const [4][]const u8 = null, | |
| 13 | 14 | }; |
| 14 | 15 | |
| 15 | 16 | pub 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 |
| 21 | 22 | try moduledeps.append(try add_files_package("root", m.root_files, m.name)); |
| 22 | 23 | } |
| 23 | 24 | try moduledeps.append(try collect_deps(dir, mpath, options)); |
| 24 | for (m.devdeps) |d| { | |
| 25 | for (m.devdeps) |*d| { | |
| 25 | 26 | if (try get_module_from_dep(d, dir, m.name, options)) |founddep| { |
| 26 | 27 | try moduledeps.append(founddep); |
| 27 | 28 | } |
| ... | ... | @@ -31,13 +32,8 @@ pub fn collect_deps_deep(dir: []const u8, mpath: []const u8, options: CollectOpt |
| 31 | 32 | .id = "root", |
| 32 | 33 | .name = "root", |
| 33 | 34 | .main = m.main, |
| 34 | .c_include_dirs = &.{}, | |
| 35 | .c_source_flags = &.{}, | |
| 36 | .c_source_files = &.{}, | |
| 37 | 35 | .deps = moduledeps.toOwnedSlice(), |
| 38 | 36 | .clean_path = "", |
| 39 | .only_os = &.{}, | |
| 40 | .except_os = &.{}, | |
| 41 | 37 | .yaml = m.yaml, |
| 42 | 38 | .dep = null, |
| 43 | 39 | }; |
| ... | ... | @@ -50,7 +46,7 @@ pub fn collect_deps(dir: []const u8, mpath: []const u8, options: CollectOptions) |
| 50 | 46 | if (m.files.len > 0) { |
| 51 | 47 | try moduledeps.append(try add_files_package(m.id, m.files, m.name)); |
| 52 | 48 | } |
| 53 | for (m.deps) |d| { | |
| 49 | for (m.deps) |*d| { | |
| 54 | 50 | if (try get_module_from_dep(d, dir, m.name, options)) |founddep| { |
| 55 | 51 | try moduledeps.append(founddep); |
| 56 | 52 | } |
| ... | ... | @@ -65,8 +61,6 @@ pub fn collect_deps(dir: []const u8, mpath: []const u8, options: CollectOptions) |
| 65 | 61 | .c_source_files = m.c_source_files, |
| 66 | 62 | .deps = moduledeps.toOwnedSlice(), |
| 67 | 63 | .clean_path = "../..", |
| 68 | .only_os = &.{}, | |
| 69 | .except_os = &.{}, | |
| 70 | 64 | .yaml = m.yaml, |
| 71 | 65 | .dep = null, |
| 72 | 66 | }; |
| ... | ... | @@ -180,8 +174,18 @@ fn get_moddir(basedir: []const u8, d: u.Dep, parent_name: []const u8, options: C |
| 180 | 174 | } |
| 181 | 175 | } |
| 182 | 176 | |
| 183 | pub 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); | |
| 177 | pub 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); | |
| 185 | 189 | switch (d.type) { |
| 186 | 190 | .system_lib => { |
| 187 | 191 | return u.Module{ |
| ... | ... | @@ -191,20 +195,17 @@ pub fn get_module_from_dep(d: u.Dep, dir: []const u8, parent_name: []const u8, o |
| 191 | 195 | .only_os = d.only_os, |
| 192 | 196 | .except_os = d.except_os, |
| 193 | 197 | .main = "", |
| 194 | .c_include_dirs = &.{}, | |
| 195 | .c_source_flags = &.{}, | |
| 196 | .c_source_files = &.{}, | |
| 197 | 198 | .deps = &[_]u.Module{}, |
| 198 | 199 | .clean_path = d.path, |
| 199 | 200 | .yaml = null, |
| 200 | .dep = d, | |
| 201 | .dep = d.*, | |
| 201 | 202 | }; |
| 202 | 203 | }, |
| 203 | 204 | else => { |
| 204 | 205 | var dd = try collect_deps(dir, try u.concat(&.{ moddir, "/zig.mod" }), options) catch |e| switch (e) { |
| 205 | 206 | error.FileNotFound => { |
| 206 | 207 | 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); | |
| 208 | 209 | if (d.type != .local) mod_from.clean_path = u.trim_prefix(moddir, dir)[1..]; |
| 209 | 210 | if (mod_from.is_for_this()) return mod_from; |
| 210 | 211 | return null; |
| ... | ... | @@ -213,7 +214,7 @@ pub fn get_module_from_dep(d: u.Dep, dir: []const u8, parent_name: []const u8, o |
| 213 | 214 | }, |
| 214 | 215 | else => e, |
| 215 | 216 | }; |
| 216 | dd.dep = d; | |
| 217 | dd.dep = d.*; | |
| 217 | 218 | const save = dd; |
| 218 | 219 | if (d.type != .local) dd.clean_path = u.trim_prefix(moddir, dir)[1..]; |
| 219 | 220 | 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 |
| 274 | 275 | \\ |
| 275 | 276 | ); |
| 276 | 277 | |
| 277 | const d: u.Dep = .{ | |
| 278 | var d: u.Dep = .{ | |
| 278 | 279 | .type = .local, |
| 279 | 280 | .path = "files", |
| 280 | 281 | .id = "", |
| 281 | 282 | .name = "self/files", |
| 282 | 283 | .main = fname, |
| 283 | 284 | .version = "absolute", |
| 284 | .c_include_dirs = &.{}, | |
| 285 | .c_source_flags = &.{}, | |
| 286 | .c_source_files = &.{}, | |
| 287 | .only_os = &.{}, | |
| 288 | .except_os = &.{}, | |
| 289 | 285 | .yaml = null, |
| 290 | 286 | .deps = &.{}, |
| 291 | 287 | }; |
| 292 | return (try get_module_from_dep(d, destination, parent_name, .{ | |
| 288 | return (try get_module_from_dep(&d, destination, parent_name, .{ | |
| 293 | 289 | .log = false, |
| 294 | 290 | .update = false, |
| 295 | 291 | })).?; |
| 296 | 292 | } |
| 293 | ||
| 294 | pub 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 @@ |
| 1 | 1 | pub const commands_to_bootstrap = struct { |
| 2 | 2 | pub const fetch = @import("./cmd/fetch.zig"); |
| 3 | pub const ci = @import("./cmd/ci.zig"); | |
| 3 | 4 | }; |
| 4 | 5 | |
| 5 | 6 | pub const commands = struct { |
| 6 | 7 | pub const init = @import("./cmd/init.zig"); |
| 7 | 8 | pub const fetch = @import("./cmd/fetch.zig"); |
| 9 | pub const ci = @import("./cmd/ci.zig"); | |
| 8 | 10 | pub const sum = @import("./cmd/sum.zig"); |
| 9 | 11 | pub const zpm = @import("./cmd/zpm.zig"); |
| 10 | 12 | pub const license = @import("./cmd/license.zig"); |
src/util/dep.zig+6-6| ... | ... | @@ -18,13 +18,13 @@ pub const Dep = struct { |
| 18 | 18 | name: []const u8, |
| 19 | 19 | main: []const u8, |
| 20 | 20 | 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 = &.{}, | |
| 26 | 26 | yaml: ?yaml.Mapping, |
| 27 | deps: []const u.Dep, | |
| 27 | deps: []u.Dep, | |
| 28 | 28 | |
| 29 | 29 | pub fn clean_path(self: Dep) ![]const u8 { |
| 30 | 30 | if (self.type == .local) { |
src/util/modfile.zig+3-3| ... | ... | @@ -20,9 +20,9 @@ pub const ModFile = struct { |
| 20 | 20 | c_include_dirs: []const []const u8, |
| 21 | 21 | c_source_flags: []const []const u8, |
| 22 | 22 | c_source_files: []const []const u8, |
| 23 | deps: []const u.Dep, | |
| 23 | deps: []u.Dep, | |
| 24 | 24 | yaml: yaml.Mapping, |
| 25 | devdeps: []const u.Dep, | |
| 25 | devdeps: []u.Dep, | |
| 26 | 26 | root_files: []const []const u8, |
| 27 | 27 | files: []const []const u8, |
| 28 | 28 | |
| ... | ... | @@ -61,7 +61,7 @@ pub const ModFile = struct { |
| 61 | 61 | }; |
| 62 | 62 | } |
| 63 | 63 | |
| 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 { | |
| 65 | 65 | const dep_list = &std.ArrayList(u.Dep).init(alloc); |
| 66 | 66 | if (mapping.get(prop)) |dep_seq| { |
| 67 | 67 | if (dep_seq == .sequence) { |
src/util/module.zig+6-6| ... | ... | @@ -14,11 +14,11 @@ pub const Module = struct { |
| 14 | 14 | id: []const u8, |
| 15 | 15 | name: []const u8, |
| 16 | 16 | 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 = &.{}, | |
| 22 | 22 | yaml: ?yaml.Mapping, |
| 23 | 23 | deps: []Module, |
| 24 | 24 | clean_path: []const u8, |
| ... | ... | @@ -27,7 +27,7 @@ pub const Module = struct { |
| 27 | 27 | pub fn from(dep: u.Dep, dir: []const u8, options: common.CollectOptions) !Module { |
| 28 | 28 | const moddeps = &std.ArrayList(Module).init(gpa); |
| 29 | 29 | defer moddeps.deinit(); |
| 30 | for (dep.deps) |d| { | |
| 30 | for (dep.deps) |*d| { | |
| 31 | 31 | if (try common.get_module_from_dep(d, dir, dep.name, options)) |founddep| { |
| 32 | 32 | try moddeps.append(founddep); |
| 33 | 33 | } |