fn findFromRoot(
gpa: Allocator,
io: Io,
roots_key: Registry.Key,
roots_subkey: []const u16,
prefix: []const u8,
) error{ OutOfMemory, InstallationNotFound, PathTooLong, VersionTooLong }!Installation {
const path = path: {
const path_w_maybe_with_trailing_slash = roots_key.getString(gpa, .{ .name = roots_subkey }, .wtf16) catch |err| switch (err) {
error.NotAString,
error.ValueNameNotFound,
error.StringNotFound,
=> return error.InstallationNotFound,
error.OutOfMemory => |e| return e,
};
defer gpa.free(path_w_maybe_with_trailing_slash);
if (!std.fs.path.isAbsoluteWindowsWtf16(path_w_maybe_with_trailing_slash)) {
return error.InstallationNotFound;
}
const path_w = std.mem.trimEnd(u16, path_w_maybe_with_trailing_slash, L("\\/"));
break :path try std.unicode.wtf16LeToWtf8Alloc(gpa, path_w);
};
errdefer gpa.free(path);
const version = version: {
var buf: [Dir.max_path_bytes]u8 = undefined;
const sdk_lib_dir_path = std.mem.print(buf[0..], "{s}\\Lib\\", .{path}) catch |err| switch (err) {
error.NoSpaceLeft => return error.PathTooLong,
};
if (!Dir.path.isAbsolute(sdk_lib_dir_path)) return error.InstallationNotFound;
// enumerate files in sdk path looking for latest version
var sdk_lib_dir = Dir.openDirAbsolute(io, sdk_lib_dir_path, .{
.iterate = true,
}) catch |err| switch (err) {
error.NameTooLong => return error.PathTooLong,
else => return error.InstallationNotFound,
};
defer sdk_lib_dir.close(io);
var iterator = sdk_lib_dir.iterate();
const versions = try iterateAndFilterByVersion(&iterator, gpa, io, prefix);
if (versions.len == 0) return error.InstallationNotFound;
defer {
for (versions[1..]) |version| gpa.free(version);
gpa.free(versions);
}
break :version versions[0];
};
errdefer gpa.free(version);
return .{ .path = path, .version = version };
}