#!/usr/bin/env bash function wayland_check() { if [ -n "$XDG_SESSION_ID" ]; then session_type=$(loginctl show-session "$XDG_SESSION_ID" -p Type 2>/dev/null | cut -d= -f2) else session_type="" fi case "$session_type" in wayland) export GDK_BACKEND=x11 echo "Running on Wayland" ;; x11) echo "Running on X" ;; "") echo "Running on TTY" ;; *) echo "Not sure where I am running" ;; esac } root="" function root_check() { if [ "$(id -u)" != 0 ]; then if [ -f /usr/bin/sudo ]; then echo "$(tput bold)INFO: Using sudo for root operations.$(tput sgr0)" root="sudo" elif [ -f /usr/bin/doas ]; then echo "$(tput bold)INFO: Using doas for root operations.$(tput sgr0)" root="doas" fi fi } function set_variables() { # DEBUG mod #bash -x ./dh 2>&1 | tee output.log #progname="${progname:="${0##*/}"}" progname="DistroHopper" version="0.91" #GTK_THEME="alt-dialog" DH_CONFIG_DIR="$HOME/.config/dh" DH_CONFIG="$DH_CONFIG_DIR/config" DH_ICON_DIR="$DH_CONFIG_DIR/icons" VMS_DIR="$HOME/vm" PATH_PREFIX="/usr/bin/" TMP_DIR="/tmp" terminal="sakura" replace='"!"' export DH_CONFIG_DIR DH_CONFIG replace DH_ICON_DIR PATH_PREFIX TMP_DIR terminal VMS_DIR #check_and_set_mode # Set traps to catch the signals and exit gracefully trap "exit" INT } # installation --------------------------------------------------------- function dependencies_check_gui() { [ -f "$PATH_PREFIX/yad" ] || echo "Yad not installed!" } function install_needed_apt() { $root apt install qemu bash coreutils ovmf grep jq lsb procps python3 genisoimage usbutils util-linux sed spice-client-gtk swtpm wget xdg-user-dirs zsync unzip yad } function install_needed_pacman() { $root pacman -S cdrtools coreutils edk2-ovmf grep jq procps python3 qemu-full sed socat spice-gtk swtpm usbutils util-linux wget xdg-user-dirs xorg-xrandr zsync getext yad } function install_needed_xbps() { $root xbps-install -S qemu bash coreutils grep jq procps-ng python3 util-linux sed spice-gtk swtpm usbutils wget xdg-user-dirs xrandr unzip zsync socat yad } function install_needed_dnf() { $root dnf install qemu bash coreutils edk2-tools grep jq lsb procps python3 genisoimage usbutils util-linux sed spice-gtk-tools swtpm wget xdg-user-dirs xrandr unzip yad } function install_dependencies() { # Find the current distribution and install dependecies if [ -f /etc/os-release ]; then if [ -f "$PATH_PREFIX/pacman" ]; then install_needed_pacman elif [ -f "$PATH_PREFIX/apt" ]; then install_needed_apt elif [ -f "$PATH_PREFIX/xbps-install" ]; then install_needed_xbps elif [ -f "$PATH_PREFIX/dnf" ]; then install_needed_dnf else echo "Error unknown distro!" #exit 1 fi fi } function create_dirs() { mkdir -p "$DH_CONFIG_DIR" touch "$DH_CONFIG" mkdir -p "$DH_ICON_DIR" } function choose_vms_dir() { NEWDIR="$(yad --width=900 --height=900 --file --directory --title="Where to save VMs?")" VMS_DIR="$NEWDIR" export VMS_DIR echo "VMS_DIR=\"$VMS_DIR\"\nexport VMS_DIR" > "$DH_CONFIG" } DH_VERSION_FILE="" function install_dh() { DH_VERSION_FILE="$DH_CONFIG_DIR/version" local install_type="fresh" if [ -f "$DH_VERSION_FILE" ]; then local old_version old_version=$(cat "$DH_VERSION_FILE") if [ "$old_version" != "$version" ]; then install_type="upgrade" echo "Upgrading DistroHopper $old_version → $version" else install_type="reinstall" echo "DistroHopper $version already installed" fi else echo "Installing DistroHopper $version" fi cp -f generate qget q dh quickemu quickreport chunkcheck "$PATH_PREFIX" >/dev/null 2>&1 || $root cp -f generate qget q dh quickemu quickreport chunkcheck "$PATH_PREFIX" cp -f icons/* "$DH_ICON_DIR/" >/dev/null 2>&1 || $root cp -f icons/* "$DH_ICON_DIR/" mkdir -p "$DH_CONFIG_DIR/ready" mkdir -p "$DH_CONFIG_DIR/supported" echo "$version" > "$DH_VERSION_FILE" } # shellcheck disable=SC2154 function create_desktop_entry() { cat <${DESKTOP_FILE} [Desktop Entry] Version=$version Type=$type Name=$name GenericName=$gname Comment=$comment Exec=$execmd Icon=$icon Terminal=$terminal X-MultipleArgs=$args Type=$type Categories=$categories StartupNotify=$notify MimeType=$mime Keywords=$keyword EOF } function desktop_entry_dh() { echo "$MSG_INTERM" run_in_terminal DESKTOP_FILE="${TMP_DIR}/dh.desktop" type='Application' name='DistroHopper' comment='Quickly download, create and run VM of any operating system.' version="${version}" execmd="sh -c 'cd ${VMS_DIR} && dh'" if [ "$interminal" = "yes" ]; then terminal='true' fi icon="$DH_ICON_DIR/hop.svg" categories='System;Virtualization;' export -f create_desktop_entry create_desktop_entry $root cp "${TMP_DIR}/dh.desktop" /usr/share/applications/ } function installation_process() { dependencies_check_gui install_dependencies create_dirs choose_vms_dir install_dh desktop_entry_dh } # basic ---------------------------------------------------------------- #run_in_terminal() { # yad --title "terminal" --text "Do you want show output in the terminal?" && interminal="yes" || interminal="no" #} function renew_ready_vms() { cd "$VMS_DIR" || { echo "ERROR: VMS_DIR not set!"; exit 1; } rm -r "$DH_CONFIG_DIR"/ready >/dev/null 2>&1 mkdir -p "$DH_CONFIG_DIR"/ready for vm_conf in *.conf; do VMname=$(basename "$VMS_DIR/$vm_conf" .conf) echo "creating $VMname" # Use fuzzy matching to find the best matching icon file (ready to run VMs) icon_name=$(basename "$VMS_DIR/$vm_conf" .conf | cut -d'-' -f -2) icon_file=$(find "$DH_ICON_DIR" -type f -iname "${icon_name// /}.*") # If no icon was found, try shorter name (ready to run VMs) if [ -z "$icon_file" ]; then icon_name=$(basename "$VMS_DIR/$vm_conf" .conf | cut -d'-' -f1) icon_file=$(find "$DH_ICON_DIR" -type f -iname "${icon_name// /}.*") fi if [ -z "$icon_file" ]; then icon_file="$DH_ICON_DIR/tux.svg" fi DESKTOP_FILE="${DH_CONFIG_DIR}/ready/${VMname}.desktop" type='Application' name="${VMname}" comment=$(qget "$VMname" | grep 'Description:' | cut -d: -f2) version="${version}" execmd="sh -c 'cd ${VMS_DIR} && quickemu -vm ${vm_conf};$SHELL'" icon="${icon_file}" categories='System;Virtualization;' create_desktop_entry done } function renew_ready() { cd "$VMS_DIR" || { echo "ERROR: VMS_DIR not set!"; exit 1; } # for files in "$VMS_DIR"/*; do # if [ ! -e *.conf ]; then # echo $"No .conf files found" # return # fi for vm_conf in *.conf; do if [ "$vm_conf" == "distrohopper.conf" ]; then continue # skip processing distrohopper.conf fi VMname=$(basename "$VMS_DIR/$vm_conf" .conf) # Use fuzzy matching to find the best matching icon file (ready to run VMs) icon_name=$(basename "$VMS_DIR/$vm_conf" .conf | cut -d'-' -f -2) icon_file=$(find "$DH_ICON_DIR" -type f -iname "${icon_name// /}.*") # If no icon was found, try shorter name (ready to run VMs) if [ -z "$icon_file" ]; then icon_name=$(basename "$VMS_DIR/$vm_conf" .conf | cut -d'-' -f1) icon_file=$(find "$DH_ICON_DIR" -type f -iname "${icon_name// /}.*") fi if [ -z "$icon_file" ]; then icon_file="$DH_ICON_DIR/tux.svg" fi # content of desktop files (ready to run VMs) mkdir -p "$DH_CONFIG_DIR/ready" cat <"$DH_CONFIG_DIR/ready/$VMname.desktop" [Desktop Entry] Type=Application Name=$VMname Exec=sh -c 'cd ${VMS_DIR} && quickemu -vm ${vm_conf}' Icon=$icon_file Categories=System;Virtualization; EOF done } function renew_supported_vms() { local qget_cmd if [ -x "./qget" ]; then qget_cmd="./qget" elif [ -x "$PATH_PREFIX/qget" ]; then qget_cmd="$PATH_PREFIX/qget" else qget_cmd="qget" fi echo "Regenerating supported" rm -r "$DH_CONFIG_DIR"/supported >/dev/null 2>&1 mkdir -p "$DH_CONFIG_DIR"/supported $qget_cmd | awk 'NR==3,/zorin/' | grep -o '[^ ]*' >"$DH_CONFIG_DIR/supported.md" while read -r get_name; do VMname=$(echo "$get_name" | tr ' ' '_') releases=$($qget_cmd "$VMname" | grep 'Releases' | cut -d: -f2 | sed 's/^ //' | sed 's/ *$//') editions=$($qget_cmd "$VMname" | grep 'Editions' | cut -d: -f2 | sed 's/^ //' | sed 's/ *$//') architectures=$($qget_cmd "$VMname" | grep "Architectures" | cut -d: -f2 | sed "s/^ //" | sed "s/ *$//") icon_name="$DH_ICON_DIR/$get_name" if [ -f "$icon_name.svg" ]; then icon_file="$icon_name.svg" elif [ -f "$icon_name.png" ]; then icon_file="$icon_name.png" else icon_file="$DH_ICON_DIR/tux.svg" fi echo "creating $VMname entry" echo "" # Check if there are editions DESKTOP_FILE="$DH_CONFIG_DIR/supported/$VMname.desktop" type="Application" name="$get_name" arch_opts="${architectures:-x86_64}" arch_opts_fmt=$(echo "$arch_opts" | tr ' ' '!') if [ -z "$editions" ]; then execmd="sh -c 'cd ${VMS_DIR} && GDK_BACKEND=x11 yad --form --field=\"Architecture:CB\" \"$arch_opts_fmt\" --field=\"Release:CB\" \"${releases// /$replace}\" | cut -d\"|\" -f2 | xargs -I{} sh -c \"qget --arch {} ${get_name} {}\";$SHELL'" elif [ "$interminal" = "yes" ]; then terminal="true" else execmd="sh -c 'cd ${VMS_DIR} && GDK_BACKEND=x11 yad --form --separator=\" \" --field=\"Architecture:CB\" \"$arch_opts_fmt\" --field=\"Release:CB\" \"${releases// /$replace}\" --field=\"Edition:CB\" \"${editions// /$replace}\" | cut -d\"|\" -f2- | xargs -I{} sh -c \"qget --arch {} ${get_name} {}\";$SHELL'" fi icon="$icon_file" categories='System;Virtualization;' create_desktop_entry done <"$DH_CONFIG_DIR"/supported.md } function distrohopper_about() { yad --about --pname=DistroHopper --image="$DH_ICON_DIR"/hop.svg --pversion="$version" \ --copyright=AGPL3 --comments="random comment" --license=ALGPL3 --authors=zenobit --website=dh.osowoso.org \ --website-label="oSoWoSo" } function help_show() { local help_text help_text="$(cat <