I am trying to make a script that automates download of SpigotMC BuildTools, detect input version ( sh build.sh <version>
) , and set a variable which is used if the version is greater or equal with 1.14 (since this release, SpigotMC discontinued the automation of auto-compilation of craftbukkit by default. Now it compiles only the spigot jar and I need both of them compiled for my personal purposes.)
Here is what I have tried (I'm a Linux newbie, so this might be messed up):
#!/bin/bash
# Sources:
# Append variables in bash : https://www.cyberciti.biz/faq/howto-linux-unix-bash-append-textto-variables/
# Check MANIFEST.MF content from jar file : https://www.manongdao.com/q-106728.html
# Check for specified property json file : https://stackoverflow.com/questions/34543829/jq-cannot-index-array-with-string
# https://www.ultralinux.org/post/json-bash/
# Bash Array : https://unix.stackexchange.com/questions/253892/syntax-error-unexpected-when-creating-an-array
# #######################################################################################################################################
#
# #######################################################################################################################################
# BuildTools Jar Info Variables
# -----------------------------
# BuilsTools working directory
buildtools_root="$(pwd)" # We use $(command) to store "command" output in a variable. We use ${command} if we have to stick other strings near it without whitespace.
# BuildTools jar location
buildtools_jar="$buildtools_root/BuildTools.jar"
# Current BuildTools jar version
buildtools_ver="$(unzip -p "$buildtools_jar" META-INF/MANIFEST.MF | grep 'Implementation-Version:' | cut -d '-' -f 5)"
# Jenkins Api-related variables.
# A. Retrieve BuildTools lastSuccessfulBuild link
targetJar="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.artifacts[].relativePath')"
lastSuccessfulBuild="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.url')"
# B. Make the download link
latestBuildToolsUrl="${lastSuccessfulBuild}artifacts/$targetJar"
# Latest BuildTools Build Version
latestBuildToolsVersion="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.number')"
displayFullName="$(curl -s 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/api/json' | jq -r '.fullDisplayName')"
# ---------------------------------------------------------------------------------------------------------------------------------------
# BuildTools Jar Run Variables
# -----------------------------
#
# #######################################################################################################################################
# This is a function to set java home to current java version in use.
javahome_set () {
JAVA_HOME=$(dirname "$(dirname "$( readlink -f /etc/alternatives/java )")")
OIFS=$IFS
IFS=':';
for i in $VAR;
do
JAVA1=$i/bin/java
JAVA2=$i/java
if [ -d "$i" ];
then
if [ ! -L "$JAVA1" ] && [ -x "$JAVA1" ] || [ ! -L "$JAVA2" ] && [ -x "$JAVA2" ]; then
echo "dropping path: $i";
else
NEW=$NEW:$i
fi
fi
done
IFS=$OIFS
JAVA_HOME=$NEW:$JAVA_HOME/bin
JAVA_HOME=${JAVA_HOME#:*}
}
javahome_set
# This function requires arguments. Checks if $1 >= $2
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
# This is a function to download the latest BuildTools version and check if download is successful.
buildtools_download () {
curl --silent "$latestBuildToolsUrl" --output BuildTools.jar #Request download to BuildTools.
if [ "$?" -eq 0 ]; then #Check if file was downloaded. It returns error code non-zero if file was not properly downloaded. (in this language)
echo "$Green Successful downloaded BuildTools.$Color_Off"
else
echo "$Red Error while downloading BuildTools. $Color_Off"
fi
}
# This is a function to check for updates for BuildTools jar
buildtools_check () {
if [ ! -e "$buildtools_jar" ]; then #If BuildTools.jar does NOT exist in "BuildTools" folder
echo "$Yellow Downloading BuildTools..."
buildtools_download
exit
elif [ -e "$buildtools_jar" ]; then
if [ "$buildtools_ver" -lt "$latestBuildToolsVersion" ]; then
echo "$Blue Updating BuildTools... $Color_Off"
rm "$buildtools_jar"
buildtools_download
fi
else
echo "$Cyan BuildTools is up to date. $Color_Off"
fi
}
info_menu () {
echo "==============================================[Local-Info]=============================================="
echo "BuildTools Root : $buildtools_root"
echo "Executable Path : $buildtools_jar"
echo "Installed Version : $buildtools_ver"
echo "JAVA_HOME Directory : $JAVA_HOME"
echo "=============================================[JsonAPI-Info]============================================="
echo "Latest Download Url: $latestBuildToolsUrl"
echo "========================================================================================================"
echo
if [ "$buildtools_ver" -eq "$latestBuildToolsVersion" ]; then
echo "$Green You have the latest SpigotMC BuildTools version. $Color_Off"
else
echo "$Yellow A new build is available : $displayFullName"
fi
echo
}
if [ -z "$1" ]; then
echo "$BCyan Usage: $0 $BBlue<version> $Color_Off" & exit #By default, $0 is the name of this file
else
if [ -d "$1" ]; then #If argument is defined
if [ "$1" = "latest" ]; then
buildtools_check
else
vercomp "$1" "1.14"
if [ $? -eq 0 -o $? -eq 1 ]; then
BothJars=(--compile craftbukkit,spigot) # means $1 >= 1.14 ; sets the $BothJars variable
buildtools_check
fi
if [ "$1" -lt "1.14" ]; then
echo "$Yellow You want to build an older server version. Good choice btw."
buildtools_check
fi
fi
fi
rm -rf "$1" && mkdir "$1"
cd "$1" || exit
java -jar ./BuildTools.jar --rev "$1" "${BothJars[@]}" --generate-source --generate-docs #../filename is for executing it from one dir far.
I have put comments for you to understand what's going on.
Can someone help me with the problem?
EDIT : If you ever played Minecraft, or if you saw different versions of Minecraft, you can encounter the following version formats:
1.7.10 ; 1.8 ; 1.13.2 ; 1.14 ; 1.15.3 (and no, there is not a '1.8.0' version. Just '1.8')
Here are examples of comparisons between versions which are mathematical false after tr
command :
1.8 > 1.7.10
- 18 > 1710
1.14 > 1.13.2
- 114 > 1132
1.15.2 < 1.16
- 1152 < 116
So... There may be problems that could affect the comparison of those numbers, since they are versions, not fractions or integers.
EDIT 2 : I will not make more than 3 edits / post. Thank you Richard K. for helping me with version checking function! I have rewritten my script to make it more complete. I store important parts in functions to save space and to be more visible. Summary : I don't understand what have I done wrong here. U_U
EDIT 3 : As of Rachid K's answer, I got this part to test:
#!/bin/bash
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
if [ -z "$1" ]; then
echo "$BCyan Usage: $0 $BBlue<version> $Color_Off" & exit #By default, $0 is the name of this file
else
if [ -d "$1" ]; then #If argument is defined
if [ "$1" = "latest" ]; then
echo "Building latest version"
else
vercomp "$1" "1.14"
rc=$?
case $rc in
0)
echo " You want to build version 1.14"
;;
1)
echo " You want to build version above 1.14"
;;
2)
echo " You want to build version below 1.14"
;;
latest)
echo " You want to build latest version."
;;
esac
fi
fi
fi
So the vercomp()
should see if : $1 is equal with string latest ; $1 is greater or equal with 1.14 ; $1 is lower than 1.14.
The function looks good, but the echo command does not display. I noticed that in some cases the echo command doesn't display due to missing double quotes. So... putting that at it. But it doesn't work. Why?
Apparently the version you get is either a number like 1.14 or the "latest" string. You need to split you check in two tests. First you check the "latest" value :
and if it is false, check the versions by using the solution proposed in this post
So, to compare the version just do: