WIP remote install and list
This commit is contained in:
parent
86bce941de
commit
6ea3710e4f
24
src/main.zig
24
src/main.zig
|
@ -11,6 +11,7 @@ pub const ZIM_BUILD = 1;
|
||||||
/// The availble arguments for the ZiM program
|
/// The availble arguments for the ZiM program
|
||||||
const Args = enum(u8) {
|
const Args = enum(u8) {
|
||||||
help,
|
help,
|
||||||
|
init,
|
||||||
install,
|
install,
|
||||||
list,
|
list,
|
||||||
use,
|
use,
|
||||||
|
@ -35,11 +36,12 @@ pub fn versionStr(allocator: std.mem.Allocator) ![]const u8 {
|
||||||
/// Returns what each argument expects to follow it
|
/// Returns what each argument expects to follow it
|
||||||
fn get_arg_parse_type(arg: Args) ArgType {
|
fn get_arg_parse_type(arg: Args) ArgType {
|
||||||
return switch (arg) {
|
return switch (arg) {
|
||||||
|
.gir => ArgType.single,
|
||||||
.help => ArgType.single,
|
.help => ArgType.single,
|
||||||
|
.init => ArgType.single,
|
||||||
.install => ArgType.expectsOneParam,
|
.install => ArgType.expectsOneParam,
|
||||||
.list => ArgType.expectsOneParam,
|
.list => ArgType.expectsOneParam,
|
||||||
.use => ArgType.expectsOneParam,
|
.use => ArgType.expectsOneParam,
|
||||||
.gir => ArgType.single,
|
|
||||||
.version => ArgType.single,
|
.version => ArgType.single,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -47,12 +49,13 @@ fn get_arg_parse_type(arg: Args) ArgType {
|
||||||
/// For a given `Args`, returns a string description of what each does
|
/// For a given `Args`, returns a string description of what each does
|
||||||
fn command_desc(arg: Args) string {
|
fn command_desc(arg: Args) string {
|
||||||
return switch (arg) {
|
return switch (arg) {
|
||||||
|
.gir => " gir\t\tPrint out ascii Gir",
|
||||||
.help => " help\t\tDisplays this help message",
|
.help => " help\t\tDisplays this help message",
|
||||||
|
.init => " init\t\tAdds the necessary PATH to the system env",
|
||||||
.install => " install\tInstall the zig version",
|
.install => " install\tInstall the zig version",
|
||||||
.list => " list\t\tLists all versions available on the system",
|
.list => " list\t\tLists all versions available on the system",
|
||||||
.use => " use\t\tSets the active version of zig to use",
|
.use => " use\t\tSets the active version of zig to use",
|
||||||
.version => " version\t\tPrint out the zim version you are using",
|
.version => " version\t\tPrint out the zim version you are using",
|
||||||
.gir => " gir\t\tPrint out ascii Gir",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +106,7 @@ fn show_context_help(arg: Args) void {
|
||||||
\\
|
\\
|
||||||
, .{});
|
, .{});
|
||||||
},
|
},
|
||||||
.gir, .version, .help => {
|
.gir, .help, .init, .version => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -118,6 +121,13 @@ fn do_arg_action(allocator: std.mem.Allocator, arg: Args, param: ?[]const u8) vo
|
||||||
.gir => {
|
.gir => {
|
||||||
utils.printGir();
|
utils.printGir();
|
||||||
},
|
},
|
||||||
|
.init => {
|
||||||
|
zim.init(allocator) catch |err| {
|
||||||
|
std.debug.print("Error running `init`\n{any}\n", .{err});
|
||||||
|
};
|
||||||
|
std.os.exit(1);
|
||||||
|
return;
|
||||||
|
},
|
||||||
.version => {
|
.version => {
|
||||||
const ver = versionStr(allocator) catch {
|
const ver = versionStr(allocator) catch {
|
||||||
std.debug.print("Error getting version\n", .{});
|
std.debug.print("Error getting version\n", .{});
|
||||||
|
@ -135,7 +145,7 @@ fn do_arg_action(allocator: std.mem.Allocator, arg: Args, param: ?[]const u8) vo
|
||||||
},
|
},
|
||||||
.install => {
|
.install => {
|
||||||
if (param == null) {
|
if (param == null) {
|
||||||
std.debug.print("Error: Expected version to follow\n\n", .{});
|
std.debug.print("Error: Expected index or version name to follow.\nRun `zim install help` for details.\n\n", .{});
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -167,13 +177,13 @@ fn do_arg_action(allocator: std.mem.Allocator, arg: Args, param: ?[]const u8) vo
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
}
|
}
|
||||||
zim.list(allocator, param.?) catch |err| {
|
zim.list(allocator, param.?) catch |err| {
|
||||||
std.debug.print("Error running `list {s}`\n{any}", .{ param.?, err });
|
std.debug.print("Error running `list {s}`\n{any}\n", .{ param.?, err });
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.use => {
|
.use => {
|
||||||
if (param == null) {
|
if (param == null) {
|
||||||
std.debug.print("Error: Expected version to follow\n\n", .{});
|
std.debug.print("Error: Expected version or index to follow.\nRun `zim use help` for details.\n\n", .{});
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
}
|
}
|
||||||
const p = param.?;
|
const p = param.?;
|
||||||
|
@ -183,7 +193,7 @@ fn do_arg_action(allocator: std.mem.Allocator, arg: Args, param: ?[]const u8) vo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zim.use(allocator, param.?) catch |err| {
|
zim.use(allocator, param.?) catch |err| {
|
||||||
std.debug.print("Error running `use {s}`\n{any}", .{ param.?, err });
|
std.debug.print("Error running `use {s}`\n{any}\n", .{ param.?, err });
|
||||||
std.os.exit(1);
|
std.os.exit(1);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,15 +30,16 @@ test {
|
||||||
|
|
||||||
pub fn printGir() void {
|
pub fn printGir() void {
|
||||||
std.debug.print(
|
std.debug.print(
|
||||||
\\ n n
|
\\ n n n n
|
||||||
\\ o ( )
|
\\ ( )
|
||||||
\\ ___/_ / I am \
|
\\ o ( I am )
|
||||||
\\ / / . o ( your )
|
\\ ___/_ o ( your )
|
||||||
\\ 0> 0 / \ Doom! /
|
\\ / / . ( Doom! )
|
||||||
\\ Lu__/ ( )
|
\\ 0> 0 / ( )
|
||||||
\\ || - u -
|
\\ Lu__/ u u u u
|
||||||
\\ o^ ^ o
|
\\ ||
|
||||||
\\ _/ / / \_
|
\\ o^ ^o
|
||||||
|
\\ ._/ | | \_
|
||||||
\\ |__|
|
\\ |__|
|
||||||
\\ O=> (O
|
\\ O=> (O
|
||||||
\\
|
\\
|
||||||
|
|
144
src/version.zig
144
src/version.zig
|
@ -1,20 +1,45 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
const string = []const u8;
|
const string = []const u8;
|
||||||
|
|
||||||
|
const JsonTokens = enum {
|
||||||
|
src,
|
||||||
|
docs,
|
||||||
|
stdDocs,
|
||||||
|
notes,
|
||||||
|
version,
|
||||||
|
bootstrap,
|
||||||
|
other,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ZVError = error{
|
||||||
|
CannotInit,
|
||||||
|
};
|
||||||
|
|
||||||
pub const ZigVersion = struct {
|
pub const ZigVersion = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
version_string: string,
|
version_string: string,
|
||||||
tarball_url: ?string,
|
tarball_url: ?string,
|
||||||
src_tarball_url: ?string,
|
src_tarball_url: ?string,
|
||||||
|
bootstrap_url: ?string,
|
||||||
platform_string: ?string,
|
platform_string: ?string,
|
||||||
docs_url: ?string,
|
docs_url: ?string,
|
||||||
|
std_docs_url: ?string,
|
||||||
|
notes_url: ?string,
|
||||||
|
latest: bool,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, scanner: *std.json.Scanner, ver_string: string) ZigVersion {
|
pub fn init(allocator: std.mem.Allocator, scanner: *std.json.Scanner, ver_string: string) ZVError!ZigVersion {
|
||||||
var version_string = allocator.dupe(u8, ver_string) catch unreachable;
|
var version_string = allocator.dupe(u8, ver_string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
var std_docs_url: ?string = null;
|
||||||
var docs_url: ?string = null;
|
var docs_url: ?string = null;
|
||||||
var tarball_url: ?string = null;
|
var tarball_url: ?string = null;
|
||||||
var platform_string: ?string = null;
|
var platform_string: ?string = null;
|
||||||
var src_tarball_url: ?string = null;
|
var src_tarball_url: ?string = null;
|
||||||
|
var bootstrap_url: ?string = null;
|
||||||
|
var notes_url: ?string = null;
|
||||||
|
var latest = false;
|
||||||
|
|
||||||
var scanning = true;
|
var scanning = true;
|
||||||
while (scanning) {
|
while (scanning) {
|
||||||
|
@ -30,31 +55,101 @@ pub const ZigVersion = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.string => {
|
.string => {
|
||||||
if (std.mem.eql(u8, token.string, "docs")) {
|
const json_tag = utils.nameToEnumTag(token.string, JsonTokens) catch JsonTokens.other;
|
||||||
const docs_token = scanner.*.next() catch unreachable;
|
switch (json_tag) {
|
||||||
docs_url = allocator.dupe(u8, docs_token.string) catch unreachable;
|
.docs => {
|
||||||
} else if (std.mem.eql(u8, token.string, "src")) {
|
const docs_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
docs_url = allocator.dupe(u8, docs_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.stdDocs => {
|
||||||
|
const std_docs_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
std_docs_url = allocator.dupe(u8, std_docs_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.src => {
|
||||||
// ignore the object begin
|
// ignore the object begin
|
||||||
checkNextToken(scanner, .object_begin);
|
checkNextToken(scanner, .object_begin);
|
||||||
_ = scanner.*.next() catch unreachable;
|
_ = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
// ignore tarball string
|
// ignore tarball string
|
||||||
checkNextToken(scanner, .string);
|
checkNextToken(scanner, .string);
|
||||||
_ = scanner.*.next() catch unreachable;
|
_ = scanner.*.next() catch {
|
||||||
const tar_token = scanner.*.next() catch unreachable;
|
return ZVError.CannotInit;
|
||||||
src_tarball_url = allocator.dupe(u8, tar_token.string) catch unreachable;
|
};
|
||||||
} else if (std.mem.eql(u8, token.string, "x86_64-linux")) {
|
const tar_token = scanner.*.next() catch {
|
||||||
platform_string = allocator.dupe(u8, token.string) catch unreachable;
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
src_tarball_url = allocator.dupe(u8, tar_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.notes => {
|
||||||
|
const std_docs_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
notes_url = allocator.dupe(u8, std_docs_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.version => {
|
||||||
|
const ver_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
version_string = allocator.dupe(u8, ver_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
latest = true;
|
||||||
|
},
|
||||||
|
.bootstrap => {
|
||||||
|
checkNextToken(scanner, .object_begin);
|
||||||
|
_ = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
// ignore tarball string
|
||||||
|
checkNextToken(scanner, .string);
|
||||||
|
_ = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
const tar_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
bootstrap_url = tar_token.string;
|
||||||
|
},
|
||||||
|
.other => {
|
||||||
|
const platform_name = "x86_64-linux";
|
||||||
|
if (std.mem.eql(u8, token.string, platform_name)) {
|
||||||
|
platform_string = allocator.dupe(u8, token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
// ignore object begin
|
// ignore object begin
|
||||||
checkNextToken(scanner, .object_begin);
|
checkNextToken(scanner, .object_begin);
|
||||||
_ = scanner.*.next() catch unreachable;
|
_ = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
checkNextToken(scanner, .string);
|
checkNextToken(scanner, .string);
|
||||||
const tar_token = scanner.*.next() catch unreachable;
|
const tar_token = scanner.*.next() catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
if (std.mem.eql(u8, tar_token.string, "tarball")) {
|
if (std.mem.eql(u8, tar_token.string, "tarball")) {
|
||||||
const tar_url_token = scanner.*.next() catch unreachable;
|
const tar_url_token = scanner.*.next() catch {
|
||||||
tarball_url = allocator.dupe(u8, tar_url_token.string) catch unreachable;
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
|
tarball_url = allocator.dupe(u8, tar_url_token.string) catch {
|
||||||
|
return ZVError.CannotInit;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
unreachable;
|
unreachable;
|
||||||
},
|
},
|
||||||
|
@ -66,7 +161,18 @@ pub const ZigVersion = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZigVersion{ .allocator = allocator, .version_string = version_string, .tarball_url = tarball_url, .src_tarball_url = src_tarball_url, .platform_string = platform_string, .docs_url = docs_url };
|
return ZigVersion{
|
||||||
|
.allocator = allocator,
|
||||||
|
.version_string = version_string,
|
||||||
|
.tarball_url = tarball_url,
|
||||||
|
.src_tarball_url = src_tarball_url,
|
||||||
|
.bootstrap_url = bootstrap_url,
|
||||||
|
.notes_url = notes_url,
|
||||||
|
.platform_string = platform_string,
|
||||||
|
.docs_url = docs_url,
|
||||||
|
.std_docs_url = std_docs_url,
|
||||||
|
.latest = latest,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {}
|
pub fn deinit() void {}
|
||||||
|
@ -87,8 +193,8 @@ pub const ZigVersion = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasTar(zv: *ZigVersion) bool {
|
pub fn available(zv: *const ZigVersion) bool {
|
||||||
return zv.tarball_url != null;
|
return zv.tarball_url != null or zv.src_tarball_url != null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
211
src/zim.zig
211
src/zim.zig
|
@ -4,16 +4,20 @@ const version = @import("version.zig");
|
||||||
const string = []const u8;
|
const string = []const u8;
|
||||||
|
|
||||||
const ZigVersion = version.ZigVersion;
|
const ZigVersion = version.ZigVersion;
|
||||||
|
const ZigVersionData = version.ZigVersionData;
|
||||||
|
|
||||||
const ZimError = error{
|
const ZimError = error{
|
||||||
|
BadIO,
|
||||||
BadParameter,
|
BadParameter,
|
||||||
MalformedJson,
|
MalformedJson,
|
||||||
|
Memory,
|
||||||
NetworkError,
|
NetworkError,
|
||||||
NotImplemented,
|
NotImplemented,
|
||||||
NoHomeConfigured,
|
NoHomeConfigured,
|
||||||
Unexpected,
|
Unexpected,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SIXTY_FOUR_KILOBYTES = 65536;
|
||||||
const BIN_SYM_ZIG_PATH = "bin/zig";
|
const BIN_SYM_ZIG_PATH = "bin/zig";
|
||||||
|
|
||||||
fn createSubDir(dir: std.fs.Dir, path: string) ZimError!void {
|
fn createSubDir(dir: std.fs.Dir, path: string) ZimError!void {
|
||||||
|
@ -106,9 +110,38 @@ fn getLocalVersionsList(
|
||||||
return versions_list;
|
return versions_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getRemoteVersionsList(allocator: std.mem.Allocator) ZimError!std.ArrayList(ZigVersion) {
|
/// Fetches all available remote versions of zig, cached locally if recently requested.
|
||||||
|
/// The caller owns the memory of the `std.ArrayList(ZigVersion)`
|
||||||
|
fn getRemoteVersionsSlice(allocator: std.mem.Allocator) ZimError![]const ZigVersion {
|
||||||
|
// Check local file first for chached network call first
|
||||||
|
const zim_dir = try openZimDir(allocator);
|
||||||
|
const now = @as(i128, @intCast(std.time.timestamp())) * 1000 * 1000;
|
||||||
|
const yesterday = now - (24 * 60 * 60 * 1000 * 1000);
|
||||||
|
var remote_versions_file = zim_dir.createFile("versions/remote_versions.json", .{ .read = true, .truncate = false }) catch {
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
defer remote_versions_file.close();
|
||||||
|
|
||||||
|
var body: string = "";
|
||||||
|
defer allocator.free(body);
|
||||||
|
|
||||||
|
const file_metadata = remote_versions_file.metadata() catch {
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (file_metadata.modified() > yesterday) {
|
||||||
|
body = remote_versions_file.readToEndAlloc(allocator, SIXTY_FOUR_KILOBYTES) catch |err| {
|
||||||
|
std.debug.print("Could not read remote versions file: {any}\n", .{err});
|
||||||
|
return ZimError.Unexpected;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (body.len == 0) {
|
||||||
|
std.debug.print("No cached versions, getting remote versions\n", .{});
|
||||||
|
|
||||||
|
// Otherwise, make network call and parse
|
||||||
const versions_json_url = "https://ziglang.org/download/index.json";
|
const versions_json_url = "https://ziglang.org/download/index.json";
|
||||||
const versions_json_uri = std.Uri.parse(versions_json_url) catch {
|
const versions_json_uri = std.Uri.parse(versions_json_url) catch {
|
||||||
|
std.debug.print("Could not parse URL for ziglang {s}\n", .{versions_json_url});
|
||||||
return ZimError.Unexpected;
|
return ZimError.Unexpected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,7 +151,7 @@ fn getRemoteVersionsList(allocator: std.mem.Allocator) ZimError!std.ArrayList(Zi
|
||||||
// Accept anything.
|
// Accept anything.
|
||||||
headers.append("accept", "*/*") catch {
|
headers.append("accept", "*/*") catch {
|
||||||
std.debug.print("Error adding headers\n", .{});
|
std.debug.print("Error adding headers\n", .{});
|
||||||
return ZimError.Unexpected;
|
return ZimError.NetworkError;
|
||||||
};
|
};
|
||||||
var client = std.http.Client{ .allocator = allocator };
|
var client = std.http.Client{ .allocator = allocator };
|
||||||
defer client.deinit();
|
defer client.deinit();
|
||||||
|
@ -139,18 +172,22 @@ fn getRemoteVersionsList(allocator: std.mem.Allocator) ZimError!std.ArrayList(Zi
|
||||||
return ZimError.NetworkError;
|
return ZimError.NetworkError;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sixty_four_kilobytes = 65536;
|
body = request.reader().readAllAlloc(allocator, SIXTY_FOUR_KILOBYTES) catch |err| {
|
||||||
const body = request.reader().readAllAlloc(allocator, sixty_four_kilobytes) catch |err| {
|
|
||||||
std.debug.print("Error getting body: {any}\n", .{err});
|
std.debug.print("Error getting body: {any}\n", .{err});
|
||||||
return ZimError.NetworkError;
|
return ZimError.NetworkError;
|
||||||
};
|
};
|
||||||
defer allocator.free(body);
|
|
||||||
|
// Write body response to file
|
||||||
|
remote_versions_file.writeAll(body) catch {
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var diag = std.json.Diagnostics{};
|
var diag = std.json.Diagnostics{};
|
||||||
var body_scanner = std.json.Scanner.initCompleteInput(allocator, body);
|
var body_scanner = std.json.Scanner.initCompleteInput(allocator, body);
|
||||||
body_scanner.enableDiagnostics(&diag);
|
body_scanner.enableDiagnostics(&diag);
|
||||||
|
|
||||||
var remote_zig_versions = std.ArrayList(ZigVersion).init(allocator);
|
var remote_zig_versions_list = std.ArrayList(ZigVersion).init(allocator);
|
||||||
|
|
||||||
var scanning = true;
|
var scanning = true;
|
||||||
var last_version: string = "";
|
var last_version: string = "";
|
||||||
|
@ -158,9 +195,11 @@ fn getRemoteVersionsList(allocator: std.mem.Allocator) ZimError!std.ArrayList(Zi
|
||||||
if (body_scanner.next()) |token| {
|
if (body_scanner.next()) |token| {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
.object_begin => {
|
.object_begin => {
|
||||||
const zv = ZigVersion.init(allocator, &body_scanner, last_version);
|
const zv = ZigVersion.init(allocator, &body_scanner, last_version) catch {
|
||||||
remote_zig_versions.append(zv) catch {
|
continue;
|
||||||
return ZimError.Unexpected;
|
};
|
||||||
|
remote_zig_versions_list.append(zv) catch {
|
||||||
|
return ZimError.Memory;
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.end_of_document => {
|
.end_of_document => {
|
||||||
|
@ -182,7 +221,9 @@ fn getRemoteVersionsList(allocator: std.mem.Allocator) ZimError!std.ArrayList(Zi
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return remote_zig_versions;
|
return remote_zig_versions_list.toOwnedSlice() catch {
|
||||||
|
return ZimError.Memory;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShellType = enum {
|
const ShellType = enum {
|
||||||
|
@ -218,13 +259,130 @@ fn printZimPathHelp(shell_tag: ?ShellType, zim_path: string) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn install(allocator: std.mem.Allocator, param: string) ZimError!void {
|
fn downloadAndExtractTarball(allocator: std.mem.Allocator, zv: ZigVersion) ZimError!void {
|
||||||
_ = param;
|
const tarball_uri = std.Uri.parse(zv.tarball_url.?) catch {
|
||||||
|
std.debug.print("Could not parse URL for tarball {s}\n", .{zv.tarball_url.?});
|
||||||
|
return ZimError.Unexpected;
|
||||||
|
};
|
||||||
|
|
||||||
|
var headers = std.http.Headers{ .allocator = allocator };
|
||||||
|
defer headers.deinit();
|
||||||
|
|
||||||
|
// Accept anything.
|
||||||
|
headers.append("accept", "*/*") catch {
|
||||||
|
std.debug.print("Error adding headers\n", .{});
|
||||||
|
return ZimError.NetworkError;
|
||||||
|
};
|
||||||
|
var client = std.http.Client{ .allocator = allocator };
|
||||||
|
defer client.deinit();
|
||||||
|
|
||||||
|
var request = client.request(.GET, tarball_uri, headers, .{}) catch {
|
||||||
|
std.debug.print("Error creating request\n", .{});
|
||||||
|
return ZimError.NetworkError;
|
||||||
|
};
|
||||||
|
defer request.deinit();
|
||||||
|
|
||||||
|
request.start() catch {
|
||||||
|
std.debug.print("Error starting request\n", .{});
|
||||||
|
return ZimError.NetworkError;
|
||||||
|
};
|
||||||
|
std.debug.print("Downloading {s}...\n", .{zv.tarball_url.?});
|
||||||
|
request.wait() catch {
|
||||||
|
std.debug.print("Error waiting for request\n", .{});
|
||||||
|
return ZimError.NetworkError;
|
||||||
|
};
|
||||||
|
|
||||||
|
const body: string = request.reader().readAllAlloc(allocator, SIXTY_FOUR_KILOBYTES * 2000) catch |err| {
|
||||||
|
std.debug.print("Error getting body: {any}\n", .{err});
|
||||||
|
return ZimError.NetworkError;
|
||||||
|
};
|
||||||
|
|
||||||
|
var zim_dir = try openZimDir(allocator);
|
||||||
|
|
||||||
|
// Get slice of absolute path to zim directory
|
||||||
|
const buf_len = 100;
|
||||||
|
var arr: [buf_len]u8 = undefined;
|
||||||
|
var buf = arr[0..];
|
||||||
|
const zim_path = zim_dir.realpath("./", buf) catch {
|
||||||
|
return ZimError.Memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Buffer length for file name `zig-<ver>.tar`
|
||||||
|
const tar_buf_len = 38;
|
||||||
|
var tar_arr: [tar_buf_len]u8 = undefined;
|
||||||
|
var tar_buf = tar_arr[0..];
|
||||||
|
const tarball_file_name = std.fmt.bufPrint(tar_buf, "zig-{s}.tar", .{ zim_path, zv.version_string }) catch {
|
||||||
|
return ZimError.Memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Buffer lenght for `<zim_path>/versions/<tarbll_file_name>`
|
||||||
|
const full_tar_buf_len = buf_len + tar_buf_len + 10;
|
||||||
|
var full_tar_arr: [full_tar_buf_len]u8 = undefined;
|
||||||
|
var full_tar_buf = full_tar_arr[0..];
|
||||||
|
const full_path_tarball_file_name = std.fmt.bufPrint(full_tar_buf, "{s}/versions/{s}", .{ zim_path, tarball_file_name}) catch {
|
||||||
|
return ZimError.Memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ver_buf_len = 100;
|
||||||
|
var ver_arr: [ver_buf_len]u8 = undefined;
|
||||||
|
var ver_buf = ver_arr[0..];
|
||||||
|
const versions_path = std.fmt.bufPrint(ver_buf, "{s}/versions", .{zim_path}) catch {
|
||||||
|
return ZimError.Memory;
|
||||||
|
};
|
||||||
|
|
||||||
|
var tarball_file = zim_dir.createFile(full_path_tarball_file_name, .{}) catch {
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
tarball_file.writer().writeAll(body) catch {
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Buffer length for new version dir name `versions/zig-<ver>/`
|
||||||
|
var proc = std.ChildProcess.init(&.{ "tar", "-xf", full_path_tarball_file_name, "-C", versions_path }, allocator);
|
||||||
|
|
||||||
|
std.debug.print("Unpacking {s}...\n", .{tarball_file_name});
|
||||||
|
_ = proc.spawnAndWait() catch |err| {
|
||||||
|
std.debug.print("Could not spawn tar child process: {any}\n", .{err});
|
||||||
|
return ZimError.Unexpected;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove tarball file
|
||||||
|
zim_dir.deleteFile(full_path_tarball_file_name) catch |err| {
|
||||||
|
std.debug.print("Could not remove {s}: {any}\n", .{tarball_file_name, err});
|
||||||
|
return ZimError.BadIO;
|
||||||
|
};
|
||||||
|
|
||||||
|
std.debug.print("{s} is installed and now locally available!\n", .{zv.version_string});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install(allocator: std.mem.Allocator, param: string) ZimError!void {
|
||||||
var zim_dir = try openZimDir(allocator);
|
var zim_dir = try openZimDir(allocator);
|
||||||
defer zim_dir.close();
|
defer zim_dir.close();
|
||||||
|
|
||||||
|
var remote_versions = try getRemoteVersionsSlice(allocator);
|
||||||
|
defer allocator.free(remote_versions);
|
||||||
|
|
||||||
|
const version_num: ?u8 = std.fmt.parseInt(u8, param, 0) catch null;
|
||||||
|
if (version_num != null) {
|
||||||
|
const num = version_num.?;
|
||||||
|
if (num > remote_versions.len) {
|
||||||
|
std.debug.print("{d} exceeds the range of available versions: {d}\n", .{ num, remote_versions.len });
|
||||||
|
return ZimError.BadParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
const zv: ZigVersion = remote_versions[version_num.? - 1];
|
||||||
|
std.debug.print("Attempting to install {s}\n", .{zv.version_string});
|
||||||
|
|
||||||
|
if (zv.tarball_url != null) {
|
||||||
|
try downloadAndExtractTarball(allocator, zv);
|
||||||
|
} else {
|
||||||
|
std.debug.print("No tarball url available for version {s}\n", .{zv.version_string});
|
||||||
|
return ZimError.Unexpected;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std.debug.print("Cannot install version from string yet\n", .{});
|
||||||
return ZimError.NotImplemented;
|
return ZimError.NotImplemented;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use(allocator: std.mem.Allocator, param: string) ZimError!void {
|
pub fn use(allocator: std.mem.Allocator, param: string) ZimError!void {
|
||||||
|
@ -290,14 +448,6 @@ pub fn use(allocator: std.mem.Allocator, param: string) ZimError!void {
|
||||||
std.debug.print("Using raw string version {s}\n", .{param});
|
std.debug.print("Using raw string version {s}\n", .{param});
|
||||||
return ZimError.NotImplemented;
|
return ZimError.NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
// std.debug.print("Local Zig Versions:\n", .{});
|
|
||||||
// var i: u8 = 0;
|
|
||||||
// while (versions_list.popOrNull()) |version| {
|
|
||||||
// std.debug.print("\n [{d}]\tZig Version {s}", .{ i + 1, version });
|
|
||||||
// i += 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZimListType = enum { local, global };
|
const ZimListType = enum { local, global };
|
||||||
|
@ -333,16 +483,29 @@ pub fn list(allocator: std.mem.Allocator, param: string) !void {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
.global => {
|
.global => {
|
||||||
var remote_versions = try getRemoteVersionsList(allocator);
|
var remote_versions = try getRemoteVersionsSlice(allocator);
|
||||||
if (remote_versions.items.len == 0) {
|
defer allocator.free(remote_versions);
|
||||||
|
|
||||||
|
if (remote_versions.len == 0) {
|
||||||
std.debug.print("Failed to get remote versions\n", .{});
|
std.debug.print("Failed to get remote versions\n", .{});
|
||||||
return ZimError.Unexpected;
|
return ZimError.Unexpected;
|
||||||
}
|
}
|
||||||
std.debug.print("Retrieved remote zig versions:\n", .{});
|
std.debug.print("Retrieved remote zig versions:\n", .{});
|
||||||
for (remote_versions.items) |remote_version| {
|
var index: u8 = 0;
|
||||||
remote_version.fmtPrint();
|
for (remote_versions) |remote_version| {
|
||||||
|
if (remote_version.available()) {
|
||||||
|
index = index + 1;
|
||||||
|
std.debug.print(" [{d}]\tzig-{s}\n", .{ index, remote_version.version_string });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
std.debug.print("\nZig versions can be installed using `zim install <version or index>`\n\n", .{});
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the `init` subcommand
|
||||||
|
pub fn init(allocator: std.mem.Allocator) !void {
|
||||||
|
_ = allocator;
|
||||||
|
return ZimError.NotImplemented;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user