feat: zupper tracks what version is in use
This commit is contained in:
parent
22c39a6712
commit
aef6ee81aa
2
gyro.zzz
2
gyro.zzz
|
@ -1,6 +1,6 @@
|
|||
pkgs:
|
||||
zupper:
|
||||
version: 0.1.0
|
||||
version: 0.2.0
|
||||
description: Zig version manager
|
||||
license: GPL-3.0
|
||||
source_url: "https://mzte.de/git/LordMZTE/zupper"
|
||||
|
|
|
@ -4,6 +4,7 @@ const json = @import("json");
|
|||
const getty = @import("getty");
|
||||
|
||||
versions: std.StringHashMap(std.SemanticVersion),
|
||||
in_use: ?[]u8 = null,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
|
@ -91,6 +92,17 @@ pub fn removeVersion(self: *Self, version: []const u8) void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn setInUse(self: *Self, in_use: ?[]const u8) !void {
|
||||
if (self.in_use) |old| {
|
||||
self.versions.allocator.free(old);
|
||||
}
|
||||
|
||||
if (in_use) |v| {
|
||||
const dup = try self.versions.allocator.dupe(u8, v);
|
||||
self.in_use = dup;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(self: *Self) !void {
|
||||
const mpath = try path(self.versions.allocator);
|
||||
defer self.versions.allocator.free(mpath);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub const version = "0.1.0";
|
||||
pub const version = "0.2.0";
|
||||
|
||||
pub const Info = struct {};
|
||||
|
||||
|
@ -13,6 +13,7 @@ pub const Install = struct {
|
|||
};
|
||||
|
||||
pub const Uninstall = struct {};
|
||||
pub const Unuse = struct {};
|
||||
pub const Update = struct {};
|
||||
pub const Use = struct {};
|
||||
|
||||
|
@ -28,6 +29,7 @@ pub const Args = union(enum) {
|
|||
info: Info,
|
||||
install: Install,
|
||||
uninstall: Uninstall,
|
||||
unuse: Unuse,
|
||||
update: Update,
|
||||
use: Use,
|
||||
};
|
||||
|
@ -42,9 +44,10 @@ const help_s =
|
|||
\\Subcommands:
|
||||
\\ {[a0]s} info prints information about the setup
|
||||
\\ {[a0]s} install <VERSIONS...> [--use, -u] downloads the given zig versions and optionally uses them
|
||||
\\ {[a0]s} uninstall <VERSIONS...> uninstall the given versions
|
||||
\\ {[a0]s} unuse unuse the version currently in use (essentially a soft-uninstall)
|
||||
\\ {[a0]s} update [VERSIONS...] update the given version, or all versions if none are given
|
||||
\\ {[a0]s} use <VERSION> uses the given version by symlinking the compiler into $PATH
|
||||
\\ {[a0]s} uninstall <VERSIONS...> uninstall the given versions
|
||||
\\
|
||||
;
|
||||
|
||||
|
|
|
@ -69,6 +69,6 @@ pub fn run(
|
|||
}
|
||||
|
||||
if (args.use) {
|
||||
try dirs.useVersion(alloc, home, positionals[0]);
|
||||
try dirs.useVersion(alloc, manifest, home, positionals[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,5 +32,9 @@ pub fn run(
|
|||
std.log.info("deleting {s}", .{ver_path});
|
||||
manifest.removeVersion(version);
|
||||
try std.fs.cwd().deleteTree(ver_path);
|
||||
|
||||
if (manifest.in_use != null and std.mem.eql(u8, manifest.in_use.?, version)) {
|
||||
try dirs.unuseCurrentVersion(alloc, manifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
25
src/commands/unuse.zig
Normal file
25
src/commands/unuse.zig
Normal file
|
@ -0,0 +1,25 @@
|
|||
const std = @import("std");
|
||||
const dirs = @import("../dirs.zig");
|
||||
const Manifest = @import("../Manifest.zig");
|
||||
const Args = @import("../args.zig").Unuse;
|
||||
|
||||
pub fn run(
|
||||
alloc: std.mem.Allocator,
|
||||
manifest: *Manifest,
|
||||
args: Args,
|
||||
positionals: []const [:0]const u8,
|
||||
) !void {
|
||||
_ = args;
|
||||
|
||||
if (positionals.len != 0) {
|
||||
std.log.err("expected exactly 0 positional arguments", .{});
|
||||
return error.Explained;
|
||||
}
|
||||
|
||||
if (manifest.in_use == null) {
|
||||
std.log.err("no version currently in use!", .{});
|
||||
return error.Explained;
|
||||
}
|
||||
|
||||
try dirs.unuseCurrentVersion(alloc, manifest);
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
const std = @import("std");
|
||||
const dirs = @import("../dirs.zig");
|
||||
const Manifest = @import("../Manifest.zig");
|
||||
const Args = @import("../args.zig").Use;
|
||||
|
||||
pub fn run(
|
||||
alloc: std.mem.Allocator,
|
||||
manifest: *Manifest,
|
||||
args: Args,
|
||||
positionals: []const [:0]const u8,
|
||||
) !void {
|
||||
|
@ -22,5 +24,5 @@ pub fn run(
|
|||
return error.Explained;
|
||||
}
|
||||
|
||||
try dirs.useVersion(alloc, home, positionals[0]);
|
||||
try dirs.useVersion(alloc, manifest, home, positionals[0]);
|
||||
}
|
||||
|
|
106
src/dirs.zig
106
src/dirs.zig
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const kf = @import("known-folders");
|
||||
const Manifest = @import("Manifest.zig");
|
||||
|
||||
pub fn zupperHome(alloc: std.mem.Allocator) ![]const u8 {
|
||||
const datapath = (try kf.getPath(alloc, .data)) orelse return error.GetDataFolder;
|
||||
|
@ -21,9 +22,44 @@ pub fn isVersionInstalled(alloc: std.mem.Allocator, home: []const u8, version: [
|
|||
return true;
|
||||
}
|
||||
|
||||
pub fn useVersion(alloc: std.mem.Allocator, home: []const u8, version: []const u8) !void {
|
||||
pub fn binInstallationPath(alloc: std.mem.Allocator) !?[]u8 {
|
||||
switch (@import("builtin").os.tag) {
|
||||
.linux => {
|
||||
const user_home = (try kf.getPath(alloc, .home)) orelse return error.GetHomeDir;
|
||||
defer alloc.free(user_home);
|
||||
return try std.fs.path.join(alloc, &.{ user_home, ".local", "bin" });
|
||||
},
|
||||
.windows => {
|
||||
return try std.fs.selfExeDirPathAlloc(alloc);
|
||||
},
|
||||
.macos => {
|
||||
const user_home = (try kf.getPath(alloc, .home)) orelse return error.GetHomeDir;
|
||||
defer alloc.free(user_home);
|
||||
// not sure if this is the correct path. mac got kind of a windowsy situation too
|
||||
return try std.fs.path.join(alloc, &.{ user_home, "Applications" });
|
||||
},
|
||||
else => {
|
||||
return null;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn useVersion(
|
||||
alloc: std.mem.Allocator,
|
||||
manifest: *Manifest,
|
||||
home: []const u8,
|
||||
version: []const u8,
|
||||
) !void {
|
||||
if (manifest.in_use != null and std.mem.eql(u8, manifest.in_use.?, version)) {
|
||||
std.log.err("version '{s}' is already in use!", .{version});
|
||||
return error.Explained;
|
||||
}
|
||||
|
||||
if (!try isVersionInstalled(alloc, home, version)) {
|
||||
std.log.err("this version isn't installed! have you tried installing it first?", .{});
|
||||
std.log.err(
|
||||
"version '{s}' isn't installed! have you tried installing it first?",
|
||||
.{version},
|
||||
);
|
||||
return error.Explained;
|
||||
}
|
||||
|
||||
|
@ -45,36 +81,22 @@ pub fn useVersion(alloc: std.mem.Allocator, home: []const u8, version: []const u
|
|||
return error.Explained;
|
||||
};
|
||||
|
||||
const target_binary_directory = switch (@import("builtin").os.tag) {
|
||||
.linux => blk: {
|
||||
const user_home = (try kf.getPath(alloc, .home)) orelse return error.GetHomeDir;
|
||||
defer alloc.free(user_home);
|
||||
break :blk try std.fs.path.join(alloc, &.{ user_home, ".local", "bin" });
|
||||
},
|
||||
.windows => blk: {
|
||||
std.log.warn(
|
||||
\\installing on windows! windows is so bad, it can't get it's conventions
|
||||
\\for locally installed programs right. i'll use my own install directory...
|
||||
,
|
||||
.{},
|
||||
);
|
||||
if (@import("builtin").os.tag == .windows) {
|
||||
std.log.warn(
|
||||
\\installing on windows! windows is so bad, it can't get it's conventions
|
||||
\\for locally installed programs right. i'll use my own install directory...
|
||||
,
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
break :blk try std.fs.selfExeDirPathAlloc(alloc);
|
||||
},
|
||||
.macos => blk: {
|
||||
const user_home = (try kf.getPath(alloc, .home)) orelse return error.GetHomeDir;
|
||||
defer alloc.free(user_home);
|
||||
// not sure if this is the correct path. mac got kind of a windowsy situation too
|
||||
break :blk try std.fs.path.join(alloc, &.{ user_home, "Applications" });
|
||||
},
|
||||
else => {
|
||||
std.log.err(
|
||||
"using a version isn't supported on {s}. please install the zig binary @ '{s}' manually",
|
||||
.{ @tagName(@import("builtin").os.tag), zig_exe_path },
|
||||
);
|
||||
const target_binary_directory = try binInstallationPath(alloc) orelse {
|
||||
std.log.err(
|
||||
"using a version isn't supported on {s}. please install the zig binary @ '{s}' manually",
|
||||
.{ @tagName(@import("builtin").os.tag), zig_exe_path },
|
||||
);
|
||||
|
||||
return;
|
||||
},
|
||||
return;
|
||||
};
|
||||
defer alloc.free(target_binary_directory);
|
||||
|
||||
|
@ -92,4 +114,28 @@ pub fn useVersion(alloc: std.mem.Allocator, home: []const u8, version: []const u
|
|||
}
|
||||
};
|
||||
try std.fs.cwd().symLink(zig_exe_path, target_binary, .{});
|
||||
try manifest.setInUse(version);
|
||||
}
|
||||
|
||||
pub fn unuseCurrentVersion(
|
||||
alloc: std.mem.Allocator,
|
||||
manifest: *Manifest,
|
||||
) !void {
|
||||
const install_dir = try binInstallationPath(alloc) orelse return;
|
||||
defer alloc.free(install_dir);
|
||||
|
||||
const target_binary = try std.fs.path.join(alloc, &.{
|
||||
install_dir,
|
||||
comptime "zig" ++ @import("builtin").target.exeFileExt(),
|
||||
});
|
||||
defer alloc.free(target_binary);
|
||||
|
||||
std.log.info("unusing zig installation @ {s}", .{target_binary});
|
||||
try std.fs.cwd().deleteFile(target_binary);
|
||||
|
||||
if (manifest.in_use) |old| {
|
||||
manifest.versions.allocator.free(old);
|
||||
}
|
||||
|
||||
manifest.in_use = null;
|
||||
}
|
||||
|
|
29
src/main.zig
29
src/main.zig
|
@ -38,42 +38,29 @@ fn runCmd(alloc: std.mem.Allocator, opts: anytype) !void {
|
|||
try args.printHelp(alloc);
|
||||
return error.Explained;
|
||||
};
|
||||
var manifest = try Manifest.load(alloc);
|
||||
defer manifest.deinit();
|
||||
|
||||
switch (verb) {
|
||||
.info => |a| {
|
||||
var manifest = try Manifest.load(alloc);
|
||||
defer manifest.deinit();
|
||||
|
||||
try @import("commands/info.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
|
||||
try manifest.save();
|
||||
},
|
||||
.install => |a| {
|
||||
var manifest = try Manifest.load(alloc);
|
||||
defer manifest.deinit();
|
||||
|
||||
try @import("commands/install.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
|
||||
try manifest.save();
|
||||
},
|
||||
.update => |a| {
|
||||
var manifest = try Manifest.load(alloc);
|
||||
defer manifest.deinit();
|
||||
|
||||
try @import("commands/update.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
|
||||
try manifest.save();
|
||||
},
|
||||
.use => |a| {
|
||||
try @import("commands/use.zig").run(alloc, a, opts.positionals);
|
||||
try @import("commands/use.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
},
|
||||
.uninstall => |a| {
|
||||
var manifest = try Manifest.load(alloc);
|
||||
defer manifest.deinit();
|
||||
|
||||
try @import("commands/uninstall.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
|
||||
try manifest.save();
|
||||
},
|
||||
.unuse => |a| {
|
||||
try @import("commands/unuse.zig").run(alloc, &manifest, a, opts.positionals);
|
||||
},
|
||||
}
|
||||
|
||||
try manifest.save();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue