const std = @import("std"); const equal = std.mem.eql; pub fn main() !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); const allocator = arena.allocator(); const arguments = try std.process.argsAlloc(allocator); var url_arg: ?[:0]const u8 = null; var prefix_arg: [:0]const u8 = "nat"; const State = enum { none, prefix, url, }; var state = State.none; for (arguments[1..]) |argument| { switch (state) { .none => { if (equal(u8, argument, "-prefix")) { state = .prefix; } else if (equal(u8, argument, "-url")) { state = .url; } else return error.InvalidInput; }, .prefix => { prefix_arg = argument; state = .none; }, .url => { url_arg = argument; state = .none; }, } } const url = url_arg orelse return error.InvalidInput; const prefix = prefix_arg; if (state != .none) return error.InvalidInput; const dot_index = std.mem.lastIndexOfScalar(u8, url, '.') orelse return error.InvalidInput; const extension_string = url[dot_index + 1 ..]; const Extension = enum { xz, gz, zip, }; const extension: Extension = inline for (@typeInfo(Extension).Enum.fields) |field| { if (std.mem.eql(u8, field.name, extension_string)) { break @enumFromInt(field.value); } } else return error.InvalidInput; const uri = try std.Uri.parse(url); var http_client = std.http.Client{ .allocator = allocator, }; defer http_client.deinit(); var buffer: [16 * 1024]u8 = undefined; var request = try http_client.open(.GET, uri, .{ .server_header_buffer = &buffer, }); defer request.deinit(); try request.send(.{}); try request.wait(); if (request.response.status != .ok) { @panic("Failure when fetching TAR"); //std.debug.panic("Status: {s} when fetching TAR {s}", .{@tagName(request.response.status), url}); } var decompressed_buffer = std.ArrayList(u8).init(allocator); switch (extension) { .xz => { var decompression = try std.compress.xz.decompress(allocator, request.reader()); defer decompression.deinit(); try decompression.reader().readAllArrayList(&decompressed_buffer, std.math.maxInt(u32)); }, .gz => { var decompression = std.compress.gzip.decompressor(request.reader()); try decompression.reader().readAllArrayList(&decompressed_buffer, std.math.maxInt(u32)); }, else => |t| @panic(@tagName(t)), } var memory_stream = std.io.fixedBufferStream(decompressed_buffer.items); const directory = try std.fs.cwd().makeOpenPath(prefix, .{}); try std.tar.pipeToFileSystem(directory, memory_stream.reader(), .{ .mode_mode = .ignore, }); }