"""Test that install_required_software declares the expected base packages. inetutils provides /usr/bin/ftp, which TRAMP's /ftp: method (ange-ftp) shells out to; Arch ships no command-line ftp client by default. It must be in the base install so every machine gets it (Craig's dirvish config has an FTP quick-access entry that depends on it). Method mirrors test_orchestrators: sed-extract install_required_software from the real `archsetup`, stub pacman_install as a recorder that echoes the package name, run, and assert membership. Run from repo root: python3 -m unittest tests.installer-steps.test_required_software """ import os import subprocess import textwrap import unittest REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) ARCHSETUP = os.path.join(REPO_ROOT, "archsetup") def required_packages(): """Return (exit_code, [package, ...]) declared by install_required_software.""" script = textwrap.dedent(f"""\ display() {{ :; }} pacman_install() {{ echo "$1"; }} source <(sed -n '/^install_required_software() {{/,/^}}/p' "{ARCHSETUP}") install_required_software """) result = subprocess.run( ["bash", "-c", script], capture_output=True, text=True, timeout=10, ) return result.returncode, result.stdout.split() class RequiredSoftware(unittest.TestCase): def test_installs_inetutils_for_ftp(self): rc, pkgs = required_packages() self.assertEqual(rc, 0) self.assertIn( "inetutils", pkgs, "inetutils (provides /usr/bin/ftp for TRAMP's /ftp: method) must be " "in the base install", ) def test_core_base_packages_present(self): # Guard a few load-bearing entries so a bad edit to the list is caught. rc, pkgs = required_packages() self.assertEqual(rc, 0) for p in ("base-devel", "git", "stow", "openssh", "curl"): self.assertIn(p, pkgs, f"{p} dropped from the base install") if __name__ == "__main__": unittest.main()