From 3475343cde840e7e47d219b6d0b5edecbae283ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20Niel=C3=A4nder?= Date: Tue, 23 Jul 2024 16:36:44 +0200 Subject: [PATCH 1/3] chore: apply zig styleguide --- src/alias.zig | 109 +++++++++++++++++-------------------------- src/architecture.zig | 19 ++++---- src/command.zig | 50 ++++++++++---------- src/download.zig | 97 ++++++++++++++++---------------------- src/extract.zig | 33 ++++++------- src/hash.zig | 22 ++++----- src/install.zig | 38 ++++++--------- src/main.zig | 22 ++++----- src/tools.zig | 24 +++++----- src/versions.zig | 13 ++---- 10 files changed, 181 insertions(+), 246 deletions(-) diff --git a/src/alias.zig b/src/alias.zig index 7fb7c46..05ba8b1 100644 --- a/src/alias.zig +++ b/src/alias.zig @@ -2,55 +2,47 @@ const std = @import("std"); const builtin = @import("builtin"); const tools = @import("tools.zig"); -pub fn setZigVersion(version: []const u8) !void { - const allocator = tools.getAllocator(); - +pub fn set_zig_version(version: []const u8) !void { + const allocator = tools.get_allocator(); var arena = std.heap.ArenaAllocator.init(allocator); defer arena.deinit(); const arena_allocator = arena.allocator(); - const userHome = tools.getHome(); - - const zigPath = try std.fs.path.join(arena_allocator, &[_][]const u8{ userHome, ".zm", "versions", version }); - const symlinkPath = try std.fs.path.join(arena_allocator, &[_][]const u8{ userHome, ".zm", "current" }); + const user_home = tools.get_home(); + const zig_path = try std.fs.path.join(arena_allocator, &[_][]const u8{ user_home, ".zm", "versions", version }); + const symlink_path = try std.fs.path.join(arena_allocator, &[_][]const u8{ user_home, ".zm", "current" }); - try updateSymlink(zigPath, symlinkPath); - try verifyZigVersion(allocator, version); + try update_symlink(zig_path, symlink_path); + try verify_zig_version(allocator, version); } -fn updateSymlink(zigPath: []const u8, symlinkPath: []const u8) !void { +fn update_symlink(zig_path: []const u8, symlink_path: []const u8) !void { if (builtin.os.tag == .windows) { - if (std.fs.path.dirname(symlinkPath)) |dirname| { - var parent_dir = try std.fs.openDirAbsolute(dirname, .{ - .iterate = true, - }); + if (std.fs.path.dirname(symlink_path)) |dirname| { + var parent_dir = try std.fs.openDirAbsolute(dirname, .{ .iterate = true }); defer parent_dir.close(); - try parent_dir.deleteTree(std.fs.path.basename(symlinkPath)); + try parent_dir.deleteTree(std.fs.path.basename(symlink_path)); } else { - @panic("sorry, dirname is not avaiable!"); + @panic("dirname is not available!"); } - if (doesDirExist(symlinkPath)) try std.fs.deleteDirAbsolute(symlinkPath); - try copyDir(zigPath, symlinkPath); + if (does_dir_exist(symlink_path)) try std.fs.deleteDirAbsolute(symlink_path); + try copy_dir(zig_path, symlink_path); } else { - if (doesFileExist(symlinkPath)) try std.fs.cwd().deleteFile(symlinkPath); - std.posix.symlink(zigPath, symlinkPath) catch |err| switch (err) { + if (does_file_exist(symlink_path)) try std.fs.cwd().deleteFile(symlink_path); + std.posix.symlink(zig_path, symlink_path) catch |err| switch (err) { error.PathAlreadyExists => { - try std.fs.cwd().deleteFile(symlinkPath); - try std.posix.symlink(zigPath, symlinkPath); + try std.fs.cwd().deleteFile(symlink_path); + try std.posix.symlink(zig_path, symlink_path); }, else => return err, }; } } -fn copyDir(source_dir: []const u8, dest_dir: []const u8) !void { - var source = try std.fs.openDirAbsolute( - source_dir, - .{ .iterate = true }, - ); +fn copy_dir(source_dir: []const u8, dest_dir: []const u8) !void { + var source = try std.fs.openDirAbsolute(source_dir, .{ .iterate = true }); defer source.close(); - // try make dir std.fs.makeDirAbsolute(dest_dir) catch |err| switch (err) { error.PathAlreadyExists => {}, else => { @@ -59,42 +51,29 @@ fn copyDir(source_dir: []const u8, dest_dir: []const u8) !void { }, }; - var dest = try std.fs.openDirAbsolute( - dest_dir, - .{ .iterate = true }, - ); + var dest = try std.fs.openDirAbsolute(dest_dir, .{ .iterate = true }); defer dest.close(); var iterate = source.iterate(); - const allocator = tools.getAllocator(); + const allocator = tools.get_allocator(); while (try iterate.next()) |entry| { const entry_name = entry.name; - const source_sub_path = try std.fs.path.join( - allocator, - &.{ source_dir, entry_name }, - ); + const source_sub_path = try std.fs.path.join(allocator, &.{ source_dir, entry_name }); defer allocator.free(source_sub_path); - const dest_sub_path = try std.fs.path.join( - allocator, - &.{ dest_dir, entry_name }, - ); + const dest_sub_path = try std.fs.path.join(allocator, &.{ dest_dir, entry_name }); defer allocator.free(dest_sub_path); switch (entry.kind) { - .directory => { - try copyDir(source_sub_path, dest_sub_path); - }, - .file => { - try std.fs.copyFileAbsolute(source_sub_path, dest_sub_path, .{}); - }, + .directory => try copy_dir(source_sub_path, dest_sub_path), + .file => try std.fs.copyFileAbsolute(source_sub_path, dest_sub_path, .{}), else => {}, } } } -fn doesDirExist(path: []const u8) bool { +fn does_dir_exist(path: []const u8) bool { const result = blk: { _ = std.fs.openDirAbsolute(path, .{}) catch |err| { switch (err) { @@ -107,7 +86,7 @@ fn doesDirExist(path: []const u8) bool { return result; } -fn doesFileExist(path: []const u8) bool { +fn does_file_exist(path: []const u8) bool { const result = blk: { _ = std.fs.cwd().openFile(path, .{}) catch |err| { switch (err) { @@ -120,31 +99,31 @@ fn doesFileExist(path: []const u8) bool { return result; } -fn verifyZigVersion(allocator: std.mem.Allocator, expectedVersion: []const u8) !void { - const actualVersion = try retrieveZigVersion(allocator); - defer allocator.free(actualVersion); +fn verify_zig_version(allocator: std.mem.Allocator, expected_version: []const u8) !void { + const actual_version = try retrieve_zig_version(allocator); + defer allocator.free(actual_version); - if (!std.mem.eql(u8, expectedVersion, actualVersion)) { - std.debug.print("Expected Zig version {s}, but currently using {s}. Please check.\n", .{ expectedVersion, actualVersion }); + if (!std.mem.eql(u8, expected_version, actual_version)) { + std.debug.print("Expected Zig version {s}, but currently using {s}. Please check.\n", .{ expected_version, actual_version }); } else { - std.debug.print("Now using Zig version {s}\n", .{expectedVersion}); + std.debug.print("Now using Zig version {s}\n", .{expected_version}); } } -fn retrieveZigVersion(allocator: std.mem.Allocator) ![]u8 { - const userHome = tools.getHome(); - const symlinkPath = try std.fs.path.join(allocator, &[_][]const u8{ userHome, ".zm", "current" }); - defer allocator.free(symlinkPath); +fn retrieve_zig_version(allocator: std.mem.Allocator) ![]u8 { + const user_home = tools.get_home(); + const symlink_path = try std.fs.path.join(allocator, &[_][]const u8{ user_home, ".zm", "current" }); + defer allocator.free(symlink_path); - var childProcess = std.process.Child.init(&[_][]const u8{ "zig", "version" }, allocator); + var child_process = std.process.Child.init(&[_][]const u8{ "zig", "version" }, allocator); - childProcess.stdin_behavior = .Close; - childProcess.stdout_behavior = .Pipe; - childProcess.stderr_behavior = .Close; + child_process.stdin_behavior = .Close; + child_process.stdout_behavior = .Pipe; + child_process.stderr_behavior = .Close; - try childProcess.spawn(); + try child_process.spawn(); - if (childProcess.stdout) |stdout| { + if (child_process.stdout) |stdout| { return try stdout.reader().readUntilDelimiterOrEofAlloc(allocator, '\n', 100) orelse return error.EmptyVersion; } diff --git a/src/architecture.zig b/src/architecture.zig index 580afd6..8ad46d3 100644 --- a/src/architecture.zig +++ b/src/architecture.zig @@ -28,21 +28,20 @@ fn archToString(arch: std.Target.Cpu.Arch) ?[]const u8 { } pub fn detect(allocator: std.mem.Allocator, params: DetectParams) !?[]u8 { - const osStr = osToString(params.os) orelse return error.UnsupportedSystem; - const archStr = archToString(params.arch) orelse return error.UnsupportedSystem; - - const len = osStr.len + archStr.len + 1; // +1 for the '-' + const os_str = osToString(params.os) orelse return error.UnsupportedSystem; + const arch_str = archToString(params.arch) orelse return error.UnsupportedSystem; + const len = os_str.len + arch_str.len + 1; // +1 for the '-' const result = try allocator.alloc(u8, len); if (params.reverse) { - @memcpy(result[0..archStr.len], archStr); - result[archStr.len] = '-'; - @memcpy(result[archStr.len + 1 ..], osStr); + @memcpy(result[0..arch_str.len], arch_str); + result[arch_str.len] = '-'; + @memcpy(result[arch_str.len + 1 ..], os_str); } else { - @memcpy(result[0..osStr.len], osStr); - result[osStr.len] = '-'; - @memcpy(result[osStr.len + 1 ..], archStr); + @memcpy(result[0..os_str.len], os_str); + result[os_str.len] = '-'; + @memcpy(result[os_str.len + 1 ..], arch_str); } return result; diff --git a/src/command.zig b/src/command.zig index 3024f23..50e1040 100644 --- a/src/command.zig +++ b/src/command.zig @@ -16,34 +16,34 @@ pub const Command = enum { Unknown, }; -pub fn handleCommands(cmd: Command, params: ?[]const u8) !void { +pub fn handle_commands(cmd: Command, params: ?[]const u8) !void { switch (cmd) { - Command.List => { - try handleList(); + .List => { + try handle_list(); }, - Command.Install => { - try installVersion(params); + .Install => { + try install_version(params); }, - Command.Use => { - try useVersion(params); + .Use => { + try use_version(params); }, - Command.Default => { - try setDefault(); + .Default => { + try set_default(); }, - Command.Version => { - try getVersion(); + .Version => { + try get_version(); }, - Command.Help => { - try displayHelp(); + .Help => { + try display_help(); }, - Command.Unknown => { - try handleUnknown(); + .Unknown => { + try handle_unknown(); }, } } -fn handleList() !void { - const allocator = tools.getAllocator(); +fn handle_list() !void { + const allocator = tools.get_allocator(); var version_list = try versions.VersionList.init(allocator); defer version_list.deinit(); @@ -52,32 +52,32 @@ fn handleList() !void { } } -fn installVersion(params: ?[]const u8) !void { +fn install_version(params: ?[]const u8) !void { if (params) |version| { - try install.fromVersion(version); + try install.from_version(version); } else { std.debug.print("Error: Please specify a version to install using 'install '.\n", .{}); } } -fn useVersion(params: ?[]const u8) !void { +fn use_version(params: ?[]const u8) !void { if (params) |version| { - try alias.setZigVersion(version); + try alias.set_zig_version(version); } else { std.debug.print("Error: Please specify a version to use with 'use '.\n", .{}); } } -fn setDefault() !void { +fn set_default() !void { std.debug.print("Handling 'default' command.\n", .{}); // Your default code here } -fn getVersion() !void { +fn get_version() !void { std.debug.print("zvm {}\n", .{options.zvm_version}); } -fn displayHelp() !void { +fn display_help() !void { const help_message = \\Usage: \\ zvm [args] @@ -100,6 +100,6 @@ fn displayHelp() !void { std.debug.print(help_message, .{}); } -fn handleUnknown() !void { +fn handle_unknown() !void { std.debug.print("Unknown command. Use 'zvm --help' for usage information.\n", .{}); } diff --git a/src/download.zig b/src/download.zig index 0e106ab..04ad2f4 100644 --- a/src/download.zig +++ b/src/download.zig @@ -1,35 +1,27 @@ const std = @import("std"); const builtin = @import("builtin"); const tools = @import("tools.zig"); -const sha2 = @import("std").crypto.hash.sha2; +const sha2 = std.crypto.hash.sha2; const architecture = @import("architecture.zig"); -const Progress = std.Progress; const alias = @import("alias.zig"); const hash = @import("hash.zig"); const lib = @import("extract.zig"); -const crypto = std.crypto; const archive_ext = if (builtin.os.tag == .windows) "zip" else "tar.xz"; pub fn content(allocator: std.mem.Allocator, version: []const u8, url: []const u8) !?[32]u8 { - // Initialize the Progress structure - const root_node = Progress.start(.{ + const root_node = std.Progress.start(.{ .root_name = "", .estimated_total_items = 4, }); - defer root_node.end(); - const data_allocator = tools.getAllocator(); - // Ensure version directory exists before any operation - const version_path = try tools.getZvmPathSegment(data_allocator, "versions"); + const data_allocator = tools.get_allocator(); + const version_path = try tools.get_zvm_path_segment(data_allocator, "versions"); defer data_allocator.free(version_path); std.fs.cwd().makePath(version_path) catch |err| switch (err) { - error.PathAlreadyExists => { - // The path already exists and is a directory, nothing to do here - // std.debug.print("Versions directory already exists: {s}\n", .{version_path}); - }, + error.PathAlreadyExists => {}, else => { std.debug.print("Failed to create versions directory: {}\n", .{err}); return err; @@ -40,18 +32,17 @@ pub fn content(allocator: std.mem.Allocator, version: []const u8, url: []const u const version_folder_name = try std.fmt.allocPrint(allocator, "versions/{s}", .{version}); defer allocator.free(version_folder_name); - const version_folder_path = try tools.getZvmPathSegment(data_allocator, version_folder_name); + const version_folder_path = try tools.get_zvm_path_segment(data_allocator, version_folder_name); defer data_allocator.free(version_folder_path); - if (checkExistingVersion(version_folder_path)) { + if (check_existing_version(version_folder_path)) { std.debug.print("→ Version {s} is already installed.\n", .{version}); std.debug.print("Do you want to reinstall? (\x1b[1mY\x1b[0mes/\x1b[1mN\x1b[0mo): ", .{}); - if (!confirmUserChoice()) { - // Ask if the version should be set as the default + if (!confirm_user_choice()) { std.debug.print("Do you want to set version {s} as the default? (\x1b[1mY\x1b[0mes/\x1b[1mN\x1b[0mo): ", .{version}); - if (confirmUserChoice()) { - try alias.setZigVersion(version); + if (confirm_user_choice()) { + try alias.set_zig_version(version); std.debug.print("Version {s} has been set as the default.\n", .{version}); return null; } else { @@ -65,29 +56,29 @@ pub fn content(allocator: std.mem.Allocator, version: []const u8, url: []const u std.debug.print("→ Version {s} is not installed. Beginning download...\n", .{version}); } - const computedHash = try downloadAndExtract(allocator, uri, version_path, version, root_node); + const computed_hash = try download_and_extract(allocator, uri, version_path, version, root_node); var set_version_node = root_node.start("Setting Version", 1); - try alias.setZigVersion(version); + try alias.set_zig_version(version); set_version_node.end(); - return computedHash; + return computed_hash; } -fn checkExistingVersion(version_path: []const u8) bool { - const openDirOptions = .{ .access_sub_paths = true, .no_follow = false }; - _ = std.fs.cwd().openDir(version_path, openDirOptions) catch return false; +fn check_existing_version(version_path: []const u8) bool { + const open_dir_options = .{ .access_sub_paths = true, .no_follow = false }; + _ = std.fs.cwd().openDir(version_path, open_dir_options) catch return false; return true; } -fn confirmUserChoice() bool { +fn confirm_user_choice() bool { var buffer: [4]u8 = undefined; _ = std.io.getStdIn().read(buffer[0..]) catch return false; return std.ascii.toLower(buffer[0]) == 'y'; } -fn downloadAndExtract( +fn download_and_extract( allocator: std.mem.Allocator, uri: std.Uri, version_path: []const u8, @@ -97,18 +88,16 @@ fn downloadAndExtract( var client = std.http.Client{ .allocator = allocator }; defer client.deinit(); - // Read the response body with 256kb buffer allocation - var headerBuffer: [262144]u8 = undefined; // 256 * 1024 = 262kb + var header_buffer: [262144]u8 = undefined; // 256 * 1024 = 262kb - var req = try client.open(.GET, uri, .{ .server_header_buffer = &headerBuffer }); + var req = try client.open(.GET, uri, .{ .server_header_buffer = &header_buffer }); defer req.deinit(); try req.send(); try req.wait(); - try std.testing.expect(req.response.status == .ok); - var zvm_dir = try openOrCreateZvmDir(); + var zvm_dir = try open_or_create_zvm_dir(); defer zvm_dir.close(); const platform = try architecture.detect(allocator, architecture.DetectParams{ .os = builtin.os.tag, .arch = builtin.cpu.arch, .reverse = false }) orelse unreachable; @@ -117,12 +106,12 @@ fn downloadAndExtract( const file_name = try std.mem.concat(allocator, u8, &[_][]const u8{ "zig-", platform, "-", version, ".", archive_ext }); defer allocator.free(file_name); - const totalSize: usize = @intCast(req.response.content_length orelse 0); - var downloadedBytes: usize = 0; + const total_size: usize = @intCast(req.response.content_length orelse 0); + var downloaded_bytes: usize = 0; - const downloadMessage = try std.fmt.allocPrint(allocator, "Downloading Zig version {s} for platform {s}...", .{ version, platform }); - defer allocator.free(downloadMessage); - var download_node = root_node.start(downloadMessage, totalSize); + const download_message = try std.fmt.allocPrint(allocator, "Downloading Zig version {s} for platform {s}...", .{ version, platform }); + defer allocator.free(download_message); + var download_node = root_node.start(download_message, total_size); const file_stream = try zvm_dir.createFile(file_name, .{}); defer file_stream.close(); @@ -136,23 +125,18 @@ fn downloadAndExtract( const bytes_read = try req.reader().read(buffer[0..]); if (bytes_read == 0) break; - downloadedBytes += bytes_read; - - download_node.setCompletedItems(downloadedBytes); - + downloaded_bytes += bytes_read; + download_node.setCompletedItems(downloaded_bytes); sha256.update(buffer[0..bytes_read]); - try file_stream.writeAll(buffer[0..bytes_read]); } download_node.end(); var extract_node = root_node.start("Extracting", 1); + const data_allocator = tools.get_allocator(); - // ~/.zm/versions/zig-macos-x86_64-0.10.0.tar.xz - const data_allocator = tools.getAllocator(); - - const zvm_path = try tools.getZvmPathSegment(data_allocator, ""); + const zvm_path = try tools.get_zvm_path_segment(data_allocator, ""); defer data_allocator.free(zvm_path); const downloaded_file_path = try std.fs.path.join(data_allocator, &.{ zvm_path, file_name }); @@ -160,8 +144,6 @@ fn downloadAndExtract( std.debug.print("Downloaded file path: {s}\n", .{downloaded_file_path}); - // Construct the full file path - // example: ~/.zm/0.10.0 const folder_path = try std.fs.path.join(allocator, &.{ version_path, version }); defer allocator.free(folder_path); @@ -170,7 +152,6 @@ fn downloadAndExtract( }; const zvm_dir_version = try std.fs.openDirAbsolute(folder_path, .{}); - const downloaded_file = try zvm_dir.openFile(downloaded_file_path, .{}); defer downloaded_file.close(); @@ -187,14 +168,14 @@ fn downloadAndExtract( return result; } -fn openOrCreateZvmDir() !std.fs.Dir { - const zvm_path = try tools.getZvmPathSegment(tools.getAllocator(), ""); - defer tools.getAllocator().free(zvm_path); +fn open_or_create_zvm_dir() !std.fs.Dir { + const zvm_path = try tools.get_zvm_path_segment(tools.get_allocator(), ""); + defer tools.get_allocator().free(zvm_path); - const openDirOptions = .{ .access_sub_paths = true, .no_follow = false }; - const potentialDir = std.fs.cwd().openDir(zvm_path, openDirOptions); + const open_dir_options = .{ .access_sub_paths = true, .no_follow = false }; + const potential_dir = std.fs.cwd().openDir(zvm_path, open_dir_options); - if (potentialDir) |dir| { + if (potential_dir) |dir| { return dir; } else |err| switch (err) { error.FileNotFound => { @@ -202,11 +183,11 @@ fn openOrCreateZvmDir() !std.fs.Dir { if (std.fs.cwd().makeDir(zvm_path)) |_| { std.debug.print("✓ Directory created successfully: {s}\n", .{zvm_path}); - } else |errMakeDir| { - std.debug.print("✗ Error: Failed to create directory. Reason: {}\n", .{errMakeDir}); + } else |err_make_dir| { + std.debug.print("✗ Error: Failed to create directory. Reason: {}\n", .{err_make_dir}); } - return std.fs.cwd().openDir(zvm_path, openDirOptions); + return std.fs.cwd().openDir(zvm_path, open_dir_options); }, else => |e| { std.debug.print("Unexpected error when checking directory: {}\n", .{e}); diff --git a/src/extract.zig b/src/extract.zig index ae55c1c..13e6eb2 100644 --- a/src/extract.zig +++ b/src/extract.zig @@ -2,43 +2,38 @@ const std = @import("std"); const builtin = @import("builtin"); const tools = @import("tools.zig"); -pub fn extract_tarxz_to_dir(allocator: std.mem.Allocator, outDir: std.fs.Dir, file: std.fs.File) !void { +pub fn extract_tarxz_to_dir(allocator: std.mem.Allocator, out_dir: std.fs.Dir, file: std.fs.File) !void { var buffered_reader = std.io.bufferedReader(file.reader()); var decompressed = try std.compress.xz.decompress(allocator, buffered_reader.reader()); defer decompressed.deinit(); - try std.tar.pipeToFileSystem(outDir, decompressed.reader(), .{ .mode_mode = .executable_bit_only, .strip_components = 1 }); + try std.tar.pipeToFileSystem(out_dir, decompressed.reader(), .{ .mode_mode = .executable_bit_only, .strip_components = 1 }); } -pub fn extract_zip_dir(outDir: std.fs.Dir, file: std.fs.File) !void { - var arena = std.heap.ArenaAllocator.init(tools.getAllocator()); +pub fn extract_zip_dir(out_dir: std.fs.Dir, file: std.fs.File) !void { + var arena = std.heap.ArenaAllocator.init(tools.get_allocator()); defer arena.deinit(); const allocator = arena.allocator(); + const tmp_path = try tools.get_zvm_path_segment(allocator, "tmpdir"); + defer std.fs.delete_dir_absolute(tmp_path) catch unreachable; - const tmp_path = try tools.getZvmPathSegment(allocator, "tmpdir"); - defer std.fs.deleteDirAbsolute(tmp_path) catch unreachable; + try std.fs.make_dir_absolute(tmp_path); + var tmp_dir = try std.fs.open_dir_absolute(tmp_path, .{ .iterate = true }); - // make tmp dir - try std.fs.makeDirAbsolute(tmp_path); - var tmp_dir = try std.fs.openDirAbsolute(tmp_path, .{ .iterate = true }); - - try std.zip.extract(tmp_dir, file.seekableStream(), .{}); + try std.zip.extract(tmp_dir, file.seekable_stream(), .{}); var iterate = tmp_dir.iterate(); - var sub_dir = blk: { const entry = try iterate.next() orelse return error.NotFound; - break :blk try tmp_dir.openDir(entry.name, .{ - .iterate = true, - }); + break :blk try tmp_dir.open_dir(entry.name, .{ .iterate = true }); }; defer sub_dir.close(); - const sub_path = try sub_dir.realpathAlloc(allocator, ""); - defer std.fs.deleteDirAbsolute(sub_path) catch unreachable; - var sub_iterate = sub_dir.iterate(); + const sub_path = try sub_dir.realpath_alloc(allocator, ""); + defer std.fs.delete_dir_absolute(sub_path) catch unreachable; + var sub_iterate = sub_dir.iterate(); while (try sub_iterate.next()) |entry| { - try std.fs.rename(sub_dir, entry.name, outDir, entry.name); + try std.fs.rename(sub_dir, entry.name, out_dir, entry.name); } } diff --git a/src/hash.zig b/src/hash.zig index 0189b1a..d02204e 100644 --- a/src/hash.zig +++ b/src/hash.zig @@ -1,15 +1,15 @@ const std = @import("std"); -const crypto = @import("std").crypto; +const crypto = std.crypto; const testing = std.testing; const mem = std.mem; -pub fn verifyHash(computedHash: [32]u8, actualHashString: []const u8) bool { - if (actualHashString.len != 64) return false; // SHA256 hash should be 64 hex characters +pub fn verify_hash(computed_hash: [32]u8, actual_hash_string: []const u8) bool { + if (actual_hash_string.len != 64) return false; // SHA256 hash should be 64 hex characters - var actualHashBytes: [32]u8 = undefined; + var actual_hash_bytes: [32]u8 = undefined; var i: usize = 0; - for (actualHashString) |char| { + for (actual_hash_string) |char| { const byte = switch (char) { '0'...'9' => char - '0', 'a'...'f' => char - 'a' + 10, @@ -18,23 +18,23 @@ pub fn verifyHash(computedHash: [32]u8, actualHashString: []const u8) bool { }; if (i % 2 == 0) { - actualHashBytes[i / 2] = byte << 4; + actual_hash_bytes[i / 2] = byte << 4; } else { - actualHashBytes[i / 2] |= byte; + actual_hash_bytes[i / 2] |= byte; } i += 1; } - return std.mem.eql(u8, computedHash[0..], actualHashBytes[0..]); + return std.mem.eql(u8, computed_hash[0..], actual_hash_bytes[0..]); } -test "verifyHash basic test" { +test "verify_hash basic test" { const sample_hash: [32]u8 = [_]u8{ 0x33, 0x9a, 0x89, 0xdc, 0x08, 0x73, 0x6b, 0x84, 0xc4, 0x75, 0x2b, 0x3d, 0xed, 0xdc, 0x0f, 0x2c, 0x71, 0xb5, 0x0b, 0x66, 0xa2, 0x68, 0x5f, 0x26, 0x77, 0x9c, 0xbb, 0xac, 0x46, 0x11, 0x1b, 0x68 }; var sample_hash_hex: [64]u8 = undefined; _ = std.fmt.bufPrint(&sample_hash_hex, "{}", .{std.fmt.fmtSliceHexLower(sample_hash[0..])}) catch unreachable; - try testing.expect(verifyHash(sample_hash, &sample_hash_hex)); - try testing.expect(!verifyHash(sample_hash, "incorrect_hash")); + try testing.expect(verify_hash(sample_hash, &sample_hash_hex)); + try testing.expect(!verify_hash(sample_hash, "incorrect_hash")); } diff --git a/src/install.zig b/src/install.zig index bb9206d..117084a 100644 --- a/src/install.zig +++ b/src/install.zig @@ -30,23 +30,19 @@ const Error = error{ const url = "https://ziglang.org/download/index.json"; -fn fetchVersionData(allocator: Allocator, requested_version: []const u8, sub_key: []const u8) !?Version { +fn fetch_version_data(allocator: Allocator, requested_version: []const u8, sub_key: []const u8) !?Version { const uri = std.Uri.parse(url) catch unreachable; - // Initialize HTTP client var client = std.http.Client{ .allocator = allocator }; defer client.deinit(); - // Read the response body with 256kb buffer allocation var buffer: [262144]u8 = undefined; // 256 * 1024 = 262kb - // Make the HTTP request var req = try client.open(.GET, uri, .{ .server_header_buffer = &buffer }); defer req.deinit(); try req.send(); try req.wait(); - // Check if request was successful try std.testing.expect(req.response.status == .ok); const read_len = try req.readAll(buffer[0..]); @@ -57,43 +53,38 @@ fn fetchVersionData(allocator: Allocator, requested_version: []const u8, sub_key var it = root.object.iterator(); while (it.next()) |entry| { - // const key_ptr = entry.key_ptr; - // const key = key_ptr.*; if (std.mem.eql(u8, entry.key_ptr.*, requested_version)) { - // Initialize fields with null. var version: ?[]const u8 = "not_set"; var date: ?[]const u8 = null; var tarball: ?[]const u8 = null; var shasum: ?[]const u8 = null; - var valObj = entry.value_ptr.*.object.iterator(); - while (valObj.next()) |value| { + var val_obj = entry.value_ptr.*.object.iterator(); + while (val_obj.next()) |value| { if (std.mem.eql(u8, value.key_ptr.*, "version")) { version = value.value_ptr.*.string; } if (std.mem.eql(u8, value.key_ptr.*, "date")) { date = value.value_ptr.*.string; } else if (std.mem.eql(u8, value.key_ptr.*, sub_key)) { - const nestedObjConst = value.value_ptr.*.object.iterator(); - var nestedObj = nestedObjConst; - while (nestedObj.next()) |nestedValue| { - if (std.mem.eql(u8, nestedValue.key_ptr.*, "tarball")) { - tarball = nestedValue.value_ptr.*.string; + var nested_obj = value.value_ptr.*.object.iterator(); + while (nested_obj.next()) |nested_value| { + if (std.mem.eql(u8, nested_value.key_ptr.*, "tarball")) { + tarball = nested_value.value_ptr.*.string; } - if (std.mem.eql(u8, nestedValue.key_ptr.*, "shasum")) { - shasum = nestedValue.value_ptr.*.string; + if (std.mem.eql(u8, nested_value.key_ptr.*, "shasum")) { + shasum = nested_value.value_ptr.*.string; } } } } - // Validate that we found all the required fields. if (date == null or tarball == null or shasum == null) { return Error.MissingExpectedFields; } const version_name = if (std.mem.eql(u8, requested_version, "master")) version.? else requested_version; - // Create the Version struct. + return Version{ .name = try allocator.dupe(u8, version_name), .date = try allocator.dupe(u8, date.?), @@ -106,8 +97,8 @@ fn fetchVersionData(allocator: Allocator, requested_version: []const u8, sub_key return null; } -pub fn fromVersion(version: []const u8) !void { - var allocator = tools.getAllocator(); +pub fn from_version(version: []const u8) !void { + var allocator = tools.get_allocator(); const platform_str = try architecture.detect(allocator, architecture.DetectParams{ .os = builtin.os.tag, @@ -118,15 +109,14 @@ pub fn fromVersion(version: []const u8) !void { var arena = std.heap.ArenaAllocator.init(allocator); defer arena.deinit(); - const version_data = try fetchVersionData(arena.allocator(), version, platform_str); + const version_data = try fetch_version_data(arena.allocator(), version, platform_str); if (version_data) |data| { std.debug.print("Install {s}\n", .{data.name}); - // Download and verify if (data.shasum) |actual_shasum| { const computed_hash = try download.content(allocator, data.name, data.tarball.?); if (computed_hash) |shasum| { - if (!hash.verifyHash(shasum, actual_shasum)) { + if (!hash.verify_hash(shasum, actual_shasum)) { return error.HashMismatch; } } diff --git a/src/main.zig b/src/main.zig index c4e3016..645ee00 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,7 +1,7 @@ const std = @import("std"); const tools = @import("tools.zig"); const Command = @import("command.zig").Command; -const handleCommands = @import("command.zig").handleCommands; +const handle_commands = @import("command.zig").handle_commands; const CommandData = struct { cmd: Command, @@ -18,25 +18,25 @@ pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer if (gpa.deinit() == .leak) @panic("memory leaked!"); - try tools.dataInit(gpa.allocator()); - defer tools.dataDeinit(); + try tools.data_init(gpa.allocator()); + defer tools.data_deinit(); - const allocator = tools.getAllocator(); + const allocator = tools.get_allocator(); const args = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, args); - const cmd_data = try parseArgs(args); - try handleCommands(cmd_data.cmd, cmd_data.params); + const cmd_data = try parse_args(args); + try handle_commands(cmd_data.cmd, cmd_data.params); } -fn parseArgs(args: []const []const u8) !CommandData { - const options = getAvailableCommands(); +fn parse_args(args: []const []const u8) !CommandData { + const options = get_available_commands(); if (args.len < 2) return CommandData{ .cmd = Command.Unknown, .params = null }; - return findCommandInArgs(args[1..], options) orelse CommandData{ .cmd = Command.Unknown, .params = null }; + return find_command_in_args(args[1..], options) orelse CommandData{ .cmd = Command.Unknown, .params = null }; } -fn getAvailableCommands() []const CommandOption { +fn get_available_commands() []const CommandOption { return &[_]CommandOption{ CommandOption{ .short_handle = "ls", .handle = "list", .cmd = Command.List }, CommandOption{ .short_handle = "i", .handle = "install", .cmd = Command.Install }, @@ -47,7 +47,7 @@ fn getAvailableCommands() []const CommandOption { }; } -fn findCommandInArgs(args: []const []const u8, options: []const CommandOption) ?CommandData { +fn find_command_in_args(args: []const []const u8, options: []const CommandOption) ?CommandData { var i: usize = 0; for (args) |arg| { for (options) |option| { diff --git a/src/tools.zig b/src/tools.zig index 49473af..1c2f75d 100644 --- a/src/tools.zig +++ b/src/tools.zig @@ -2,40 +2,38 @@ const std = @import("std"); const builtin = @import("builtin"); var allocator: std.mem.Allocator = undefined; - var home_dir: []const u8 = undefined; pub const log = std.log.scoped(.zvm); -/// init the data -pub fn dataInit(tmp_allocator: std.mem.Allocator) !void { +/// Initialize the data. +pub fn data_init(tmp_allocator: std.mem.Allocator) !void { allocator = tmp_allocator; - // setting the home dir home_dir = if (builtin.os.tag == .windows) try std.process.getEnvVarOwned(allocator, "USERPROFILE") else std.posix.getenv("HOME") orelse "."; } -/// deinit the data -pub fn dataDeinit() void { +/// Deinitialize the data. +pub fn data_deinit() void { if (builtin.os.tag == .windows) allocator.free(home_dir); } -/// get home dir -pub fn getHome() []const u8 { +/// Get home directory. +pub fn get_home() []const u8 { return home_dir; } -/// get the allocator -pub fn getAllocator() std.mem.Allocator { +/// Get the allocator. +pub fn get_allocator() std.mem.Allocator { return allocator; } -pub fn getZvmPathSegment(_allocator: std.mem.Allocator, segment: []const u8) ![]u8 { +pub fn get_zvm_path_segment(tmp_allocator: std.mem.Allocator, segment: []const u8) ![]u8 { return std.fs.path.join( - _allocator, - &[_][]const u8{ getHome(), ".zm", segment }, + tmp_allocator, + &[_][]const u8{ get_home(), ".zm", segment }, ); } diff --git a/src/versions.zig b/src/versions.zig index 35ffb6b..f180f2a 100644 --- a/src/versions.zig +++ b/src/versions.zig @@ -1,6 +1,6 @@ const std = @import("std"); -// TODO: The url should be stored in a separate config file +// TODO: The URL should be stored in a separate config file. const url = "https://ziglang.org/download/index.json"; const uri = std.Uri.parse(url) catch unreachable; @@ -11,26 +11,20 @@ pub const VersionList = struct { allocator: std.mem.Allocator, pub fn init(allocator: std.mem.Allocator) !VersionList { - // Initialize HTTP client var client = std.http.Client{ .allocator = allocator }; defer client.deinit(); - // Read the response body with 256kb buffer allocation var buffer: [262144]u8 = undefined; // 256 * 1024 = 262kb - // Make the HTTP request var req = try client.open(.GET, uri, .{ .server_header_buffer = &buffer }); defer req.deinit(); - // send http request try req.send(); - - // wait response try req.wait(); - // Check if request was successful - if (req.response.status != .ok) + if (req.response.status != .ok) { return error.ListResponseNotOk; + } const len = try req.readAll(buffer[0..]); @@ -38,7 +32,6 @@ pub const VersionList = struct { defer json.deinit(); const root = json.value; - // Initialize array list to hold versions var lists = std.ArrayList([]const u8).init(allocator); var iterate = root.object.iterator(); From f7091a699c04f75980d2544799ab700001699049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20Niel=C3=A4nder?= Date: Tue, 23 Jul 2024 16:47:09 +0200 Subject: [PATCH 2/3] chore: add assert --- src/alias.zig | 14 +++++++++++++- src/download.zig | 7 +++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/alias.zig b/src/alias.zig index 05ba8b1..af913e4 100644 --- a/src/alias.zig +++ b/src/alias.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const assert = std.debug.assert; const builtin = @import("builtin"); const tools = @import("tools.zig"); @@ -17,6 +18,9 @@ pub fn set_zig_version(version: []const u8) !void { } fn update_symlink(zig_path: []const u8, symlink_path: []const u8) !void { + assert(zig_path.len > 0); + assert(symlink_path.len > 0); + if (builtin.os.tag == .windows) { if (std.fs.path.dirname(symlink_path)) |dirname| { var parent_dir = try std.fs.openDirAbsolute(dirname, .{ .iterate = true }); @@ -40,6 +44,9 @@ fn update_symlink(zig_path: []const u8, symlink_path: []const u8) !void { } fn copy_dir(source_dir: []const u8, dest_dir: []const u8) !void { + assert(source_dir.len > 0); + assert(dest_dir.len > 0); + var source = try std.fs.openDirAbsolute(source_dir, .{ .iterate = true }); defer source.close(); @@ -103,6 +110,9 @@ fn verify_zig_version(allocator: std.mem.Allocator, expected_version: []const u8 const actual_version = try retrieve_zig_version(allocator); defer allocator.free(actual_version); + assert(actual_version.len > 0); + assert(std.mem.eql(u8, expected_version, actual_version)); + if (!std.mem.eql(u8, expected_version, actual_version)) { std.debug.print("Expected Zig version {s}, but currently using {s}. Please check.\n", .{ expected_version, actual_version }); } else { @@ -124,7 +134,9 @@ fn retrieve_zig_version(allocator: std.mem.Allocator) ![]u8 { try child_process.spawn(); if (child_process.stdout) |stdout| { - return try stdout.reader().readUntilDelimiterOrEofAlloc(allocator, '\n', 100) orelse return error.EmptyVersion; + const version = try stdout.reader().readUntilDelimiterOrEofAlloc(allocator, '\n', 100) orelse return error.EmptyVersion; + assert(version.len > 0); + return version; } return error.FailedToReadVersion; diff --git a/src/download.zig b/src/download.zig index 04ad2f4..de3ddaa 100644 --- a/src/download.zig +++ b/src/download.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const assert = std.debug.assert; const builtin = @import("builtin"); const tools = @import("tools.zig"); const sha2 = std.crypto.hash.sha2; @@ -10,6 +11,9 @@ const lib = @import("extract.zig"); const archive_ext = if (builtin.os.tag == .windows) "zip" else "tar.xz"; pub fn content(allocator: std.mem.Allocator, version: []const u8, url: []const u8) !?[32]u8 { + assert(version.len > 0); + assert(url.len > 0); + const root_node = std.Progress.start(.{ .root_name = "", .estimated_total_items = 4, @@ -85,6 +89,9 @@ fn download_and_extract( version: []const u8, root_node: std.Progress.Node, ) ![32]u8 { + assert(version_path.len > 0); + assert(version.len > 0); + var client = std.http.Client{ .allocator = allocator }; defer client.deinit(); From 09bacfbc1a76a1d1a89a15c27554c541c69bb2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hendrik=20Niel=C3=A4nder?= Date: Tue, 23 Jul 2024 16:55:31 +0200 Subject: [PATCH 3/3] chore: bump version to 0.4.3 --- build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig b/build.zig index 08f73a4..852dbc5 100644 --- a/build.zig +++ b/build.zig @@ -6,7 +6,7 @@ const CrossTargetInfo = struct { name: []const u8, }; // Semantic version of your application -const version = std.SemanticVersion{ .major = 0, .minor = 4, .patch = 2 }; +const version = std.SemanticVersion{ .major = 0, .minor = 4, .patch = 3 }; const min_zig_string = "0.13.0";