From 18f9fc81e198463975408a00ab5bb3f79e6626f2 Mon Sep 17 00:00:00 2001 From: Julian Lobbes Date: Mon, 1 Aug 2022 13:01:32 +0200 Subject: [PATCH] feat: add dependency check --- README.md | 4 +++- core/exceptions.py | 7 +++++++ core/utils.py | 50 +++++++++++++++++++++++++++++++++++----------- udib.py | 5 +++-- 4 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 core/exceptions.py diff --git a/README.md b/README.md index 7c3f7f7..a1cdaf5 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,12 @@ Using UDIB to create ISOs requires the following software: - `xorriso` *(1.5.4 known to work)* - **Debian (bullseye):** [xorriso](https://packages.debian.org/bullseye/xorriso) - **Arch Linux:** [extra/libisoburn](extra/libisoburn) -- GNU `gpg` *(2.2.32 known to work)* +- GNU `gpg` - preinstalled on most distributions - GNU `cpio` - preinstalled on most distributions +- GNU `sha512sum` + - preinstalled on most distributions Internet access is (obviously) required if you want to fetch any files using UDIB. diff --git a/core/exceptions.py b/core/exceptions.py new file mode 100644 index 0000000..282a6dd --- /dev/null +++ b/core/exceptions.py @@ -0,0 +1,7 @@ +"""Some general exception classes used throughout the program.""" + + +class MissingDependencyError(RuntimeError): + """Raised if a required system dependency is missing.""" + + pass diff --git a/core/utils.py b/core/utils.py index d1c7a63..ffb846e 100644 --- a/core/utils.py +++ b/core/utils.py @@ -1,19 +1,20 @@ """A collection of general utilities, not specific to any module.""" -from pathlib import Path -from tempfile import TemporaryDirectory -from sys import exit -from os import remove, rename -from subprocess import run, STDOUT, PIPE - -from cli.clibella import Printer -from net.download import download_file -from net.scrape import get_debian_iso_urls -from gpg.verify import assert_detached_signature_is_valid -from gpg.exceptions import VerificationFailedError -from gpg.keystore import debian_signing_key_is_imported, import_debian_signing_key from crypt import crypt, METHOD_SHA512 from getpass import getpass +from os import remove, rename +from pathlib import Path +from subprocess import run, STDOUT, PIPE +from sys import exit +from tempfile import TemporaryDirectory + +from cli.clibella import Printer +from exceptions import MissingDependencyError +from gpg.exceptions import VerificationFailedError +from gpg.keystore import debian_signing_key_is_imported, import_debian_signing_key +from gpg.verify import assert_detached_signature_is_valid +from net.download import download_file +from net.scrape import get_debian_iso_urls def hash_user_password(printer=None): @@ -38,6 +39,31 @@ def hash_user_password(printer=None): p.info("Password hash:") p.info(crypt(password, crypt.METHOD_SHA512)) +def assert_system_dependencies_installed(): + """Checks whether all system dependencies required by udib are installed. + + The programs used by udib must be accessible within the system's PATH + environment variable. + + Raises + ------ + MissingDependencyError + If a required dependency is not installed. + """ + + _REQUIRED_PROGRAMS = [ + "xorriso", "gpg", "cpio", "sha512sum", + ] + + for program in _REQUIRED_PROGRAMS: + try: + run(["command", "-v", program], shell=True, check=True) + except subprocess.CalledProcessError: + raise MissingDependencyError( + f"Program not installed or not in $PATH: " + f"'{program}'." + ) + def find_all_files_under(parent_dir): """Recursively finds all files anywhere under the specified directory. diff --git a/udib.py b/udib.py index e8d2045..cd6fde8 100755 --- a/udib.py +++ b/udib.py @@ -7,7 +7,7 @@ from tempfile import TemporaryDirectory from cli.clibella import Printer from cli.parser import get_argument_parser -from core.utils import download_and_verify_debian_iso +from core.utils import assert_system_dependencies_installed, download_and_verify_debian_iso from iso.injection import inject_preseed_file_into_iso from net.download import download_file from net.scrape import get_debian_preseed_file_urls, get_debian_iso_urls @@ -15,9 +15,10 @@ from net.scrape import get_debian_preseed_file_urls, get_debian_iso_urls def main(): + # check for dependencies + assert_system_dependencies_installed() # create a CLI printer p = Printer() - # create an argument parser and read arguments parser = get_argument_parser() args = parser.parse_args()