Skip to content

refactor(bin): rename binary to zfetch and modularize#72

Merged
jiacai2050 merged 4 commits intomainfrom
refactor-zfetch
Mar 18, 2026
Merged

refactor(bin): rename binary to zfetch and modularize#72
jiacai2050 merged 4 commits intomainfrom
refactor-zfetch

Conversation

@jiacai2050
Copy link
Owner

Refactor monolithic implementation into a modular architecture with OS-specific modules (Linux, macOS, FreeBSD). Add JSON output support. Rename binary to zfetch to reflect its Zig origin.

Refactor monolithic implementation into a modular architecture with OS-specific modules (Linux, macOS, FreeBSD). Add JSON output support. Rename binary to zfetch to reflect its Zig origin.
Copilot AI review requested due to automatic review settings March 18, 2026 01:43
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the system information fetching tool by modularizing its codebase and expanding its platform compatibility. The changes aim to improve maintainability, facilitate future development, and provide more flexible output options for users. The core functionality remains the same, but the underlying structure is now more robust and extensible.

Highlights

  • Binary Renaming: The system information fetcher binary has been renamed from fastfetch to zfetch to better reflect its Zig origin.
  • Modular Architecture: The monolithic implementation has been refactored into a modular architecture, separating common utilities from OS-specific implementations for Linux, macOS, and FreeBSD.
  • FreeBSD Support: New platform-specific modules have been added to introduce full support for FreeBSD.
  • JSON Output Support: The zfetch tool now includes an option to output system information in JSON format, enhancing its utility for scripting and integration.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant and well-executed refactoring of the fastfetch binary into the newly named zfetch. The modular architecture with OS-specific implementations for Linux, macOS, and now FreeBSD is a major improvement for maintainability and extensibility. The addition of JSON output is also a valuable feature. While the overall changes are excellent, I've identified a few issues, including a critical bug in package counting on FreeBSD, a high-severity bug in package counting on macOS, and a potential crash in disk usage calculation. I've also provided suggestions to improve performance and code clarity.

Comment on lines +510 to +535
var dir = fs.openDirAbsolute(
"/var/db/pkg/local.sqlite",
.{},
) catch {
// Fallback: count directories in /var/db/pkg.
var pkg_dir = fs.openDirAbsolute(
"/var/db/pkg",
.{ .iterate = true },
) catch return "Unknown";
defer pkg_dir.close();
var count: u32 = 0;
var iter = pkg_dir.iterate();
while (try iter.next()) |entry| {
if (entry.kind == .directory) count += 1;
}
if (count > 0) {
return fmt.allocPrint(
allocator,
"{d} (pkg)",
.{count},
);
}
return "Unknown";
};
defer dir.close();
return "Unknown";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The implementation of getPackagesPkg for FreeBSD appears to be incorrect. It attempts to use fs.openDirAbsolute on a file path (/var/db/pkg/local.sqlite), which will fail. If it were to succeed (e.g., if the path was a directory), the function would incorrectly return "Unknown" without processing it. The logic for handling the SQLite database is missing.

This should be refactored to either correctly implement the SQLite database query or be simplified to only contain the fallback logic if the primary implementation is not ready.

    // TODO: Implement sqlite query for /var/db/pkg/local.sqlite
    // For now, using fallback to count directories in /var/db/pkg.
    var pkg_dir = fs.openDirAbsolute(
        "/var/db/pkg",
        .{ .iterate = true },
    ) catch return "Unknown";
    defer pkg_dir.close();
    var count: u32 = 0;
    var iter = pkg_dir.iterate();
    while (try iter.next()) |entry| {
        if (entry.kind == .directory) count += 1;
    }
    if (count > 0) {
        return fmt.allocPrint(
            allocator,
            "{d} (pkg)",
            .{count},
        );
    }
    return "Unknown";

}
}
if (dup) continue;
assert(seen_count < seen_dev.len);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using assert here could cause the program to crash in debug builds if more than 8 mount points with unique device IDs are processed. It's safer to handle this case gracefully with a runtime check, for example by skipping devices that would overflow the seen_dev array.

        if (seen_count >= seen_dev.len) continue;

.{count},
);
}
break; // Only use the first found path.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The break statement here is causing a bug in package counting. If Homebrew is installed at /opt/homebrew/Cellar but contains no packages, the loop will break and will not check the alternative path /usr/local/Cellar. This will result in an incorrect package count of zero. The break should be removed to ensure all potential Homebrew installation paths are checked.

build.zig Outdated
Comment on lines 253 to 255
if (target_os != .macos and target_os != .linux and target_os != .freebsd) {
return null;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This condition check for supported operating systems can be made more concise and readable by using a switch statement. This is generally preferred in Zig for matching against multiple enum values.

        switch (target_os) {
            .macos, .linux, .freebsd => {},
            else => return null,
        }

Comment on lines +161 to +166
const formatted = try fmt.allocPrint(
allocator,
"{f}",
.{std.json.fmt(info, .{})},
);
try writer.writeAll(formatted);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for JSON output allocates a string for the entire JSON object before writing it to stdout. This can be inefficient, especially if the system information becomes more detailed in the future. It's better to stream the JSON output directly to the writer to avoid the intermediate allocation.

        try std.json.stringify(info, .{}, writer);

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the former fastfetch binary into a new zfetch binary with a shared common module and per-OS backends, and introduces a --format=json output mode.

Changes:

  • Renames the binary from fastfetch to zfetch and updates the build to compile/link it on macOS/Linux/FreeBSD only.
  • Splits platform-specific logic into src/bin/zfetch/{linux,macos,freebsd}.zig with shared helpers in src/bin/zfetch/common.zig.
  • Updates documentation to reflect the renamed program and new sample output.

Reviewed changes

Copilot reviewed 2 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/bin/zfetch.zig New entrypoint: argument parsing, info collection, text/JSON output.
src/bin/zfetch/common.zig Shared helpers (disk, IP, uptime/memory parsing, package counting) + tests moved here.
src/bin/zfetch/linux.zig Linux backend wired to common /proc//sys helpers.
src/bin/zfetch/macos.zig macOS backend using sysctl, CoreGraphics, CoreFoundation, IOKit.
src/bin/zfetch/freebsd.zig FreeBSD backend using sysctl + shared helpers.
src/bin/fastfetch.zig Removed monolithic implementation.
docs/content/programs/zfetch.org Renames docs page and updates demo snippet/output.
build.zig Swaps fastfetch for zfetch and adjusts platform gating/linking.
Comments suppressed due to low confidence (1)

docs/content/programs/zfetch.org:10

  • The feature list says zfetch "Supports both macOS and Linux", but the implementation/build rules also include FreeBSD. Update the documentation to reflect FreeBSD support (or clarify the actual supported set).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Add FreeBSD targets to CI and release scripts. Refactor zfetch to use a
common POSIX module for host info collection and update build logic for
platform-specific exclusions.
Fix project name mismatch in build blacklist ("zig-fetch").
Replace strict assertions with defensive continues to prevent edge-case failures.
Remove unused imports and refactor JSON formatting for improved clarity.
@jiacai2050 jiacai2050 merged commit 200d24c into main Mar 18, 2026
9 checks passed
@jiacai2050 jiacai2050 deleted the refactor-zfetch branch March 18, 2026 02:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants