ss7m / paleofetch

neofetch, but written in C
MIT License
167 stars 49 forks source link

Support for other package managers #50

Open ss7m opened 4 years ago

ss7m commented 4 years ago

I would like for paleofetch to support package managers other than pacman. But since I only have pacman installed on my computer, it's difficult for me to figure how to do that.

If you want paleofetch to support your favorite package manager, please reply to this issue with the following information:

allisio commented 4 years ago

While it would certainly be great if users of other distributions contributed how to get the number of installed packages on their systems, it'd be possible to take up the mantle yourself with Docker without polluting your system or bothering with full-fledged virtual machines.

$ yay -S docker
# docker pull fedora
# docker run -it fedora

And bam!, you're at a shell on a Fedora system.

allisio commented 4 years ago

I went ahead and got a feel for what this looks like across the distroverse. Turns out it's an utter mess, but I do think the nftw() approach will make this easier than it might've been.

Alpine Linux

count lines matching /^P:/ in /lib/apk/db/installed

Arch Linux (and derivatives)

count level-1 directories in /var/lib/pacman/local/

Bedrock Linux

(╯°□°)╯︵ ┻━┻

CRUX

count blank lines in /var/lib/pkg/db

Debian (and derivatives?)

?

Fedora

sqlite3 /var/lib/dnf/history.sqlite 'SELECT COUNT(*) FROM rpm' :cry:

Gentoo Linux

count level-2 directories in /var/db/pkg/

GoboLinux

count level-1 directories in /Programs/

Slackware

count level-1 files in /var/log/packages/

Solus

count level-1 directories in /var/lib/eopkg/package/

Void Linux

count <key> elements (- 1) in /var/db/xbps/pkgdb-*.plist XML file (joy)

ss7m commented 4 years ago

I hate to say it, but it increasingly seems like shelling out might be the best option. It'd be a lot easier to support/ debug/ add to. The work to results ratio isn't good enough to right a unique method for each package manager. (especially regarding Fedora's case). Anything else will probably end up begin too complicated and much too error prone.

In which case, adding support for other package managers is as simple as pillaging neofetch's source code :smirk:

ss7m commented 4 years ago

Latest commit in the branch packages is a proof of concept for how to go about this. I figured fork/exec would be faster than system, but this still more than doubles the running time.

allisio commented 4 years ago

Hm... any reason not to do something like this?

FILE *proc = popen("pacman -Qq | wc -l", "r");
fscanf(proc, "%d", &num_packages);

I know it looks like we're basically just scripting at this point, but it's almost as fast as forking and definitely a lot cleaner. We could just have a map from distro -> command that contains what to run such that concatenating | wc -l onto the end gives us the figure we're looking for.

[allis@io ~/paleofetch] $ thyme 100 ./foo
     77 0.007
      9 0.008
     11 0.009
      2 0.010
      1 0.011
[allis@io ~/paleofetch] $ thyme 100 ./bar
     76 0.008
      9 0.009
     12 0.010
      3 0.011

We're essentially tripling our runtime either way, but I'd understand if you wanted to stay with the fork/exec approach to save that millisecond; it sounds crazy, but that's a substantial portion of the time it takes for paleofetch to do its thing (which is awesome).

ss7m commented 4 years ago

In the realm of shaving off milliseconds, I managed to cut off a couple by forking at the very start rather than when get_packages_pacman is called

allisio commented 4 years ago

That's awesome that forking early saves as much time as it does; I think we should definitely go with that approach. Now it's just a matter of making query_package_database() work quickly in as many environments as possible, and to that end I've taken this approach.

We offload the distribution detection to the Makefile, since we can nice-and-neatly just source /etc/os-release to get a unique identifier for determining which command to run to get the package count. I figured we might as well get the distro name while we were there, which saves us having to parse the file during runtime.

This did do away with some error-checking, but I'm almost positive that file will always exist on any Linux system.

ss7m commented 4 years ago

Wow that looks really good- I especially like the idea of determining the distro at build time

ss7m commented 4 years ago

Is your implementation of query_package_database done enough to start a PR for it?

Titaniumtown commented 4 years ago

With bedrock linux, you can just do what neofetch seems to do, search for all of those other distros' package manager files and display all of them.

Titaniumtown commented 4 years ago

Look at the packages section: Screenshot from 2020-05-03 22-08-16

allisio commented 4 years ago

I've been mulling over how best to account for fancy situations (such as Flatpak and Bedrock) without severely impacting our performance, but I haven't been able to come up with anything that strikes me as a satisfactory compromise.

On the one hand, we could just have a list of every package manager and how to get its count, and just "try it and see" irrespective of distro. This would probably take us from our current sub-centisecond execution time to somewhere in the neighborhood of 10x that, which would suck.

Alternatively, we proceed with the drafted approach and special-case things like Flatpak and Bedrock, which feels a little sloppy but is probably the better way.