Files
love-release/love-release.sh
Antonin Décimo 6302efed97 Options & file args support with GNU getopt
Short options are stored in the OPTIONS variable, and longs in
LONG_OPTIONS. Modules scripts need to add theses to be able to use
options. Theses lines are then parsed by sed at make-time and added to
the corresponding variable in the main script.

init_module now requires a third argument corresponding to the option
that will trigger the execution of the module.

Files can also be passed by argument to zip. They are stored in the
FILES array.

check_deps:
    - add dependency check for GNU getopt,
    - echo errors to stderr

gen_version now returns 0 on success and 1 on failure.

Add short_help function. Shown if -h options is passed, or on parsing
options failure.

exit_module:
    - add 'options' exit value if there is an error while parsing the
      options,
    - add 'version' exit value if there is an error while generating
      LÖVE version from user input.

dump_var shows files to zip.

Script will now exit if it has not been embedded nor installed.
Fix bugs with default module.
2015-06-22 22:54:49 +02:00

419 lines
10 KiB
Bash
Executable File

#!/usr/bin/env bash
# LÖVE version
LOVE_DEF_VERSION=0.9.2
# Helper functions
# Dependencies check
check_deps () {
command -v curl > /dev/null 2>&1 || {
>&2 echo "curl is not installed. Aborting."
local EXIT=true
}
command -v zip > /dev/null 2>&1 || {
>&2 echo "zip is not installed. Aborting."
local EXIT=true
}
command -v unzip > /dev/null 2>&1 || {
>&2 echo "unzip is not installed. Aborting."
local EXIT=true
}
command -v getopt > /dev/null 2>&1 || {
local opt=false
} && {
unset GETOPT_COMPATIBLE
local out=$(getopt -T)
if [[ $? -eq 4 && -z $out ]]; then
local opt=false
fi
}
if [[ $opt == false ]]; then
>&2 echo "GNU getopt is not installed. Aborting."
local EXIT=true
fi
command -v lua > /dev/null 2>&1 || {
echo "lua is not installed. Install it to ease your releases."
} && {
LUA=true
}
if [[ $EXIT == true ]]; then
exit 1
fi
}
# Get user confirmation, simple Yes/No question
## $1: message, usually just a question
## $2: default choice, 0 - yes; 1 - no, default - yes
## return: 0 - yes, 1 - no
get_user_confirmation () {
if [[ -z $2 || $2 == "0" ]]; then
read -n 1 -p "$1 [Y/n]: " yn
local default=0
else
read -n 1 -p "$1 [y/N]: " yn
local default=1
fi
case $yn in
[Yy]* )
echo; return 0;;
[Nn]* )
echo; return 1;;
"" )
return $default;;
* )
echo; return $default;;
esac
}
# Generate LÖVE version variables
## $1: LÖVE version string
## return: 0 - string matched, 1 - else
gen_version () {
if [[ $1 =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
LOVE_VERSION=$1
LOVE_VERSION_MAJOR=${BASH_REMATCH[1]}
LOVE_VERSION_MINOR=${BASH_REMATCH[2]}
LOVE_VERSION_REVISION=${BASH_REMATCH[3]}
return 0
fi
return 1
}
# Compare two LÖVE versions
## $1: First LÖVE version
## $2: comparison operator
## "ge", "le", "gt" "lt"
## ">=", "<=", ">", "<"
## $3: Second LÖVE version
## return: 0 - true, 1 - false
compare_version () {
if [[ $1 =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
local v1_maj=${BASH_REMATCH[1]}
local v1_min=${BASH_REMATCH[2]}
local v1_rev=${BASH_REMATCH[3]}
else
return 1
fi
if [[ $2 =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
local v2_maj=${BASH_REMATCH[1]}
local v2_min=${BASH_REMATCH[2]}
local v2_rev=${BASH_REMATCH[3]}
else
return 1
fi
case $2 in
ge|\>= )
if (( $v1_maj >= $v2_maj && $v1_min >= $v2_min && $v1_rev >= $v2_rev )); then
return 0
else
return 1
fi
;;
le|\<= )
if (( $v1_maj <= $v2_maj && $v1_min <= $v2_min && $v1_rev <= $v2_rev )); then
return 0
else
return 1
fi
;;
gt|\> )
if (( $v1_maj > $v2_maj || ( $v1_max == $v2_max && $v1_min > $v2_min ) ||
( $v1_max == $v2_max && $v1_min == $v2_min && $v1_rev > $v2_rev ) )); then
return 0
else
return 1
fi
;;
lt|\< )
if (( $v1_maj < $v2_maj || ( $v1_max == $v2_max && $v1_min < $v2_min ) ||
( $v1_max == $v2_max && $v1_min == $v2_min && $v1_rev < $v2_rev ) )); then
return 0
else
return 1
fi
;;
esac
}
# Escape directory name for zip
## $1: directory path
## echo: escaped directory path
dir_escape () {
local dir="$1"
if [ -d "$dir" ]; then
if [ "${dir::1}" != "/" ]; then
dir="/$dir"
fi
if [ "${dir: -1}" != "*" ]; then
if [ "${dir: -1}" != "/" ]; then
dir="$dir/*"
else
dir="$dir*"
fi
fi
fi
echo "$dir"
}
# Read configuration
## $1: system name
read_config () {
if [[ $LUA == true ]] && [[ -f "conf.lua" ]]; then
local var=$(lua - <<EOF
f = loadfile("conf.lua")
t, love = {window = {}, modules = {}, screen = {}}, {}
f()
love.conf(t)
-- "love", "windows", "osx", "debian" or "android"
os = "$1"
fields = {
"identity", "version", "game_version", "icon", "exclude",
"title", "author", "email", "url", "description", }
for _, f in ipairs(fields) do
t[f] = t[f] or ""
end
for _, v in ipairs(t.os) do
t.os[v] = {}
end
if os == "default" then
if not t.os then t.os = {} end
if not t.os.love then t.os.love = {} end
t.os.default = t.os.love
end
if t.os[os] then
print(os:upper()..'=true')
for _, f in ipairs(fields) do
t.os[os][f] = t.os[os][f] or t[f]
if type(t.os[os][f]) == "table" then
str = f:upper()..'=('
for _, v in ipairs(t.os[os][f]) do
str = str..' "'..v..'"'
end
str = str..' )'
print(str)
else
print(f:upper()..'="'..t.os[os][f]..'"')
end
end
else
print(os:upper()..'=false')
end
if t.os.windows and os == "windows" then
t.os.windows.x32 = t.os.windows.x32 and true or false
t.os.windows.x64 = t.os.windows.x64 and true or false
t.os.windows.installer = t.os.windows.installer and true or false
t.os.windows.appid = t.os.windows.appid or ""
print("X32="..tostring(t.os.windows.x32))
print("X64="..tostring(t.os.windows.x64))
print("INSTALLER="..tostring(t.os.windows.installer))
print("APPID="..t.os.windows.appid)
end
EOF
)
eval "$var"
fi
}
# Test if default module should be executed
default_module () {
if [[ $? -ne 2 ]]; then
DEFAULT_MODULE=false
fi
}
# Print short help
short_help () {
cat <<EOF
Usage: love-release.sh [options...] [files...]
Options:
-h Print short help
-n <name> Set the project's name
-r <release> Set the release directory
-v <version> Set the LÖVE version
EOF
}
dump_var () {
echo "LOVE_VERSION=$LOVE_VERSION"
echo "LOVE_DEF_VERSION=$LOVE_DEF_VERSION"
echo "LOVE_WEB_VERSION=$LOVE_WEB_VERSION"
echo
echo "RELEASE_DIR=$RELEASE_DIR"
echo "CACHE_DIR=$CACHE_DIR"
echo
echo "IDENTITY=$IDENTITY"
echo "GAME_VERSION=$GAME_VERSION"
echo "ICON=$ICON"
echo
echo "TITLE=$TITLE"
echo "AUTHOR=$AUTHOR"
echo "EMAIL=$EMAIL"
echo "URL=$URL"
echo "DESCRIPTION=$DESCRIPTION"
echo
echo "${FILES[@]}"
}
# Modules functions
# Init module
## $1: Pretty module name
## $2: Configuration module name
## $3: Module option
## return: 0 - if module should be executed, else exit 2
init_module () {
(
opt="$3"
if (( ${#opt} == 1 )); then opt="-$opt"
elif (( ${#opt} >= 2 )); then opt="--$opt"; fi
eval set -- "$ARGS"
while true; do
case "$1" in
$opt ) exit 0 ;;
-- ) exit 1 ;;
* ) shift ;;
esac
done
)
local opt=$?
local module="$2"
read_config "$module"
module=${module^^}
if (( $opt == 1 )); then
if [[ ${!module} == false ]]; then exit_module "execute"; fi
fi
if compare_version "$LOVE_VERSION" ">" "$VERSION"; then
echo "LÖVE $LOVE_VERSION is out ! Your project uses LÖVE ${VERSION}."
gen_version $VERSION
unset VERSION
fi
MODULE="$1"
mkdir -p "$RELEASE_DIR" "$CACHE_DIR"
echo "Generating $TITLE with LÖVE $LOVE_VERSION for ${MODULE}..."
return 0
}
# Create the LÖVE file
## $1: Compression level 0-9
create_love_file () {
LOVE_FILE="$RELEASE_DIR"/"$TITLE".love
zip -FS -$1 -r "$LOVE_FILE" \
-x "$0" "${RELEASE_DIR#$PWD/}/*" \
$(ls -Ap | grep "^\." | sed -e 's/^/\//g' -e 's/\/$/\/*/g') @ \
"${FILES[@]}"
}
# Exit module
## $1: optional error identifier
## $2: optional error message, printed if $1=="undef" or unidentified error
exit_module () {
if [[ -z $1 ]]; then
echo "Done !"
exit 0
fi
case $1 in
execute )
exit 2 ;;
binary )
>&2 echo "LÖVE $LOVE_VERSION could not be found or downloaded."
exit 3 ;;
options )
exit 4 ;;
version )
>&2 echo "LÖVE version string is invalid."
exit 5 ;;
undef|* )
if [[ -n $2 ]]; then
>&2 echo "$2"
fi
exit 1 ;;
esac
}
# Main
check_deps
# Get latest LÖVE version number
gen_version $LOVE_DEF_VERSION
LOVE_WEB_VERSION=$(curl -s https://love2d.org/releases.xml | grep -m 2 "<title>" | tail -n 1 | grep -Eo "[0-9]+.[0-9]+.[0-9]+")
gen_version $LOVE_WEB_VERSION
INSTALLED=false
EMBEDDED=false
DEFAULT_MODULE=true
TITLE="$(basename $(pwd))"
RELEASE_DIR=releases
CACHE_DIR=~/.cache/love-release
FILES=()
OPTIONS="lhn:r:v:"
LONG_OPTIONS=""
ARGS=$(getopt -o "$OPTIONS" -l "$LONG_OPTIONS" -n 'love-release' -- "$@")
if (( $? != 0 )); then short_help; exit_module "options"; fi
eval set -- "$ARGS"
while true; do
case "$1" in
-n ) TITLE="$2"; shift 2 ;;
-r ) RELEASE_DIR="$2"; shift 2 ;;
-v ) if ! gen_version "$2"; then exit_module "version"; fi; shift 2 ;;
-h ) short_help; exit 0 ;;
-- ) shift; break ;;
* ) shift ;;
esac
done
for arg do
FILES+=( "$arg" )
done
if (( ${#FILES} == 0 )); then FILES+=( "." ); fi
if [[ $INSTALLED == false && $EMBEDDED == false ]]; then
exit_module "undef" "love-release has not been installed, and is not embedded into one script."
fi
if [[ $EMBEDDED == true ]]; then
: # include_scripts_here
elif [[ $INSTALLED == true ]]; then
SCRIPTS_DIR="scripts"
for file in "$SCRIPTS_DIR"/*.sh; do
(source "$file")
default_module
done
fi
(
(init_module "LÖVE" "love" "l")
if [[ $? -eq 0 || $DEFAULT_MODULE == true ]]; then
init_module "LÖVE" "default"
create_love_file 9
exit_module
fi
)
exit 0