Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/core/remove.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ pub fn remove(ctx: *context.CliContext, version: []const u8, is_zls: bool, debug
assert(true_version.len > 0);
assert(true_version.len <= version.len or is_zls);

if (!is_zls) {
try clear_default_if_active(ctx, true_version);
}

// Get current path using path buffer.
var current_path_buffer = try ctx.scratch(.path);
defer current_path_buffer.release();
Expand Down Expand Up @@ -141,3 +145,30 @@ pub fn remove(ctx: *context.CliContext, version: []const u8, is_zls: bool, debug
}
}
}

fn clear_default_if_active(ctx: *context.CliContext, version: []const u8) !void {
assert(version.len > 0);
assert(version.len <= limits.limits.version_string_length_maximum);

var default_version_buffer: [limits.limits.version_string_length_maximum]u8 = undefined;
const default_version = detect_version.find_default_version_in_buffer(
ctx,
&default_version_buffer,
) catch null;

const value = default_version orelse return;
if (!util_tool.eql_str(value, version)) return;

var default_version_path_buffer = try ctx.scratch(.path);
defer default_version_path_buffer.release();

const default_version_path = try util_data.get_zvm_path_segment(
default_version_path_buffer,
"default_version",
);

std.Io.Dir.deleteFileAbsolute(ctx.io, default_version_path) catch |err| switch (err) {
error.FileNotFound => {},
else => return err,
};
}
2 changes: 1 addition & 1 deletion src/core/remove_installed.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
&prompt_buffer,
"Remove active {s} version {s}?",
.{ command.tool.to_string(), version_str },
) catch unreachable;

Check warning on line 41 in src/core/remove_installed.zig

View workflow job for this annotation

GitHub Actions / lint

suppressed-errors

Caught error is mishandled with `unreachable`

const confirmed = confirm.confirm_destructive(ctx.io, prompt, true, ctx.no_input) catch |err| switch (err) {
error.RequiresConfirmation => util_output.exit_with(
Expand Down Expand Up @@ -83,7 +83,7 @@

pub fn progress_items(command: validation.ValidatedCommand.RemoveCommand) u16 {
_ = command;
return 2;
return 0;
}

/// Decide whether removing `version_str` would tear down the active install.
Expand Down
17 changes: 10 additions & 7 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,6 @@ pub fn main(process_init: std.process.Init) !void {

metadata.init_config();

if (shim.is_shim_name(basename)) {
try shim.run(process_init.io, basename, arguments[1..]);
unreachable;
}

// Inspect environment for color-mode resolution before any output is emitted.
// Color must be resolved before the first emitter is created so that even
// error messages during parsing respect the terminal and environment.
Expand Down Expand Up @@ -171,6 +166,11 @@ pub fn main(process_init: std.process.Init) !void {
};
try util_output.set_mode(default_output_config);

if (shim.is_shim_name(basename)) {
try shim.run(process_init.io, basename, arguments[1..]);
unreachable;
}

// Pre-scan for verbose flags so parse-error fatals respect --verbose.
// Why: parser.parse_command_line emits its own fatals (unknown option,
// duplicate, etc.). If verbose is only applied after that returns, the
Expand Down Expand Up @@ -225,10 +225,13 @@ pub fn main(process_init: std.process.Init) !void {
};
context_instance.assume_yes = parsed_command_line.global_config.assume_yes;
context_instance.no_input = parsed_command_line.global_config.no_input;
const progress_item_count = get_progress_item_count(parsed_command_line.command);
const root_node = std.Progress.start(process_init.io, .{
.root_name = "zvm",
.estimated_total_items = get_progress_item_count(parsed_command_line.command),
.disable_printing = final_output_config.mode != .human_readable or !stderr_is_tty,
.estimated_total_items = progress_item_count,
.disable_printing = progress_item_count == 0 or
final_output_config.mode != .human_readable or
!stderr_is_tty,
});

execute_command(context_instance, parsed_command_line.command, root_node) catch |err| {
Expand Down
18 changes: 15 additions & 3 deletions src/platform/signals.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const exit_code_interrupted = 130;

var interrupt_requested = std.atomic.Value(bool).init(false);
var cleanup_running = std.atomic.Value(bool).init(false);
var blocking_wait_running = std.atomic.Value(bool).init(false);

pub fn install_handler() void {
switch (builtin.os.tag) {
Expand All @@ -30,12 +31,23 @@ pub fn end_cleanup() void {
cleanup_running.store(false, .release);
}

pub fn begin_blocking_wait() void {
blocking_wait_running.store(true, .release);
if (requested()) std.process.exit(exit_code_interrupted);
}

pub fn end_blocking_wait() void {
blocking_wait_running.store(false, .release);
}

fn request_interrupt() void {
if (cleanup_running.load(.acquire)) {
const already_requested = interrupt_requested.swap(true, .acq_rel);
if (already_requested or
cleanup_running.load(.acquire) or
blocking_wait_running.load(.acquire))
{
std.process.exit(exit_code_interrupted);
}

interrupt_requested.store(true, .release);
}

fn install_handler_posix() void {
Expand Down
35 changes: 30 additions & 5 deletions src/shim.zig
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
) !void {
assert(is_shim_name(program_name));
const tool_name = if (util_tool.eql_str(program_name, "zig") or util_tool.eql_str(program_name, "zig.exe")) "zig" else "zls";
const is_zls = util_tool.eql_str(tool_name, "zls");

var version_buffer: [memory_limits.limits.version_string_length_maximum]u8 = undefined;
const version = detect_version.detect_version_for_shim(
Expand All @@ -69,12 +70,12 @@
error.OutOfMemory => @panic("out of memory in shim version detection"),
else => {
log.err("Failed to detect version: {s}", .{@errorName(err)});
return run_current(io, tool_name, remaining_arguments);
return run_current(io, tool_name, is_zls, remaining_arguments);
},
};

if (util_tool.eql_str(version, "current")) {
return run_current(io, tool_name, remaining_arguments);
return run_current(io, tool_name, is_zls, remaining_arguments);
}

var adjusted_arguments_buffer: [memory_limits.limits.arguments_maximum][]const u8 = undefined;
Expand All @@ -88,24 +89,32 @@
return;
}

if (util_tool.eql_str(tool_name, "zig")) {
if (!is_zls) {
if (auto_install_version_gracefully(io, version)) {
if (try run_versioned_if_available(io, tool_name, version, adjusted_arguments)) {
return;
}
}
}

return run_current(io, tool_name, remaining_arguments);
return run_current(io, tool_name, is_zls, remaining_arguments);
}

fn run_current(io: std.Io, program_name: []const u8, arguments: []const []const u8) !void {
fn run_current(
io: std.Io,
program_name: []const u8,
is_zls: bool,
arguments: []const []const u8,
) !void {
var buffers: ShimBuffers = undefined;

Check warning on line 109 in src/shim.zig

View workflow job for this annotation

GitHub Actions / lint

unsafe-undefined

`undefined` is missing a safety comment
buffers.exec_arguments_count = 0;

const home = try get_home_path(&buffers);
const zvm_home = try get_zvm_home_path(&buffers, home);
const tool_path = try build_tool_path(&buffers, program_name, zvm_home);
if (!tool_path_exists(io, tool_path)) {
report_no_active_version(is_zls);
}
try exec_tool(io, &buffers, tool_path, arguments);
}

Expand All @@ -115,7 +124,7 @@
version: []const u8,
arguments: []const []const u8,
) !bool {
var buffers: ShimBuffers = undefined;

Check warning on line 127 in src/shim.zig

View workflow job for this annotation

GitHub Actions / lint

unsafe-undefined

`undefined` is missing a safety comment
buffers.exec_arguments_count = 0;

const home = try get_home_path(&buffers);
Expand Down Expand Up @@ -165,6 +174,22 @@
}
}

fn report_no_active_version(is_zls: bool) noreturn {
if (!is_zls) {
util_output.exit_with(
.version_not_found,
"No active Zig version selected. Run `zvm use <version>` first.",
.{},
);
}

util_output.exit_with(
.version_not_found,
"No active zls version selected. Run `zvm use --zls <version>` first.",
.{},
);
}

fn adjust_arguments(
version: []const u8,
original_arguments: []const []const u8,
Expand Down Expand Up @@ -194,7 +219,7 @@

if (util_tool.eql_str(version, "current")) return error.AlreadyCurrent;

var context_storage: Context.CliContext = undefined;

Check warning on line 222 in src/shim.zig

View workflow job for this annotation

GitHub Actions / lint

unsafe-undefined

`undefined` is missing a safety comment
const install_args = &[_][]const u8{ "zvm", "install", version };

const context = Context.CliContext.init_locked(
Expand Down
11 changes: 6 additions & 5 deletions src/util/confirm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
const std = @import("std");
const builtin = @import("builtin");
const assert = std.debug.assert;
const signals = @import("../platform/signals.zig");

const max_prompt_length_bytes = 256;
const max_response_length_bytes = 32;
Expand Down Expand Up @@ -94,13 +95,13 @@ pub fn confirm_destructive(
var read_buffer: [max_response_length_bytes]u8 = undefined;
var stdin_reader = std.Io.File.stdin().reader(io, &read_buffer);

var line_buffer: [max_response_length_bytes]u8 = undefined;
const bytes_read = stdin_reader.interface.readSliceShort(&line_buffer) catch
signals.begin_blocking_wait();
defer signals.end_blocking_wait();
const line = stdin_reader.interface.takeDelimiter('\n') catch
return error.StdinReadFailed;
if (bytes_read == 0) return !default_no == false; // EOF on TTY: treat as no.
if (line == null) return !default_no == false; // EOF on TTY: treat as no.

const newline_index = std.mem.indexOfScalar(u8, line_buffer[0..bytes_read], '\n') orelse bytes_read;
const response = std.mem.trim(u8, line_buffer[0..newline_index], " \t\r");
const response = std.mem.trim(u8, line.?, " \t\r");

return interpret_response(response, default_no);
}
Expand Down
Loading
Loading