nativity/build/fetcher.zig
2024-03-24 08:58:05 -06:00

97 lines
3.0 KiB
Zig

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