Differentiate @world and non-@world sets in package field#2231
Differentiate @world and non-@world sets in package field#2231hydrospherics wants to merge 20 commits intofastfetch-cli:devfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Portage set differentiation to the Packages module by splitting the previous single emerge count into emerge-world, emerge-system, and emerge-deps, and exposes the new fields in formatting/JSON/schema.
Changes:
- Implement Gentoo/Portage detection that derives
world,system, anddepscounts from Portage files and installed package DB. - Update Packages module output to show either combined emerge total or the three split counts depending on
combined. - Extend format args, JSON output, and documented JSON schema to include
emerge-world,emerge-system, andemerge-deps.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
| src/modules/packages/packages.c | Prints split emerge counts when not combined; exposes new format args and JSON keys. |
| src/detection/packages/packages_linux.c | Adds Portage parsing to compute world/system/deps counts. |
| src/detection/packages/packages.h | Extends FFPackagesResult with new Portage split fields. |
| doc/json_schema.json | Documents new packagesFormat placeholders for split emerge counts. |
You can also share your feedback on Copilot code review. Take the survey.
|
thanks, on it
…On Tue, Mar 17, 2026, 8:00 PM Copilot ***@***.***> wrote:
***@***.**** commented on this pull request.
Pull request overview
Adds Portage set differentiation to the Packages module by splitting the
previous single emerge count into emerge-world, emerge-system, and
emerge-deps, and exposes the new fields in formatting/JSON/schema.
*Changes:*
- Implement Gentoo/Portage detection that derives world, system, and
deps counts from Portage files and installed package DB.
- Update Packages module output to show either combined emerge total
or the three split counts depending on combined.
- Extend format args, JSON output, and documented JSON schema to
include emerge-world, emerge-system, and emerge-deps.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and
generated 10 comments.
File Description
src/modules/packages/packages.c Prints split emerge counts when not
combined; exposes new format args and JSON keys.
src/detection/packages/packages_linux.c Adds Portage parsing to compute
world/system/deps counts.
src/detection/packages/packages.h Extends FFPackagesResult with new
Portage split fields.
doc/json_schema.json Documents new packagesFormat placeholders for split
emerge counts.
------------------------------
You can also share your feedback on Copilot code review. Take the survey
<https://www.surveymonkey.com/r/XP6L3XJ>.
------------------------------
In src/detection/packages/packages_linux.c
<#2231 (comment)>
:
> + for (const char* line = content.chars; *line; )
+ {
+ const char* eol = strchr(line, '\n');
+ if (!eol) eol = content.chars + content.length;
+ if (*line == '*') ++count;
+ else if (*line == '-' && line + 1 < eol && line[1] == '*' && count > 0) --count;
+ line = (*eol) ? eol + 1 : eol;
The profile packages parsing only decrements the count for lines
beginning with "-*". However the logic increments on '*', so a removal
line like "-sys-apps/foo" (no *) will currently be ignored and the count
will be too high. It would be more consistent to parse '-' removals for
individual atoms (and also ignore blank/whitespace/comment lines) so the
net system count reflects additions/removals.
------------------------------
In src/detection/packages/packages_linux.c
<#2231 (comment)>
:
> + for (const char* line = content.chars; *line; )
+ {
+ const char* eol = strchr(line, '\n');
+ if (!eol) eol = content.chars + content.length;
+ if (*line != '#') ++world;
+ line = (*eol) ? eol + 1 : eol;
+ }
World file parsing counts every line whose first character is not '#',
which will also count empty lines or lines with leading whitespace before a
comment. Consider trimming leading whitespace and skipping empty lines so
emerge-world is stable across different file formatting.
------------------------------
In src/detection/packages/packages_linux.c
<#2231 (comment)>
:
> + uint32_t deps = (world + system < total) ? total - world - system : 0;
+
If world + system ends up greater than total, deps becomes 0 but the
reported split counts will sum to more than the actual installed package
total. That can also break the UI logic that assumes the per-manager counts
partition the total. Consider clamping the split counts so world + system
+ deps always equals total (e.g. clamp world to total, then system to total
- world, then derive deps).
------------------------------
In src/detection/packages/packages.h
<#2231 (comment)>
:
> uint32_t emerge;
+ uint32_t emergeDeps;
+ uint32_t emergeSys;
+ uint32_t emergeWorld;
FFPackagesResult.all is computed by summing every uint32_t field before
all (see src/detection/packages/packages.c). Adding
emergeDeps/emergeSys/emergeWorld while keeping emerge means Gentoo counts
will be included multiple times in all, breaking the displayed {all}
value and comma/remaining-count logic. Consider storing only the split
emerge counts (and deriving the combined emerge count at print/JSON time),
or otherwise ensure only one emerge total participates in the all
accumulation.
------------------------------
In src/detection/packages/packages_linux.c
<#2231 (comment)>
:
> + uint32_t baseDirLen = baseDir->length;
+ ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ROOT "/etc/portage/make.profile");
+ char resolved[PATH_MAX] = {0};
+ if (realpath(baseDir->chars, resolved))
+ {
+ FF_STRBUF_AUTO_DESTROY profileDir = ffStrbufCreateS(resolved);
+ system = getProfSysPackages(&profileDir, 0);
baseDir is already prefixed with FASTFETCH_TARGET_DIR_ROOT in
ffDetectPackagesImpl. Appending FASTFETCH_TARGET_DIR_ROOT
"/etc/portage/make.profile" here will duplicate the prefix when
TARGET_DIR_ROOT is non-empty (e.g. Termux/custom builds), producing an
invalid path. Append just "/etc/portage/make.profile" (or use
FASTFETCH_TARGET_DIR_ETC consistently without also pre-appending root).
------------------------------
In src/modules/packages/packages.c
<#2231 (comment)>
:
> @@ -17,6 +17,7 @@ bool ffPrintPackages(FFPackagesOptions* options)
return false;
}
+ uint32_t emergeAll = counts.emerge;
emergeAll is currently set from counts.emerge. With the new split fields,
keeping counts.emerge populated will break counts.all (it gets summed
automatically). Consider deriving emergeAll from the split counts (emergeWorld
+ emergeSys + emergeDeps) and leaving counts.emerge at 0 so counts.all
stays correct.
------------------------------
In src/modules/packages/packages.c
<#2231 (comment)>
:
> @@ -408,6 +421,9 @@ bool ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
FF_APPEND_PACKAGE_COUNT(choco)
FF_APPEND_PACKAGE_COUNT(dpkg)
FF_APPEND_PACKAGE_COUNT(emerge)
JSON output still emits "emerge" from counts.emerge. If counts.emerge is
zeroed to avoid double-counting in {all}, this key will become incorrect.
Emit "emerge" as the derived combined count (world+system+deps) instead,
while keeping the split keys as-is.
------------------------------
In doc/json_schema.json
<#2231 (comment)>
:
> + "packagesFormat": {
+ "description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of all combined emerge packages\n 7. {emerge-world}: Number of @world emerge packages\n 8. {emerge-system}: Number of @System emerge packages\n 9. {emerge-deps}: Number of emerged dependencies\n 10. {eopkg}: Number of eopkg packages\n 11. {xbps}: Number of xbps packages\n 12. {nix-system}: Number of nix-system packages\n 13. {nix-user}: Number of nix-user packages\n 14. {nix-default}: Number of nix-default packages\n 15. {apk}: Number of apk packages\n 16. {pkg}: Number of pkg packages\n 17. {flatpak-system}: Number of flatpak-system app packages\n 18. {flatpak-user}: Number of flatpak-user app packages\n 19. {snap}: Number of snap packages\n 20. {brew}: Number of brew packages\n 21. {brew-cask}: Number of brew-cask packages\n 22. {macports}: Number of macports packages\n 23. {scoop-user}: Number of scoop-user packages\n 24. {scoop-global}: Number of scoop-global packages\n 25. {choco}: Number of choco packages\n 26. {pkgtool}: Number of pkgtool packages\n 27. {paludis}: Number of paludis packages\n 28. {winget}: Number of winget packages\n 29. {opkg}: Number of opkg packages\n 30. {am-system}: Number of am-system packages\n 31. {sorcery}: Number of sorcery packages\n 32. {lpkg}: Number of lpkg packages\n 33. {lpkgbuild}: Number of lpkgbuild packages\n 34. {guix-system}: Number of guix-system packages\n 35. {guix-user}: Number of guix-user packages\n 36. {guix-home}: Number of guix-home packages\n 37. {linglong}: Number of linglong packages\n 38. {pacstall}: Number of pacstall packages\n 39. {mport}: Number of mport packages\n 40. {am-user}: Number of am-user (aka appman) packages\n 41. {pkgsrc}: Number of pkgsrc packages\n 42. {hpkg-system}: Number of hpkg-system packages\n 43. {hpkg-user}: Number of hpkg-user packages\n 44. {pisi}: Number of pisi packages\n 45. {soar}: Number of soar packages\n 46. {kiss}: Number of kiss packages\n 47. {moss}: Number of moss packages\n 48. {nix-all}: Total number of all nix packages\n 49. {flatpak-all}: Total number of all flatpak app packages\n 50. {brew-all}: Total number of all brew packages\n 51. {guix-all}: Total number of all guix packages\n 52. {hpkg-all}: Total number of all hpkg packages",
"type": "string"
},
- "physicaldiskFormat": {
+ "physicaldiskFormat": {
"description": "Output format of the module `PhysicalDisk`. See Wiki for formatting syntax\n 1. {size}: Device size (formatted)\n 2. {name}: Device name\n 3. {interconnect}: Device interconnect type\n 4. {dev-path}: Device raw file path\n 5. {serial}: Serial number\n 6. {physical-type}: Device kind (SSD or HDD)\n 7. {removable-type}: Device kind (Removable or Fixed)\n 8. {readonly-type}: Device kind (Read-only or Read-write)\n 9. {revision}: Product revision\n 10. {temperature}: Device temperature (formatted)",
This hunk introduces tab indentation before JSON object keys (
"packagesFormat", "physicaldiskFormat"). JSON allows tabs, but the
surrounding file uses spaces, so this looks accidental and creates
inconsistent formatting (and may fail style/format checks if any exist).
Replace the leading tabs with spaces to match the rest of the schema file.
------------------------------
In src/detection/packages/packages_linux.c
<#2231 (comment)>
:
> + const char* eol = strchr(line, '\n');
+ if (!eol) eol = content.chars + content.length;
+ if (*line == '*') ++system;
+ else if (*line == '-' && line + 1 < eol && line[1] == '*' && system > 0) --system;
+ line = (*eol) ? eol + 1 : eol;
+ }
+ }
+ ffStrbufSubstrBefore(baseDir, baseDirLen);
+ }
+
+ uint32_t deps = (world + system < total) ? total - world - system : 0;
+
+ packageCounts->emergeWorld += world;
+ packageCounts->emergeSys += system;
+ packageCounts->emergeDeps += deps;
+ packageCounts->emerge += total;
This updates both the split emerge counts and packageCounts->emerge
(total). Because all is calculated as the sum of all uint32_t fields
before all, this will double-count emerge in the total package count.
Prefer not storing emerge in the result at all (derive it later as
emergeWorld+emergeSys+emergeDeps), or ensure only one of these
contributes to all.
------------------------------
In src/modules/packages/packages.c
<#2231 (comment)>
:
> @@ -160,6 +170,9 @@ bool ffPrintPackages(FFPackagesOptions* options)
FF_ARG(counts.dpkg, "dpkg"),
FF_ARG(counts.rpm, "rpm"),
FF_ARG(counts.emerge, "emerge"),
In formatted output, {emerge} is still bound to counts.emerge. If emerge
is split (and counts.emerge must remain 0 to avoid inflating {all}), pass
the derived combined value (e.g. emergeAll) for the "emerge" format arg
instead of counts.emerge, so {emerge} continues to work.
—
Reply to this email directly, view it on GitHub
<#2231 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A25YECYRPXUNL4DYCDOWTK34RE463AVCNFSM6AAAAACWUPUKA2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTSNRQGIZTKOJTGE>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds Portage (@world/@system/deps) differentiation to the Packages module so emerge counts can be shown as either a single combined total or as split sub-counts.
Changes:
- Split emerge detection into
emerge-world,emerge-system, andemerge-deps, while retaining a combinedemergevalue. - Update module output/format args and JSON output to expose the new emerge sub-counts.
- Update documentation schema text for the Packages formatting placeholders.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| src/modules/packages/packages.c | Prints/exports split emerge counts when not combined; adds module args for new placeholders and JSON output keys. |
| src/detection/packages/packages_linux.c | Implements Linux Portage set parsing for world/system and derives deps from total. |
| src/detection/packages/packages.h | Extends FFPackagesResult with new emerge fields and adjusts struct layout around all. |
| doc/json_schema.json | Updates the packagesFormat placeholder documentation to include the new emerge placeholders. |
You can also share your feedback on Copilot code review. Take the survey.
|
I checked the file in https://distrosea.com. I don't see a comment line. If it's a auto-generated file, I don't think it will contain comment or empty line. |
➜ anthony@asta ~ cat /var/lib/portage/world
app-admin/doas
app-arch/7zip
app-arch/unrar
app-containers/podman
app-editors/nano
app-editors/vim
app-eselect/eselect-repository
app-misc/fastfetch
app-misc/jq
app-misc/sl
app-portage/eix
app-portage/genlop
app-portage/gentoolkit
app-shells/nushell
app-text/ghostscript-gpl
app-text/mupdf
dev-dotnet/dotnet-sdk-bin
dev-lang/zig
dev-util/android-tools
dev-util/pkgcheck
dev-util/pkgdev
games-misc/cowsay
games-misc/nyancat
gnome-base/dconf-editor
gnome-base/gnome-light
gnome-extra/gnome-browser-connector
gnome-extra/gnome-shell-extensions
gnome-extra/gnome-tweaks
llvm-core/lld
media-fonts/noto
media-fonts/noto-cjk
media-gfx/imagemagick
media-gfx/iscan
media-gfx/sane-backends
media-libs/libsdl2
media-libs/libv4l
media-libs/tiff
media-video/celluloid
media-video/ffmpeg
net-dns/bind-tools
net-misc/networkmanager
net-misc/whois
net-misc/yt-dlp
net-p2p/transmission
net-print/cups
net-print/cups-filters
net-print/cups-meta
net-print/epson-inkjet-printer-escpr
net-print/libcupsfilters
net-wireless/wireless-regdb
sys-apps/baobab
sys-apps/cpuid
sys-apps/mlocate
sys-apps/pciutils
sys-apps/qdiskinfo
sys-apps/ripgrep
sys-apps/systemd
sys-auth/rtkit
sys-block/io-scheduler-udev-rules
sys-boot/efibootmgr
sys-boot/gnu-efi
sys-boot/grub
sys-boot/plymouth
sys-firmware/intel-microcode
sys-firmware/sof-firmware
sys-fs/btrfs-progs
sys-fs/dosfstools
sys-fs/ntfs3g
sys-kernel/git-sources
sys-kernel/installkernel
sys-kernel/linux-firmware
sys-kernel/linux-headers
sys-libs/glibc
sys-power/thermald
www-client/brave-browser
www-client/lynx
x11-terms/ptyxisit is basically a file that lists out the packages that I explicitly added through emerge. |
|
@hydrospherics Why do you think it may contain empty or comment lines? |
it usually doesnt (portage handles it fine), but copilot suggested that I harden the parsing anyway. maybe I guess.. some people edit their world file manually? |
|
People can even run Counting the number of |
|
The code of counting |
true, I do that alot for some reason.. but AI is AI, it wants to handhold in some way. |
I see, so I guess I'll go rm counting the hell, maybe even count non-world as |
5f85cf9 to
9d5078c
Compare
Removed the addition of 'emerge-all' count to the JSON object.
There was a problem hiding this comment.
Pull request overview
This PR aims to improve Gentoo/Portage package reporting by splitting the single emerge count into separate set-based counters, aligning Portage reporting closer to how other ecosystems (e.g., Nix) are differentiated.
Changes:
- Replaced the single
emergecounter withemerge-worldandemerge-systemcounters, plus anemerge-allaggregate for formatting. - Updated Linux package detection to read
/var/lib/portage/worldand derive a second count from the total installed set. - Updated the packages module’s formatting args and JSON schema documentation to reflect the new placeholders.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
src/modules/packages/packages.c |
Updates printing/format args to expose emerge-world, emerge-system, and emerge-all. |
src/detection/packages/packages_linux.c |
Adds a Portage-specific counting routine that reads the world file and splits totals. |
src/detection/packages/packages.h |
Replaces emerge field with emergeWorld/emergeSystem in the result struct. |
doc/json_schema.json |
Updates the packagesFormat description to document the new format tokens. |
You can also share your feedback on Copilot code review. Take the survey.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@ceamac What's your opinion? TLDR: This PR splits emerge packages count into |
2cd87ae to
aa3a141
Compare
|
force pushed to amend the commit message from the merge new changes thing (I did that on web). Also, we could consider aliasing |
|
LGTM, but I don't know if |
Yes, Most distributions keep track of which packages are manually installed and which are dependencies only, so they can be cleaned when no longer needed (see Other than the Where Some people have more manually defined sets, so counting only the packages from the I will look over the implementation in the weekend, now I only read the discussion. |
Yeah, looking back I have no idea what I was thinking trying to count As for Anyways, thanks for dropping by for now though. |
Ahh, I didn't mean that it would cause confusion, it's just that, some people might not have their configs up ahead so yea. Your call though. |
295a9df to
d593cf3
Compare
resolves #2230 and #2229 (gonna link them here anyway even if they're closed)
emergecount intoemerge-world, andemerge-system.detection reads
/var/lib/portage/worldfor@world, and non-@world(a.k.a.emerge-system), and derives non-@worldviatotal - world.For Copilot:
1.
ffStrbufCountC(content, '\n')computation is intentional since this is a fetch tool, not a dependency resolver2.
@systemset pkg counting was previously present, but removed as per maintainer's advice because the code underneath is really fragile3. non-
@worldpkgs and dependencies were consolidated toemerge-systembecause in Gentoo, you technically can't remove either since there'll be dependents, much like a system pkg itself. Who even pulls in Glibc intentionally?