about summary refs log tree commit diff stats
path: root/pkgs/by-name/fu/fupdate/fupdate.sh
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/fu/fupdate/fupdate.sh')
-rwxr-xr-xpkgs/by-name/fu/fupdate/fupdate.sh197
1 files changed, 197 insertions, 0 deletions
diff --git a/pkgs/by-name/fu/fupdate/fupdate.sh b/pkgs/by-name/fu/fupdate/fupdate.sh
new file mode 100755
index 00000000..4322610a
--- /dev/null
+++ b/pkgs/by-name/fu/fupdate/fupdate.sh
@@ -0,0 +1,197 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+UPDATE_SCRIPT_NAME="update.sh"
+CONFIG_DIRECTORY_PATH="$HOME/.local/share/flake-update"
+
+# Both are used in version()
+# shellcheck disable=SC2034
+AUTHORS="Soispha"
+# shellcheck disable=SC2034
+YEARS="2023"
+
+UPDATE_SCRIPT_NOT_WANTED=false
+
+# Searches upward for a `UPDATE_SCRIPT_NAME` script
+# Returns a path to the script if it exists, otherwise nothing is returned
+check_for_update_script() {
+    dirname="$(search_upward_files "$UPDATE_SCRIPT_NAME")"
+    if [ "$dirname" ]; then
+        printf "%s/%s" "$dirname" "$UPDATE_SCRIPT_NAME"
+    fi
+}
+
+# Checks if a given path to the update script is allowed.
+# Takes the path as input
+# Return 0, if allowed, 1 if not.
+check_for_allowed_update_script() {
+    update_script="$1"
+    config_path="${CONFIG_DIRECTORY_PATH}${update_script}"
+    update_script_hash="$(sha256sum "$update_script")"
+    if [ -f "$config_path" ]; then
+        if [ "$(cat "$config_path")" = "$update_script_hash" ]; then
+            dbg "Recorded hash matches"
+            return 0
+        else
+            dbg "Recorded hash \'$(cat "$config_path")\' does not match real hash \'$update_script_hash\', assuming not allowed"
+            return 1
+        fi
+    else
+        dbg "Path \'$config_path\' does not exist, assuming not allowed"
+        return 1
+    fi
+}
+
+# Asks the user if they want to allow a given script.
+# Takes the path as input
+ask_to_allow_update_script() {
+    update_script="$1"
+    config_path="${CONFIG_DIRECTORY_PATH}${update_script}"
+    update_script_hash="$(sha256sum "$update_script")"
+    println "\033[2J" # clear the screen
+    cat "$update_script"
+    readp "Do you want to allow this script?[N/y]: " allow
+    # shellcheck disable=SC2154
+    dbg "allow is: $allow"
+    case "$allow" in
+    [yY])
+        dbg "allowed script"
+        dbg "storing contents in: $config_path"
+        mkdir --parents "$(dirname "$config_path")"
+        print "$update_script_hash" >"$config_path"
+        ;;
+    *)
+        UPDATE_SCRIPT_NOT_ALLOWED=true
+        ;;
+    esac
+}
+
+# Runs the provided script and continues to update the nix flake
+# Takes the path to the script and the directory to the flake as arguments
+# If the path to the update script is empty, it will be ignored
+update() {
+    update_script="$1"
+    flake_base_dir="$2"
+    shift 2
+    dbg "Provided following args to update script: '$*'"
+
+    cd "$flake_base_dir" || die "Provided dir \'$flake_base_dir\' can not be accessed"
+    dbg "changed directory to: $flake_base_dir"
+
+    nix flake update
+
+    if ! [ "$update_script" = "" ] && ! [ "$UPDATE_SCRIPT_NOT_WANTED" = "true" ]; then
+        "$update_script" "$@"
+    fi
+
+    if grep '[^0-9]_[0-9]' flake.lock >/dev/null; then
+        batgrep '[^0-9]_[0-9]' flake.lock
+        die "Your flake.nix contains duplicate inputs!"
+    fi
+}
+
+help() {
+    cat <<EOF
+This is a Nix flake update manager.
+
+USAGE:
+    $NAME [--help | --version] [flake [--no-script] | <some other command>]
+
+OPTIONS:
+    --help   | -h
+                            Display this help and exit.
+
+    --version   | -v
+                            Display version and copyright information and exit.
+
+    --no-script
+                            Avoid running the 'update.sh' script
+COMMANDS:
+    flake
+                            update the flake project
+
+    <some other command>
+                            runs a executable called "update-<some other command>", if it exists
+EOF
+}
+
+main() {
+    if ! [ "$UPDATE_SCRIPT_NOT_ALLOWED" = true ]; then
+        update_script="$(check_for_update_script)"
+        flake_base_dir="$(search_flake_base_dir)" # Assume, that the update script is in the base dir
+        dbg "update_script is: $update_script"
+        dbg "flake_base_dir is: $flake_base_dir"
+
+        if [ "$update_script" = "" ]; then
+            update "" "$flake_base_dir" "$@"
+        elif check_for_allowed_update_script "$update_script" && ! [ "$update_script" = "" ]; then
+            update "$update_script" "$flake_base_dir" "$@"
+        else
+            ask_to_allow_update_script "$update_script"
+            main "$@"
+        fi
+    fi
+}
+
+if [ "$#" -eq 0 ]; then
+    main
+    exit 0
+fi
+
+for input in "$@"; do
+    case "$input" in
+    "--help" | "-h")
+        help
+        exit 0
+        ;;
+    "--version" | "-v")
+        version
+        exit 0
+        ;;
+    "--no-script" | "-n")
+        UPDATE_SCRIPT_NOT_WANTED=true
+        ;;
+    "--")
+        end_of_cli_options=true
+
+        # Stop processing args after that marker.
+        break
+        ;;
+    esac
+    [ "$end_of_cli_options" = "true" ] && break
+done
+
+case "$1" in
+"flake")
+    shift 1
+
+    # Filter out fupdate specific flags
+    while [ "$1" != "--" ]; do
+        # FIXME: This check allows to add a flag multiple times, but this should probably
+        # not be allowed <2024-03-29>
+        case "$1" in
+        "--no-script" | "-n")
+            shift 1
+            ;;
+        *)
+            break
+            ;;
+        esac
+    done
+
+    [ "$1" = "--" ] && shift 1
+    main "$@"
+    ;;
+*)
+    command="$1"
+    shift 1
+    [ "$1" = "--" ] && shift 1
+    if which update-"$command" >/dev/null 2>&1; then
+        update-"$command" "$@"
+    else
+        die "command \"update-$command\" is not executable, or does not exist"
+    fi
+    ;;
+esac