| author | |
| committer | |
| log | 3067870757cf26d522e0bea5d99da52080da543e |
| tree | efb9f48a91c79209f454cba232e66ee3990d69a8 |
| parent | 266730c68904083e0b94edb86a925587b4339600 |
4 files changed, 92 insertions(+), 0 deletions(-)
README.md+8| ... | @@ -64,6 +64,14 @@ zigmod fetch | ... | @@ -64,6 +64,14 @@ zigmod fetch |
| 64 | - This command takes no parameters and will generate a `deps.zig` in the root of your project. | 64 | - This command takes no parameters and will generate a `deps.zig` in the root of your project. |
| 65 | - `deps.zig` should not be checked into your source control. | 65 | - `deps.zig` should not be checked into your source control. |
| 66 | 66 | ||
| 67 | ### `sum` command | ||
| 68 | ``` | ||
| 69 | zigmod sum | ||
| 70 | ``` | ||
| 71 | |||
| 72 | - This will generate a `zig.sum` file with the blake3 hashes of your modules. | ||
| 73 | - Place that hash in the `hash: blake3:<hash>` property of a dependency to be able to check it with `verify`. | ||
| 74 | |||
| 67 | ### Adding `deps.zig` to `build.zig` | 75 | ### Adding `deps.zig` to `build.zig` |
| 68 | ```diff | 76 | ```diff |
| 69 | const Builder = @import("std").build.Builder; | 77 | const Builder = @import("std").build.Builder; |
src/cmd_sum.zig created+42| ... | @@ -0,0 +1,42 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const gpa = std.heap.c_allocator; | ||
| 3 | |||
| 4 | const known_folders = @import("known-folders"); | ||
| 5 | const u = @import("./util/index.zig"); | ||
| 6 | const common = @import("./common.zig"); | ||
| 7 | |||
| 8 | // | ||
| 9 | // | ||
| 10 | |||
| 11 | pub fn execute(args: [][]u8) !void { | ||
| 12 | // | ||
| 13 | const home = try known_folders.getPath(gpa, .home); | ||
| 14 | const dir = try std.fmt.allocPrint(gpa, "{}{}", .{home, "/.cache/zigmod"}); | ||
| 15 | const top_module = try common.collect_deps(dir, "./zig.mod"); | ||
| 16 | |||
| 17 | // | ||
| 18 | const f = try std.fs.cwd().createFile("./zig.sum", .{}); | ||
| 19 | defer f.close(); | ||
| 20 | const w = f.writer(); | ||
| 21 | |||
| 22 | // | ||
| 23 | const module_list = &std.ArrayList(u.Module).init(gpa); | ||
| 24 | try dedupe_mod_list(module_list, top_module); | ||
| 25 | |||
| 26 | for (module_list.items) |m| { | ||
| 27 | const hash = try m.get_hash(dir); | ||
| 28 | try w.print("{} {}\n", .{m.clean_path, hash}); | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | fn dedupe_mod_list(list: *std.ArrayList(u.Module), module: u.Module) anyerror!void { | ||
| 33 | if (u.list_contains_gen(u.Module, list, module)) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | if (module.clean_path.len > 0) { | ||
| 37 | try list.append(module); | ||
| 38 | } | ||
| 39 | for (module.deps) |m| { | ||
| 40 | try dedupe_mod_list(list, m); | ||
| 41 | } | ||
| 42 | } | ||
src/main.zig+1| ... | @@ -10,6 +10,7 @@ const commands = struct { | ... | @@ -10,6 +10,7 @@ const commands = struct { |
| 10 | const init = @import("./cmd_init.zig"); | 10 | const init = @import("./cmd_init.zig"); |
| 11 | // const add = @import("./cmd_add.zig"); | 11 | // const add = @import("./cmd_add.zig"); |
| 12 | const fetch = @import("./cmd_fetch.zig"); | 12 | const fetch = @import("./cmd_fetch.zig"); |
| 13 | const sum = @import("./cmd_sum.zig"); | ||
| 13 | }; | 14 | }; |
| 14 | 15 | ||
| 15 | pub fn main() !void { | 16 | pub fn main() !void { |
src/util/module.zig+41| ... | @@ -1,10 +1,15 @@ | ... | @@ -1,10 +1,15 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const gpa = std.heap.c_allocator; | ||
| 2 | 3 | ||
| 3 | const u = @import("index.zig"); | 4 | const u = @import("index.zig"); |
| 4 | 5 | ||
| 5 | // | 6 | // |
| 6 | // | 7 | // |
| 7 | 8 | ||
| 9 | const b = 1; | ||
| 10 | const kb = b * 1024; | ||
| 11 | const mb = kb * 1024; | ||
| 12 | |||
| 8 | pub const Module = struct { | 13 | pub const Module = struct { |
| 9 | name: []const u8, | 14 | name: []const u8, |
| 10 | main: []const u8, | 15 | main: []const u8, |
| ... | @@ -26,4 +31,40 @@ pub const Module = struct { | ... | @@ -26,4 +31,40 @@ pub const Module = struct { |
| 26 | .clean_path = try dep.clean_path(), | 31 | .clean_path = try dep.clean_path(), |
| 27 | }; | 32 | }; |
| 28 | } | 33 | } |
| 34 | |||
| 35 | pub fn eql(self: Module, another: Module) bool { | ||
| 36 | return std.mem.eql(u8, self.clean_path, another.clean_path); | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn get_hash(self: Module, cdpath: []const u8) ![]const u8 { | ||
| 40 | const file_list_1 = &std.ArrayList([]const u8).init(gpa); | ||
| 41 | try u.file_list(try u.concat(&[_][]const u8{cdpath, "/", self.clean_path}), file_list_1); | ||
| 42 | |||
| 43 | const file_list_2 = &std.ArrayList([]const u8).init(gpa); | ||
| 44 | for (file_list_1.items) |item| { | ||
| 45 | const _a = u.trim_prefix(item, cdpath)[1..]; | ||
| 46 | const _b = u.trim_prefix(_a, self.clean_path)[1..]; | ||
| 47 | if (_b[0] == '.') continue; | ||
| 48 | try file_list_2.append(_b); | ||
| 49 | } | ||
| 50 | |||
| 51 | std.sort.sort([]const u8, file_list_2.items, void{}, struct { | ||
| 52 | pub fn lt(context: void, lhs: []const u8, rhs: []const u8) bool { | ||
| 53 | return std.mem.lessThan(u8, lhs, rhs); | ||
| 54 | } | ||
| 55 | }.lt); | ||
| 56 | |||
| 57 | const h = &std.crypto.hash.Blake3.init(.{}); | ||
| 58 | for (file_list_2.items) |item| { | ||
| 59 | const abs_path = try u.concat(&[_][]const u8{cdpath, "/", self.clean_path, "/", item}); | ||
| 60 | const file = try std.fs.openFileAbsolute(abs_path, .{}); | ||
| 61 | defer file.close(); | ||
| 62 | const input = try file.reader().readAllAlloc(gpa, mb); | ||
| 63 | h.update(input); | ||
| 64 | } | ||
| 65 | var out: [32]u8 = undefined; | ||
| 66 | h.final(&out); | ||
| 67 | const hex = try std.fmt.allocPrint(gpa, "{x}", .{out}); | ||
| 68 | return hex; | ||
| 69 | } | ||
| 29 | }; | 70 | }; |