Browse Source

zig update 0.12.0 (remove ziget dependency)

Jonathan Marler 10 tháng trước cách đây
mục cha
commit
24bcacc5be
10 tập tin đã thay đổi với 285 bổ sung565 xóa
  1. 7 7
      .github/workflows/artifact.yml
  2. 0 212
      GitRepoStep.zig
  3. 0 2
      README.md
  4. 118 56
      build.zig
  5. 23 0
      build.zig.zon
  6. 0 213
      build2.zig
  7. 17 7
      test.zig
  8. 2 2
      win32exelink.zig
  9. 0 1
      zigetsha
  10. 118 65
      zigup.zig

+ 7 - 7
.github/workflows/artifact.yml

@@ -12,19 +12,19 @@ jobs:
       - uses: actions/checkout@v2
       - uses: goto-bus-stop/setup-zig@v1
         with:
-          version: 0.11.0
+          version: 0.12.0
       - run: |
-          zig build test -Dfetch -Dci_target=${{matrix.os}}-${{matrix.arch}}
+          zig build test -Dci_target=${{matrix.os}}-${{matrix.arch}}
       - run: |
-          zig build -Dfetch -Dci_target=ubuntu-latest-x86_64 -p zig-out-ubuntu-latest-x86_64
+          zig build -Dci_target=ubuntu-latest-x86_64 -p zig-out-ubuntu-latest-x86_64
       - run: |
-          zig build -Dfetch -Dci_target=ubuntu-latest-aarch64 -p zig-out-ubuntu-latest-aarch64
+          zig build -Dci_target=ubuntu-latest-aarch64 -p zig-out-ubuntu-latest-aarch64
       - run: |
-          zig build -Dfetch -Dci_target=macos-latest-x86_64 -p zig-out-macos-latest-x86_64
+          zig build -Dci_target=macos-latest-x86_64 -p zig-out-macos-latest-x86_64
       - run: |
-          zig build -Dfetch -Dci_target=macos-latest-aarch64 -p zig-out-macos-latest-aarch64
+          zig build -Dci_target=macos-latest-aarch64 -p zig-out-macos-latest-aarch64
       - run: |
-          zig build -Dfetch -Dci_target=windows-latest-x86_64 -p zig-out-windows-latest-x86_64
+          zig build -Dci_target=windows-latest-x86_64 -p zig-out-windows-latest-x86_64
       - uses: actions/upload-artifact@v2
         with:
           name: zigup ${{ matrix.os }}-${{ matrix.arch }}

+ 0 - 212
GitRepoStep.zig

@@ -1,212 +0,0 @@
-//! Publish Date: 2023_03_19
-//! This file is hosted at github.com/marler8997/zig-build-repos and is meant to be copied
-//! to projects that use it.
-const std = @import("std");
-const GitRepoStep = @This();
-
-pub const ShaCheck = enum {
-    none,
-    warn,
-    err,
-
-    pub fn reportFail(self: ShaCheck, comptime fmt: []const u8, args: anytype) void {
-        switch (self) {
-            .none => unreachable,
-            .warn => std.log.warn(fmt, args),
-            .err => {
-                std.log.err(fmt, args);
-                std.os.exit(0xff);
-            },
-        }
-    }
-};
-
-step: std.build.Step,
-url: []const u8,
-name: []const u8,
-branch: ?[]const u8 = null,
-sha: []const u8,
-path: []const u8,
-sha_check: ShaCheck = .warn,
-fetch_enabled: bool,
-
-var cached_default_fetch_option: ?bool = null;
-pub fn defaultFetchOption(b: *std.build.Builder) bool {
-    if (cached_default_fetch_option) |_| {} else {
-        cached_default_fetch_option = if (b.option(bool, "fetch", "automatically fetch network resources")) |o| o else false;
-    }
-    return cached_default_fetch_option.?;
-}
-
-pub fn create(b: *std.build.Builder, opt: struct {
-    url: []const u8,
-    branch: ?[]const u8 = null,
-    sha: []const u8,
-    path: ?[]const u8 = null,
-    sha_check: ShaCheck = .warn,
-    fetch_enabled: ?bool = null,
-    first_ret_addr: ?usize = null,
-}) *GitRepoStep {
-    var result = b.allocator.create(GitRepoStep) catch @panic("memory");
-    const name = std.fs.path.basename(opt.url);
-    result.* = GitRepoStep{
-        .step = std.build.Step.init(.{
-            .id = .custom,
-            .name = b.fmt("clone git repository '{s}'", .{name}),
-            .owner = b,
-            .makeFn = make,
-            .first_ret_addr = opt.first_ret_addr orelse @returnAddress(),
-            .max_rss = 0,
-        }),
-        .url = opt.url,
-        .name = name,
-        .branch = opt.branch,
-        .sha = opt.sha,
-        .path = if (opt.path) |p| b.allocator.dupe(u8, p) catch @panic("OOM") else b.pathFromRoot(b.pathJoin(&.{ "dep", name })),
-        .sha_check = opt.sha_check,
-        .fetch_enabled = if (opt.fetch_enabled) |fe| fe else defaultFetchOption(b),
-    };
-    return result;
-}
-
-// TODO: this should be included in std.build, it helps find bugs in build files
-fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.Step) bool {
-    for (step.dependencies.items) |dep| {
-        // TODO: should probably use step.loop_flag to prevent infinite recursion
-        //       when a circular reference is encountered, or maybe keep track of
-        //       the steps encounterd with a hash set
-        if (dep == dep_candidate or hasDependency(dep, dep_candidate))
-            return true;
-    }
-    return false;
-}
-
-fn make(step: *std.Build.Step, prog_node: *std.Progress.Node) !void {
-    _ = prog_node;
-    const self = @fieldParentPtr(GitRepoStep, "step", step);
-
-    std.fs.accessAbsolute(self.path, .{}) catch {
-        const branch_args = if (self.branch) |b| &[2][]const u8{ " -b ", b } else &[2][]const u8{ "", "" };
-        if (!self.fetch_enabled) {
-            std.debug.print("Error: git repository '{s}' does not exist\n", .{self.path});
-            std.debug.print("       Use -Dfetch to download it automatically, or run the following to clone it:\n", .{});
-            std.debug.print("       git clone {s}{s}{s} {s} && git -C {3s} checkout {s} -b fordep\n", .{
-                self.url,
-                branch_args[0],
-                branch_args[1],
-                self.path,
-                self.sha,
-            });
-            std.os.exit(1);
-        }
-
-        {
-            var args = std.ArrayList([]const u8).init(self.step.owner.allocator);
-            defer args.deinit();
-            try args.append("git");
-            try args.append("clone");
-            try args.append(self.url);
-            // TODO: clone it to a temporary location in case of failure
-            //       also, remove that temporary location before running
-            try args.append(self.path);
-            if (self.branch) |branch| {
-                try args.append("-b");
-                try args.append(branch);
-            }
-            try run(self.step.owner, args.items);
-        }
-        try run(self.step.owner, &[_][]const u8{
-            "git",
-            "-C",
-            self.path,
-            "checkout",
-            self.sha,
-            "-b",
-            "fordep",
-        });
-    };
-
-    try self.checkSha();
-}
-
-fn checkSha(self: GitRepoStep) !void {
-    if (self.sha_check == .none)
-        return;
-
-    const result: union(enum) { failed: anyerror, output: []const u8 } = blk: {
-        const result = std.ChildProcess.exec(.{
-            .allocator = self.step.owner.allocator,
-            .argv = &[_][]const u8{
-                "git",
-                "-C",
-                self.path,
-                "rev-parse",
-                "HEAD",
-            },
-            .cwd = self.step.owner.build_root.path,
-            .env_map = self.step.owner.env_map,
-        }) catch |e| break :blk .{ .failed = e };
-        try std.io.getStdErr().writer().writeAll(result.stderr);
-        switch (result.term) {
-            .Exited => |code| {
-                if (code == 0) break :blk .{ .output = result.stdout };
-                break :blk .{ .failed = error.GitProcessNonZeroExit };
-            },
-            .Signal => break :blk .{ .failed = error.GitProcessFailedWithSignal },
-            .Stopped => break :blk .{ .failed = error.GitProcessWasStopped },
-            .Unknown => break :blk .{ .failed = error.GitProcessFailed },
-        }
-    };
-    switch (result) {
-        .failed => |err| {
-            return self.sha_check.reportFail("failed to retreive sha for repository '{s}': {s}", .{ self.name, @errorName(err) });
-        },
-        .output => |output| {
-            if (!std.mem.eql(u8, std.mem.trimRight(u8, output, "\n\r"), self.sha)) {
-                return self.sha_check.reportFail("repository '{s}' sha does not match\nexpected: {s}\nactual  : {s}\n", .{ self.name, self.sha, output });
-            }
-        },
-    }
-}
-
-fn run(builder: *std.build.Builder, argv: []const []const u8) !void {
-    {
-        var msg = std.ArrayList(u8).init(builder.allocator);
-        defer msg.deinit();
-        const writer = msg.writer();
-        var prefix: []const u8 = "";
-        for (argv) |arg| {
-            try writer.print("{s}\"{s}\"", .{ prefix, arg });
-            prefix = " ";
-        }
-        std.log.info("[RUN] {s}", .{msg.items});
-    }
-
-    var child = std.ChildProcess.init(argv, builder.allocator);
-    child.stdin_behavior = .Ignore;
-    child.stdout_behavior = .Inherit;
-    child.stderr_behavior = .Inherit;
-    child.cwd = builder.build_root.path;
-    child.env_map = builder.env_map;
-
-    try child.spawn();
-    const result = try child.wait();
-    switch (result) {
-        .Exited => |code| if (code != 0) {
-            std.log.err("git clone failed with exit code {}", .{code});
-            std.os.exit(0xff);
-        },
-        else => {
-            std.log.err("git clone failed with: {}", .{result});
-            std.os.exit(0xff);
-        },
-    }
-}
-
-// Get's the repository path and also verifies that the step requesting the path
-// is dependent on this step.
-pub fn getPath(self: *const GitRepoStep, who_wants_to_know: *const std.build.Step) []const u8 {
-    if (!hasDependency(who_wants_to_know, &self.step))
-        @panic("a step called GitRepoStep.getPath but has not added it as a dependency");
-    return self.path;
-}

+ 0 - 2
README.md

@@ -58,8 +58,6 @@ Zigup is currently built/tested using zig 0.11.0.
 
 # Dependencies
 
-zigup depends on https://github.com/marler8997/ziget which in turn depends on other projects depending on which SSL backend is selected.  You can provide `-Dfetch` to `zig build` to automatically clone all repository dependencies, otherwise, the build will report a missing dependency error with an explanation of how to clone it.
-
 The windows target depends on https://github.com/SuperAuguste/zarc to extract zip files.  This repo might point to my fork if there are needed changes pending the acceptance of a PR: https://github.com/marler8997/zarc.
 
 On linux and macos, zigup depends on `tar` to extract the compiler archive files (this may change in the future).

+ 118 - 56
build.zig

@@ -1,66 +1,128 @@
-//! This build.zig file boostraps the real build in build2.zig
-
-// NOTE: need to wait on https://github.com/ziglang/zig/pull/9989 before doing this
-//       to make build errors reasonable
 const std = @import("std");
-const Builder = std.build.Builder;
-
-const GitRepoStep = @import("GitRepoStep.zig");
+const builtin = @import("builtin");
+const Pkg = std.build.Pkg;
 
-pub fn build(b: *Builder) !void {
-    buildNoreturn(b);
+fn unwrapOptionalBool(optionalBool: ?bool) bool {
+    if (optionalBool) |b| return b;
+    return false;
 }
-fn buildNoreturn(b: *Builder) noreturn {
-    const err = buildOrFail(b);
-    std.log.err("{s}", .{@errorName(err)});
-    if (@errorReturnTrace()) |trace| {
-        std.debug.dumpStackTrace(trace.*);
+
+pub fn build(b: *std.Build) !void {
+    //var github_release_step = b.step("github-release", "Build the github-release binaries");
+    //try addGithubReleaseExe(b, github_release_step, ziget_repo, "x86_64-linux", .std);
+
+    const target = if (b.option([]const u8, "ci_target", "the CI target being built")) |ci_target|
+        b.resolveTargetQuery(try std.zig.CrossTarget.parse(.{ .arch_os_abi = ci_target_map.get(ci_target) orelse {
+            std.log.err("unknown ci_target '{s}'", .{ci_target});
+            std.process.exit(1);
+        } }))
+    else
+        b.standardTargetOptions(.{});
+
+    const optimize = b.standardOptimizeOption(.{});
+
+    const win32exelink_mod: ?*std.Build.Module = blk: {
+        if (target.result.os.tag == .windows) {
+            const exe = b.addExecutable(.{
+                .name = "win32exelink",
+                .root_source_file = .{ .path = "win32exelink.zig" },
+                .target = target,
+                .optimize = optimize,
+            });
+            break :blk b.createModule(.{
+                .root_source_file = exe.getEmittedBin(),
+            });
+        }
+        break :blk null;
+    };
+
+    const exe = try addZigupExe(
+        b,
+        target,
+        optimize,
+        win32exelink_mod,
+    );
+    b.installArtifact(exe);
+
+    const run_cmd = b.addRunArtifact(exe);
+    run_cmd.step.dependOn(b.getInstallStep());
+
+    const run_step = b.step("run", "Run the app");
+    run_step.dependOn(&run_cmd.step);
+    if (b.args) |args| {
+        run_cmd.addArgs(args);
     }
-    std.os.exit(0xff);
+
+    addTest(b, exe, target, optimize);
 }
-fn buildOrFail(b: *Builder) anyerror {
-    const ziget_repo = GitRepoStep.create(b, .{
-        .url = "https://github.com/marler8997/ziget",
-        .branch = null,
-        .sha = @embedFile("zigetsha"),
-        .fetch_enabled = true,
+
+fn addTest(
+    b: *std.Build,
+    exe: *std.Build.Step.Compile,
+    target: std.Build.ResolvedTarget,
+    optimize: std.builtin.Mode,
+) void {
+    const test_exe = b.addExecutable(.{
+        .name = "test",
+        .root_source_file = .{ .path = "test.zig" },
+        .target = target,
+        .optimize = optimize,
     });
-    const build2 = addBuild(b, .{ .path = "build2.zig" }, .{});
-    build2.addArgs(try getBuildArgs(b));
-
-    var progress = std.Progress{};
-    {
-        var prog_node = progress.start("clone ziget", 1);
-        ziget_repo.step.make(prog_node) catch |e| return e;
-        prog_node.end();
-    }
-    {
-        var prog_node = progress.start("run build2.zig", 1);
-        build2.step.make(prog_node) catch |err| switch (err) {
-            error.MakeFailed => std.os.exit(0xff), // error already printed by subprocess, hopefully?
-            error.MakeSkipped => @panic("impossible?"),
-        };
-        prog_node.end();
-    }
-    std.os.exit(0);
+    const run_cmd = b.addRunArtifact(test_exe);
+
+    // TODO: make this work, add exe install path as argument to test
+    //run_cmd.addArg(exe.getInstallPath());
+    _ = exe;
+    run_cmd.step.dependOn(b.getInstallStep());
+
+    const test_step = b.step("test", "test the executable");
+    test_step.dependOn(&run_cmd.step);
 }
 
-// TODO: remove the following if https://github.com/ziglang/zig/pull/9987 is integrated
-fn getBuildArgs(self: *Builder) ![]const [:0]const u8 {
-    const args = try std.process.argsAlloc(self.allocator);
-    return args[5..];
+fn addZigupExe(
+    b: *std.Build,
+    target: std.Build.ResolvedTarget,
+    optimize: std.builtin.Mode,
+    win32exelink_mod: ?*std.Build.Module,
+) !*std.Build.Step.Compile {
+    const exe = b.addExecutable(.{
+        .name = "zigup",
+        .root_source_file = .{ .path = "zigup.zig" },
+        .target = target,
+        .optimize = optimize,
+    });
+
+    if (target.result.os.tag == .windows) {
+        exe.root_module.addImport("win32exelink", win32exelink_mod.?);
+        if (b.lazyDependency("zarc", .{})) |zarc_dep| {
+            exe.root_module.addImport("zarc", zarc_dep.module("zarc"));
+        }
+    }
+
+    return exe;
 }
-pub fn addBuild(self: *Builder, build_file: std.build.FileSource, _: struct {}) *std.build.RunStep {
-    const run_step = std.build.RunStep.create(
-        self,
-        self.fmt("zig build {s}", .{build_file.getDisplayName()}),
-    );
-    run_step.addArg(self.zig_exe);
-    run_step.addArg("build");
-    run_step.addArg("--build-file");
-    run_step.addFileSourceArg(build_file);
-    run_step.addArg("--cache-dir");
-    const cache_root_path = self.cache_root.path orelse @panic("todo");
-    run_step.addArg(self.pathFromRoot(cache_root_path));
-    return run_step;
+
+fn addGithubReleaseExe(
+    b: *std.Build,
+    github_release_step: *std.build.Step,
+    comptime target_triple: []const u8,
+) !void {
+    const small_release = true;
+
+    const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = target_triple });
+    const mode = if (small_release) .ReleaseSafe else .Debug;
+    const exe = try addZigupExe(b, target, mode);
+    if (small_release) {
+        exe.strip = true;
+    }
+    exe.setOutputDir("github-release" ++ std.fs.path.sep_str ++ target_triple);
+    github_release_step.dependOn(&exe.step);
 }
+
+const ci_target_map = std.ComptimeStringMap([]const u8, .{
+    .{ "ubuntu-latest-x86_64", "x86_64-linux" },
+    .{ "macos-latest-x86_64", "x86_64-macos" },
+    .{ "windows-latest-x86_64", "x86_64-windows" },
+    .{ "ubuntu-latest-aarch64", "aarch64-linux" },
+    .{ "macos-latest-aarch64", "aarch64-macos" },
+});

+ 23 - 0
build.zig.zon

@@ -0,0 +1,23 @@
+.{
+    .name = "zigup",
+    .version = "0.0.1",
+
+    .dependencies = .{
+        .zarc = .{
+            .url = "https://github.com/marler8997/zarc/archive/6ed370681d0e0c5d8ef32ad63e440d0b3effc8a8.tar.gz",
+            .hash = "1220a69ceaac42e5a3593161c3b4ab1ce7dbc574b1a80398a7cb3100fbfa07baf372",
+            .lazy = true,
+        },
+    },
+
+    .paths = .{
+        "LICENSE",
+        "README.md",
+        "build.zig",
+        "build.zig.zon",
+        "fixdeletetree.zig",
+        "test.zig",
+        "win32exelink.zig",
+        "zigup.zig",
+    },
+}

+ 0 - 213
build2.zig

@@ -1,213 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const Builder = std.build.Builder;
-const Pkg = std.build.Pkg;
-
-// TODO: make this work with "GitRepoStep.zig", there is a
-//       problem with the -Dfetch option
-const GitRepoStep = @import("dep/ziget/GitRepoStep.zig");
-
-const zigetbuild = @import("dep/ziget/build.zig");
-const SslBackend = zigetbuild.SslBackend;
-
-fn unwrapOptionalBool(optionalBool: ?bool) bool {
-    if (optionalBool) |b| return b;
-    return false;
-}
-
-pub fn build(b: *Builder) !void {
-    const ziget_repo = GitRepoStep.create(b, .{
-        .url = "https://github.com/marler8997/ziget",
-        .branch = null,
-        .sha = @embedFile("zigetsha"),
-    });
-
-    // TODO: implement this if/when we get @tryImport
-    //if (zigetbuild) |_| { } else {
-    //    std.log.err("TODO: add zigetbuild package and recompile/reinvoke build.d", .{});
-    //    return;
-    //}
-
-    //var github_release_step = b.step("github-release", "Build the github-release binaries");
-    //try addGithubReleaseExe(b, github_release_step, ziget_repo, "x86_64-linux", .std);
-
-    const target = if (b.option([]const u8, "ci_target", "the CI target being built")) |ci_target|
-        try std.zig.CrossTarget.parse(.{ .arch_os_abi = ci_target_map.get(ci_target) orelse {
-            std.log.err("unknown ci_target '{s}'", .{ci_target});
-            std.os.exit(1);
-        } })
-    else
-        b.standardTargetOptions(.{});
-
-    const optimize = b.standardOptimizeOption(.{});
-
-    const win32exelink_mod: ?*std.Build.Module = blk: {
-        if (target.getOs().tag == .windows) {
-            const exe = b.addExecutable(.{
-                .name = "win32exelink",
-                .root_source_file = .{ .path = "win32exelink.zig" },
-                .target = target,
-                .optimize = optimize,
-            });
-            break :blk b.createModule(.{
-                .source_file = exe.getEmittedBin(),
-            });
-        }
-        break :blk null;
-    };
-
-    // TODO: Maybe add more executables with different ssl backends
-    const exe = try addZigupExe(
-        b,
-        ziget_repo,
-        target,
-        optimize,
-        win32exelink_mod,
-        .iguana,
-    );
-    b.installArtifact(exe);
-
-    const run_cmd = b.addRunArtifact(exe);
-    run_cmd.step.dependOn(b.getInstallStep());
-
-    const run_step = b.step("run", "Run the app");
-    run_step.dependOn(&run_cmd.step);
-    if (b.args) |args| {
-        run_cmd.addArgs(args);
-    }
-
-    addTest(b, exe, target, optimize);
-}
-
-fn addTest(b: *Builder, exe: *std.build.LibExeObjStep, target: std.zig.CrossTarget, optimize: std.builtin.Mode) void {
-    const test_exe = b.addExecutable(.{
-        .name = "test",
-        .root_source_file = .{ .path = "test.zig" },
-        .target = target,
-        .optimize = optimize,
-    });
-    const run_cmd = b.addRunArtifact(test_exe);
-
-    // TODO: make this work, add exe install path as argument to test
-    //run_cmd.addArg(exe.getInstallPath());
-    _ = exe;
-    run_cmd.step.dependOn(b.getInstallStep());
-
-    const test_step = b.step("test", "test the executable");
-    test_step.dependOn(&run_cmd.step);
-}
-
-fn addZigupExe(
-    b: *Builder,
-    ziget_repo: *GitRepoStep,
-    target: std.zig.CrossTarget,
-    optimize: std.builtin.Mode,
-    win32exelink_mod: ?*std.build.Module,
-    ssl_backend: ?SslBackend,
-) !*std.build.LibExeObjStep {
-    const require_ssl_backend = b.allocator.create(RequireSslBackendStep) catch unreachable;
-    require_ssl_backend.* = RequireSslBackendStep.init(b, "the zigup exe", ssl_backend);
-
-    const exe = b.addExecutable(.{
-        .name = "zigup",
-        .root_source_file = .{ .path = "zigup.zig" },
-        .target = target,
-        .optimize = optimize,
-    });
-
-    exe.step.dependOn(&ziget_repo.step);
-    zigetbuild.addZigetModule(exe, ssl_backend, ziget_repo.getPath(&exe.step));
-
-    if (targetIsWindows(target)) {
-        exe.addModule("win32exelink", win32exelink_mod.?);
-        const zarc_repo = GitRepoStep.create(b, .{
-            .url = "https://github.com/marler8997/zarc",
-            .branch = "protected",
-            .sha = "2e5256624d7871180badc9784b96dd66d927d604",
-            .fetch_enabled = true,
-        });
-        exe.step.dependOn(&zarc_repo.step);
-        const zarc_repo_path = zarc_repo.getPath(&exe.step);
-        const zarc_mod = b.addModule("zarc", .{
-            .source_file = .{ .path = b.pathJoin(&.{ zarc_repo_path, "src", "main.zig" }) },
-        });
-        exe.addModule("zarc", zarc_mod);
-    }
-
-    exe.step.dependOn(&require_ssl_backend.step);
-    return exe;
-}
-
-fn targetIsWindows(target: std.zig.CrossTarget) bool {
-    if (target.os_tag) |tag|
-        return tag == .windows;
-    return builtin.target.os.tag == .windows;
-}
-
-const SslBackendFailedStep = struct {
-    step: std.build.Step,
-    context: []const u8,
-    backend: SslBackend,
-    pub fn init(b: *Builder, context: []const u8, backend: SslBackend) SslBackendFailedStep {
-        return .{
-            .step = std.build.Step.init(.custom, "SslBackendFailedStep", b.allocator, make),
-            .context = context,
-            .backend = backend,
-        };
-    }
-    fn make(step: *std.build.Step) !void {
-        const self = @fieldParentPtr(RequireSslBackendStep, "step", step);
-        std.debug.print("error: the {s} failed to add the {s} SSL backend\n", .{ self.context, self.backend });
-        std.os.exit(1);
-    }
-};
-
-const RequireSslBackendStep = struct {
-    step: std.build.Step,
-    context: []const u8,
-    backend: ?SslBackend,
-    pub fn init(b: *Builder, context: []const u8, backend: ?SslBackend) RequireSslBackendStep {
-        return .{
-            .step = std.build.Step.init(.{
-                .id = .custom,
-                .name = "RequireSslBackend",
-                .owner = b,
-                .makeFn = make,
-            }),
-            .context = context,
-            .backend = backend,
-        };
-    }
-    fn make(step: *std.build.Step, prog_node: *std.Progress.Node) !void {
-        _ = prog_node;
-        const self = @fieldParentPtr(RequireSslBackendStep, "step", step);
-        if (self.backend) |_| {} else {
-            std.debug.print("error: {s} requires an SSL backend:\n", .{self.context});
-            inline for (zigetbuild.ssl_backends) |field| {
-                std.debug.print("    -D{s}\n", .{field.name});
-            }
-            std.os.exit(1);
-        }
-    }
-};
-
-fn addGithubReleaseExe(b: *Builder, github_release_step: *std.build.Step, ziget_repo: []const u8, comptime target_triple: []const u8, comptime ssl_backend: SslBackend) !void {
-    const small_release = true;
-
-    const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = target_triple });
-    const mode = if (small_release) .ReleaseSafe else .Debug;
-    const exe = try addZigupExe(b, ziget_repo, target, mode, ssl_backend);
-    if (small_release) {
-        exe.strip = true;
-    }
-    exe.setOutputDir("github-release" ++ std.fs.path.sep_str ++ target_triple ++ std.fs.path.sep_str ++ @tagName(ssl_backend));
-    github_release_step.dependOn(&exe.step);
-}
-
-const ci_target_map = std.ComptimeStringMap([]const u8, .{
-    .{ "ubuntu-latest-x86_64", "x86_64-linux" },
-    .{ "macos-latest-x86_64", "x86_64-macos" },
-    .{ "windows-latest-x86_64", "x86_64-windows" },
-    .{ "ubuntu-latest-aarch64", "aarch64-linux" },
-    .{ "macos-latest-aarch64", "aarch64-macos" },
-});

+ 17 - 7
test.zig

@@ -34,6 +34,15 @@ pub fn main() !u8 {
         zigup,
         .{},
     );
+    if (builtin.os.tag == .windows) {
+        const zigup_pdb = comptime "." ++ sep ++ bin_dir ++ sep ++ "zigup.pdb";
+        try std.fs.cwd().copyFile(
+            comptime "zig-out" ++ sep ++ "bin" ++ sep ++ "zigup.pdb",
+            std.fs.cwd(),
+            zigup_pdb,
+            .{},
+        );
+    }
 
     const install_args = if (builtin.os.tag == .windows) [_][]const u8{} else [_][]const u8{ "--install-dir", install_dir };
     const zigup_args = &[_][]const u8{zigup} ++ install_args;
@@ -265,7 +274,8 @@ pub fn main() !u8 {
             allocator.free(result.stdout);
             allocator.free(result.stderr);
         }
-        try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "HTTP request failed"));
+        try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "download"));
+        try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "failed"));
     }
     try testing.expectEqual(@as(u32, 2), try getCompilerCount(install_dir));
 
@@ -310,7 +320,7 @@ pub fn main() !u8 {
     // NOTE: this test will eventually break when these builds are cleaned up,
     //       we should support downloading from bazel and use that instead since
     //       it should be more permanent
-    try runNoCapture(zigup_args ++ &[_][]const u8{"0.11.0-dev.4263+f821543e4"});
+    try runNoCapture(zigup_args ++ &[_][]const u8{ "0.12.0-dev.3639+9cfac4718" });
 
     std.log.info("Success", .{});
     return 0;
@@ -338,7 +348,7 @@ fn checkZigVersion(allocator: std.mem.Allocator, zig: []const u8, compare: []con
 }
 
 fn getCompilerCount(install_dir: []const u8) !u32 {
-    var dir = try std.fs.cwd().openIterableDir(install_dir, .{});
+    var dir = try std.fs.cwd().openDir(install_dir, .{ .iterate = true });
     defer dir.close();
     var it = dir.iterate();
     var count: u32 = 0;
@@ -360,7 +370,7 @@ fn trailNl(s: []const u8) []const u8 {
     return if (s.len == 0 or s[s.len - 1] != '\n') "\n" else "";
 }
 
-fn dumpExecResult(result: std.ChildProcess.ExecResult) void {
+fn dumpExecResult(result: std.ChildProcess.RunResult) void {
     if (result.stdout.len > 0) {
         std.debug.print("--- STDOUT ---\n{s}{s}--------------\n", .{ result.stdout, trailNl(result.stdout) });
     }
@@ -376,13 +386,13 @@ fn runNoCapture(argv: []const []const u8) !void {
     dumpExecResult(result);
     try passOrThrow(result.term);
 }
-fn runCaptureOuts(allocator: std.mem.Allocator, argv: []const []const u8) !std.ChildProcess.ExecResult {
+fn runCaptureOuts(allocator: std.mem.Allocator, argv: []const []const u8) !std.ChildProcess.RunResult {
     {
         const cmd = try std.mem.join(allocator, " ", argv);
         defer allocator.free(cmd);
         std.log.info("RUN: {s}", .{cmd});
     }
-    return try std.ChildProcess.exec(.{ .allocator = allocator, .argv = argv, .env_map = &child_env_map });
+    return try std.ChildProcess.run(.{ .allocator = allocator, .argv = argv, .env_map = &child_env_map });
 }
 fn passOrThrow(term: std.ChildProcess.Term) error{ChildProcessFailed}!void {
     if (!execResultPassed(term)) {
@@ -390,7 +400,7 @@ fn passOrThrow(term: std.ChildProcess.Term) error{ChildProcessFailed}!void {
         return error.ChildProcessFailed;
     }
 }
-fn passOrDumpAndThrow(result: std.ChildProcess.ExecResult) error{ChildProcessFailed}!void {
+fn passOrDumpAndThrow(result: std.ChildProcess.RunResult) error{ChildProcessFailed}!void {
     if (!execResultPassed(result.term)) {
         dumpExecResult(result);
         std.log.err("child process failed with {}", .{result.term});

+ 2 - 2
win32exelink.zig

@@ -75,14 +75,14 @@ fn consoleCtrlHandler(ctrl_type: u32) callconv(@import("std").os.windows.WINAPI)
     log.info("caught ctrl signal {d} ({s}), stopping process...", .{ ctrl_type, name });
     const exit_code = switch (global.child.kill() catch |err| {
         log.err("failed to kill process, error={s}", .{@errorName(err)});
-        std.os.exit(0xff);
+        std.process.exit(0xff);
     }) {
         .Exited => |e| e,
         .Signal => 0xff,
         .Stopped => 0xff,
         .Unknown => 0xff,
     };
-    std.os.exit(exit_code);
+    std.process.exit(exit_code);
     unreachable;
 }
 

+ 0 - 1
zigetsha

@@ -1 +0,0 @@
-9020437522f092860c513b1e96dcc250c7dea0aa

+ 118 - 65
zigup.zig

@@ -5,7 +5,6 @@ const mem = std.mem;
 const ArrayList = std.ArrayList;
 const Allocator = mem.Allocator;
 
-const ziget = @import("ziget");
 const zarc = @import("zarc");
 
 const fixdeletetree = @import("fixdeletetree.zig");
@@ -36,36 +35,82 @@ fn loginfo(comptime fmt: []const u8, args: anytype) void {
     }
 }
 
-fn download(allocator: Allocator, url: []const u8, writer: anytype) !void {
-    var download_options = ziget.request.DownloadOptions{
-        .flags = 0,
-        .allocator = allocator,
-        .maxRedirects = 10,
-        .forwardBufferSize = 4096,
-        .maxHttpResponseHeaders = 8192,
-        .onHttpRequest = ignoreHttpCallback,
-        .onHttpResponse = ignoreHttpCallback,
-    };
-    var dowload_state = ziget.request.DownloadState.init();
-    try ziget.request.download(
-        ziget.url.parseUrl(url) catch unreachable,
-        writer,
-        download_options,
-        &dowload_state,
-    );
+pub fn oom(e: error{OutOfMemory}) noreturn {
+    @panic(@errorName(e));
 }
 
-fn downloadToFileAbsolute(allocator: Allocator, url: []const u8, file_absolute: []const u8) !void {
-    const file = try std.fs.createFileAbsolute(file_absolute, .{});
-    defer file.close();
-    try download(allocator, url, file.writer());
+const DownloadResult = union(enum) {
+    ok: void,
+    err: []u8,
+    pub fn deinit(self: DownloadResult, allocator: Allocator) void {
+        switch (self) {
+            .ok => {},
+            .err => |e| allocator.free(e),
+        }
+    }
+};
+fn download(allocator: Allocator, url: []const u8, writer: anytype) DownloadResult {
+    const uri = std.Uri.parse(url) catch |err| std.debug.panic(
+        "failed to parse url '{s}' with {s}", .{url, @errorName(err)}
+    );
+
+    var client = std.http.Client{ .allocator = allocator };
+    defer client.deinit();
+
+    client.initDefaultProxies(allocator) catch |err| return .{ .err = std.fmt.allocPrint(
+        allocator, "failed to query the HTTP proxy settings with {s}", .{ @errorName(err) }
+    ) catch |e| oom(e) };
+
+    var header_buffer: [4096]u8 = undefined;
+    var request = client.open(.GET, uri, .{
+        .server_header_buffer = &header_buffer,
+        .keep_alive = false,
+    }) catch |err| return .{ .err = std.fmt.allocPrint(
+        allocator, "failed to connect to the HTTP server with {s}", .{ @errorName(err) }
+    ) catch |e| oom(e) };
+
+    defer request.deinit();
+
+    request.send() catch |err| return .{ .err = std.fmt.allocPrint(
+        allocator, "failed to send the HTTP request with {s}", .{ @errorName(err) }
+    ) catch |e| oom(e) };
+    request.wait() catch |err| return .{ .err = std.fmt.allocPrint(
+        allocator, "failed to read the HTTP response headers with {s}", .{ @errorName(err) }
+    ) catch |e| oom(e) };
+
+    if (request.response.status != .ok) return .{ .err = std.fmt.allocPrint(
+        allocator,
+        "HTTP server replied with unsuccessful response '{d} {s}'",
+        .{ @intFromEnum(request.response.status), request.response.status.phrase() orelse "" },
+    ) catch |e| oom(e) };
+
+    // TODO: we take advantage of request.response.content_length
+
+    var buf: [std.mem.page_size]u8 = undefined;
+    while (true) {
+        const len = request.reader().read(&buf) catch |err| return .{ .err = std.fmt.allocPrint(
+            allocator, "failed to read the HTTP response body with {s}'", .{ @errorName(err) }
+        ) catch |e| oom(e) };
+        if (len == 0)
+            return .ok;
+        writer.writeAll(buf[0..len]) catch |err| return .{ .err = std.fmt.allocPrint(
+            allocator, "failed to write the HTTP response body with {s}'", .{ @errorName(err) }
+        ) catch |e| oom(e) };
+    }
 }
 
-fn downloadToString(allocator: Allocator, url: []const u8) ![]u8 {
-    var response_array_list = try ArrayList(u8).initCapacity(allocator, 20 * 1024); // 20 KB (modify if response is expected to be bigger)
-    errdefer response_array_list.deinit();
-    try download(allocator, url, response_array_list.writer());
-    return response_array_list.toOwnedSlice();
+const DownloadStringResult = union(enum) {
+    ok: []u8,
+    err: []u8,
+
+};
+fn downloadToString(allocator: Allocator, url: []const u8) DownloadStringResult {
+    var response_array_list = ArrayList(u8).initCapacity(allocator, 20 * 1024) catch |e| oom(e); // 20 KB (modify if response is expected to be bigger)
+    defer response_array_list.deinit();
+    switch (download(allocator, url, response_array_list.writer())) {
+        .ok => return .{ .ok = response_array_list.toOwnedSlice() catch |e| oom(e) },
+        .err => |e| return .{ .err = e },
+    }
 }
 
 fn ignoreHttpCallback(request: []const u8) void {
@@ -73,7 +118,7 @@ fn ignoreHttpCallback(request: []const u8) void {
 }
 
 fn getHomeDir() ![]const u8 {
-    return std.os.getenv("HOME") orelse {
+    return std.posix.getenv("HOME") orelse {
         std.log.err("cannot find install directory, $HOME environment variable is not set", .{});
         return error.MissingHomeEnvironmentVariable;
     };
@@ -282,13 +327,13 @@ pub fn main2() !u8 {
                 if (!std.mem.eql(u8, version_string, "master"))
                     break :init_resolved version_string;
 
-                var optional_master_dir: ?[]const u8 = blk: {
-                    var install_dir = std.fs.openIterableDirAbsolute(install_dir_string, .{}) catch |e| switch (e) {
+                const optional_master_dir: ?[]const u8 = blk: {
+                    var install_dir = std.fs.openDirAbsolute(install_dir_string, .{ .iterate = true }) catch |e| switch (e) {
                         error.FileNotFound => break :blk null,
                         else => return e,
                     };
                     defer install_dir.close();
-                    break :blk try getMasterDir(allocator, &install_dir.dir);
+                    break :blk try getMasterDir(allocator, &install_dir);
                 };
                 // no need to free master_dir, this is a short lived program
                 break :init_resolved optional_master_dir orelse {
@@ -408,10 +453,11 @@ const DownloadIndex = struct {
 };
 
 fn fetchDownloadIndex(allocator: Allocator) !DownloadIndex {
-    const text = downloadToString(allocator, download_index_url) catch |e| switch (e) {
-        else => {
-            std.log.err("failed to download '{s}': {}", .{ download_index_url, e });
-            return e;
+    const text = switch (downloadToString(allocator, download_index_url)) {
+        .ok => |text| text,
+        .err => |err| {
+            std.log.err("download '{s}' failed: {s}", .{download_index_url, err});
+            return error.AlreadyReported;
         },
     };
     errdefer allocator.free(text);
@@ -443,24 +489,24 @@ pub fn loggyRenameAbsolute(old_path: []const u8, new_path: []const u8) !void {
     try std.fs.renameAbsolute(old_path, new_path);
 }
 
-pub fn loggySymlinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags: std.fs.SymLinkFlags) !void {
+pub fn loggySymlinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags: std.fs.Dir.SymLinkFlags) !void {
     loginfo("ln -s '{s}' '{s}'", .{ target_path, sym_link_path });
     // NOTE: can't use symLinkAbsolute because it requires target_path to be absolute but we don't want that
     //       not sure if it is a bug in the standard lib or not
     //try std.fs.symLinkAbsolute(target_path, sym_link_path, flags);
     _ = flags;
-    try std.os.symlink(target_path, sym_link_path);
+    try std.posix.symlink(target_path, sym_link_path);
 }
 
 /// returns: true if the symlink was updated, false if it was already set to the given `target_path`
-pub fn loggyUpdateSymlink(target_path: []const u8, sym_link_path: []const u8, flags: std.fs.SymLinkFlags) !bool {
+pub fn loggyUpdateSymlink(target_path: []const u8, sym_link_path: []const u8, flags: std.fs.Dir.SymLinkFlags) !bool {
     var current_target_path_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
     if (std.fs.readLinkAbsolute(sym_link_path, &current_target_path_buffer)) |current_target_path| {
         if (std.mem.eql(u8, target_path, current_target_path)) {
             loginfo("symlink '{s}' already points to '{s}'", .{ sym_link_path, target_path });
             return false; // already up-to-date
         }
-        try std.os.unlink(sym_link_path);
+        try std.posix.unlink(sym_link_path);
     } else |e| switch (e) {
         error.FileNotFound => {},
         error.NotLink => {
@@ -468,7 +514,7 @@ pub fn loggyUpdateSymlink(target_path: []const u8, sym_link_path: []const u8, fl
                 "unable to update/overwrite the 'zig' PATH symlink, the file '{s}' already exists and is not a symlink\n",
                 .{ sym_link_path},
             );
-            std.os.exit(1);
+            std.process.exit(1);
         },
         else => return e,
     }
@@ -486,7 +532,8 @@ fn existsAbsolute(absolutePath: []const u8) !bool {
         error.SymLinkLoop => return e,
         error.FileBusy => return e,
         error.Unexpected => unreachable,
-        error.InvalidUtf8 => unreachable,
+        error.InvalidUtf8 => return e,
+        error.InvalidWtf8 => return e,
         error.ReadOnlyFileSystem => unreachable,
         error.NameTooLong => unreachable,
         error.BadPathName => unreachable,
@@ -498,7 +545,7 @@ fn listCompilers(allocator: Allocator) !void {
     const install_dir_string = try getInstallDir(allocator, .{ .create = false });
     defer allocator.free(install_dir_string);
 
-    var install_dir = std.fs.openIterableDirAbsolute(install_dir_string, .{}) catch |e| switch (e) {
+    var install_dir = std.fs.openDirAbsolute(install_dir_string, .{ .iterate = true }) catch |e| switch (e) {
         error.FileNotFound => return,
         else => return e,
     };
@@ -521,10 +568,10 @@ fn keepCompiler(allocator: Allocator, compiler_version: []const u8) !void {
     const install_dir_string = try getInstallDir(allocator, .{ .create = true });
     defer allocator.free(install_dir_string);
 
-    var install_dir = try std.fs.openIterableDirAbsolute(install_dir_string, .{});
+    var install_dir = try std.fs.openDirAbsolute(install_dir_string, .{ .iterate = true });
     defer install_dir.close();
 
-    var compiler_dir = install_dir.dir.openDir(compiler_version, .{}) catch |e| switch (e) {
+    var compiler_dir = install_dir.openDir(compiler_version, .{}) catch |e| switch (e) {
         error.FileNotFound => {
             std.log.err("compiler not found: {s}", .{compiler_version});
             return error.AlreadyReported;
@@ -543,12 +590,12 @@ fn cleanCompilers(allocator: Allocator, compiler_name_opt: ?[]const u8) !void {
     const default_comp_opt = try getDefaultCompiler(allocator);
     defer if (default_comp_opt) |default_compiler| allocator.free(default_compiler);
 
-    var install_dir = std.fs.openIterableDirAbsolute(install_dir_string, .{}) catch |e| switch (e) {
+    var install_dir = std.fs.openDirAbsolute(install_dir_string, .{ .iterate = true }) catch |e| switch (e) {
         error.FileNotFound => return,
         else => return e,
     };
     defer install_dir.close();
-    const master_points_to_opt = try getMasterDir(allocator, &install_dir.dir);
+    const master_points_to_opt = try getMasterDir(allocator, &install_dir);
     defer if (master_points_to_opt) |master_points_to| allocator.free(master_points_to);
     if (compiler_name_opt) |compiler_name| {
         if (getKeepReason(master_points_to_opt, default_comp_opt, compiler_name)) |reason| {
@@ -556,7 +603,7 @@ fn cleanCompilers(allocator: Allocator, compiler_name_opt: ?[]const u8) !void {
             return error.AlreadyReported;
         }
         loginfo("deleting '{s}{c}{s}'", .{ install_dir_string, std.fs.path.sep, compiler_name });
-        try fixdeletetree.deleteTree(install_dir.dir, compiler_name);
+        try fixdeletetree.deleteTree(install_dir, compiler_name);
     } else {
         var it = install_dir.iterate();
         while (try it.next()) |entry| {
@@ -568,7 +615,7 @@ fn cleanCompilers(allocator: Allocator, compiler_name_opt: ?[]const u8) !void {
             }
 
             {
-                var compiler_dir = try install_dir.dir.openDir(entry.name, .{});
+                var compiler_dir = try install_dir.openDir(entry.name, .{});
                 defer compiler_dir.close();
                 if (compiler_dir.access("keep", .{})) |_| {
                     loginfo("keeping '{s}' (has keep file)", .{entry.name});
@@ -579,7 +626,7 @@ fn cleanCompilers(allocator: Allocator, compiler_name_opt: ?[]const u8) !void {
                 }
             }
             loginfo("deleting '{s}{c}{s}'", .{ install_dir_string, std.fs.path.sep, entry.name });
-            try fixdeletetree.deleteTree(install_dir.dir, entry.name);
+            try fixdeletetree.deleteTree(install_dir, entry.name);
         }
     }
 }
@@ -632,16 +679,16 @@ fn readMasterDir(buffer: *[std.fs.MAX_PATH_BYTES]u8, install_dir: *std.fs.Dir) !
 fn getDefaultCompiler(allocator: Allocator) !?[]const u8 {
     var buffer: [std.fs.MAX_PATH_BYTES + 1]u8 = undefined;
     const slice_path = (try readDefaultCompiler(allocator, &buffer)) orelse return null;
-    var path_to_return = try allocator.alloc(u8, slice_path.len);
-    std.mem.copy(u8, path_to_return, slice_path);
+    const path_to_return = try allocator.alloc(u8, slice_path.len);
+    @memcpy(path_to_return, slice_path);
     return path_to_return;
 }
 
 fn getMasterDir(allocator: Allocator, install_dir: *std.fs.Dir) !?[]const u8 {
     var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
     const slice_path = (try readMasterDir(&buffer, install_dir)) orelse return null;
-    var path_to_return = try allocator.alloc(u8, slice_path.len);
-    std.mem.copy(u8, path_to_return, slice_path);
+    const path_to_return = try allocator.alloc(u8, slice_path.len);
+    @memcpy(path_to_return, slice_path);
     return path_to_return;
 }
 
@@ -754,7 +801,7 @@ fn verifyPathLink(allocator: Allocator, path_link: []const u8) !void {
             }
         }
     } else {
-        var path_it = std.mem.tokenize(u8, std.os.getenv("PATH") orelse "", ":");
+        var path_it = std.mem.tokenize(u8, std.posix.getenv("PATH") orelse "", ":");
         while (path_it.next()) |path| {
             switch (try compareDir(path_link_dir_id, path)) {
                 .missing => continue,
@@ -798,11 +845,11 @@ fn enforceNoZig(path_link: []const u8, exe: []const u8) !void {
 
 const FileId = struct {
     dev: if (builtin.os.tag == .windows) u32 else blk: {
-        var st: std.os.Stat = undefined;
+        const st: std.posix.Stat = undefined;
         break :blk @TypeOf(st.dev);
     },
     ino: if (builtin.os.tag == .windows) u64 else blk: {
-        var st: std.os.Stat = undefined;
+        const st: std.posix.Stat = undefined;
         break :blk @TypeOf(st.ino);
     },
 
@@ -818,7 +865,7 @@ const FileId = struct {
                 .ino = (@as(u64, @intCast(info.nFileIndexHigh)) << 32) | @as(u64, @intCast(info.nFileIndexLow)),
             };
         }
-        const st = try std.os.fstat(file.handle);
+        const st = try std.posix.fstat(file.handle);
         return FileId{
             .dev = st.dev,
             .ino = st.ino,
@@ -886,7 +933,7 @@ fn createExeLink(link_target: []const u8, path_link: []const u8) !void {
                 "unable to create the exe link, the path '{s}' is a directory\n",
                 .{ path_link},
             );
-            std.os.exit(1);
+            std.process.exit(1);
         },
         else => |e| return e,
     };
@@ -927,16 +974,22 @@ fn installCompiler(allocator: Allocator, compiler_dir: []const u8, url: []const
         const archive_absolute = try std.fs.path.join(allocator, &[_][]const u8{ installing_dir, archive_basename });
         defer allocator.free(archive_absolute);
         loginfo("downloading '{s}' to '{s}'", .{ url, archive_absolute });
-        downloadToFileAbsolute(allocator, url, archive_absolute) catch |e| switch (e) {
-            error.HttpNon200StatusCode => {
-                // TODO: more information would be good
-                std.log.err("HTTP request failed (TODO: improve ziget library to get better error)", .{});
+
+        switch (blk: {
+            const file = try std.fs.createFileAbsolute(archive_absolute, .{});
+            // note: important to close the file before we handle errors below
+            //       since it will delete the parent directory of this file
+            defer file.close();
+            break :blk download(allocator, url, file.writer());
+        }) {
+            .ok => {},
+            .err => |err| {
+                std.log.err("download '{s}' failed: {s}", .{url, err});
                 // this removes the installing dir if the http request fails so we dont have random directories
                 try loggyDeleteTreeAbsolute(installing_dir);
                 return error.AlreadyReported;
             },
-            else => return e,
-        };
+        }
 
         if (std.mem.endsWith(u8, archive_basename, ".tar.xz")) {
             archive_root_dir = archive_basename[0 .. archive_basename.len - ".tar.xz".len];
@@ -1004,7 +1057,7 @@ fn logRun(allocator: Allocator, argv: []const []const u8) !void {
         } else {
             prefix = true;
         }
-        std.mem.copy(u8, buffer[offset .. offset + arg.len], arg);
+        @memcpy(buffer[offset .. offset + arg.len], arg);
         offset += arg.len;
     }
     std.debug.assert(offset == buffer.len);