Skip to content

Commit

Permalink
feat: use std.tar.pipeToFileSystem
Browse files Browse the repository at this point in the history
  • Loading branch information
hendriknielaender committed Jan 26, 2024
1 parent 59c9fe5 commit d16c20a
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 728 deletions.
7 changes: 5 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
// Add a global option for versioning
const options = b.addOptions();
options.addOption(std.log.Level, "log_level", b.option(std.log.Level, "log_level", "The Log Level to be used.") orelse .info);
options.addOption(std.SemanticVersion, "zvm_version", version);

const exe = b.addExecutable(.{
Expand All @@ -44,7 +45,8 @@ pub fn build(b: *std.Build) void {
exe.linkSystemLibrary("archive"); // libarchive
exe.linkSystemLibrary("lzma"); // liblzma

exe.addOptions("options", options);
const exe_options_module = options.createModule();
exe.root_module.addImport("options", exe_options_module);

b.installArtifact(exe);

Expand Down Expand Up @@ -92,7 +94,8 @@ pub fn build(b: *std.Build) void {
rel_exe.linkSystemLibrary("archive"); // libarchive
rel_exe.linkSystemLibrary("lzma"); // liblzma

rel_exe.addOptions("options", options);
const rel_exe_options_module = options.createModule();
rel_exe.root_module.addImport("options", rel_exe_options_module);

const install = b.addInstallArtifact(rel_exe, .{});
install.dest_dir = .prefix;
Expand Down
8 changes: 4 additions & 4 deletions src/architecture.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ pub fn detect(allocator: std.mem.Allocator, params: DetectParams) !?[]u8 {
const result = try allocator.alloc(u8, len);

if (params.reverse) {
std.mem.copy(u8, result[0..archStr.len], archStr);
@memcpy(result[0..archStr.len], archStr);
result[archStr.len] = '-';
std.mem.copy(u8, result[archStr.len + 1 ..], osStr);
@memcpy(result[archStr.len + 1 ..], osStr);
} else {
std.mem.copy(u8, result[0..osStr.len], osStr);
@memcpy(result[0..osStr.len], osStr);
result[osStr.len] = '-';
std.mem.copy(u8, result[osStr.len + 1 ..], archStr);
@memcpy(result[osStr.len + 1 ..], archStr);
}

return result;
Expand Down
1 change: 0 additions & 1 deletion src/deps/libarchive
Submodule libarchive deleted from 67a20c
53 changes: 29 additions & 24 deletions src/download.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const architecture = @import("architecture.zig");
const Progress = std.Progress;
const alias = @import("alias.zig");
const hash = @import("hash.zig");
const lib = @import("libarchive/libarchive.zig");
const lib = @import("extract.zig");
const crypto = std.crypto;

const archive_ext = if (builtin.os.tag == .windows) "zip" else "tar.xz";
Expand Down Expand Up @@ -85,9 +85,12 @@ fn downloadAndExtract(allocator: std.mem.Allocator, uri: std.Uri, version_path:
var client = std.http.Client{ .allocator = allocator };
defer client.deinit();

var req = try client.request(.GET, uri, .{ .allocator = allocator }, .{});
const sendOptions = std.http.Client.Request.SendOptions{};

var req = try client.open(.GET, uri, .{ .allocator = allocator }, .{});
defer req.deinit();
try req.start();

try req.send(sendOptions);
try req.wait();

try std.testing.expect(req.response.status == .ok);
Expand All @@ -101,6 +104,8 @@ fn downloadAndExtract(allocator: std.mem.Allocator, uri: std.Uri, version_path:
const file_name = try std.mem.concat(allocator, u8, &[_][]const u8{ "zig-", platform, "-", version, ".", archive_ext });
defer allocator.free(file_name);

std.debug.print("Constructed file name: {s}\n", .{file_name});

const totalSize = req.response.content_length orelse 0;
var downloadedBytes: usize = 0;

Expand All @@ -112,6 +117,8 @@ fn downloadAndExtract(allocator: std.mem.Allocator, uri: std.Uri, version_path:
const file_stream = try zvm_dir.createFile(file_name, .{});
defer file_stream.close();

std.debug.print("Download complete, file written: {s}\n", .{file_name});

var sha256 = sha2.Sha256.init(.{});

while (true) {
Expand All @@ -129,39 +136,37 @@ fn downloadAndExtract(allocator: std.mem.Allocator, uri: std.Uri, version_path:
try file_stream.writeAll(buffer[0..bytes_read]);
}

const file_path = try zvm_dir.realpathAlloc(allocator, file_name);
defer allocator.free(file_path);
//const file_path = try zvm_dir.realpathAlloc(allocator, file_stream);
//defer allocator.free(file_path);
download_node.end();

// libarchive can't set dest path so it extracts to cwd
// rename here moves the extracted folder to the correct path
// (cwd)/zig-linux-x86_64-0.11.0 -> ~/zvm/versions/0.11.0
var extract_node = root_node.start("Extracting", 1);
extract_node.activate();
progress.refresh();
_ = try lib.extractTarXZ(file_path);
extract_node.end();
// TODO: use std.tar.pipeToFileSystem() in the future, currently very slow
const c_allocator = std.heap.c_allocator;

var move_node = root_node.start("Copy Files", 1);
move_node.activate();
progress.refresh();
const folder_name = try std.fmt.allocPrint(allocator, "zig-{s}-{s}", .{ platform, version });
defer allocator.free(folder_name);
// ~/.zm/versions/zig-macos-x86_64-0.10.0.tar.xz
const zvm_path = try getZvmPathSegment("");
const downloaded_file_path = try std.fs.path.join(allocator, &.{ zvm_path, file_name });
defer allocator.free(downloaded_file_path);

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);

std.fs.makeDirAbsolute(version_path) catch {};
std.debug.print("folder_path: {s}\n", .{folder_path});
std.fs.makeDirAbsolute(folder_path) catch {};

//std.debug.print("Renaming '{s}' to '{s}'\n", .{ folder_name, folder_path });
const zvm_dir_version = try std.fs.openDirAbsolute(folder_path, .{});

if (std.fs.cwd().rename(folder_name, folder_path)) |_| {
//std.debug.print("✓ Successfully renamed {s} to {s}.\n", .{ folder_name, folder_path });
} else |err| {
std.debug.print("✗ Error: Failed to rename {s} to {s}. Reason: {any}\n", .{ folder_name, folder_path, err });
}
move_node.end();
const downloaded_file = try zvm_dir.openFile(downloaded_file_path, .{});
defer downloaded_file.close();

_ = try lib.extract_tarxz_to_dir(c_allocator, zvm_dir_version, downloaded_file);
extract_node.end();

var result: [32]u8 = undefined;
sha256.final(&result);
Expand Down
8 changes: 8 additions & 0 deletions src/extract.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const std = @import("std");

pub fn extract_tarxz_to_dir(allocator: std.mem.Allocator, outDir: 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 = .ignore });
}
6 changes: 4 additions & 2 deletions src/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ fn fetchVersionData(allocator: Allocator, requested_version: []const u8, sub_key
var client = std.http.Client{ .allocator = allocator };
defer client.deinit();

const sendOptions = std.http.Client.Request.SendOptions{};

// Make the HTTP request
var req = try client.request(.GET, uri, .{ .allocator = allocator }, .{});
var req = try client.open(.GET, uri, .{ .allocator = allocator }, .{});
defer req.deinit();
try req.start();
try req.send(sendOptions);
try req.wait();

// Check if request was successful
Expand Down
Loading

0 comments on commit d16c20a

Please sign in to comment.