Skip to content

Instantly share code, notes, and snippets.

@menduz
Last active September 20, 2023 20:16
Show Gist options
  • Save menduz/bb0ac68912fec9902193d9a443bfe3a5 to your computer and use it in GitHub Desktop.
Save menduz/bb0ac68912fec9902193d9a443bfe3a5 to your computer and use it in GitHub Desktop.
zig dependency checker
const DependencyChecker = struct {
/// map(module_name -> set(module_hash))
package_name_to_hashes: std.StringHashMap(std.StringHashMap(bool)),
const Self = @This();
const dependencies = @import("root").dependencies;
fn check_transitive_dependency(self: *Self, comptime module_name: []const u8, comptime module_hash: []const u8, comptime level: comptime_int) void {
const package = @field(dependencies.packages, module_hash);
const entry = self.package_name_to_hashes.getOrPut(module_name) catch unreachable;
if (entry.found_existing) {
// add hash to the set
_ = entry.value_ptr.getOrPut(module_hash) catch unreachable;
} else {
entry.value_ptr.* = std.StringHashMap(bool).init(self.package_name_to_hashes.allocator);
_ = entry.value_ptr.*.getOrPut(module_hash) catch unreachable;
// recurse
inline for (package.deps) |name_hash_tuple| {
self.check_transitive_dependency(name_hash_tuple.@"0", name_hash_tuple.@"1", level + 1);
}
}
}
fn print_dependencies(self: *Self, comptime module_name: []const u8, comptime module_hash: []const u8, comptime level: comptime_int) void {
const package = @field(dependencies.packages, module_hash);
if (self.package_name_to_hashes.getEntry(module_name)) |entry| {
if (entry.value_ptr.count() == 1) {
std.debug.print(" " ** level ++ module_name ++ "\n", .{});
} else {
std.debug.print(" " ** level ++ module_name ++ " ⚠️ (" ++ module_hash ++ ")\n", .{});
}
inline for (package.deps) |name_hash_tuple| {
self.print_dependencies(name_hash_tuple.@"0", name_hash_tuple.@"1", level + 1);
}
}
}
pub fn run(allocator: std.mem.Allocator) void {
var checker: Self = .{
.package_name_to_hashes = std.StringHashMap(std.StringHashMap(bool)).init(allocator),
};
inline for (dependencies.root_deps) |name_hash_tuple| {
checker.check_transitive_dependency(name_hash_tuple.@"0", name_hash_tuple.@"1", 0);
}
var iter = checker.package_name_to_hashes.iterator();
var should_fail = false;
while (iter.next()) |entry| {
if (entry.value_ptr.count() > 1) {
std.debug.print("WARNING: The dependency {s} is used with multiple versions ({d}).\n", .{ entry.key_ptr.*, entry.value_ptr.count() });
should_fail = true;
}
}
inline for (dependencies.root_deps) |name_hash_tuple| {
checker.print_dependencies(name_hash_tuple.@"0", name_hash_tuple.@"1", 0);
}
{ //deinit
iter = checker.package_name_to_hashes.iterator();
while (iter.next()) |entry| {
entry.value_ptr.deinit();
}
checker.package_name_to_hashes.deinit();
}
if (should_fail) {
@panic("Inconsistent dependencies. Check the logs.");
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment