89luca89 / distrobox

Use any linux distribution inside your terminal. Enable both backward and forward compatibility with software and freedom to use whatever distribution you’re more comfortable with. Mirror available at: https://gitlab.com/89luca89/distrobox
https://distrobox.it/
GNU General Public License v3.0
10.07k stars 416 forks source link

[Suggestion] Use `/etc/os-release` or `/etc/lsb_release` for distrobox-upgrade #744

Open uncomfyhalomacro opened 1 year ago

uncomfyhalomacro commented 1 year ago

Detecting which package manager is available through command can be faulty. For example, I have osc installed in my system before and tried out distrobox - osc also pulls dnf as part of the recommends (?). And because of that this may have mess up my distrobox install causing it to look for dnf even after I removed it - related issue #706 .

Wouldn't it be better to use /etc/os-release or /etc/lsb_release to check which distro someone has at first and use the default package manager then use command as a fallback later?

Errata: osc does not have dnf installed as part of recommends. But I do believe it might be some obs-service-* package that has dnf as part of its recommends since I used to run osc on the host with those plugins.

PS: This could be a good discussion to look out for. Not a high priority to be honest since all of us are busy with our lives at this moment.

CC: @luc14n0 @89luca89

89luca89 commented 1 year ago

Thanks @uncomfyhalomacro This is indeed a possible improvement, it has been brought up before, but hadn't the time/will to look into it

Open to suggestions :)

luc14n0 commented 1 year ago

This should be quite straightforward to be done. We can source the file with . /etc/os-release, then we have access to the variables declared there. ID seems like a nice prospect because its short and lower case. ID_LIKE looks interesting too, for example if all Debian based distros define it as debian - like Ubuntu does -, that would make our lives easier.

Then we can use case to choose the right package manager:

case "${ID_LIKE}" in
    debian) package_manager=apt ;;
    ...
esac

The tough part is researching /etc/os-release of the countless distros around, perhaps the community is willing to give a hand with that.

If no one takes a stab at this, in my next round of distrobox contributions I could add this task to my Todo list.

89luca89 commented 1 year ago

Yea the fact that we can simply source it is really nice

We need more info about which thing we can use to just infere the pkg manager Latest batch of commits to init now allows for more flexibility in packages, they are checked before installed, this allows to declare a dependency that is called differently between 2 OSes with the same package manager (see maybe ubuntu 23 vs debian 8)

The only thing that we might lose (i'm just guessing) is the ability to "just try and see if it works" Like now you just have to have a supported pkg manager With this other approach you need a supported distribution name, which is not a given sometimes

89luca89 commented 1 year ago

Here is a list of all the os-release in all the different distros in the compatibility list

os-release-ubi.txt os-release-sl-7.txt os-release-beige.txt os-release-mageia.txt os-release-toolbox.txt os-release-apricot.txt os-release-ubi-init.txt os-release-centos-7.txt os-release-8-init-8.txt os-release-8-base-8.txt os-release-fedora-39.txt os-release-fedora-38.txt os-release-fedora-37.txt os-release-fedora-36.txt os-release-debian-10.txt os-release-eol-wheezy.txt os-release-ubi-minimal.txt os-release-leap-latest.txt os-release-alpine-3-16.txt os-release-alpine-3-15.txt os-release-almalinux-9.txt os-release-almalinux-8.txt os-release-ubuntu-22-04.txt os-release-ubuntu-20-04.txt os-release-ubuntu-18-04.txt os-release-ubuntu-16-04.txt os-release-ubuntu-14-04.txt os-release-rockylinux-9.txt os-release-rockylinux-8.txt os-release-stage3-latest.txt os-release-oraclelinux-9.txt os-release-oraclelinux-8.txt os-release-oraclelinux-7.txt os-release-docker-latest.txt os-release-debian-stable.txt os-release-amazonlinux-2.txt os-release-amazonlinux-1.txt os-release-alpine-latest.txt os-release-toolbox-latest.txt os-release-slackware-14-2.txt os-release-debian-testing.txt os-release-centos-stream9.txt os-release-centos-stream8.txt os-release-debian-unstable.txt os-release-clearlinux-base.txt os-release-distrobox-latest.txt os-release-archlinux-latest.txt os-release-wolfi-base-latest.txt os-release-tumbleweed-latest.txt os-release-rockylinux-latest.txt os-release-neurodebian-nd100.txt os-release-fedora-toolbox-39.txt os-release-fedora-toolbox-38.txt os-release-fedora-toolbox-37.txt os-release-debian-toolbox-11.txt os-release-debian-toolbox-10.txt os-release-clearlinux-latest.txt os-release-archlinux-toolbox.txt os-release-oraclelinux-9-slim.txt os-release-oraclelinux-8-slim.txt os-release-oraclelinux-7-slim.txt os-release-kali-rolling-latest.txt os-release-alpine-toolbox-edge.txt os-release-alpine-toolbox-3-17.txt os-release-alpine-toolbox-3-16.txt os-release-almalinux-toolbox-9.txt os-release-almalinux-toolbox-8.txt os-release-almalinux-9-minimal.txt os-release-ubuntu-toolbox-22-04.txt os-release-ubuntu-toolbox-20-04.txt os-release-ubuntu-toolbox-18-04.txt os-release-ubuntu-toolbox-16-04.txt os-release-rockylinux-toolbox-9.txt os-release-rockylinux-toolbox-8.txt os-release-rockylinux-8-minimal.txt os-release-debian-toolbox-testing.txt os-release-centos-toolbox-stream9.txt os-release-centos-toolbox-stream8.txt os-release-opensuse-toolbox-latest.txt os-release-debian-toolbox-unstable.txt os-release-debian-stable-backports.txt os-release-debian-testing-backports.txt os-release-void-linux-latest-full-x86_64.txt os-release-amazonlinux-2022-0-20220531-0.txt os-release-void-linux-latest-full-x86_64-musl.txt

luc14n0 commented 1 year ago

Yeah, we need to have a closer looking to see if there's really a pattern we can rely on rather than going with distroA|distroD|distroH|distroL|distroO) if command -v foo; then package_manager=foo; fi.

The only thing that we might lose (i'm just guessing) is the ability to "just try and see if it works" Like now you just have to have a supported pkg manager With this other approach you need a supported distribution name, which is not a given sometimes

Yeah, I see the lines of code increasing a bit with this proposed approach. The "try and see" approach should work most of the time, because most of the time distros only have package manager. And if there's only one package, most likely there's only one canonical way of updating the system.

However, there could be corner cases where things could end up not so pretty, with the current approach. The more people use distrobox the more likely such a thing could happen.

89luca89 commented 1 year ago

Yeah, we need to have a closer looking to see if there's really a pattern we can rely on rather than going with distroA|distroD|distroH|distroL|distroO) if command -v foo; then package_manager=foo; fi.

Yea that's what I fear :/ (and definitely won't do)

And if there's only one package, most likely there's only one canonical way of updating the system.

However, there could be corner cases where things could end up not so pretty, with the current approach. The more people use distrobox the more likely such a thing could happen.

This in fact can be a problem if/when openSUSE migrates to dnf but maybe doing a mixed approach can be useful like:

if command -v package_manager; then
    > we get from os-release the distro
    > package_manager install list of packages for detected distro
    > else we install the package list for the most associated distro (dnf-fedora/rh, apt-debian etc etc)

so we just add a little logic to the present approach this way

luc14n0 commented 1 year ago

To be honest, I don't see openSUSE switching to DNF as its default package manager.

However, I had the same thought about some cases needing a mixed approach. I'm gonna think this over when I get some time to spare.

89luca89 commented 1 year ago

Thanks for the help!

marcosps commented 10 months ago

To be honest, I don't see openSUSE switching to DNF as its default package manager.

However, I had the same thought about some cases needing a mixed approach. I'm gonna think this over when I get some time to spare.

Hey @luc14n0, did you manage to think about the issue?

doccaz commented 10 months ago

I made a script to evaluate what fields can be used based on these samples. My experience with enterprise distros would suggest using CPE, which is guaranteed to be unique. However, I see that quite a few (40 out of 84 to be exact) do not have that field.

Also:

So, my proposal would be to use NAME to simplify things.

get_distros.sh.txt summary.txt

doccaz commented 10 months ago

Further analyzing, we have 25 unique NAME tags:

erico@suselab-erico:~/Projetos/distrobox> egrep "NAME" summary.txt | sort  | uniq
--> NAME=[AlmaLinux]
--> NAME=[Alpine Linux]
--> NAME=[Amazon Linux]
--> NAME=[Amazon Linux AMI]
--> NAME=[Arch Linux]
--> NAME=[CentOS Linux]
--> NAME=[CentOS Stream]
--> NAME=[Clear Linux OS]
--> NAME=[Crystal Linux]
--> NAME=[Debian GNU/Linux]
--> NAME=[Deepin]
--> NAME=[Fedora Linux]
--> NAME=[Gentoo]
--> NAME=[Kali GNU/Linux]
--> NAME=[Mageia]
--> NAME=[openSUSE Leap]
--> NAME=[openSUSE Tumbleweed]
--> NAME=[Oracle Linux Server]
--> NAME=[Red Hat Enterprise Linux]
--> NAME=[Rocky Linux]
--> NAME=[Scientific Linux]
--> NAME=[Slackware]
--> NAME=[Ubuntu]
--> NAME=[Void]
--> NAME=[Wolfi]

So, I guess we'd only need a "case" for these items only to define the corresponding package manager.

doccaz commented 10 months ago

So, it would boil down to something like this:

#!/bin/bash
DISTRO_NAME=$(egrep "^NAME=.*" ${1}| cut -d\= -f2-)

if [[ ${DISTRO_NAME} =~ "Ubuntu" ]] || [[ ${DISTRO_NAME} =~ "Debian" ]]; then
        echo "we should use apt-get!"
elif [[ ${DISTRO_NAME} =~ "Red Hat" ]] || [[ ${DISTRO_NAME} =~ "Oracle Linux" ]] || [[ ${DISTRO_NAME} =~ "CentOS" ]] || [[ ${DISTRO_NAME} =~ "AlmaLinux" ]]; then
        echo "we should use dnf!"
elif [[ ${DISTRO_NAME} =~ "Arch" ]]; then
        echo "we should use pacman!"
elif [[ ${DISTRO_NAME} =~ "SUSE" ]]; then
        echo "we should use zypper!"
else 
        echo "I don't know! ¯\_(ツ)_/¯ "
fi

Testing:

erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-archlinux-latest.txt 
we should use pacman!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-almalinux-9-minimal.txt 
we should use dnf!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-centos-7.txt 
we should use dnf!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-debian-stable.txt 
we should use apt-get!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-ubuntu-14-04.txt 
we should use apt-get!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-opensuse-toolbox-latest.txt 
we should use zypper!
erico@suselab-erico:~/Projetos/distrobox> ./guess_packager.sh samples/os-release-wolfi-base-latest.txt 
I don't know! ¯\_(ツ)_/¯ 
doccaz commented 10 months ago

And of course, if there are exceptions, like suppose there 4 versions of CentOS and one of them doesn't support DNF... test the other fields, preferrably PRETTY_NAME and then VERSION, if it exists.

marcosps commented 9 months ago

Checkihg the distrobox-upgrade script, where the checks if a package manager is installed, we could just call a function, like the one that @doccaz did, and then compare which package returned, instead of checking which package manager is installed. What do you think @89luca89 ?

uncomfyhalomacro commented 9 months ago

Yeah my suggestion seems flaky after I read all suggestions here, especially from @doccaz

89luca89 commented 9 months ago

Thanks for thinking about this!

Only problem I see is supporting unknown distros

For example, wolfi vs alpine, both use apk but different /etc/os-release

The proposed solution would make it "hardcoded" which family of distros we support, Not that this is wrong, but it's a paradigm shift that should be thought about

doccaz commented 9 months ago

Thanks for thinking about this!

Only problem I see is supporting unknown distros

For example, wolfi vs alpine, both use apk but different /etc/os-release

The proposed solution would make it "hardcoded" which family of distros we support, Not that this is wrong, but it's a paradigm shift that should be thought about

In this case, you could resort to the other available fields, like PRETTY_NAME or VERSION, as I mentioned.

89luca89 commented 9 months ago

Thanks for thinking about this! Only problem I see is supporting unknown distros For example, wolfi vs alpine, both use apk but different /etc/os-release The proposed solution would make it "hardcoded" which family of distros we support, Not that this is wrong, but it's a paradigm shift that should be thought about

In this case, you could resort to the other available fields, like PRETTY_NAME or VERSION, as I mentioned.

image

That doesn't always work

Another thing would maybe do a pkg manager detection fallback

1 - ID 2 - NAME 3 - PRETTY_NAME 4 - we fallback to pkg manager detection like now

doccaz commented 9 months ago

That doesn't always work

Another thing would maybe do a pkg manager detection fallback

1 - ID 2 - NAME 3 - PRETTY_NAME 4 - we fallback to pkg manager detection like now

Exactly. If everything else fails, test for the package manager binaries.

sandorex commented 8 months ago

Im late to the discussion but this may be worth doing until proper solution is in place? Basically order package managers by niche-ness(?)

For example on openSUSE, if zypper is checked first then it will not look for dnf so quick order i thought of This still cannot deal with idk installing pacman on ubuntu but does it really have to handle that?

swupd
xbps-install
apk
emerge
slackpkg
pacman
zypper # must be before dnf because openSUSE
dnf
microdnf # dnf should probably be preferred
yum # must be after dnf
apt-get

Looking forward to your thoughts

89luca89 commented 8 months ago

mmh this would be a little stopgap, but that would do some damage on an opensuse with both dnf and zypper installed (I guess?? I do not know if installing dnf removes zypper and vice versa :man_shrugging: )

marcosps commented 8 months ago

I believe that we can have both, as there are some packages that install dnf, IIRC. But either way, for such a tool like distrobox, I believe that preferring zypper is safe. I never saw anyone using dnf on openSUSE as by default zypper is the package manager.

sandorex commented 8 months ago

According to opensuse wiki dnf is in the repos but also it is never mentioned that it is unsupported only thing i could find is the following

Specific functionality that is enabled by default with zypper can not be reproduced using DNF without the additional installation of plugins. Functionality such as "protected" packages and snapper integration require the use of plugins.

I do not know if installing dnf removes zypper and vice versa 🤷‍♂️

No, dnf is available to install but zypper is kept, i do not know if zypper can be uninstalled but would that really be something distrobox need to care about if zypper works and is the default?

EDIT: Also on archlinux you can install apt and dnf but i do not think we should care for such cases

marcosps commented 8 months ago

IMHO, distrobox should first respect the default package manager for a distro. After this is done, well, some corner cases could be handled. (And yes, I understand that's kind of messed up to have two package managers, but what do I know?).