Skip to content

Commit 4005179

Browse files
build: upgrade zig from 0.15 to 0.16 (#128)
* zig 0.16.0 compat * remove util compat * lint fix * fix * ci: use 0.16.0 * fix
1 parent a0b40d3 commit 4005179

30 files changed

Lines changed: 593 additions & 681 deletions

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Checkout code
13-
uses: actions/checkout@v5
13+
uses: actions/checkout@v6
1414

1515
- name: Setup Zig
1616
uses: mlugg/setup-zig@v2
1717
with:
18-
version: 0.15.1
18+
version: 0.16.0
1919

2020
- name: Build release
2121
run: zig build release

.github/workflows/zig.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ jobs:
1515
os: [ubuntu-latest, macos-latest, windows-latest]
1616
runs-on: ${{matrix.os}}
1717
steps:
18-
- uses: actions/checkout@v5
18+
- uses: actions/checkout@v6
1919
- uses: mlugg/setup-zig@v2
2020
with:
21-
version: 0.15.1
21+
version: 0.16.0
2222
- run: zig build test
2323
lint:
2424
runs-on: ubuntu-latest
2525
steps:
26-
- uses: actions/checkout@v5
26+
- uses: actions/checkout@v6
2727
- uses: mlugg/setup-zig@v2
2828
- run: zig fmt --check src/*.zig
2929
- uses: DonIsaac/zlint-action@v0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ zvm completions fish > ~/.config/fish/completions/zvm.fish
233233
## 🏗️ Building from Source
234234

235235
### Prerequisites
236-
- Zig 0.15.1 or later
236+
- Zig 0.16.0 or later
237237

238238
### Build Steps
239239
```bash

build.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ const builtin = @import("builtin");
33

44
const Build = std.Build;
55

6-
const min_zig_string = "0.15.1";
7-
const semver = std.SemanticVersion{ .major = 0, .minor = 16, .patch = 5 };
8-
const semver_string = "0.17.0";
6+
const min_zig_string = "0.16.0";
7+
const semver = std.SemanticVersion{ .major = 0, .minor = 18, .patch = 0 };
8+
const semver_string = "0.18.0";
99

1010
// comptime detect the zig version
1111
comptime {

src/Context.zig

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub const CliContext = struct {
2323
/// Static memory system for any remaining allocations.
2424
static_mem: static_memory.StaticMemory,
2525

26+
/// Process-owned I/O implementation.
27+
io: std.Io,
28+
2629
/// Singleton instance - set during initialization.
2730
var instance: ?*CliContext = null;
2831

@@ -31,6 +34,7 @@ pub const CliContext = struct {
3134
context_storage: *CliContext,
3235
static_buffer: []u8,
3336
arguments: []const []const u8,
37+
io: std.Io,
3438
) !*CliContext {
3539
// context_storage is a pointer, not optional - can't be null in Zig
3640
assert(static_buffer.len > 0);
@@ -45,6 +49,7 @@ pub const CliContext = struct {
4549

4650
// Initialize core systems
4751
try init_core_systems(context_storage, static_buffer);
52+
context_storage.io = io;
4853

4954
// Copy command line arguments
5055
try copy_args(context_storage, arguments);
@@ -114,13 +119,10 @@ pub const CliContext = struct {
114119
fn init_home_directory(context_storage: *CliContext) !void {
115120
const home = blk: {
116121
if (builtin.os.tag == .windows) {
117-
const key_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral("USERPROFILE");
118-
const home_w = std.process.getenvW(key_w) orelse break :blk "./";
119-
const home_len = std.unicode.wtf16LeToWtf8(&context_storage.home_dir_buffer, home_w);
120-
break :blk context_storage.home_dir_buffer[0..home_len];
122+
break :blk util_tool.getenv_cross_platform("USERPROFILE") orelse "./";
121123
}
122124

123-
break :blk std.posix.getenv("HOME") orelse "./";
125+
break :blk util_tool.getenv_cross_platform("HOME") orelse "./";
124126
};
125127

126128
// Validate home directory
@@ -210,24 +212,21 @@ pub const CliContext = struct {
210212

211213
// buffer is a pointer, not optional - no need for null check
212214

213-
var fixed_buffer_stream = std.Io.fixedBufferStream(buffer.slice());
214215
const home_dir = self.get_home_dir();
215216
assert(home_dir.len > 0);
216217

217218
// Follow XDG Base Directory specification
218-
if (util_tool.getenv_cross_platform("XDG_DATA_HOME")) |xdg_data| {
219-
try fixed_buffer_stream.writer().print("{s}/.zm/{s}", .{ xdg_data, segment });
220-
} else {
221-
// Use XDG default: $HOME/.local/share/.zm
222-
try fixed_buffer_stream.writer().print("{s}/.local/share/.zm/{s}", .{ home_dir, segment });
223-
}
219+
const result = if (util_tool.getenv_cross_platform("XDG_DATA_HOME")) |xdg_data|
220+
try std.fmt.bufPrint(buffer.slice(), "{s}/.zm/{s}", .{ xdg_data, segment })
221+
else
222+
try std.fmt.bufPrint(buffer.slice(), "{s}/.local/share/.zm/{s}", .{ home_dir, segment });
224223

225-
const result = try buffer.set(fixed_buffer_stream.getWritten());
224+
const path = try buffer.set(result);
226225

227-
assert(result.len > 0);
228-
assert(result.len <= limits.limits.path_length_maximum);
226+
assert(path.len > 0);
227+
assert(path.len <= limits.limits.path_length_maximum);
229228

230-
return result;
229+
return path;
231230
}
232231

233232
/// Get a ZON allocator
@@ -267,7 +266,7 @@ pub const CliContext = struct {
267266
const pool_stats = self.get_pool_stats();
268267

269268
var buffer: [limits.limits.io_buffer_size_maximum]u8 = undefined;
270-
var stderr_writer = std.fs.File.Writer.init(std.fs.File.stderr(), &buffer);
269+
var stderr_writer = std.Io.File.stderr().writer(self.io, &buffer);
271270
const stderr = &stderr_writer.interface;
272271
try stderr.print("\n=== ZVM Resource Usage ===\n", .{});
273272
try stderr.print("{any}\n", .{mem_usage});

src/cli/validation.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ fn validate_install(raw: raw_args.RawArgs.InstallArgs) !ValidatedCommand.Install
342342
util_output.fatal(.invalid_arguments, "patch version too large in '{s}' (maximum: 999)", .{version_str});
343343
},
344344
error.LatestNotSupported => {
345-
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.15.1'", .{});
345+
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.16.0'", .{});
346346
},
347347
};
348348

@@ -403,7 +403,7 @@ fn validate_remove(raw: raw_args.RawArgs.RemoveArgs) !ValidatedCommand.RemoveCom
403403
util_output.fatal(.invalid_arguments, "patch version too large in '{s}' (maximum: 999)", .{version_str});
404404
},
405405
error.LatestNotSupported => {
406-
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.15.1'", .{});
406+
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.16.0'", .{});
407407
},
408408
};
409409

@@ -454,7 +454,7 @@ fn validate_use(raw: raw_args.RawArgs.UseArgs) !ValidatedCommand.UseCommand {
454454
util_output.fatal(.invalid_arguments, "patch version too large in '{s}' (maximum: 999)", .{version_str});
455455
},
456456
error.LatestNotSupported => {
457-
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.15.1'", .{});
457+
util_output.fatal(.invalid_arguments, "'latest' is not supported. Use 'master' for the development version or a specific version like '0.16.0'", .{});
458458
},
459459
};
460460

src/commands/clean.zig

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn clean_download_store(ctx: *context.CliContext, emit_human: bool) !StoreCleanu
5353
defer store_buffer.reset();
5454

5555
const store_path = try util_data.get_zvm_store(store_buffer);
56-
var store_dir = std.fs.openDirAbsolute(store_path, .{ .iterate = true }) catch |err| {
56+
var store_dir = std.Io.Dir.openDirAbsolute(ctx.io, store_path, .{ .iterate = true }) catch |err| {
5757
if (err == error.FileNotFound) {
5858
if (emit_human) {
5959
util_output.info("No old download artifacts found to clean.", .{});
@@ -63,9 +63,9 @@ fn clean_download_store(ctx: *context.CliContext, emit_human: bool) !StoreCleanu
6363

6464
return err;
6565
};
66-
defer store_dir.close();
66+
defer store_dir.close(ctx.io);
6767

68-
const cleanup = try remove_download_artifacts(&store_dir);
68+
const cleanup = try remove_download_artifacts(ctx.io, &store_dir);
6969
if (!emit_human) return cleanup;
7070

7171
if (cleanup.files_removed == 0) {
@@ -81,18 +81,18 @@ fn clean_download_store(ctx: *context.CliContext, emit_human: bool) !StoreCleanu
8181
return cleanup;
8282
}
8383

84-
fn remove_download_artifacts(store_dir: *std.fs.Dir) !StoreCleanup {
84+
fn remove_download_artifacts(io: std.Io, store_dir: *std.Io.Dir) !StoreCleanup {
8585
var iterator = store_dir.iterate();
8686
var cleanup = StoreCleanup{};
8787

88-
while (try iterator.next()) |entry| {
88+
while (try iterator.next(io)) |entry| {
8989
if (entry.kind != .file) continue;
9090

91-
const file = try store_dir.openFile(entry.name, .{});
92-
const file_info = try file.stat();
93-
file.close();
91+
const file = try store_dir.openFile(io, entry.name, .{});
92+
const file_info = try file.stat(io);
93+
file.close(io);
9494

95-
try store_dir.deleteFile(entry.name);
95+
try store_dir.deleteFile(io, entry.name);
9696
cleanup.files_removed += 1;
9797
cleanup.bytes_freed += file_info.size;
9898
}
@@ -147,7 +147,7 @@ fn read_current_version(
147147
.zig => try util_data.get_zvm_current_zig(current_path_buffer),
148148
.zls => try util_data.get_zvm_current_zls(current_path_buffer),
149149
};
150-
if (!util_tool.does_path_exist(current_path)) return null;
150+
if (!util_tool.does_path_exist(ctx.io, current_path)) return null;
151151

152152
var output_buffer: [limits.limits.temp_buffer_size]u8 = undefined;
153153
const version_output = util_data.get_current_version(
@@ -180,16 +180,16 @@ fn clean_versions_for_tool(
180180
.zig => try util_data.get_zvm_zig_version(versions_path_buffer),
181181
.zls => try util_data.get_zvm_zls_version(versions_path_buffer),
182182
};
183-
var versions_dir = std.fs.openDirAbsolute(versions_path, .{ .iterate = true }) catch |err| {
183+
var versions_dir = std.Io.Dir.openDirAbsolute(ctx.io, versions_path, .{ .iterate = true }) catch |err| {
184184
if (err == error.FileNotFound) return 0;
185185
return err;
186186
};
187-
defer versions_dir.close();
187+
defer versions_dir.close(ctx.io);
188188

189189
var iterator = versions_dir.iterate();
190190
var versions_removed: usize = 0;
191191

192-
while (try iterator.next()) |entry| {
192+
while (try iterator.next(ctx.io)) |entry| {
193193
if (entry.kind != .directory) continue;
194194

195195
if (current_version) |current| {
@@ -208,7 +208,7 @@ fn clean_versions_for_tool(
208208
util_output.info(" Removing {s} {s}", .{ tool.to_string(), entry.name });
209209
}
210210

211-
try versions_dir.deleteTree(entry.name);
211+
try versions_dir.deleteTree(ctx.io, entry.name);
212212
versions_removed += 1;
213213
}
214214

@@ -218,18 +218,19 @@ fn clean_versions_for_tool(
218218
test "remove_download_artifacts deletes only files" {
219219
var tmp_dir = std.testing.tmpDir(.{});
220220
defer tmp_dir.cleanup();
221+
const io = std.testing.io;
221222

222-
const artifact = try tmp_dir.dir.createFile("artifact.tar.xz", .{});
223-
try artifact.writeAll("artifact");
224-
artifact.close();
223+
const artifact = try tmp_dir.dir.createFile(io, "artifact.tar.xz", .{});
224+
try artifact.writeStreamingAll(io, "artifact");
225+
artifact.close(io);
225226

226-
try tmp_dir.dir.makeDir("versions");
227+
try tmp_dir.dir.createDir(io, "versions", .default_dir);
227228

228229
var dir = tmp_dir.dir;
229-
const cleanup = try remove_download_artifacts(&dir);
230+
const cleanup = try remove_download_artifacts(io, &dir);
230231

231232
try std.testing.expectEqual(@as(usize, 1), cleanup.files_removed);
232233
try std.testing.expectEqual(@as(u64, 8), cleanup.bytes_freed);
233-
try std.testing.expectError(error.FileNotFound, dir.access("artifact.tar.xz", .{}));
234-
try dir.access("versions", .{});
234+
try std.testing.expectError(error.FileNotFound, dir.access(io, "artifact.tar.xz", .{}));
235+
try dir.access(io, "versions", .{});
235236
}

src/commands/env.zig

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,12 @@ pub fn execute(
3737
}
3838

3939
fn build_zvm_bin_path(ctx: *context.CliContext, buffer: []u8) ![]const u8 {
40-
var stream = std.Io.fixedBufferStream(buffer);
4140
const home_dir = ctx.get_home_dir();
4241

43-
if (util_tool.getenv_cross_platform("XDG_DATA_HOME")) |xdg_data| {
44-
try stream.writer().print("{s}/.zm/bin", .{xdg_data});
45-
} else {
46-
try stream.writer().print("{s}/.local/share/.zm/bin", .{home_dir});
47-
}
48-
49-
return stream.getWritten();
42+
return if (util_tool.getenv_cross_platform("XDG_DATA_HOME")) |xdg_data|
43+
try std.fmt.bufPrint(buffer, "{s}/.zm/bin", .{xdg_data})
44+
else
45+
try std.fmt.bufPrint(buffer, "{s}/.local/share/.zm/bin", .{home_dir});
5046
}
5147

5248
fn detect_shell_name(shell: ?validation.ShellType, buffer: []u8) ![]const u8 {
@@ -78,8 +74,8 @@ fn detect_windows_shell(buffer: []u8) ![]const u8 {
7874
}
7975

8076
fn build_env_text(shell_name: []const u8, zvm_bin_path: []const u8, buffer: []u8) ![]const u8 {
81-
var stream = std.Io.fixedBufferStream(buffer);
82-
const writer = stream.writer();
77+
var writer_state: std.Io.Writer = .fixed(buffer);
78+
const writer: *std.Io.Writer = &writer_state;
8379

8480
if (std.mem.indexOf(u8, shell_name, "fish") != null) {
8581
try writer.print("# Add this to your ~/.config/fish/config.fish:\n", .{});
@@ -107,14 +103,13 @@ fn build_env_text(shell_name: []const u8, zvm_bin_path: []const u8, buffer: []u8
107103
try writer.print("export PATH=\"{s}:$PATH\"\n", .{zvm_bin_path});
108104
}
109105

110-
return stream.getWritten();
106+
return writer_state.buffered();
111107
}
112108

113109
fn get_windows_env_var(comptime var_name: []const u8, buffer: []u8) !?[]const u8 {
114110
if (builtin.os.tag != .windows) return null;
115-
const key_w = comptime std.unicode.wtf8ToWtf16LeStringLiteral(var_name);
116-
const result_w = std.process.getenvW(key_w) orelse return null;
117-
const result_len = std.unicode.wtf16LeToWtf8(buffer, result_w);
118-
if (result_len > buffer.len) return error.BufferTooSmall;
119-
return buffer[0..result_len];
111+
const value = util_tool.getenv_cross_platform(var_name) orelse return null;
112+
if (value.len > buffer.len) return error.BufferTooSmall;
113+
@memcpy(buffer[0..value.len], value);
114+
return buffer[0..value.len];
120115
}

src/commands/help.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ const install_help_text =
5959
\\ --zls Install ZLS instead of Zig
6060
\\
6161
\\EXAMPLES:
62-
\\ zvm install 0.15.1
62+
\\ zvm install 0.16.0
6363
\\ zvm i master
64-
\\ zvm install --zls 0.15.1
64+
\\ zvm install --zls 0.16.0
6565
\\
6666
;
6767

@@ -77,7 +77,7 @@ const remove_help_text =
7777
\\ --zls Remove ZLS instead of Zig
7878
\\
7979
\\EXAMPLES:
80-
\\ zvm remove 0.15.1
80+
\\ zvm remove 0.16.0
8181
\\ zvm rm --zls master
8282
\\
8383
;
@@ -94,7 +94,7 @@ const use_help_text =
9494
\\ --zls Select ZLS instead of Zig
9595
\\
9696
\\EXAMPLES:
97-
\\ zvm use 0.15.1
97+
\\ zvm use 0.16.0
9898
\\ zvm u --zls master
9999
\\
100100
;
@@ -288,7 +288,7 @@ test "help command executes without error" {
288288
_ = try util_output.init_global(output_config);
289289

290290
const command = validation.ValidatedCommand.HelpCommand{ .topic = .general };
291-
const progress_node = std.Progress.start(.{ .root_name = "test" });
291+
const progress_node = std.Progress.start(std.testing.io, .{ .root_name = "test" });
292292
defer progress_node.end();
293293

294294
var mock_ctx: context.CliContext = undefined;

src/commands/list.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ fn collect_versions(
4242
.zig => try util_data.get_zvm_zig_version(versions_path_buffer),
4343
.zls => try util_data.get_zvm_zls_version(versions_path_buffer),
4444
};
45-
var versions_dir = std.fs.openDirAbsolute(versions_path, .{ .iterate = true }) catch |err| {
45+
var versions_dir = std.Io.Dir.openDirAbsolute(ctx.io, versions_path, .{ .iterate = true }) catch |err| {
4646
if (err == error.FileNotFound) return 0;
4747
return err;
4848
};
49-
defer versions_dir.close();
49+
defer versions_dir.close(ctx.io);
5050

5151
var version_count: usize = 0;
5252
var iterator = versions_dir.iterate();
5353

54-
while (try iterator.next()) |entry| {
54+
while (try iterator.next(ctx.io)) |entry| {
5555
if (entry.kind != .directory) continue;
5656
if (entry.name[0] == '.') continue;
5757
if (version_count >= versions.len) break;

0 commit comments

Comments
 (0)