From 3df5ee94112cb47ea560cd846afc7fa41ac67c1a Mon Sep 17 00:00:00 2001
From: Matthijs van der Burgh <MatthijsBurgh@outlook.com>
Date: Fri, 16 Aug 2024 15:40:00 +0200
Subject: [PATCH] Add tue-install-apt-key-source

---
 installer/parse_install_yaml.py |  34 ++++++++
 installer/tue-install-impl.bash | 142 ++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+)

diff --git a/installer/parse_install_yaml.py b/installer/parse_install_yaml.py
index 6faf22dfa..1c9791bba 100755
--- a/installer/parse_install_yaml.py
+++ b/installer/parse_install_yaml.py
@@ -59,6 +59,37 @@ def type_git(install_item: Mapping, allowed_keys: Optional[List[str]] = None) ->
     return " ".join(command)
 
 
+def type_apt_key_source(install_item: Mapping) -> str:
+    dist_exts = install_item.get("distribution-extensions")
+    key_file = install_item.get("key-file")
+    key_fingerprint = install_item.get("key-fingerprint")
+    key_url = install_item.get("key-url")
+    repo_components = install_item.get("repo-components")
+    repo_url = install_item.get("repo-url")
+    source_file = install_item.get("source-file")
+
+    args: List[str] = []
+
+    if not isinstance(dist_exts, list):
+        raise ValueError("distribution-extensions should be a list")
+    for dist_ext in dist_exts:
+        args.append(f"--distribution-extension={dist_ext}")
+
+    args.append(f"--key-file={key_file}")
+    args.append(f"--key-fingerprint={key_fingerprint}")
+    args.append(f"--key-url={key_url}")
+
+    if not isinstance(repo_components, list):
+        raise ValueError("repo-components should be a list")
+    for repo_component in repo_components:
+        args.append(f"--repo-component={repo_component}")
+
+    args.append(f"--repo-url={repo_url}")
+    args.append(f"--source-file={source_file}")
+
+    return " ".join(args)
+
+
 def catkin_git(source: Mapping) -> str:
     """
     Function to generate installation command for catkin git targets from the extracted yaml
@@ -245,6 +276,9 @@ def get_distro_item(
 
                 command = f"tue-install-{install_type} {pkg_name}"
 
+            elif install_type in ["apt-key-source", "apt-key-source-now"]:
+                command = f"tue-install-{install_type} {type_apt_key_source(install_item)}"
+
             else:
                 raise ValueError(f"Unknown install type: '{install_type}'")
 
diff --git a/installer/tue-install-impl.bash b/installer/tue-install-impl.bash
index 148a5d8e6..b476aa057 100755
--- a/installer/tue-install-impl.bash
+++ b/installer/tue-install-impl.bash
@@ -1097,6 +1097,148 @@ function tue-install-ppa-now
 
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
+function tue-install-apt-key-source-now
+{
+    tue-install-debug "tue-install-apt-key-source-now $*"
+
+    local distribution_extensions key_file key_fingerprint key_url repo_url source_file
+    distribution_extensions=()
+    repo_components=()
+    if [[ -n $1 ]]
+    then
+        for i in "$@"
+        do
+            case $i in
+                --distribution-extension=* )
+                    distribution_extensions+=("${i#*=}") ;;
+                --key-file=* )
+                    key_file="${i#*=}" ;;
+                --key-fingerprint=* )
+                    key_fingerprint="${i#*=}" ;;
+                --key-url=* )
+                    key_url="${i#*=}" ;;
+                --repo-component=* )
+                    repo_components+=("${i#*=}") ;;
+                --repo-url=* )
+                    repo_url="${i#*=}" ;;
+                --source-file=* )
+                    source_file="${i#*=}" ;;
+                * )
+                    tue-install-error "Unknown input variable ${i}" ;;
+            esac
+        done
+    fi
+
+    if [[ ! ${#distribution_extensions[@]} ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs at least 1 distribution-extension"
+    fi
+
+    if [[ -z "${key_file}" ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs key-file"
+    fi
+
+    if [[ -z "${key_fingerprint}" ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs key-fingerprint"
+    fi
+
+    if [[ -z "${key_url}" ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs key-url"
+    fi
+
+    if [[ -z "${repo_url}" ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs repo-url"
+    fi
+
+    if [[ -z "${source_file}" ]]
+    then
+        tue-install-error "Invalid tue-install-apt-key-source-now call: needs source-file"
+    fi
+
+    local key_folder name
+    name=${TUE_INSTALL_CURRENT_TARGET%-setup}
+    key_folder=$(dirname "${key_file}")
+
+    if [[ $(dirname "${source_file}") == "." ]]
+    then
+        tue-install-debug "Making source_file '${source_file}' relative to '/etc/apt/sources.list.d/'"
+        source_file="/etc/apt/sources.list.d/${source_file}"
+    fi
+
+    local arch distribution
+    arch=$(dpkg --print-architecture)
+    distribution=$(lsb_release -cs)
+
+    local distribution_components
+    distribution_components=()
+    for dist_ext in "${distribution_extensions[@]}"
+    do
+        distribution_components+=("${distribution}${dist_ext:+-${dist_ext}}")
+    done
+
+    local source_url
+    source_url="deb [arch=${arch} signed-by=${key_file}] ${repo_url} ${distribution_components[*]} ${repo_components[*]}"
+
+    local apt_needs_to_be_updated key_needs_to_be_added source_needs_to_be_added
+    key_needs_to_be_added=false
+    source_needs_to_be_added=false
+    apt_needs_to_be_updated=false
+
+    if [[ ! -f "${key_file}" ]]
+    then
+        tue-install-debug "Keyring '${key_file}' doesn't exist yet."
+        key_needs_to_be_added=true
+    elif ! gpg --show-keys "${key_file}" | grep -q "${key_fingerprint}" &> /dev/null
+    then
+        tue-install-debug "Keyring '${key_file}' doesn't match the fingerprint '${key_fingerprint}'."
+        key_needs_to_be_added=true
+    else
+        tue-install-debug "Not updating the existing GPG of the ${name} repository with fingerprint '${key_fingerprint}'"
+    fi
+
+    if [[ "${key_needs_to_be_added}" == "true" ]]
+    then
+        tue-install-debug "Making sure '${key_folder}' folder exists with the correct permissions."
+        tue-install-pipe sudo install -m 0755 -d "${key_folder}"
+        tue-install-debug "Downloading gpg key of ${name} repo with fingerprint '${key_fingerprint}'."
+        curl -fsSL "${key_url}" | sudo gpg --dearmor --yes -o "${key_file}"
+        tue-install-debug "Successfully added/updated ${name} repository GPG key"
+
+        apt_needs_to_be_updated=true
+    fi
+
+    if [[ ! -f "${source_file}" ]]
+    then
+        tue-install-debug "Adding ${name} sources to apt-get"
+        source_needs_to_be_added=true
+    elif [[ $(cat "${source_file}") != "${source_url}" ]]
+    then
+        tue-install-debug "Updating ${name} sources to apt-get"
+        source_needs_to_be_added=true
+    else
+        tue-install-debug "${name} sources already added to apt-get"
+    fi
+
+    if [[ "${source_needs_to_be_added}" == "true" ]]
+    then
+        echo "${source_url}" | sudo tee "${source_file}" > /dev/null
+        tue-install-debug "Successfully added/updated ${name} source file in apt"
+
+        apt_needs_to_be_updated=true
+    fi
+
+    if [[ "${apt_needs_to_be_updated}" == "true" ]]
+    then
+        tue-install-apt-get-update
+    fi
+}
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
 function _tue-install-pip
 {
     local pv name