From 3067870757cf26d522e0bea5d99da52080da543e Mon Sep 17 00:00:00 2001 From: Meghan Date: Sat, 21 Nov 2020 16:14:03 -0800 Subject: [PATCH] add the sum command --- README.md | 8 ++++++++ src/cmd_sum.zig | 42 ++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 1 + src/util/module.zig | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 src/cmd_sum.zig diff --git a/README.md b/README.md index b562fd278aa8058a47e541512b79a01c694fc665..bf4e63c89d1a089c9dbf21672403de85c95b46d5 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,14 @@ zigmod fetch - This command takes no parameters and will generate a `deps.zig` in the root of your project. - `deps.zig` should not be checked into your source control. +### `sum` command +``` +zigmod sum +``` + +- This will generate a `zig.sum` file with the blake3 hashes of your modules. +- Place that hash in the `hash: blake3:` property of a dependency to be able to check it with `verify`. + ### Adding `deps.zig` to `build.zig` ```diff const Builder = @import("std").build.Builder; diff --git a/src/cmd_sum.zig b/src/cmd_sum.zig new file mode 100644 index 0000000000000000000000000000000000000000..ac226fb07591f7b639518e4d71c9cd4c65e1d372 --- /dev/null +++ b/src/cmd_sum.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const gpa = std.heap.c_allocator; + +const known_folders = @import("known-folders"); +const u = @import("./util/index.zig"); +const common = @import("./common.zig"); + +// +// + +pub fn execute(args: [][]u8) !void { + // + const home = try known_folders.getPath(gpa, .home); + const dir = try std.fmt.allocPrint(gpa, "{}{}", .{home, "/.cache/zigmod"}); + const top_module = try common.collect_deps(dir, "./zig.mod"); + + // + const f = try std.fs.cwd().createFile("./zig.sum", .{}); + defer f.close(); + const w = f.writer(); + + // + const module_list = &std.ArrayList(u.Module).init(gpa); + try dedupe_mod_list(module_list, top_module); + + for (module_list.items) |m| { + const hash = try m.get_hash(dir); + try w.print("{} {}\n", .{m.clean_path, hash}); + } +} + +fn dedupe_mod_list(list: *std.ArrayList(u.Module), module: u.Module) anyerror!void { + if (u.list_contains_gen(u.Module, list, module)) { + return; + } + if (module.clean_path.len > 0) { + try list.append(module); + } + for (module.deps) |m| { + try dedupe_mod_list(list, m); + } +} diff --git a/src/main.zig b/src/main.zig index 78dc33ace2c561f795fb23c27e473d4d96571ed9..810b3cda07e058bad4d914e254bee7fe6c3930f6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -10,6 +10,7 @@ const commands = struct { const init = @import("./cmd_init.zig"); // const add = @import("./cmd_add.zig"); const fetch = @import("./cmd_fetch.zig"); + const sum = @import("./cmd_sum.zig"); }; pub fn main() !void { diff --git a/src/util/module.zig b/src/util/module.zig index af0499f99609edaa02cc6b885f5632063d4fa618..29bb07286155968f0f1ab7b85b860426bb45a704 100644 --- a/src/util/module.zig +++ b/src/util/module.zig @@ -1,10 +1,15 @@ const std = @import("std"); +const gpa = std.heap.c_allocator; const u = @import("index.zig"); // // +const b = 1; +const kb = b * 1024; +const mb = kb * 1024; + pub const Module = struct { name: []const u8, main: []const u8, @@ -26,4 +31,40 @@ pub const Module = struct { .clean_path = try dep.clean_path(), }; } + + pub fn eql(self: Module, another: Module) bool { + return std.mem.eql(u8, self.clean_path, another.clean_path); + } + + pub fn get_hash(self: Module, cdpath: []const u8) ![]const u8 { + const file_list_1 = &std.ArrayList([]const u8).init(gpa); + try u.file_list(try u.concat(&[_][]const u8{cdpath, "/", self.clean_path}), file_list_1); + + const file_list_2 = &std.ArrayList([]const u8).init(gpa); + for (file_list_1.items) |item| { + const _a = u.trim_prefix(item, cdpath)[1..]; + const _b = u.trim_prefix(_a, self.clean_path)[1..]; + if (_b[0] == '.') continue; + try file_list_2.append(_b); + } + + std.sort.sort([]const u8, file_list_2.items, void{}, struct { + pub fn lt(context: void, lhs: []const u8, rhs: []const u8) bool { + return std.mem.lessThan(u8, lhs, rhs); + } + }.lt); + + const h = &std.crypto.hash.Blake3.init(.{}); + for (file_list_2.items) |item| { + const abs_path = try u.concat(&[_][]const u8{cdpath, "/", self.clean_path, "/", item}); + const file = try std.fs.openFileAbsolute(abs_path, .{}); + defer file.close(); + const input = try file.reader().readAllAlloc(gpa, mb); + h.update(input); + } + var out: [32]u8 = undefined; + h.final(&out); + const hex = try std.fmt.allocPrint(gpa, "{x}", .{out}); + return hex; + } }; -- 2.54.0