about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/scripts/source/apps/fupdate.sh
blob: da89d16a0300a0252796630dab134c964c63f48c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#! /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
        ;;
    esac
    [ "$end_of_cli_options" = "true" ] && break
done

case "$1" in
"flake")
    shift 1
    [ "$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