diff --git a/.github/workflows/windows-installer.yaml b/.github/workflows/windows-installer.yaml new file mode 100644 index 0000000..c484de5 --- /dev/null +++ b/.github/workflows/windows-installer.yaml @@ -0,0 +1,18 @@ +name: windows-installer +on: + push: + paths: + - "src/zigverm-setup/main.zig" + tags: + - "*" + pull_request: + +jobs: + install-on-windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: mlugg/setup-zig@v2 + with: + version: master + - run: zig build run-zigverm-setup diff --git a/build.zig.zon b/build.zig.zon index 9ecc51b..8d26238 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -3,8 +3,8 @@ .version = "0.7.3", .dependencies = .{ .zip = .{ - .url = "https://github.com/AMythicDev/zip.zig/archive/refs/tags/v0.3.5.tar.gz", - .hash = "zip-0.3.4-eQGR_2ZcAABR1yEieYpo6fo7-JqIsBTGnwi3FiQ1uM5B", + .url = "https://github.com/AMythicDev/zip.zig/archive/refs/tags/v0.3.6.tar.gz", + .hash = "zip-0.3.4-eQGR_w1jAADGiS9F5F3vHnME13KeTDBWcbGyjLfNtvjE", }, }, .minimum_zig_version = "0.15.1", diff --git a/src/cli.zig b/src/cli.zig index 867c709..dd43dc7 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -53,7 +53,8 @@ pub const Cli = union(enum) { reference: ?[]const u8, pub fn read_args(alloc: Allocator, io: std.Io, args: std.process.Args) anyerror!Cli { - var arg_iter = args.iterate(); + var arg_iter = try args.iterateAllocator(alloc); + defer arg_iter.deinit(); _ = arg_iter.next(); var command: Cli = undefined; diff --git a/src/install.zig b/src/install.zig index 5ba765c..c080dfe 100644 --- a/src/install.zig +++ b/src/install.zig @@ -89,10 +89,10 @@ fn get_correct_tarball(alloc: Allocator, io: Io, client: *Client, tarball_dw_fil if (!hash_matched) { if (tries < 3) { - std.log.warn("Hashes do match for downloaded tarball. Retrying again...", .{}); + std.log.warn("Hashes do not match for downloaded tarball. Retrying again...", .{}); tarball = try get_correct_tarball(alloc, io, client, tarball_dw_filename, tarball_url, total_size, shasum, cp, tries + 1); } else { - std.log.err("Hashes do match for downloaded tarball. Exitting", .{}); + std.log.err("Hashes do not match for downloaded tarball. Exiting", .{}); return error.BadChecksum; } } @@ -122,31 +122,32 @@ pub fn downloadTarball(alloc: Allocator, io: Io, client: *Client, tb_url: []cons var redir_buf: [1024]u8 = undefined; var response = try req.?.receiveHead(&redir_buf); + var active_tarball_size = tarball_size; + if (tarball_size > 0 and response.head.status != .partial_content) { + active_tarball_size = 0; + try tb_writer.seekTo(0); + } + var reader = response.reader(&.{}); var buff: [1024]u8 = undefined; - // Convert everything into f64 for less typing in calculating % download and download speed - var dlnow = std.atomic.Value(f32).init(0); - const total_size_d: f64 = @floatFromInt(total_size); - const tarball_size_d: f64 = @floatFromInt(tarball_size); + var dlnow = std.atomic.Value(usize).init(0); + const tarball_size_u: usize = @intCast(active_tarball_size); - const progress_thread = try std.Thread.spawn(.{}, download_progress_bar, .{ io, &dlnow, tarball_size_d, total_size_d }); + const progress_thread = try std.Thread.spawn(.{}, download_progress_bar, .{ io, &dlnow, tarball_size_u, total_size }); const tbw_intf = &tb_writer.interface; - while (tarball_size_d + dlnow.load(AtomicOrder.monotonic) <= total_size_d) { + while (true) { const len = try reader.readSliceShort(&buff); - _ = try tbw_intf.write(buff[0..len]); - _ = dlnow.fetchAdd(@floatFromInt(len), AtomicOrder.monotonic); - - if (len < buff.len) { - break; - } + try tbw_intf.writeAll(buff[0..len]); + _ = dlnow.fetchAdd(len, AtomicOrder.monotonic); + if (len < buff.len) break; } progress_thread.join(); try tb_writer.end(); } -pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(f32), tarball_size: f64, total_size: f64) !void { +pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(usize), tarball_size: usize, total_size: usize) !void { const stderr = File.stderr(); var stderrw = stderr.writer(io, &.{}); const stderr_writer = &stderrw.interface; @@ -158,14 +159,14 @@ pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(f32), tarball_size var downloaded = dlnow.load(AtomicOrder.monotonic); while (true) { - const pcnt_complete: u8 = @intFromFloat((downloaded + tarball_size) * 100 / total_size); + const pcnt_complete: u8 = @intCast((downloaded + tarball_size) * 100 / total_size); const newbars: u8 = pcnt_complete / 2; for (bars..newbars) |i| { std.mem.copyForwards(u8, progress_bar[i * 3 .. i * 3 + 3], "█"); } bars = newbars; const time_passed: f64 = @floatFromInt(start.untilNow(io, clock).toSeconds()); - const speed = downloaded / 1024 / time_passed; + const speed = @as(f64, @floatFromInt(downloaded)) / 1024.0 / time_passed; try stderr_writer.print("\x1b[G\x1b[0K\t\x1b[33m{s}\x1b[0m{s} {d}% {d:.1}KB/s", .{ progress_bar[0 .. newbars * 3], progress_bar[newbars * 3 ..], pcnt_complete, speed }); if (downloaded + tarball_size >= total_size) break; diff --git a/src/zig/main.zig b/src/zig/main.zig index 35d4186..82ffba9 100644 --- a/src/zig/main.zig +++ b/src/zig/main.zig @@ -11,7 +11,7 @@ pub fn main(init: std.process.Init) !void { var version: ?[]const u8 = null; var version_specified = false; - var args_iter = init.minimal.args.iterate(); + var args_iter = try init.minimal.args.iterateAllocator(alloc); _ = args_iter.next(); const next_arg = args_iter.next(); diff --git a/src/zigverm-setup/main.zig b/src/zigverm-setup/main.zig index 8242188..ecae920 100644 --- a/src/zigverm-setup/main.zig +++ b/src/zigverm-setup/main.zig @@ -26,6 +26,7 @@ const DownloadTarball = struct { self.file_handle = try download_dir.createFile(io, self.filename, .{ .read = true, .truncate = false }); self.writer = self.file_handle.?.writer(io, &buf); self.file_size = @intCast(try self.file_handle.?.length(io)); + self.writer.?.pos = self.file_size; } fn deinit(self: *Self, io: Io) !void { @@ -162,25 +163,26 @@ fn download_tarball( var redir_buf: [1024]u8 = undefined; var response = try req.?.receiveHead(&redir_buf); + var active_tarball_size = tarball_size; + if (tarball_size > 0 and response.head.status != .partial_content) { + active_tarball_size = 0; + try tb_writer.seekTo(0); + } + var reader = response.reader(&.{}); var buff: [1024]u8 = undefined; - // Convert everything into f64 for less typing in calculating % download and download speed - var dlnow = std.atomic.Value(f32).init(0); - const total_size_d: f64 = @floatFromInt(total_size); - const tarball_size_d: f64 = @floatFromInt(tarball_size); + var dlnow = std.atomic.Value(usize).init(0); + const tarball_size_u: usize = @intCast(active_tarball_size); - const progress_thread = try std.Thread.spawn(.{}, download_progress_bar, .{ io, &dlnow, tarball_size_d, total_size_d }); + const progress_thread = try std.Thread.spawn(.{}, download_progress_bar, .{ io, &dlnow, tarball_size_u, total_size }); const tbw_intf = &tb_writer.interface; - while (tarball_size_d + dlnow.load(AtomicOrder.monotonic) <= total_size_d) { + while (true) { const len = try reader.readSliceShort(&buff); - _ = try tbw_intf.write(buff[0..len]); - _ = dlnow.fetchAdd(@floatFromInt(len), AtomicOrder.monotonic); - - if (len < buff.len) { - break; - } + try tbw_intf.writeAll(buff[0..len]); + _ = dlnow.fetchAdd(len, AtomicOrder.monotonic); + if (len < buff.len) break; } progress_thread.join(); try tb_writer.end(); @@ -222,7 +224,7 @@ fn read_github_releases_data(alloc: std.mem.Allocator, io: Io, client: *Client) return try json.parseFromTokenSource(json.Value, alloc, &json_reader, .{}); } -pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(f32), tarball_size: f64, total_size: f64) !void { +pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(usize), tarball_size: usize, total_size: usize) !void { const stderr = std.Io.File.stderr(); var stderrw = std.Io.File.Writer.init(stderr, io, &.{}); const stderr_writer = &stderrw.interface; @@ -235,14 +237,14 @@ pub fn download_progress_bar(io: Io, dlnow: *std.atomic.Value(f32), tarball_size var downloaded = dlnow.load(AtomicOrder.monotonic); while (true) { - const pcnt_complete: u8 = @intFromFloat((downloaded + tarball_size) * 100 / total_size); + const pcnt_complete: u8 = @intCast((downloaded + tarball_size) * 100 / total_size); const newbars: u8 = pcnt_complete / 2; for (bars..newbars) |i| { std.mem.copyForwards(u8, progress_bar[i * 3 .. i * 3 + 3], "█"); } bars = newbars; const time_passed: f64 = @floatFromInt(start.untilNow(io, clock).toSeconds()); - const speed = downloaded / 1024 / time_passed; + const speed = @as(f64, @floatFromInt(downloaded)) / 1024.0 / time_passed; try stderr_writer.print("\x1b[G\x1b[0K\t\x1b[33m{s}\x1b[0m{s} {d}% {d:.1}KB/s", .{ progress_bar[0 .. newbars * 3], progress_bar[newbars * 3 ..], pcnt_complete, speed }); if (downloaded + tarball_size >= total_size) break;