-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
259 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
#!/bin/bash | ||
|
||
# Trivial "Makefile-like" script for deploying this mod | ||
|
||
# Ideas: | ||
# Configure tar (backup) command-line arguments | ||
# Configure cp command-line arguments and/or behavior | ||
|
||
SELF="$(dirname "$0")" | ||
MOD_NAME="$(basename "$(readlink -f "$(dirname $0)")")" | ||
|
||
print_usage() { | ||
cat <<EOF >&2 | ||
usage: $0 [-h] [-v|-V] [-n] [-b DIR] [-C] [-N DIR] [-a ARG] [ACTION] | ||
actions: | ||
diff compare local and deployed versions of this mod (default) | ||
cp copy this mod to the Noita mods directory | ||
options: | ||
-h print this message and exit | ||
-v enable verbose diagnostics | ||
-V enable verbose diagnostics and set -x | ||
-n dry run; don't actually do anything | ||
-b DIR backup destination into DIR/ before overwriting | ||
-C disable color formatting | ||
-N DIR specify path to Noita game directory | ||
-a ARG prepend ARG to the diff command-line | ||
environment variables: | ||
NOITA path to Noita game directory | ||
STEAM path to steam root directory (used if NOITA isn't defined) | ||
EOF | ||
} | ||
|
||
NOITA_PATH="${NOITA:-}" | ||
declare -a DIFF_ARGS=() | ||
|
||
while getopts "hvVnb:CN:a:" arg; do | ||
case "$arg" in | ||
h) print_usage; exit 0;; | ||
v) DEBUG=1;; | ||
V) DEBUG=1; set -x;; | ||
b) BACKUP="$OPTARG";; | ||
n) DRY_RUN=1;; | ||
C) NOCOLOR=1;; | ||
N) NOITA_PATH="$OPTARG";; | ||
a) DIFF_ARGS+=("$OPTARG");; | ||
esac | ||
done | ||
shift $((OPTIND - 1)) | ||
|
||
ACTION="${1:-diff}" | ||
|
||
color() { # code message... | ||
let ncodes=$#-1 | ||
local IFS=';' | ||
local code=${*:1:$ncodes} | ||
local msg="${@:$#}" | ||
if [[ -z "${NOCOLOR:-}" ]]; then | ||
echo -e "\033[${code}m${msg}\033[0m" | ||
else | ||
echo "${msg}" | ||
fi | ||
} | ||
|
||
diag() { # prefix message... | ||
echo -e "$1: ${@:2}" >&2 | ||
} | ||
|
||
error() { diag "$(color 1 91 ERROR)" "$@"; } | ||
info() { diag "$(color 1 94 INFO)" "$@"; } | ||
warn() { diag "$(color 1 93 WARNING)" "$@"; } | ||
debug() { if [[ -n "${DEBUG:-}" ]]; then diag "$(color 1 92 DEBUG)" "$@"; fi; } | ||
|
||
dry() { # command... | ||
if [[ -z "${DRY_RUN:-}" ]]; then | ||
$@; return $? | ||
fi | ||
info "$(color 93 DRY): $@" | ||
return 0 # assume success | ||
} | ||
|
||
checked() { # command... | ||
local -a cmdargs=() | ||
for arg in "$@"; do | ||
local argq="$(printf '%q' "$arg")" | ||
if [[ "$argq" != "$arg" ]]; then | ||
cmdargs+=("'$arg'") | ||
else | ||
cmdargs+=("$arg") | ||
fi | ||
done | ||
debug "checked argv=${#cmdargs[@]} ${cmdargs[@]}" | ||
$@ | ||
local status=$? | ||
if [[ $status -ne 0 ]]; then | ||
error "command ${cmdargs[0]} exited non-zero $status" | ||
exit 1 | ||
fi | ||
return $status | ||
} | ||
|
||
# Compare two directories. Returns 1 on differences. | ||
compare_mods() { # local remote | ||
local diff_args=(${DIFF_ARGS[@]}) | ||
diff_args+=(-x "$(basename "$0")") # because this script isn't required | ||
diff_args+=(-x "*.tar.gz") # because backups | ||
if [[ -z "${DEBUG:-}" ]]; then | ||
diff_args+=("-q") | ||
fi | ||
if [[ -d "$2" ]]; then | ||
debug "diff ${diff_args[@]} -r -x '.*' '$1' '$2'" | ||
diff ${diff_args[@]} -r -x '.*' "$1" "$2" | ||
return $? | ||
fi | ||
return 1 | ||
} | ||
|
||
# Locate the Steam root directory | ||
find_steam() { | ||
if [[ -n "${STEAM:-}" ]]; then | ||
echo "$STEAM" | ||
return 0 | ||
fi | ||
|
||
if [[ -d "$HOME/.steam" ]]; then | ||
for link in steam root; do | ||
local slink="$HOME/.steam/$link" | ||
if [[ -h "$slink" && -d "$slink" ]]; then | ||
echo "$(readlink -f "$slink")" | ||
return 0 | ||
fi | ||
done | ||
fi | ||
|
||
return 1 | ||
} | ||
|
||
# True if the given path is a Noita installation directory | ||
is_noita_dir() { # path | ||
test -f "$1/noita.exe" | ||
return $? | ||
} | ||
|
||
# Locate the Noita game directory (the directory containing noita.exe) | ||
find_noita() { | ||
local noita_path="${NOITA_PATH:-}" | ||
if [[ -z "$noita_path" ]]; then | ||
local steam_root="$(find_steam)" | ||
if [[ $? -ne 0 ]]; then | ||
error "Failed to find Steam root directory" | ||
error "Please specify '-m path/to/Noita'" | ||
return 1 | ||
fi | ||
|
||
for sapps in SteamApps steamapps; do # this changed sometime after Ubuntu 12 | ||
if is_noita_dir "$steam_root/$sapps/common/Noita"; then | ||
noita_path="$steam_root/$sapps/common/Noita" | ||
fi | ||
done | ||
fi | ||
|
||
if [[ -z "$noita_path" ]]; then | ||
error "failed to locate Noita; please specify '-m path/to/Noita'" | ||
elif ! is_noita_dir "$noita_path"; then | ||
error "$noita_path does not contain noita.exe; is this the correct path?" | ||
else | ||
echo "$noita_path" | ||
return 0 | ||
fi | ||
return 1 | ||
} | ||
|
||
# Archive the given path | ||
archive_path() { # archive-name path | ||
local tar_file="$(readlink -f "$1")" | ||
if [[ -z "$tar_file" ]]; then | ||
error "failed to resolve $1" | ||
return 1 | ||
fi | ||
|
||
local -a tar_args=() | ||
if [[ -n "${DEBUG:-}" ]]; then | ||
tar_args+=(cvfz) | ||
else | ||
tar_args+=(cfz) | ||
fi | ||
tar_args+=("$tar_file") | ||
tar_args+=(--exclude .git) | ||
tar_args+=(--exclude '*.swp') | ||
|
||
pushd "$2/.." >/dev/null | ||
checked tar ${tar_args[@]} "$(basename "$2")" | ||
popd >/dev/null | ||
} | ||
|
||
# Check if this archive is unique among the others in the directory | ||
archive_is_unique() { # path file | ||
local file_hash="$(md5sum "$2" | awk '{ print $1 }')" | ||
local file_name="$(basename "$2")" | ||
for file in "$1"/*; do | ||
local test_name="$(basename "$file")" | ||
if [[ "$test_name" != "$file_name" ]]; then | ||
local test_hash="$(md5sum "$file" | awk '{ print $1 }')" | ||
if [[ "$test_hash" == "$file_hash" ]]; then | ||
warn "Archive $2 duplicates $file" | ||
return 1 | ||
fi | ||
fi | ||
done | ||
return 0 | ||
} | ||
|
||
NOITA="$(find_noita)" | ||
if [[ $? -ne 0 ]]; then | ||
error "Aborting" | ||
exit 1 | ||
fi | ||
|
||
DEST_DIR="$NOITA/mods/$MOD_NAME" | ||
debug "Comparing . (as $MOD_NAME) with $DEST_DIR" | ||
|
||
compare_mods "$SELF" "$DEST_DIR" | ||
DIFF_STATUS=$? | ||
|
||
if [[ $DIFF_STATUS -eq 0 ]]; then | ||
info "No differences detected" | ||
exit 0 | ||
fi | ||
|
||
info "Detected differences between local and deployed directories" | ||
if [[ "$ACTION" == "cp" ]]; then | ||
info "Copying . to $DEST_DIR" | ||
|
||
# Should we create a backup of the deployed directory? | ||
if [[ -n "${BACKUP:-}" ]]; then | ||
BKFILE="$BACKUP/$MOD_NAME-$(date +%Y%m%d-%H%M%S).tar.gz" | ||
checked archive_path "$BKFILE" "$DEST_DIR" | ||
info "Backed-up $DEST_DIR to $BKFILE" | ||
if ! archive_is_unique "$BACKUP" "$BKFILE"; then | ||
warn "$BKFILE duplicates a previous backup file; removing" | ||
checked rm "$BKFILE" | ||
fi | ||
fi | ||
|
||
# Deploy this mod to the destination directory | ||
if dry checked rm -r "$DEST_DIR"; then | ||
mkdir "$DEST_DIR" 2>/dev/null | ||
if dry checked cp -r "$SELF/*" "$DEST_DIR"; then | ||
info "Done" | ||
fi | ||
fi | ||
|
||
else | ||
info "Execute '$0 [ARGS...] cp' to deploy $MOD_NAME" | ||
fi | ||
|
||
|