pmbootstrap: Don't use 'sudo' when running as root v3 SUPERSEDED

Hugo Osvaldo Barrera: 1
 Don't use 'sudo' when running as root

 5 files changed, 25 insertions(+), 7 deletions(-)
#995599 .build.yml failed
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~postmarketos/pmbootstrap-devel/patches/41395/mbox | git am -3
Learn more about email & git

[PATCH pmbootstrap v3] Don't use 'sudo' when running as root Export this patch

This cancels the need to install and configure `sudo` or `doas` on
single-user installations (e.g.: a VM dedicated to running pmbootstrap).

Fixes: https://gitlab.com/postmarketOS/pmbootstrap/-/issues/2224

v3 fixed linting issues raise by `pmbootstrap.py ci --fast`. I've cached the
result of `os.getuid()` and `which_sudo` entirely, so it only runs once.

`which_sudo` will return None if no command is required to run as root. I've
kept the `sudo` function because without it I'd need to replicate check of
whether the result is None is each of the call sites for `which_sudo`.

This could be improved a _wee_ bit by using `functools.cache`, but that
requires Python >= 3.9.

 pmb/chroot/root.py     |  6 ++++--
 pmb/config/__init__.py | 11 ++++++++++-
 pmb/config/sudo.py     | 11 +++++++++--
 pmb/helpers/run.py     |  2 +-
 test/test_run_core.py  |  2 +-
 5 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/pmb/chroot/root.py b/pmb/chroot/root.py
index a14177ad..4e5fc586 100644
--- a/pmb/chroot/root.py
+++ b/pmb/chroot/root.py
@@ -78,8 +78,10 @@ def root(args, cmd, suffix="native", working_dir="/", output="log",
    executables = executables_absolute_path()
    cmd_chroot = [executables["chroot"], chroot, "/bin/sh", "-c",
                  pmb.helpers.run.flat_cmd(cmd, working_dir)]
    cmd_sudo = [pmb.config.sudo, "env", "-i", executables["sh"], "-c",
                pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)]
    cmd_sudo = pmb.config.sudo([
        "env", "-i", executables["sh"], "-c",
        pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)]
    return pmb.helpers.run_core.core(args, msg, cmd_sudo, None, output,
                                     output_return, check, True,
diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py
index 32c46bb8..ee230d34 100644
--- a/pmb/config/__init__.py
+++ b/pmb/config/__init__.py
@@ -58,7 +58,16 @@ required_programs = [
sudo = which_sudo()

def sudo(cmd: list[str]) -> list[str]:
    """Adapt a command to run as root."""
    sudo = which_sudo()
    if sudo:
        return [sudo, *cmd]
        return cmd

# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
config_keys = ["aports",
diff --git a/pmb/config/sudo.py b/pmb/config/sudo.py
index fe876987..1e227534 100644
--- a/pmb/config/sudo.py
+++ b/pmb/config/sudo.py
@@ -2,13 +2,20 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import shutil
from functools import lru_cache

def which_sudo():
def which_sudo() -> str | None:
    """Returns a command required to run commands as root, if any.

    Find whether sudo or doas is installed for commands that require root.
    Allows user to override preferred sudo with PMB_SUDO env variable.

    if os.getuid() == 0:
        return None

    supported_sudos = ['doas', 'sudo']

    user_set_sudo = os.getenv("PMB_SUDO")
diff --git a/pmb/helpers/run.py b/pmb/helpers/run.py
index b172b356..9835434a 100644
--- a/pmb/helpers/run.py
+++ b/pmb/helpers/run.py
@@ -72,7 +72,7 @@ def root(args, cmd, working_dir=None, output="log", output_return=False,
    if env:
        cmd = ["sh", "-c", flat_cmd(cmd, env=env)]
    cmd = [pmb.config.sudo] + cmd
    cmd = pmb.config.sudo(cmd)

    return user(args, cmd, working_dir, output, output_return, check, env,
diff --git a/test/test_run_core.py b/test/test_run_core.py
index a4600fb8..879eb560 100644
--- a/test/test_run_core.py
+++ b/test/test_run_core.py
@@ -83,7 +83,7 @@ def test_foreground_pipe(args):
    assert ret == (-9, "first\n")

    # Kill with output timeout as root
    cmd = [pmb.config.sudo, "sh", "-c", "printf first; sleep 2; printf second"]
    cmd = pmb.config.sudo(["sh", "-c", "printf first; sleep 2; printf second"])
    args.timeout = 0.3
    ret = func(args, cmd, output_return=True, output_timeout=True,
pmbootstrap/patches/.build.yml: FAILED in 17m6s

[Don't use 'sudo' when running as root][0] v3 from [Hugo Osvaldo Barrera][1]

[0]: https://lists.sr.ht/~postmarketos/pmbootstrap-devel/patches/41395
[1]: mailto:hugo@whynothugo.nl

✗ #995599 FAILED pmbootstrap/patches/.build.yml https://builds.sr.ht/~postmarketos/job/995599