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
14 changes: 5 additions & 9 deletions src/cli/bundle.zig
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const [
if (std.mem.eql(u8, sub, "install")) return cmdInstall(ctx, allocator, rest);
if (std.mem.eql(u8, sub, "cleanup")) return cmdCleanup(ctx, allocator, rest);
if (std.mem.eql(u8, sub, "create")) return cmdCreate(ctx, allocator, rest);
if (std.mem.eql(u8, sub, "list")) return cmdList(ctx, allocator);
if (std.mem.eql(u8, sub, "remove")) return cmdRemove(ctx, allocator, rest);
if (std.mem.eql(u8, sub, "list")) return cmdList(ctx);
if (std.mem.eql(u8, sub, "remove")) return cmdRemove(ctx, rest);
if (std.mem.eql(u8, sub, "export")) return cmdExport(ctx, allocator, rest);
if (std.mem.eql(u8, sub, "import")) return cmdImport(ctx, allocator, rest);

Expand Down Expand Up @@ -279,8 +279,7 @@ fn cmdCleanup(ctx: *const AppCtx, allocator: std.mem.Allocator, rest: []const []
output.success("bundle cleanup complete", .{});
}

fn cmdList(ctx: *const AppCtx, allocator: std.mem.Allocator) !void {
_ = allocator;
fn cmdList(ctx: *const AppCtx) !void {
var db = try openDb(ctx);
defer db.close();

Expand All @@ -298,8 +297,7 @@ fn cmdList(ctx: *const AppCtx, allocator: std.mem.Allocator) !void {
if (!any) output.info("no bundles registered", .{});
}

fn cmdRemove(ctx: *const AppCtx, allocator: std.mem.Allocator, rest: []const []const u8) !void {
_ = allocator;
fn cmdRemove(ctx: *const AppCtx, rest: []const []const u8) !void {
if (rest.len != 1) {
output.err("bundle remove: expected <name>", .{});
return BundleError.InvalidArgs;
Expand Down Expand Up @@ -337,7 +335,7 @@ fn cmdCreate(ctx: *const AppCtx, allocator: std.mem.Allocator, rest: []const []c
var manifest = manifest_mod.Manifest.init(allocator);
defer manifest.deinit();
try populateFromInstalled(&manifest, &db);
try writeManifest(ctx, allocator, manifest, out_path, format);
try writeManifest(ctx, manifest, out_path, format);
output.success("wrote {s}", .{out_path});
}

Expand Down Expand Up @@ -469,12 +467,10 @@ fn readManifest(

fn writeManifest(
ctx: *const AppCtx,
allocator: std.mem.Allocator,
manifest: manifest_mod.Manifest,
path: []const u8,
format: Format,
) !void {
_ = allocator;
const file = if (std.fs.path.isAbsolute(path))
std.Io.Dir.createFileAbsolute(ctx.io, path, .{ .truncate = true }) catch return BundleError.WriteFailed
else
Expand Down
3 changes: 1 addition & 2 deletions src/cli/completions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ pub fn scriptFor(shell: Shell) []const u8 {
};
}

pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const []const u8) !void {
_ = allocator;
pub fn execute(ctx: *const AppCtx, args: []const []const u8) !void {
if (help.showIfRequested(ctx, args, "completions")) return;

if (args.len == 0) {
Expand Down
4 changes: 1 addition & 3 deletions src/cli/doctor.zig
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ fn checkLocalSources(ctx: CheckCtx, name: []const u8) CheckResult {
};
defer db.close();

const missing = countMissingLocalSources(ctx.io, ctx.allocator, &db);
const missing = countMissingLocalSources(ctx.io, &db);
if (missing.total == 0 or missing.stale == 0) {
printCheck(name, .ok, null);
return .ok;
Expand Down Expand Up @@ -655,10 +655,8 @@ pub const LocalSourceCensus = struct {
/// reported by the separate SQLite-integrity check above.
pub fn countMissingLocalSources(
io: std.Io,
allocator: std.mem.Allocator,
db: *sqlite.Database,
) LocalSourceCensus {
_ = allocator;
var census: LocalSourceCensus = .{ .total = 0, .stale = 0 };
var stmt = db.prepare("SELECT full_name FROM kegs WHERE tap = 'local';") catch return census;
defer stmt.finalize();
Expand Down
33 changes: 8 additions & 25 deletions src/cli/info.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const [
if (db_opt) |*db| {
// Schema is idempotent; info's API fallback handles a broken DB gracefully.
schema.initSchema(db) catch {};
if (!force_cask and try emitInstalledFormula(allocator, db, name, prefix, stdout, json_mode, colorize)) return;
if (!force_formula and try emitInstalledCask(allocator, db, name, stdout, json_mode, colorize)) return;
if (!force_cask and try emitInstalledFormula(db, name, prefix, stdout, json_mode, colorize)) return;
if (!force_formula and try emitInstalledCask(db, name, stdout, json_mode, colorize)) return;
}

// Not locally installed — fall back to Homebrew API metadata so
Expand All @@ -75,14 +75,13 @@ pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const [
// missed or the DB was absent entirely.
if (try emitApiMetadata(ctx, allocator, name, stdout, json_mode, colorize, force_cask, force_formula)) return;

try emitNotFound(allocator, name, stdout, json_mode);
try emitNotFound(name, stdout, json_mode);
}

/// If `name` is an installed formula, write its info row and return
/// true (caller stops). Returns false when the lookup misses so the
/// caller can try the cask path.
fn emitInstalledFormula(
allocator: std.mem.Allocator,
db: *sqlite.Database,
name: []const u8,
prefix: []const u8,
Expand All @@ -100,7 +99,7 @@ fn emitInstalledFormula(
if (!installed) return false;

if (json_mode) {
try writeJsonInfo(allocator, db, name, true, &stmt, stdout);
try writeJsonInfo(name, true, &stmt, stdout);
} else {
try writeHumanInfo(name, true, &stmt, prefix, stdout, colorize);
}
Expand All @@ -109,7 +108,6 @@ fn emitInstalledFormula(

/// Cask counterpart to `emitInstalledFormula`.
fn emitInstalledCask(
allocator: std.mem.Allocator,
db: *sqlite.Database,
name: []const u8,
stdout: *std.Io.Writer,
Expand All @@ -118,7 +116,7 @@ fn emitInstalledCask(
) !bool {
if (cask_mod.lookupInstalled(db, name) == null) return false;
if (json_mode) {
try writeJsonCaskInfo(allocator, db, name, stdout);
try writeJsonCaskInfo(db, name, stdout);
} else {
try writeHumanCaskInfo(db, name, stdout, colorize);
}
Expand All @@ -128,13 +126,12 @@ fn emitInstalledCask(
/// Terminal output for a package the user asked about that is
/// neither installed locally nor known to the Homebrew API.
fn emitNotFound(
allocator: std.mem.Allocator,
name: []const u8,
stdout: *std.Io.Writer,
json_mode: bool,
) !void {
if (json_mode) {
try writeJsonNotInstalled(allocator, name, stdout);
try writeJsonNotInstalled(name, stdout);
return;
}
var buf: [4096]u8 = undefined;
Expand Down Expand Up @@ -187,7 +184,7 @@ fn emitApiFormula(
var f = formula_mod.parseFormula(allocator, body) catch return false;
defer f.deinit();

if (json_mode) try writeApiFormulaJson(allocator, &f, stdout) else try writeApiFormulaHuman(&f, stdout, colorize);
if (json_mode) try writeApiFormulaJson(&f, stdout) else try writeApiFormulaHuman(&f, stdout, colorize);
return true;
}

Expand All @@ -205,7 +202,7 @@ fn emitApiCask(
var c = cask_mod.parseCask(allocator, body) catch return false;
defer c.deinit();

if (json_mode) try writeApiCaskJson(allocator, &c, stdout) else try writeApiCaskHuman(&c, stdout, colorize);
if (json_mode) try writeApiCaskJson(&c, stdout) else try writeApiCaskHuman(&c, stdout, colorize);
return true;
}

Expand All @@ -220,20 +217,16 @@ fn writeApiCaskHuman(c: *const cask_mod.Cask, stdout: *std.Io.Writer, colorize:
}

fn writeApiFormulaJson(
allocator: std.mem.Allocator,
f: *const formula_mod.Formula,
stdout: *std.Io.Writer,
) !void {
_ = allocator;
try encodeApiFormulaJson(stdout, f);
}

fn writeApiCaskJson(
allocator: std.mem.Allocator,
c: *const cask_mod.Cask,
stdout: *std.Io.Writer,
) !void {
_ = allocator;
try encodeApiCaskJson(stdout, c);
}

Expand Down Expand Up @@ -402,11 +395,9 @@ pub fn openDb(prefix: []const u8) ?sqlite.Database {
/// sqlite statement — used when the DB is missing or the package has
/// simply never been installed.
fn writeJsonNotInstalled(
allocator: std.mem.Allocator,
name: []const u8,
stdout: *std.Io.Writer,
) !void {
_ = allocator;
try stdout.writeAll("{\"name\":");
try output.jsonStr(stdout, name);
try stdout.writeAll(",\"type\":\"formula\",\"installed\":false}\n");
Expand Down Expand Up @@ -450,16 +441,11 @@ fn writeHumanInfo(
}

fn writeJsonInfo(
allocator: std.mem.Allocator,
db: *sqlite.Database,
name: []const u8,
installed: bool,
stmt: *sqlite.Statement,
stdout: *std.Io.Writer,
) !void {
_ = db;
_ = allocator;

try stdout.writeAll("{\"name\":");
try output.jsonStr(stdout, name);
try stdout.writeAll(",\"type\":\"formula\",\"installed\":");
Expand Down Expand Up @@ -520,7 +506,6 @@ fn writeHumanCaskInfo(
}

fn writeJsonCaskInfo(
allocator: std.mem.Allocator,
db: *sqlite.Database,
name: []const u8,
stdout: *std.Io.Writer,
Expand All @@ -534,8 +519,6 @@ fn writeJsonCaskInfo(
const found = stmt.step() catch false;
if (!found) return;

_ = allocator;

const token = if (stmt.columnText(0)) |t| std.mem.sliceTo(t, 0) else name;
const cask_name = if (stmt.columnText(1)) |n| std.mem.sliceTo(n, 0) else name;
const ver = if (stmt.columnText(2)) |v| std.mem.sliceTo(v, 0) else "";
Expand Down
28 changes: 14 additions & 14 deletions src/cli/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ fn executeWithOpts(
output.info("{s} is already installed", .{pkg});
// Fast-path skips the protocol; positive signal so consumers
// can tell idempotent success from "command never ran".
output.emitNdjsonEvent(allocator, .already_installed, pkg, null);
output.emitNdjsonEvent(.already_installed, pkg, null);
}
return;
}
Expand Down Expand Up @@ -339,12 +339,12 @@ fn executeWithOpts(
output.err("Another mt process is running. Wait or run mt doctor.", .{});
return InstallError.LockError;
};
output.emitNdjsonEvent(allocator, .lock_acquired, "", null);
output.emitNdjsonEvent(.lock_acquired, "", null);
}
defer if (lk) |*l| l.release();
// LIFO: install_complete must precede release in the deferred chain,
// and the outer holder owns the matching pair when we skipped here.
defer if (lk != null and output.isNdjson()) output.emitNdjsonEvent(allocator, .install_complete, "", null);
defer if (lk != null and output.isNdjson()) output.emitNdjsonEvent(.install_complete, "", null);

// Main-thread HTTP client; workers borrow from `http_pool` instead.
var http = client_mod.HttpClient.init(ctx.io, ctx.environ, allocator);
Expand Down Expand Up @@ -449,7 +449,7 @@ fn executeWithOpts(
output.err("Failed to resolve {s}: {s}", .{ pkg_name, @errorName(e) });
continue;
};
output.emitNdjsonEvent(allocator, .resolved, pkg_name, null);
output.emitNdjsonEvent(.resolved, pkg_name, null);
} else {
installCask(ctx, allocator, pkg_name, &db, &api, dry_run) catch |e| {
output.err("Failed to install {s}: {s}", .{ pkg_name, @errorName(e) });
Expand All @@ -470,7 +470,7 @@ fn executeWithOpts(
const tag: []const u8 = if (job.is_dep) " (dependency)" else "";
output.info(" {s} {s}{s}", .{ job.name, job.version_str, tag });
// No transition outcome to report on a plan-only run.
output.emitNdjsonEvent(allocator, .would_install, job.name, null);
output.emitNdjsonEvent(.would_install, job.name, null);
}
return;
}
Expand Down Expand Up @@ -586,9 +586,9 @@ fn executeWithOpts(
if (output.isNdjson()) {
for (all_jobs.items) |job| {
if (!job.succeeded) continue;
output.emitNdjsonEvent(allocator, .downloaded, job.name, "ok");
output.emitNdjsonEvent(allocator, .extracted, job.name, "ok");
output.emitNdjsonEvent(allocator, .stored, job.name, "ok");
output.emitNdjsonEvent(.downloaded, job.name, "ok");
output.emitNdjsonEvent(.extracted, job.name, "ok");
output.emitNdjsonEvent(.stored, job.name, "ok");
}
}

Expand Down Expand Up @@ -677,12 +677,12 @@ fn executeWithOpts(
"Failed to materialize {s}: {s} ({s})",
.{ job.name, @errorName(err), cellar_mod.describeError(err) },
);
output.emitNdjsonEvent(allocator, .materialized, job.name, "failed");
output.emitNdjsonEvent(.materialized, job.name, "failed");
try failed_kegs.put(job.name, {});
failed_count += 1;
continue;
}
output.emitNdjsonEvent(allocator, .materialized, job.name, "ok");
output.emitNdjsonEvent(.materialized, job.name, "ok");

// Failed-dep → skip: installing on a broken graph yields a dyld-unresolvable
// keg. Remove the already-materialised keg so orphans don't linger.
Expand Down Expand Up @@ -770,7 +770,7 @@ fn linkAndRecord(

linker.link(keg_path, job.name, keg_id) catch |err| {
output.err("Failed to link {s}: {s}", .{ job.name, @errorName(err) });
output.emitNdjsonEvent(allocator, .linked, job.name, "failed");
output.emitNdjsonEvent(.linked, job.name, "failed");
// Rollback: unlink what was partially created + remove DB record + cellar.
linker.unlink(keg_id) catch {};
deleteKeg(db, keg_id);
Expand All @@ -779,8 +779,8 @@ fn linkAndRecord(
};
// `recorded` after both succeed — link rollback undoes the keg
// row, so an early emit would lie if `linked:failed` follows.
output.emitNdjsonEvent(allocator, .linked, job.name, "ok");
output.emitNdjsonEvent(allocator, .recorded, job.name, "ok");
output.emitNdjsonEvent(.linked, job.name, "ok");
output.emitNdjsonEvent(.recorded, job.name, "ok");
linker.linkOpt(job.name, job.version_str) catch {};
recordDeps(db, keg_id, formula);
} else {
Expand All @@ -790,7 +790,7 @@ fn linkAndRecord(
return InstallError.RecordFailed;
};
// keg-only has no public link phase to roll back.
output.emitNdjsonEvent(allocator, .recorded, job.name, "ok");
output.emitNdjsonEvent(.recorded, job.name, "ok");
linker.linkOpt(job.name, job.version_str) catch {};
recordDeps(db, keg_id, formula);
}
Expand Down
4 changes: 2 additions & 2 deletions src/cli/install/download.zig
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ pub fn collectFormulaJobs(
defer if (!dep_json_consumed) allocator.free(dep_json);

const dep_formula = cache.getOrParse(dep.name, dep_json) catch continue;
const dep_bottle = formula_mod.resolveBottle(allocator, dep_formula) catch continue;
const dep_bottle = formula_mod.resolveBottle(dep_formula) catch continue;

// Check for duplicate (another top-level pkg may share a dep)
var is_dup = false;
Expand Down Expand Up @@ -468,7 +468,7 @@ pub fn collectFormulaJobs(
}

// Add main formula
const bottle = formula_mod.resolveBottle(allocator, formula) catch {
const bottle = formula_mod.resolveBottle(formula) catch {
output.err("No bottle available for {s} on this platform", .{formula.name});
return InstallError.NoBottle;
};
Expand Down
6 changes: 2 additions & 4 deletions src/cli/list.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const output = @import("../ui/output.zig");
const color = @import("../ui/color.zig");
const help = @import("help.zig");

pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const []const u8) !void {
pub fn execute(ctx: *const AppCtx, args: []const []const u8) !void {
if (help.showIfRequested(ctx, args, "list")) return;

// Parse per-command flags. `--json`, `--quiet`/`-q`, `--verbose`/`-v`,
Expand Down Expand Up @@ -59,7 +59,7 @@ pub fn execute(ctx: *const AppCtx, allocator: std.mem.Allocator, args: []const [
defer stdout.flush() catch {};

if (json_mode) {
try writeJsonOutput(ctx, allocator, &db, show_formula, show_cask, show_pinned, stdout);
try writeJsonOutput(ctx, &db, show_formula, show_cask, show_pinned, stdout);
} else {
try writeHumanOutput(&db, show_formula, show_cask, show_versions, show_pinned, stdout);
}
Expand Down Expand Up @@ -229,14 +229,12 @@ fn writeStyledSpan(

fn writeJsonOutput(
ctx: *const AppCtx,
allocator: std.mem.Allocator,
db: *sqlite.Database,
show_formula: bool,
show_cask: bool,
show_pinned: bool,
stdout: *std.Io.Writer,
) !void {
_ = allocator;
const start_ts = std.Io.Clock.real.now(ctx.io).toMilliseconds();
try buildListJson(db, stdout, show_formula, show_cask, show_pinned, start_ts);
}
Expand Down
Loading
Loading