Compare commits
13 commits
Author | SHA1 | Date | |
---|---|---|---|
12c921d58c | |||
02fd112b65 | |||
ed72799023 | |||
412287cb40 | |||
3ac0d0f544 | |||
2a4e7d0f48 | |||
29a8f8df03 | |||
36a08d533d | |||
7c805820f8 | |||
11f1939fe9 | |||
593aee055a | |||
e3e56e8804 | |||
e65e0136bd |
17 changed files with 180 additions and 197 deletions
38
.forgejo/workflows/release.yml
Normal file
38
.forgejo/workflows/release.yml
Normal file
|
@ -0,0 +1,38 @@
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: docker-x86_64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Zig
|
||||
uses: https://github.com/goto-bus-stop/setup-zig@v2
|
||||
with:
|
||||
version: 0.12.0
|
||||
|
||||
- name: Setup Packages
|
||||
run: |
|
||||
apt update
|
||||
apt install -y ca-certificates zip libarchive-dev libarchive13
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
zig build -Doptimize=ReleaseFast
|
||||
|
||||
- name: Zip
|
||||
run: |
|
||||
mkdir release
|
||||
cd zig-out
|
||||
zip -r ../release/zupper-linux-x86_64.zip .
|
||||
|
||||
- name: Upload
|
||||
uses: actions/forgejo-release@v1
|
||||
with:
|
||||
direction: upload
|
||||
release-dir: release
|
||||
token: ${{ env.GITHUB_TOKEN }}
|
22
.forgejo/workflows/test.yml
Normal file
22
.forgejo/workflows/test.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
on: [push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Zig
|
||||
uses: https://github.com/goto-bus-stop/setup-zig@v2
|
||||
with:
|
||||
version: 0.12.0
|
||||
|
||||
- name: Setup Packages
|
||||
run: |
|
||||
apt update
|
||||
apt install -y ca-certificates libarchive-dev libarchive13
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
zig fmt --check .
|
|
@ -1,24 +0,0 @@
|
|||
pipeline:
|
||||
build:
|
||||
image: debian # not using alpine so we get a glibc build
|
||||
commands:
|
||||
- apt update
|
||||
- apt install -y curl jq xz-utils libarchive-dev libarchive13
|
||||
|
||||
# Install Zig
|
||||
- curl $(curl https://ziglang.org/download/index.json | jq -r '.master."x86_64-linux".tarball') -o /tmp/zig.tar.xz
|
||||
- tar xf /tmp/zig.tar.xz --directory=/tmp
|
||||
- export PATH="$(echo /tmp/zig-*):$PATH"
|
||||
|
||||
- zig build -Doptimize=ReleaseFast
|
||||
|
||||
publish:
|
||||
image: woodpeckerci/plugin-gitea-release
|
||||
settings:
|
||||
base_url: https://mzte.de/git
|
||||
api_key:
|
||||
from_secret: forgejo_key
|
||||
title: tag-${CI_COMMIT_TAG}
|
||||
files: zig-out/bin/zupper
|
||||
when:
|
||||
event: tag
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
A Zig version manager, written in zig.
|
||||
|
||||
WARNING: zupper is alpha software! Expect bugs!
|
||||
|
||||
## features
|
||||
|
||||
- managing multiple zig installations
|
||||
|
@ -46,7 +44,8 @@ apt install \
|
|||
|
||||
2. Install the zig toolchain
|
||||
|
||||
Zupper requires the development version of Zig (0.11.0). Make sure you install one of the latest versions of Zig.
|
||||
Zupper requires the 0.12.0 version of Zig. You can get a compiler from the
|
||||
[Zig website](https://ziglang.org), or your distribution's package manager.
|
||||
|
||||
3. Build it!
|
||||
|
||||
|
|
46
build.zig
46
build.zig
|
@ -4,18 +4,27 @@ pub fn build(b: *std.Build) !void {
|
|||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
//const opts = b.addOptions();
|
||||
//opts.addOption([]const u8, "version", ?);
|
||||
const args_dep = b.dependency("args", .{ .target = target, .optimize = optimize });
|
||||
const known_folders_dep = b.dependency("known_folders", .{});
|
||||
const ansi_term_dep = b.dependency("ansi_term", .{ .target = target, .optimize = optimize });
|
||||
const getty_dep = b.dependency("getty", .{ .target = target, .optimize = optimize });
|
||||
const getty_json_dep = b.dependency("getty_json", .{ .target = target, .optimize = optimize });
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zupper",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
|
||||
exe.strip = optimize != .Debug and optimize != .ReleaseSafe;
|
||||
addDeps(b, exe);
|
||||
exe.root_module.linkSystemLibrary("archive", .{});
|
||||
|
||||
exe.root_module.addImport("zig-args", args_dep.module("args"));
|
||||
exe.root_module.addImport("known-folders", known_folders_dep.module("known-folders"));
|
||||
exe.root_module.addImport("ansi-term", ansi_term_dep.module("ansi-term"));
|
||||
exe.root_module.addImport("getty", getty_dep.module("getty"));
|
||||
exe.root_module.addImport("json", getty_json_dep.module("json"));
|
||||
|
||||
b.installArtifact(exe);
|
||||
|
||||
|
@ -28,32 +37,3 @@ pub fn build(b: *std.Build) !void {
|
|||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
fn addDeps(b: *std.Build, exe: *std.Build.CompileStep) void {
|
||||
const module_opts = .{ .target = exe.target, .optimize = exe.optimize };
|
||||
exe.addModule(
|
||||
"zig-args",
|
||||
b.dependency("args", module_opts).module("args"),
|
||||
);
|
||||
exe.addModule(
|
||||
"known-folders",
|
||||
b.dependency("known_folders", .{}).module("known-folders"),
|
||||
);
|
||||
exe.addModule(
|
||||
"ansi-term",
|
||||
b.dependency("ansi_term", module_opts).module("ansi-term"),
|
||||
);
|
||||
exe.addModule(
|
||||
"getty",
|
||||
b.dependency("getty", module_opts).module("getty"),
|
||||
);
|
||||
exe.addModule(
|
||||
"json",
|
||||
b.dependency("getty_json", module_opts).module("json"),
|
||||
);
|
||||
|
||||
exe.linkLibC();
|
||||
|
||||
// used to unpack downloaded zig packages
|
||||
exe.linkSystemLibrary("archive");
|
||||
}
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
.{
|
||||
.name = "zupper",
|
||||
.version = "0.3.0",
|
||||
.version = "1.0.0",
|
||||
|
||||
.paths = .{""},
|
||||
|
||||
.dependencies = .{
|
||||
.args = .{
|
||||
.url = "https://mzte.de/git/mirrors/zig-args/archive/91d1e89fb89a4d01dec7c9aec95b0a324080ebcc.tar.gz",
|
||||
.hash = "12203d04cafc97f952d74cdb077e74c0ab3414f9f6b5fbd159112c62bfa584a0dbed",
|
||||
.url = "git+https://git.mzte.de/mirrors/zig-args.git#89f18a104d9c13763b90e97d6b4ce133da8a3e2b",
|
||||
.hash = "12203ded54c85878eea7f12744066dcb4397177395ac49a7b2aa365bf6047b623829",
|
||||
},
|
||||
.known_folders = .{
|
||||
.url = "https://github.com/ziglibs/known-folders/archive/fa75e1bc672952efa0cf06160bbd942b47f6d59b.tar.gz",
|
||||
.hash = "122048992ca58a78318b6eba4f65c692564be5af3b30fbef50cd4abeda981b2e7fa5",
|
||||
.url = "git+https://github.com/ziglibs/known-folders.git#2aa7f2e9855d45b20072e15107fb379b9380adbe",
|
||||
.hash = "12209925016f4b5486a713828ead3bcc900fa4f039c93de1894aa7d5253f7633b92c",
|
||||
},
|
||||
.ansi_term = .{
|
||||
.url = "https://github.com/ziglibs/ansi-term/archive/1614b61486d567b59abe11a097d11aa6ce679819.tar.gz",
|
||||
.hash = "1220647eea49d2c48d5e59354291e975f813be3cc5a9d9920a50bbfaa40a891a06ee",
|
||||
.url = "git+https://github.com/LordMZTE/ansi-term.git#73c03175068679685535111dbea72cade075719e",
|
||||
.hash = "1220ea86ace34b38e49c1d737c5f857d88346af10695a992b38e10cb0a73b6a19ef7",
|
||||
},
|
||||
.getty = .{
|
||||
.url = "https://github.com/getty-zig/getty/archive/6bdd2307748525ba98f5538234cf4768074e8a18.tar.gz",
|
||||
.hash = "122032aa72f6a4f58d4e0b7c381dbb855423189fa94e96b290c9bdfbe6e2752045c7",
|
||||
.url = "https://github.com/getty-zig/getty/archive/d27b9c72c553ee7e9fb383aa955ae1a705cde215.tar.gz",
|
||||
.hash = "12208cf585a316dddfb837fb7397b0cc4a9974716adf63f856171fbd6e99cb9b131d",
|
||||
},
|
||||
.getty_json = .{
|
||||
.url = "https://github.com/getty-zig/json/archive/3e3cf7bbc9894fa58978f3615524cdbf635aa6b7.tar.gz",
|
||||
.hash = "122017ccb426b5f5690fdda438134852e940796b0ac619eb2648782a7879146f4fcd",
|
||||
.url = "git+https://github.com/getty-zig/json.git#11946ff9d2f159cb06aaf423ce13bd8aa2a481e7",
|
||||
.hash = "1220829a91cb0804b35dadb6eb453cd9694b16d624e02493dc712ad43fd8681095f1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@ const dirs = @import("dirs.zig");
|
|||
const json = @import("json");
|
||||
const getty = @import("getty");
|
||||
|
||||
versions: std.StringHashMap(std.SemanticVersion),
|
||||
in_use: ?[]u8 = null,
|
||||
const Data = struct {
|
||||
versions: std.StringHashMap(std.SemanticVersion),
|
||||
in_use: ?[]u8 = null,
|
||||
};
|
||||
|
||||
data: getty.de.Result(Data),
|
||||
|
||||
const Self = @This();
|
||||
|
||||
|
@ -16,7 +20,8 @@ pub fn path(alloc: std.mem.Allocator) ![]const u8 {
|
|||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
json.de.free(self.versions.allocator, self.*, null);
|
||||
self.data.deinit();
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
|
@ -39,7 +44,7 @@ pub fn load(alloc: std.mem.Allocator) !Self {
|
|||
const data = try f.readToEndAlloc(alloc, std.math.maxInt(usize));
|
||||
defer alloc.free(data);
|
||||
|
||||
const self = json.fromSlice(alloc, Self, data) catch |e| {
|
||||
const deser = json.fromSlice(alloc, Data, data) catch |e| {
|
||||
std.log.err(
|
||||
\\failed to deserialize manifest! someone messed with my files! (how dare you!): {s}
|
||||
\\try deleting '{s}'
|
||||
|
@ -49,24 +54,23 @@ pub fn load(alloc: std.mem.Allocator) !Self {
|
|||
return error.Explained;
|
||||
};
|
||||
|
||||
return self;
|
||||
return .{ .data = deser };
|
||||
} else {
|
||||
return .{
|
||||
.versions = std.StringHashMap(std.SemanticVersion).init(alloc),
|
||||
};
|
||||
var arena = try alloc.create(std.heap.ArenaAllocator);
|
||||
arena.* = std.heap.ArenaAllocator.init(alloc);
|
||||
return .{ .data = .{
|
||||
.value = .{
|
||||
.versions = std.StringHashMap(std.SemanticVersion).init(arena.allocator()),
|
||||
},
|
||||
.arena = arena,
|
||||
} };
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setVersion(self: *Self, k: []const u8, v: ?[]const u8) !void {
|
||||
const k_d = try self.versions.allocator.dupe(u8, k);
|
||||
errdefer self.versions.allocator.free(k_d);
|
||||
const k_d = try self.data.arena.allocator().dupe(u8, k);
|
||||
|
||||
const gopr = try self.versions.getOrPut(k_d);
|
||||
|
||||
if (gopr.found_existing) {
|
||||
self.versions.allocator.free(k_d);
|
||||
json.de.free(self.versions.allocator, gopr.value_ptr.*, null);
|
||||
}
|
||||
const gopr = try self.data.value.versions.getOrPut(k_d);
|
||||
|
||||
// this is the actual version. this is used in the manifest
|
||||
// to keep the version of master up to date.
|
||||
|
@ -76,39 +80,29 @@ pub fn setVersion(self: *Self, k: []const u8, v: ?[]const u8) !void {
|
|||
};
|
||||
|
||||
// we move the strings in the semver to the manifest allocator so getty can free them
|
||||
if (semver.pre) |x| semver.pre = try self.versions.allocator.dupe(u8, x);
|
||||
errdefer if (semver.pre) |x| self.versions.allocator.free(x);
|
||||
|
||||
if (semver.build) |x| semver.build = try self.versions.allocator.dupe(u8, x);
|
||||
errdefer if (semver.build) |x| self.versions.allocator.free(x);
|
||||
if (semver.pre) |x| semver.pre = try self.data.arena.allocator().dupe(u8, x);
|
||||
if (semver.build) |x| semver.build = try self.data.arena.allocator().dupe(u8, x);
|
||||
|
||||
gopr.value_ptr.* = semver;
|
||||
}
|
||||
|
||||
pub fn removeVersion(self: *Self, version: []const u8) void {
|
||||
if (self.versions.fetchRemove(version)) |kv| {
|
||||
json.de.free(self.versions.allocator, kv.key, null);
|
||||
json.de.free(self.versions.allocator, kv.value, null);
|
||||
}
|
||||
_ = self.data.value.versions.remove(version);
|
||||
}
|
||||
|
||||
pub fn setInUse(self: *Self, in_use: ?[]const u8) !void {
|
||||
if (self.in_use) |old| {
|
||||
self.versions.allocator.free(old);
|
||||
}
|
||||
|
||||
if (in_use) |v| {
|
||||
const dup = try self.versions.allocator.dupe(u8, v);
|
||||
self.in_use = dup;
|
||||
const dup = try self.data.arena.allocator().dupe(u8, v);
|
||||
self.data.value.in_use = dup;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(self: *Self) !void {
|
||||
const mpath = try path(self.versions.allocator);
|
||||
defer self.versions.allocator.free(mpath);
|
||||
const mpath = try path(self.data.arena.child_allocator);
|
||||
defer self.data.arena.child_allocator.free(mpath);
|
||||
|
||||
var outfile = try std.fs.cwd().createFile(mpath, .{});
|
||||
defer outfile.close();
|
||||
|
||||
try json.toWriter(self.versions.allocator, self, outfile.writer());
|
||||
try json.toWriter(self.data.arena.child_allocator, self.data.value, outfile.writer());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub const version = "0.3.0";
|
||||
pub const version = "1.0.0";
|
||||
|
||||
pub const Info = struct {};
|
||||
|
||||
|
|
|
@ -25,12 +25,12 @@ pub fn run(
|
|||
.{ args.version, @tagName(@import("builtin").os.tag) },
|
||||
);
|
||||
|
||||
if (manifest.versions.count() == 0) {
|
||||
if (manifest.data.value.versions.count() == 0) {
|
||||
try stdout.writeAll("no installed versions\n");
|
||||
} else {
|
||||
try stdout.writeAll("installed versions:\n");
|
||||
|
||||
var iter = manifest.versions.iterator();
|
||||
var iter = manifest.data.value.versions.iterator();
|
||||
while (iter.next()) |kv| {
|
||||
try stdout.print("\t{s}\t{}\n", .{ kv.key_ptr.*, kv.value_ptr.* });
|
||||
}
|
||||
|
|
|
@ -44,16 +44,43 @@ pub fn run(
|
|||
defer version_index.deinit();
|
||||
|
||||
for (positionals) |version_arg| {
|
||||
const version = version_index.data.get(version_arg) orelse {
|
||||
std.log.err("no such version available!", .{});
|
||||
var exactv_buf: [1024]u8 = undefined;
|
||||
const version = version_index.value.get(version_arg) orelse exactv: {
|
||||
std.log.warn("no such version in index! trying exact version...", .{});
|
||||
|
||||
std.log.info("available versions: ", .{});
|
||||
var kiter = version_index.data.keyIterator();
|
||||
while (kiter.next()) |v| {
|
||||
std.log.info("\t{s}", .{v.*});
|
||||
const exactv_url = try std.fmt.bufPrint(
|
||||
&exactv_buf,
|
||||
"https://ziglang.org/builds/zig-{s}-{s}-{s}.tar.xz",
|
||||
.{
|
||||
@tagName(@import("builtin").os.tag),
|
||||
@tagName(@import("builtin").target.cpu.arch),
|
||||
version_arg,
|
||||
},
|
||||
);
|
||||
|
||||
std.log.info("exact version URL: '{s}'", .{exactv_url});
|
||||
|
||||
const exactv_result = http.fetch(.{
|
||||
.location = .{ .url = exactv_url },
|
||||
.method = .HEAD,
|
||||
}) catch |e| {
|
||||
std.log.err("checking exact version: {}", .{e});
|
||||
return error.Explained;
|
||||
};
|
||||
|
||||
if (exactv_result.status.class() != .success) {
|
||||
std.log.info("no such exact version available ({} {s})! available versions: ", .{
|
||||
@intFromEnum(exactv_result.status),
|
||||
exactv_result.status.phrase() orelse "<unknown>",
|
||||
});
|
||||
var kiter = version_index.value.keyIterator();
|
||||
while (kiter.next()) |v| {
|
||||
std.log.info("\t{s}", .{v.*});
|
||||
}
|
||||
return error.Explained;
|
||||
}
|
||||
|
||||
return error.Explained;
|
||||
break :exactv net.Version{ .file = .{ .tarball = exactv_url } };
|
||||
};
|
||||
|
||||
const version_file = version.file orelse {
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn run(
|
|||
manifest.removeVersion(version);
|
||||
try std.fs.cwd().deleteTree(ver_path);
|
||||
|
||||
if (manifest.in_use != null and std.mem.eql(u8, manifest.in_use.?, version)) {
|
||||
if (manifest.data.value.in_use != null and std.mem.eql(u8, manifest.data.value.in_use.?, version)) {
|
||||
try dirs.unuseCurrentVersion(alloc, manifest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub fn run(
|
|||
return error.Explained;
|
||||
}
|
||||
|
||||
if (manifest.in_use == null) {
|
||||
if (manifest.data.value.in_use == null) {
|
||||
std.log.err("no version currently in use!", .{});
|
||||
return error.Explained;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ pub fn run(
|
|||
|
||||
var updated_any = false;
|
||||
|
||||
var manifest_version_iter = manifest.versions.iterator();
|
||||
var manifest_version_iter = manifest.data.value.versions.iterator();
|
||||
while (manifest_version_iter.next()) |version| {
|
||||
// if the user provided arguments, only update those versions
|
||||
if (positionals.len != 0) {
|
||||
|
@ -42,7 +42,7 @@ pub fn run(
|
|||
continue;
|
||||
}
|
||||
|
||||
const idx_version = version_index.data.get(version.key_ptr.*) orelse {
|
||||
const idx_version = version_index.value.get(version.key_ptr.*) orelse {
|
||||
std.log.warn(
|
||||
"the installed version '{s}' is not in the version index",
|
||||
.{version.key_ptr.*},
|
||||
|
@ -95,22 +95,10 @@ pub fn run(
|
|||
|
||||
try net.downloadVersionTo(&http, version_file.tarball, install_path);
|
||||
|
||||
json.de.free(
|
||||
manifest.versions.allocator,
|
||||
version.value_ptr.*,
|
||||
null,
|
||||
);
|
||||
|
||||
// move the strings to the manifest allocator so it
|
||||
// complies with what getty.de.free expects
|
||||
//
|
||||
// we don't use manifest.setVersion here because that'd be kinda dodgy as we're
|
||||
// iterating the map here
|
||||
if (idx_semver.pre) |x| idx_semver.pre = try manifest.versions.allocator.dupe(u8, x);
|
||||
errdefer if (idx_semver.pre) |x| manifest.versions.allocator.free(x);
|
||||
|
||||
if (idx_semver.build) |x| idx_semver.build = try manifest.versions.allocator.dupe(u8, x);
|
||||
errdefer if (idx_semver.build) |x| manifest.versions.allocator.free(x);
|
||||
if (idx_semver.pre) |x| idx_semver.pre = try manifest.data.arena.allocator().dupe(u8, x);
|
||||
if (idx_semver.build) |x| idx_semver.build = try manifest.data.arena.allocator().dupe(u8, x);
|
||||
|
||||
version.value_ptr.* = idx_semver;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn useVersion(
|
|||
home: []const u8,
|
||||
version: []const u8,
|
||||
) !void {
|
||||
if (manifest.in_use != null and std.mem.eql(u8, manifest.in_use.?, version)) {
|
||||
if (manifest.data.value.in_use != null and std.mem.eql(u8, manifest.data.value.in_use.?, version)) {
|
||||
std.log.err("version '{s}' is already in use!", .{version});
|
||||
return error.Explained;
|
||||
}
|
||||
|
@ -133,9 +133,5 @@ pub fn unuseCurrentVersion(
|
|||
std.log.info("unusing zig installation @ {s}", .{target_binary});
|
||||
try std.fs.cwd().deleteFile(target_binary);
|
||||
|
||||
if (manifest.in_use) |old| {
|
||||
manifest.versions.allocator.free(old);
|
||||
}
|
||||
|
||||
manifest.in_use = null;
|
||||
manifest.data.value.in_use = null;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ const zig_args = @import("zig-args");
|
|||
const args = @import("args.zig");
|
||||
const Manifest = @import("Manifest.zig");
|
||||
|
||||
pub const std_options = struct {
|
||||
pub const logFn = @import("log.zig").log;
|
||||
pub const log_level = .debug;
|
||||
pub const std_options = std.Options{
|
||||
.log_level = .debug,
|
||||
.logFn = @import("log.zig").log,
|
||||
};
|
||||
|
||||
pub fn main() !u8 {
|
||||
|
|
30
src/net.zig
30
src/net.zig
|
@ -3,11 +3,10 @@ const c = @import("ffi.zig").c;
|
|||
const ansiterm = @import("ansi-term");
|
||||
const getty = @import("getty");
|
||||
const json = @import("json");
|
||||
const OwnedDeserData = @import("owned_deser_data.zig").OwnedDeserData;
|
||||
const Manifest = @import("Manifest.zig");
|
||||
|
||||
pub const VersionFile = struct {
|
||||
tarball: [:0]const u8,
|
||||
tarball: []const u8,
|
||||
|
||||
pub const @"getty.db" = struct {
|
||||
pub const attributes = .{
|
||||
|
@ -38,23 +37,23 @@ pub const Version = struct {
|
|||
|
||||
pub const VersionMap = std.StringHashMap(Version);
|
||||
|
||||
pub fn getVersionIndex(http: *std.http.Client) !OwnedDeserData(VersionMap) {
|
||||
pub fn getVersionIndex(http: *std.http.Client) !getty.de.Result(VersionMap) {
|
||||
const alloc = http.allocator;
|
||||
std.log.info("getting version index", .{});
|
||||
|
||||
var req = try http.request(
|
||||
var header_buf: [1024 * 4]u8 = undefined;
|
||||
|
||||
var req = try http.open(
|
||||
.GET,
|
||||
comptime std.Uri.parse("https://ziglang.org/download/index.json") catch unreachable,
|
||||
std.http.Headers.init(alloc), // freed by req.deinit
|
||||
.{},
|
||||
.{ .server_header_buffer = &header_buf },
|
||||
);
|
||||
defer req.deinit();
|
||||
|
||||
try req.start();
|
||||
try req.finish();
|
||||
try req.send();
|
||||
try req.wait();
|
||||
|
||||
return try OwnedDeserData(VersionMap).fromJsonReader(alloc, req.reader());
|
||||
return try json.fromReader(alloc, VersionMap, req.reader());
|
||||
}
|
||||
|
||||
/// concurrently downloads and unpacks a version to the given path
|
||||
|
@ -64,8 +63,6 @@ pub fn downloadVersionTo(
|
|||
url_str: []const u8,
|
||||
target: []const u8,
|
||||
) !void {
|
||||
const alloc = http.allocator;
|
||||
|
||||
const url = try std.Uri.parse(url_str);
|
||||
|
||||
std.log.info(
|
||||
|
@ -76,11 +73,16 @@ pub fn downloadVersionTo(
|
|||
.{ url_str, target },
|
||||
);
|
||||
|
||||
var req = try http.request(.GET, url, std.http.Headers.init(alloc), .{});
|
||||
var header_buf: [1024 * 4]u8 = undefined;
|
||||
|
||||
var req = try http.open(
|
||||
.GET,
|
||||
url,
|
||||
.{ .server_header_buffer = &header_buf },
|
||||
);
|
||||
defer req.deinit();
|
||||
|
||||
try req.start();
|
||||
try req.finish();
|
||||
try req.send();
|
||||
try req.wait();
|
||||
|
||||
const DLState = struct {
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
const std = @import("std");
|
||||
const getty = @import("getty");
|
||||
const json = @import("json");
|
||||
|
||||
/// a super handy data type that wraps some data deserialized using getty-json with
|
||||
/// an arena allocator for memory management.
|
||||
pub fn OwnedDeserData(comptime T: type) type {
|
||||
return struct {
|
||||
data: T,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.arena.deinit();
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn fromJsonReader(alloc: std.mem.Allocator, reader: anytype) !Self {
|
||||
// we use an arena here, even though getty does provide it's own deinit function for
|
||||
// deserialized data, I've never observed that actually clean everything up :P
|
||||
var arena = std.heap.ArenaAllocator.init(alloc);
|
||||
errdefer arena.deinit();
|
||||
|
||||
var deser = json.Deserializer(null, @TypeOf(reader)).init(alloc, reader);
|
||||
defer deser.deinit();
|
||||
|
||||
const data = try getty.deserialize(arena.allocator(), T, deser.deserializer());
|
||||
|
||||
return .{
|
||||
.data = data,
|
||||
.arena = arena,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fromJson(alloc: std.mem.Allocator, json_data: []const u8) !Self {
|
||||
var fbs = std.io.fixedBufferStream(json_data);
|
||||
return try fromJsonReader(alloc, fbs.reader());
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue