aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/fu/fupdate-flake
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/fu/fupdate-flake')
-rwxr-xr-xpkgs/by-name/fu/fupdate-flake/fupdate-flake.sh180
-rw-r--r--pkgs/by-name/fu/fupdate-flake/package.nix25
2 files changed, 205 insertions, 0 deletions
diff --git a/pkgs/by-name/fu/fupdate-flake/fupdate-flake.sh b/pkgs/by-name/fu/fupdate-flake/fupdate-flake.sh
new file mode 100755
index 00000000..6d343995
--- /dev/null
+++ b/pkgs/by-name/fu/fupdate-flake/fupdate-flake.sh
@@ -0,0 +1,180 @@
+#! /usr/bin/env sh
+
+UPDATE_SCRIPT_NAME="update.sh"
+
+info() {
+ echo "Info: $1"
+}
+dbg() {
+ [ -n "$DEBUG_ENABLE" ] && echo "Debug: $1"
+}
+die() {
+ echo "Error: $1"
+ exit 1
+}
+
+# Search for a file “upwards”.
+# This will return the relative path from "$1" to the found file.
+#
+# # Type
+# upfind :: Path -> String -> Path
+#
+# # Arguments
+# $1
+# : The directory to use as start of your search.
+#
+# $2
+# : The file to search for.
+#
+# # Example
+# upfind "/home/user1" "/usr"
+# => /usr
+upfind() {
+ starting_directory="$(readlink --canonicalize "$1")"
+ search_string="$2"
+
+ current_directory="$starting_directory"
+
+ while
+ search_result=$(fd "$search_string" "$current_directory/" --max-depth 1)
+ dbg "Debugging upfind - search in $current_directory gives: $search_result"
+ [ -z "$search_result" ] && [ "$current_directory" != "/" ]
+ do current_directory=$(dirname "$current_directory"); done
+
+ realpath --relative-to="$1" "$search_result"
+}
+
+# Construct the storage path for the update script allowed hashes.
+#
+# # Type
+# get_storage_path :: Path -> Path
+#
+# # Arguments
+# $1
+# : The path to the update script
+#
+# # Returns
+# The constructed storage path.
+get_storage_path() {
+ update_script="$(realpath "$1")"
+
+ storage_path="$XDG_DATE_HOME/fupdate-flake/$update_script"
+ echo "$storage_path"
+}
+
+# Checks if a given path to the update script is allowed.
+#
+# # Type
+# is_allowed :: Path -> bool
+#
+# # Arguments
+# $1
+# : The path to the update script to check.
+#
+# # Return exit code
+# 0
+# : If the update script is allowed
+#
+# 1
+# : If it is not.
+is_allowed() {
+ update_script="$(realpath "$1")"
+
+ storage_path="$(get_storage_path "$update_script")"
+
+ # Use this invocation, to also include the path to the `$update_script`
+ update_script_hash="$(sha256sum "$update_script")"
+
+ if [ -f "$storage_path" ]; then
+ if [ "$(cat "$storage_path")" = "$update_script_hash" ]; then
+ return 0
+ else
+ return 1
+ fi
+ else
+ return 1
+ fi
+}
+
+# Asks the user if they want to allow a given script.
+#
+# # Type
+# ask_to_allow_update_script :: Path
+#
+# # Arguments
+# $1
+# : The path to the update script to ask for.
+ask_to_allow_update_script() {
+ update_script="$(realpath "$1")"
+
+ printf "\033[2J" # clear the screen
+ cat "$update_script"
+
+ printf "Do you want to allow this script?[N/y]: "
+ read -r allow
+
+ case "$allow" in
+ [yY])
+ info "Update script allowed."
+
+ storage_path="$(get_storage_path "$update_script")"
+ update_script_hash="$(sha256sum "$update_script")"
+
+ mkdir --parents "$(dirname "$storage_path")"
+ printf "%s" "$update_script_hash" >"$storage_path"
+ ;;
+ *)
+ info "Update script not allowed."
+ ;;
+ esac
+}
+
+# Performs a full update.
+# This consists of running an update script.
+# Additionally, it also checks for duplicated inputs in a `flake.lock` file, if it exists.
+#
+# # Type
+# update :: Path -> Path -> [String]
+#
+# # Arguments
+# $1
+# : The path to the update script to execute.
+#
+# $2
+# : The base directory from which to start the update.
+#
+# $3
+# : Arguments to pass to the update script.
+update() {
+ update_script="$1"
+ base_directory="$2"
+ shift 2
+
+ cd "$base_directory" || die "The provided base directory '$base_directory' cannot be accessed"
+ dbg "Changed directory to: $base_directory"
+
+ dbg "Executing update script ('$update_script') following args: '$*'"
+ "$update_script" "$@"
+
+ if [ -f "flake.lock" ] && grep '[^0-9]_[0-9]' flake.lock --quiet; then
+ batgrep '[^0-9]_[0-9]' flake.lock
+ die "Your flake.nix contains duplicate inputs!"
+ fi
+}
+
+main() {
+ base_directory="$(git rev-parse --show-toplevel)"
+ update_script="$(upfind "$PWD" "$UPDATE_SCRIPT_NAME")"
+ dbg "update_script is: $update_script"
+
+ if [ "$update_script" = "" ]; then
+ die "Failed to find update script."
+ elif is_allowed "$update_script"; then
+ update "$update_script" "$base_directory" "$@"
+ else
+ ask_to_allow_update_script "$update_script"
+ is_allowed "$update_script" && main "$@"
+ fi
+}
+
+# vim: ft=sh
diff --git a/pkgs/by-name/fu/fupdate-flake/package.nix b/pkgs/by-name/fu/fupdate-flake/package.nix
new file mode 100644
index 00000000..d2784169
--- /dev/null
+++ b/pkgs/by-name/fu/fupdate-flake/package.nix
@@ -0,0 +1,25 @@
+{
+ writeShellApplication,
+ # Dependencies
+ coreutils,
+ fd,
+ gnugrep,
+ bat-extras, # For `batgrep`
+ bat, # used by batgrep
+ gnused, # required by batgrep
+}:
+writeShellApplication {
+ name = "fupdate-flake";
+ tetx = builtins.readFile ./fupdate-flake.sh;
+
+ inheritPath = false;
+
+ runtimeInputs = [
+ coreutils
+ fd
+ gnugrep
+ bat-extras # For `batgrep`
+ bat # Used by `batgrep`
+ gnused # Required by `batgrep`
+ ];
+}