# vim: ft=sh die() { echo "$@" >&2 kill $$ } # Returns name of this module module_id() { $(basename "$0") } # Status file for this module MC_STATUS_FILE="$MC_STATUS_DIR/$(module_id)" # Return hash of given file from status file # First argument have to be a path to output file installed_hash() { awk -F '\t' -v regex="^$1$" '/$2 ~ regex { print $1 }' "$MC_STATUS_FILE" } # Hash of currently installed file # Access remote resource # It connects to remote server and requests resource for given plugin. # It expects only one argument and that is resource identifier. remote_source() { local res="$1" local mod_id="$(module_id)" if [ -n "$MC_LOCAL_DIR" ]; then "$MC_LOCAL_DIR/request.sh" "$mod_id:$res" else ssh -i ~/.ssh/multiconfig multiconfig@cynerd.cz -- "$mod_id:$res" fi } # Defined and create QUEUE file for this instance MC_QUEUE_FILE="$(mktemp multiconfig-$(module_id).queue.XXXXXX)" touch "$MC_QUEUE_FILE" # Variable signaling if file was updated or not change=false # Install given file # First argument has to be a identifier string for remote script # Second argument has to be an output file (absolute path). inst() { local src="$1" local out="$2" [ -f "$MC_QUEUE_FILE" ] || die "inst can be called only before apply call!" grep -q "\t$out$" || die "inst can be called on one output only once!" # TODO verify that this output is not already in queue local tmp="$(mktemp multiconfig.XXXXXXXXXX)" remote_source "$src" > "$tmp" local refhash="$(installed_hash "$out")" if [ -n "$refhash" ]; then change=false if [ -f "$out" ]; then local cursha="$(sha256 "$out")" if [ "$cursha" != "$(sha256 "$tmp")" ]; then echo "Updating file ($src): $out" [ "$cursha" = "$refhash" ] || echo "File was edited manually! $out" echo "$tmp $out" >> "$MC_QUEUE_FILE" change=true fi else echo "Output is not a file! $out" echo "$tmp $out" >> "$MC_QUEUE_FILE" change=true fi else echo "New file ($src): $out" echo "$tmp $out" >> "$MC_QUEUE_FILE" change=true fi } # Apply all queued changes and cleanup apply() { local new="$MC_STATUS_FILE.new" echo -n > "$new" while IFS=\t read src out; do if [ -e "$out" ]; then local trash="$MC_TRASH_DIR/$out.$(date +%y%m%d%H%M%S)" if [ -f "$out" ]; then if [ "$(installed_hash "$out")" != "$(sha256 "$out")" ]; then echo "File was manually changed: $out -> $trash" cp "$out" "$trash" fi else echo "Path exists but is not a file: $out -> $trash" mv "$out" "$trash" fi fi echo "Updating: $out" mv "$src" "$out" sha256 "$out" >> "$new" done < "$MC_QUEUE_FILE" rm "$MC_QUEUE_FILE" mv "$new" "$MC_STATUS_FILE" change= } # TODO somehow add support for installing directories. Most probably by having # remote script returning list of files in directory and then calling inst on # them. # Returns string informing you of distribution type but only if given distribution # is supported. If ditribution is not supported then it returns "unknown". distribution() { if [ -f /etc/gentoo-release ]; then echo "gentoo" elif [ -f /etc/alpine-release ]; then echo "alpine" elif [ -f /etc/openwrt_version ]; then echo "openwrt" else echo "unknown" fi }