diff --git a/README.md b/README.md index 5200eef..d17e547 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ zigup clean [] # mark a compiler to keep zigup keep + +# run a specific version of the copmiler +zigup run ... ``` # How the compilers are managed diff --git a/test.zig b/test.zig index 04c12bd..8dd2302 100644 --- a/test.zig +++ b/test.zig @@ -133,7 +133,16 @@ pub fn main() !u8 { } try runNoCapture(zigup_args ++ &[_][]const u8 {"default", "0.5.0"}); try testing.expectEqual(@as(u32, 3), try getCompilerCount(install_dir)); - + { + const result = try runCaptureOuts(allocator, zigup_args ++ &[_][]const u8 {"run", "0.6.0", "version"}); + defer { allocator.free(result.stdout); allocator.free(result.stderr); } + try testing.expectEqualSlices(u8, "0.6.0\n", result.stdout); + } + { + const result = try runCaptureOuts(allocator, zigup_args ++ &[_][]const u8 {"run", "doesnotexist", "version"}); + defer { allocator.free(result.stdout); allocator.free(result.stderr); } + try testing.expectEqualSlices(u8, "error: compiler 'doesnotexist' does not exist, fetch it first with: zigup fetch doesnotexist\n", result.stderr); + } try runNoCapture(zigup_args ++ &[_][]const u8 {"keep", "0.6.0"}); // doesn't delete anything because we have keepfile and master doens't get deleted try runNoCapture(zigup_args ++ &[_][]const u8 {"clean"}); diff --git a/zigup.zig b/zigup.zig index a04066f..753a02a 100644 --- a/zigup.zig +++ b/zigup.zig @@ -30,8 +30,11 @@ const archive_ext = if (builtin.os.tag == .windows) "zip" else "tar.xz"; var global_optional_install_dir: ?[]const u8 = null; var global_optional_path_link: ?[]const u8 = null; +var global_enable_log = true; fn loginfo(comptime fmt: []const u8, args: anytype) void { - std.debug.print(fmt ++ "\n", args); + if (global_enable_log) { + std.debug.print(fmt ++ "\n", args); + } } fn download(allocator: Allocator, url: []const u8, writer: anytype) !void { @@ -142,6 +145,7 @@ fn help() void { \\ zigup clean [VERSION] deletes the given compiler version, otherwise, cleans all compilers \\ that aren't the default, master, or marked to keep. \\ zigup keep VERSION mark a compiler to be kept during clean + \\ zigup run VERSION ARGS... run the given VERSION of the compiler with the given ARGS... \\ \\Uncommon Usage: \\ @@ -205,6 +209,9 @@ pub fn main2() !u8 { help(); return 0; } else { + if (newlen == 0 and std.mem.eql(u8, "run", arg)) { + return try runCompiler(allocator, args[i+1..]); + } args[newlen] = args[i]; newlen += 1; } @@ -307,6 +314,41 @@ pub fn main2() !u8 { //const optionalInstallPath = try find_zigs(allocator); } +pub fn runCompiler(allocator: Allocator, args: []const []const u8) !u8 { + // disable log so we don't add extra output to whatever the compiler will output + global_enable_log = false; + if (args.len <= 1) { + std.log.err("zigup run requires at least 2 arguments: zigup run VERSION PROG ARGS...", .{}); + return 1; + } + const version_string = args[0]; + const install_dir_string = try getInstallDir(allocator, .{ .create = true }); + defer allocator.free(install_dir_string); + + const compiler_dir = try std.fs.path.join(allocator, &[_][]const u8{ install_dir_string, version_string }); + defer allocator.free(compiler_dir); + if (!try existsAbsolute(compiler_dir)) { + std.log.err("compiler '{s}' does not exist, fetch it first with: zigup fetch {0s}", .{version_string}); + return 1; + } + + var argv = std.ArrayList([]const u8).init(allocator); + try argv.append(try std.fs.path.join(allocator, &.{ compiler_dir, "files", "zig" ++ builtin.target.exeFileExt() })); + try argv.appendSlice(args[1..]); + + // TODO: use "execve" if on linux + const proc = try std.ChildProcess.init(argv.items, allocator); + defer proc.deinit(); + const ret_val = try proc.spawnAndWait(); + switch (ret_val) { + .Exited => |code| return code, + else => |result| { + std.log.err("compiler exited with {}", .{result}); + return 0xff; + }, + } +} + const SetDefault = enum { set_default, leave_default }; fn fetchCompiler(allocator: Allocator, version_arg: []const u8, set_default: SetDefault) !void {