diff --git a/test.zig b/test.zig index 6600b71..2e9110e 100644 --- a/test.zig +++ b/test.zig @@ -126,6 +126,41 @@ pub fn main() !u8 { dumpExecResult(result); try testing.expect(std.mem.eql(u8, result.stdout, "0.7.0\n")); } + + // verify we print a nice error message if we can't update the symlink + // because it's a directory + { + const zig_exe_link = comptime "scratch" ++ sep ++ "bin" ++ sep ++ "zig" ++ builtin.target.exeFileExt(); + + if (std.fs.cwd().access(zig_exe_link, .{})) { + try std.fs.cwd().deleteFile(zig_exe_link); + } else |err| switch (err) { + error.FileNotFound => {}, + else => |e| return e, + } + try std.fs.cwd().makeDir(zig_exe_link); + + const result = try runCaptureOuts(allocator, zigup_args ++ &[_][]const u8{ "default", "0.7.0" }); + defer { + allocator.free(result.stdout); + allocator.free(result.stderr); + } + dumpExecResult(result); + switch (result.term) { + .Exited => |code| try testing.expectEqual(@as(u8, 1), code), + else => |term| std.debug.panic("unexpected exit {}", .{term}), + } + if (builtin.os.tag == .windows) { + try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "unable to create the exe link, the path '")); + try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "' is a directory")); + } else { + try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "unable to update/overwrite the 'zig' PATH symlink, the file '")); + try testing.expect(std.mem.containsAtLeast(u8, result.stderr, 1, "' already exists and is not a symlink")); + } + + try std.fs.cwd().deleteDir(zig_exe_link); + } + { const result = try runCaptureOuts(allocator, zigup_args ++ &[_][]const u8{ "fetch", "0.7.0" }); defer { diff --git a/zigup.zig b/zigup.zig index 25a78f1..d759be1 100644 --- a/zigup.zig +++ b/zigup.zig @@ -463,6 +463,13 @@ pub fn loggyUpdateSymlink(target_path: []const u8, sym_link_path: []const u8, fl try std.os.unlink(sym_link_path); } else |e| switch (e) { error.FileNotFound => {}, + error.NotLink => { + std.debug.print( + "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); + }, else => return e, } try loggySymlinkAbsolute(target_path, sym_link_path, flags); @@ -865,7 +872,16 @@ fn createExeLink(link_target: []const u8, path_link: []const u8) !void { std.debug.print("Error: path_link (size {}) is too large (max {})\n", .{ path_link.len, std.fs.MAX_PATH_BYTES }); return error.AlreadyReported; } - const file = try std.fs.cwd().createFile(path_link, .{}); + const file = std.fs.cwd().createFile(path_link, .{}) catch |err| switch (err) { + error.IsDir => { + std.debug.print( + "unable to create the exe link, the path '{s}' is a directory\n", + .{ path_link}, + ); + std.os.exit(1); + }, + else => |e| return e, + }; defer file.close(); try file.writer().writeAll(win32exelink.content[0..win32exelink.exe_offset]); try file.writer().writeAll(link_target);