Compare commits

...

4 commits

5 changed files with 136 additions and 43 deletions

View file

@ -11,10 +11,19 @@ var dryCmd = &cobra.Command{
Short: "poor man's nix flake check", Short: "poor man's nix flake check",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
oizys.CheckFlake(flake) oizys.CheckFlake(flake)
oizys.NixDryRun(flake, host) oizys.NixDryRun(flake, host, verbose)
}, },
} }
var verbose bool
func init() { func init() {
rootCmd.AddCommand(dryCmd) rootCmd.AddCommand(dryCmd)
dryCmd.Flags().BoolVarP(
&verbose,
"verbose",
"v",
false,
"show verbose output",
)
} }

View file

@ -29,11 +29,12 @@ func TerminalSize() (int, int) {
return w, h return w, h
} }
func ParseDryRunOutput(nixOutput string) { func ParseDryRunOutput(nixOutput string, verbose bool) {
output := termenv.NewOutput(os.Stdout) output := termenv.NewOutput(os.Stdout)
parts := strings.Split(nixOutput, "\nthese") parts := strings.Split(nixOutput, "\nthese")
if len(parts) != 3 { if len(parts) != 3 {
log.Println("no changes...") log.Println("no changes...")
log.Println(output)
return return
} }
built := strings.Split(strings.TrimSpace(parts[1]), "\n")[1:] built := strings.Split(strings.TrimSpace(parts[1]), "\n")[1:]
@ -58,15 +59,18 @@ func ParseDryRunOutput(nixOutput string) {
rows = append(rows, table.Row{hash, name}) rows = append(rows, table.Row{hash, name})
} }
w, _ := TerminalSize() if verbose {
columns := []table.Column{
{Title: "hash", Width: 34}, w, _ := TerminalSize()
{Title: "pkg", Width: int(w / 4)}, columns := []table.Column{
{Title: "hash", Width: 34},
{Title: "pkg", Width: int(w / 4)},
}
ShowTable(columns, rows)
} }
ShowTable(columns, rows)
} }
func NixDryRun(flake string, host string) { func NixDryRun(flake string, host string, verbose bool) {
output := termenv.NewOutput(os.Stdout) output := termenv.NewOutput(os.Stdout)
path := Output(flake, host) path := Output(flake, host)
cmd := exec.Command("nix", "build", path, "--dry-run") cmd := exec.Command("nix", "build", path, "--dry-run")
@ -85,7 +89,7 @@ func NixDryRun(flake string, host string) {
fmt.Println(string(result)) fmt.Println(string(result))
log.Fatal(err) log.Fatal(err)
} }
ParseDryRunOutput(string(result)) ParseDryRunOutput(string(result), verbose)
} }
func NixosRebuild(subcmd string, flake string, rest ...string) { func NixosRebuild(subcmd string, flake string, rest ...string) {

View file

@ -34,7 +34,6 @@ pub fn init(allocator: Allocator) !Cli {
try subcmd.addArg(Arg.positional("forward", null, null)); try subcmd.addArg(Arg.positional("forward", null, null));
try subcmd.addArg(Arg.singleValueOption("flake", 'f', "path to flake")); try subcmd.addArg(Arg.singleValueOption("flake", 'f', "path to flake"));
try subcmd.addArg(Arg.singleValueOption("host", null, "hostname (default: current host)")); try subcmd.addArg(Arg.singleValueOption("host", null, "hostname (default: current host)"));
try subcmd.addArg(Arg.booleanOption("no-pinix", null, "don't use pinix"));
try oizys.addSubcommand(subcmd.*); try oizys.addSubcommand(subcmd.*);
} }

View file

@ -9,7 +9,6 @@ host: []const u8,
cache_name: []const u8, cache_name: []const u8,
output: []const u8, output: []const u8,
cmd: OizysCmd, cmd: OizysCmd,
no_pinix: bool,
debug: bool = false, debug: bool = false,
forward: ?[][]const u8, forward: ?[][]const u8,
@ -25,39 +24,52 @@ pub const OizysCmd = enum {
pub fn init(allocator: std.mem.Allocator, matches: *const ArgMatches, forward: ?[][]const u8) !Oizys { pub fn init(allocator: std.mem.Allocator, matches: *const ArgMatches, forward: ?[][]const u8) !Oizys {
const cmd = matches.subcommand.?.name; const cmd = matches.subcommand.?.name;
const flags = matches.subcommandMatches(cmd).?; const flags = matches.subcommandMatches(cmd).?;
const host = flags.getSingleValue("host") orelse var oizys = Oizys{
try Oizys.getDefaultHostName(allocator);
const flake = flags.getSingleValue("flake") orelse
try Oizys.getDefaultFlake(allocator);
return Oizys{
.allocator = allocator, .allocator = allocator,
.host = host, .host = undefined,
.flake = flake, .flake = undefined,
.output = try std.fmt.allocPrint( .output = undefined,
allocator,
"{s}#nixosConfigurations.{s}.config.system.build.toplevel",
.{ flake, host },
),
.cmd = std.meta.stringToEnum(OizysCmd, cmd).?, .cmd = std.meta.stringToEnum(OizysCmd, cmd).?,
.cache_name = flags.getSingleValue("cache") orelse "daylin", .cache_name = flags.getSingleValue("cache") orelse "daylin",
.no_pinix = flags.containsArg("no-pinix"),
.forward = forward, .forward = forward,
}; };
if (flags.getSingleValue("host")) |host| {
oizys.host = try allocator.dupe(u8, host);
} else {
oizys.host = try Oizys.getDefaultHostName(allocator);
}
if (flags.getSingleValue("flake")) |flake| {
oizys.flake = try allocator.dupe(u8, flake);
} else {
oizys.flake = try Oizys.getDefaultFlake(allocator);
}
oizys.output = try std.fmt.allocPrint(
allocator,
"{s}#nixosConfigurations.{s}.config.system.build.toplevel",
.{ oizys.flake, oizys.host },
);
return oizys;
// return Oizys{
// .allocator = allocator,
// .host = host,
// .flake = flake,
// .output = try std.fmt.allocPrint(
// allocator,
// "{s}#nixosConfigurations.{s}.config.system.build.toplevel",
// .{ flake, host },
// ),
// .cmd = std.meta.stringToEnum(OizysCmd, cmd).?,
// .cache_name = flags.getSingleValue("cache") orelse "daylin",
// .forward = forward,
// };
} }
pub fn deinit(self: *Oizys) void { pub fn deinit(self: *Oizys) void {
self.allocator.free(self.flake); self.allocator.free(self.flake);
self.allocator.free(self.host);
self.allocator.free(self.output); self.allocator.free(self.output);
} self.allocator.free(self.host);
pub fn nix(self: *Oizys) []const u8 {
return if (self.no_pinix) "nix" else "pix";
}
pub fn nixos_rebuild(self: *Oizys) []const u8 {
return if (self.no_pinix) "nixos-rebuild" else "pixos-rebuild";
} }
pub fn getDefaultHostName(allocator: Allocator) ![]const u8 { pub fn getDefaultHostName(allocator: Allocator) ![]const u8 {
@ -89,8 +101,8 @@ pub fn runNixCmd(self: *Oizys, cmd: NixCmd, argv: []const []const u8) !void {
defer args.deinit(); defer args.deinit();
switch (cmd) { switch (cmd) {
NixCmd.Nix => try args.append(self.nix()), NixCmd.Nix => try args.append("nix"),
NixCmd.NixosRebuild => try args.appendSlice(&.{ "sudo", self.nixos_rebuild() }), NixCmd.NixosRebuild => try args.appendSlice(&.{ "sudo", "nixos-rebuild" }),
} }
try args.appendSlice(argv); try args.appendSlice(argv);
if (self.forward) |fwd| try args.appendSlice(fwd); if (self.forward) |fwd| try args.appendSlice(fwd);
@ -117,12 +129,77 @@ pub fn cache(self: *Oizys) !void {
_ = try p.spawnAndWait(); _ = try p.spawnAndWait();
} }
const DryResult = struct {
allocator: Allocator,
fetch: [][]const u8,
build: [][]const u8,
pub fn parse(allocator: Allocator, output: []const u8) !DryResult {
var it = std.mem.splitSequence(u8, output, ":\n");
_ = it.next();
var fetch = std.ArrayList([]const u8).init(allocator);
var build = std.ArrayList([]const u8).init(allocator);
if (it.next()) |x| {
try parseLines(x, &fetch);
} else {
return error.DryParseError;
}
if (it.next()) |x| {
try parseLines(x, &build);
} else {
return error.DryParseError;
}
return .{
.allocator = allocator,
.fetch = try fetch.toOwnedSlice(),
.build = try build.toOwnedSlice(),
};
}
pub fn deinit(self: *DryResult) void {
self.allocator.free(self.fetch);
self.allocator.free(self.build);
// for (self.fetch) |item| {
// self.allocator.free(item);
// }
// for (self.build) |item| {
// self.allocator.free(item);
// }
}
fn parseLines(buffer: []const u8, list: *std.ArrayList([]const u8)) !void {
var lines = std.mem.splitSequence(u8, buffer, "\n");
while (lines.next()) |line| {
try list.append(line);
}
}
};
pub fn dry(self: *Oizys) !void {
const cmd_output = try std.ChildProcess.run(.{
.allocator = self.allocator,
.argv = &.{ "nix", "build", self.output, "--dry-run" },
});
defer self.allocator.free(cmd_output.stdout);
defer self.allocator.free(cmd_output.stderr);
var result = try DryResult.parse(self.allocator, cmd_output.stderr);
defer result.deinit();
std.debug.print(
"to fetch: {d}\nto build: {d}\n",
.{ result.fetch.len, result.build.len },
);
}
pub fn run(self: *Oizys) !void { pub fn run(self: *Oizys) !void {
switch (self.cmd) { switch (self.cmd) {
.@"switch" => try self.runNixCmd(NixCmd.NixosRebuild, &.{ "switch", "--flake", self.flake }), .@"switch" => try self.runNixCmd(.NixosRebuild, &.{ "switch", "--flake", self.flake }),
.boot => try self.runNixCmd(NixCmd.NixosRebuild, &.{ "boot", "--flake", self.flake }),
.dry => try self.runNixCmd(NixCmd.Nix, &.{ "build", self.output, "--dry-run" }), .boot => try self.runNixCmd(.NixosRebuild, &.{ "boot", "--flake", self.flake }),
.build => try self.runNixCmd(NixCmd.Nix, &.{ "build", self.output }), .dry => try self.dry(),
.build => try self.runNixCmd(.Nix, &.{ "build", self.output }),
.output => { .output => {
const stdout = std.io.getStdOut().writer(); const stdout = std.io.getStdOut().writer();
try stdout.print("{s}\n", .{self.output}); try stdout.print("{s}\n", .{self.output});

View file

@ -4,9 +4,13 @@ const Cli = @import("Cli.zig");
pub fn main() !void { pub fn main() !void {
// memory management isn't hard :P // memory management isn't hard :P
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); // var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit(); // defer arena.deinit();
const allocator = arena.allocator(); // const allocator = arena.allocator();
//
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
var cli = try Cli.init(allocator); var cli = try Cli.init(allocator);
try cli.parse(); try cli.parse();