Tags: lispking/zvm
Tags
refactor(network): extract streamBodyToFile and ProxyTunnel HTTP helpers Add sendHttpGet, readHttpStatus, and skipHeaders methods to ProxyTunnel to eliminate duplicated request/response parsing in downloadViaProxyTunnel and downloadFileViaProxyTunnel. Extract streamBodyToFile helper that handles both progress display and plain streaming without progress. This removes the duplicated download loops from downloadToFileWithProxy (normal mode) and downloadFileViaProxyTunnel (proxy mode). Result: - downloadViaProxyTunnel reduced from ~50 lines to ~15 lines - downloadFileViaProxyTunnel reduced from ~90 lines to ~25 lines - downloadToFileWithProxy progress logic delegated to streamBodyToFile
feat(update): add periodic version check with 24h cache Add update_check module that checks GitHub Releases for newer zvm versions. The check runs after install and mirrorlist commands (both already require network), and caches results for 24 hours in ~/.cache/zvm/_update_check to avoid redundant API calls. The hint is non-blocking and non-interactive — it prints a yellow notice like "A new version of zvm is available: v0.2.0" without prompting or interrupting the command flow. The upgrade command is excluded since it already performs its own version check. Refactor upgrade.zig to reuse versionGt, stripVPrefix, and extractVersionFromRelease from the new module, eliminating ~50 lines of duplicate version parsing logic.
fix(probe): guard POSIX-only code for Windows cross-compilation Add comptime `if (native_os == .windows) return;` guards to probeThreadMainPosix and tickerThread so their POSIX-specific libc calls (clock_gettime, getaddrinfo, socket, nanosleep, write) are not type-checked when compiling for Windows targets. In probeAll, guard clock_gettime calls with comptime branching. On Windows the ticker thread is skipped entirely (progress display is cosmetic), and probe threads use the std.http.Client fallback path (probeThreadMainWindows). Fixes aarch64-windows-gnu CI build failure.
feat: concurrent mirror probing, download progress, and active versio… …n protection - Replace serial mirror latency probing with concurrent probing using Zig 0.16 Io.Group fibers. Direct connections probe all mirrors in parallel (batch size 8), reducing total probe time from sum of all latencies to the slowest single probe. Proxy/curl path remains sequential since std.process.run blocks the event loop. - Add download progress indicator showing percentage, downloaded/total size, and transfer speed. Uses chunked stream loop with ~10 updates per second. Clears line with ANSI escape to prevent ghost characters from shorter previous updates. Curl proxy path uses -# flag for native progress bar. - Block removal of the currently active version with actionable guidance: list other installed versions for switching, or suggest installing a new version first when none are available.
refactor: migrate entire codebase to Zig 0.16.0 I/O API Upgrade zvm to compile against Zig 0.16.0, which introduces a fundamental I/O revolution — every filesystem and network operation now requires an explicit io: std.Io parameter threaded through the call chain. Key API migrations in this commit: - main() signature: pub fn main() void → pub fn main(init: std.process.Init) !void using init.gpa, init.io, init.environ_map, init.minimal.args - File/Dir operations: std.fs.cwd() → std.Io.Dir.cwd() with io param - File close: file.close() → file.close(io) - Dir close: dir.close() → dir.close(io) - Dir iteration: iter.next() → iter.next(io) - Dir rename: dir.rename(old, new) → dir.rename(old, dir, new, io) - Symlink: std.posix.symlink() → std.Io.Dir.symLinkAbsolute(io, ...) - File reading: reader.allocRemaining() → reader.interface.allocRemaining() - Subprocess: std.process.Child.run() → std.process.run(alloc, io, opts) - Spawn: std.process.Child.init/spawn/wait → std.process.spawn/wait - Timestamps: std.time.timestamp() → Io.Clock.Timestamp.now(io, .real) - Latency: std.time.Instant → Io.Timestamp.now(io, .awake) + durationTo() - Zip extract: std.zip.extract(cwd, io, reader, opts) → extract(cwd, reader, opts) - Term fields: .Exited/.Signal → .exited/.signal (lowercase) - CLI args: argsWithAllocator → Args.Iterator.initAllocator - Env vars: getEnvVarOwned → environ_map.get() - Build: build_options.minimum_zig_version bumped to 0.14.0 Architecture: io and environ_map stored in ZVM struct to minimize signature changes across command handlers — all commands access zvm.io and zvm.environ_map as needed. Verified: binary compiles and passes basic smoke tests (help, version, ls)
fix(proxy): set max_output_bytes for curl subprocess downloads Zig 0.15.x defaults std.process.Child.run max_output_bytes to 50KB, which is too small for the ziglang.org version map JSON (~76KB). This caused StdoutStreamTooLong errors when proxy is configured, silently masked as DownloadFailed. Set max_output_bytes to 10MB in downloadMemoryViaCurl to accommodate the version map and other in-memory download responses.
ci(release): add stable latest release for permalink downloads Add a separate 'latest' release that is updated on every tag push, so users can download zvm without knowing the version number: https://github.com/lispking/zvm/releases/latest/download/zvm-aarch64-macos.tar.gz The build job now produces two sets of packages per platform: - Versioned: zvm-v0.1.0-aarch64-macos.tar.gz (for tagged release) - Latest: zvm-aarch64-macos.tar.gz (stable name for latest release) The create-release job: 1. Creates a versioned release with versioned assets 2. Deletes the old 'latest' release and creates a new one with stable-named assets, so the permalink always resolves Also update README install section to show the stable download URLs for all platforms with one-line install commands.