diff --git a/tests.d/1003-lib-string/00.tests.sh b/tests.d/1003-lib-string/00.tests.sh index 38d161e..23646ec 100644 --- a/tests.d/1003-lib-string/00.tests.sh +++ b/tests.d/1003-lib-string/00.tests.sh @@ -28,6 +28,10 @@ function testString::bumpSemanticVersion() { echo "→ bumping 1.2.3-alpha patch false" string::bumpSemanticVersion "1.2.156-alpha" "patch" "false" && echo "${RETURNED_VALUE}" + echo + echo "→ bumping aze patch false" + (string::bumpSemanticVersion "aze" "patch" "false") || echo "Failed as expected" + test::endTest "Testing string::bumpSemanticVersion" 0 } @@ -220,6 +224,31 @@ function testString::trim() { test::endTest "Testing string::trim function" 0 } +function testString::compareSemanticVersion() { + echo "→ string::compareSemanticVersion '1.2.3' '1.2.3'" + string::compareSemanticVersion '1.2.3' '1.2.3' && echo "0=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '1.2.3-alpha' '1.2.4+az123'" + string::compareSemanticVersion '1.2.3-alpha' '1.2.4+az123' && echo "-1=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '1.2.3' '1.2.2'" + string::compareSemanticVersion '1.2.3' '1.2.2' && echo "1=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '2.2.3' '1.2.3-alpha'" + string::compareSemanticVersion '2.2.3' '1.2.3-alpha' && echo "1=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '1.2.3+a1212' '1.3.3'" + string::compareSemanticVersion '1.2.3+a1212' '1.3.3' && echo "-1=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '1.2.3-alpha+a123123' '1.2.3-alpha+123zer'" + string::compareSemanticVersion '1.2.3-alpha+a123123' '1.2.3-alpha+123zer' && echo "0=${RETURNED_VALUE}" + echo + echo "→ string::compareSemanticVersion '1.2a.3' '1.2.3derp'" + (string::compareSemanticVersion '1.2a.3' '1.2.3derp') || echo "Failed as expected" + + test::endTest "Testing string::compareSemanticVersion function" 0 +} + function main() { testString::bumpSemanticVersion testString::kebabCaseToSnakeCase @@ -233,6 +262,7 @@ function main() { testString::split testString::regexGetFirst testString::trim + testString::compareSemanticVersion } main \ No newline at end of file diff --git a/tests.d/1003-lib-string/results.approved.md b/tests.d/1003-lib-string/results.approved.md index 0957e4e..5d481a9 100644 --- a/tests.d/1003-lib-string/results.approved.md +++ b/tests.d/1003-lib-string/results.approved.md @@ -26,6 +26,15 @@ Exit code: `0` → bumping 1.2.3-alpha patch false 1.2.157-alpha + +→ bumping aze patch false +Failed as expected +``` + +**Error** output: + +```log +ERROR Failed to bump the version ⌜aze⌝ because it is not valid semantic version. ``` ### Testing string::kebabCaseToSnakeCase @@ -238,3 +247,38 @@ hello=⌜hello⌝ hello=⌜hello⌝ ``` +### Testing string::compareSemanticVersion function + +Exit code: `0` + +**Standard** output: + +```plaintext +→ string::compareSemanticVersion '1.2.3' '1.2.3' +0=0 + +→ string::compareSemanticVersion '1.2.3-alpha' '1.2.4+az123' +-1=-1 + +→ string::compareSemanticVersion '1.2.3' '1.2.2' +1=1 + +→ string::compareSemanticVersion '2.2.3' '1.2.3-alpha' +1=1 + +→ string::compareSemanticVersion '1.2.3+a1212' '1.3.3' +-1=-1 + +→ string::compareSemanticVersion '1.2.3-alpha+a123123' '1.2.3-alpha+123zer' +0=0 + +→ string::compareSemanticVersion '1.2a.3' '1.2.3derp' +Failed as expected +``` + +**Error** output: + +```log +ERROR Failed to compare versions ⌜1.2a.3⌝ and ⌜1.2.3derp⌝ because they are not valid semantic versions. +``` + diff --git a/tests.d/1101-self-build-utils/results.approved.md b/tests.d/1101-self-build-utils/results.approved.md index f2c0ffe..320ac0c 100644 --- a/tests.d/1101-self-build-utils/results.approved.md +++ b/tests.d/1101-self-build-utils/results.approved.md @@ -129,7 +129,7 @@ CMD_ARGUMENTS_NAME_func=0 "arg1" 1 "arg2" 2 "arg3" CMD_COMMAND_func='cmd' CMD_DESCRIPTION_func=$'A long description.\n\nIn a multi-line string.\n\nWith 3 paragraphs.' CMD_EXAMPLES_DESCRIPTION_func=0 $'Call command with option1, option2 and some arguments.\n' -CMD_EXAMPLES_NAME_func=0 "command -o -2 value1 arg1 more1 more2" +CMD_EXAMPLES_NAME_func=0 "valet command -o -2 value1 arg1 more1 more2" CMD_FILETOSOURCE_func='source' CMD_FUNCTION_NAME_cmd='func' CMD_MAX_COMMAND_WIDTH='3' diff --git a/tests.d/1102-self-build/results.approved.md b/tests.d/1102-self-build/results.approved.md index c2a063a..15dcd38 100644 --- a/tests.d/1102-self-build/results.approved.md +++ b/tests.d/1102-self-build/results.approved.md @@ -73,9 +73,9 @@ CMD_DESCRIPTION_this=$'Valet helps you browse, understand and execute your custo CMD_EXAMPLES_DESCRIPTION_selfMock2=0 $'Call command1 with option1, option2 and some arguments.\n' CMD_EXAMPLES_DESCRIPTION_showCommandHelp=0 "Shows the help for the command cmd" 1 "Shows the help for the sub command ⌜subCmd⌝ of the command ⌜cmd⌝" 2 $'Shows the help for the program without any color and with a maximum of 50 columns\n' CMD_EXAMPLES_DESCRIPTION_this=0 "Displays this help text." 1 $'Active ⌜verbose⌝ mode and run the command ⌜a-command⌝ with the sub command ⌜and-sub-command⌝.\n' -CMD_EXAMPLES_NAME_selfMock2=0 "self mock2 -o -2 value1 arg1 more1 more2" -CMD_EXAMPLES_NAME_showCommandHelp=0 "help cmd" 1 "help cmd subCmd" 2 "help --no-colors --columns 50" -CMD_EXAMPLES_NAME_this=0 "--help" 1 "-v a-command and-sub-command" +CMD_EXAMPLES_NAME_selfMock2=0 "valet self mock2 -o -2 value1 arg1 more1 more2" +CMD_EXAMPLES_NAME_showCommandHelp=0 "valet help cmd" 1 "valet help cmd subCmd" 2 "valet help --no-colors --columns 50" +CMD_EXAMPLES_NAME_this=0 "valet --help" 1 "valet -v a-command and-sub-command" CMD_FILETOSOURCE_selfBuild='valet.d/commands.d/self-build.sh' CMD_FILETOSOURCE_selfConfig='valet.d/commands.d/self-config.sh' CMD_FILETOSOURCE_selfExport='valet.d/commands.d/self-export.sh' diff --git a/tests.d/1103-self-release/results.approved.md b/tests.d/1103-self-release/results.approved.md index d1d7819..cf6ef23 100644 --- a/tests.d/1103-self-release/results.approved.md +++ b/tests.d/1103-self-release/results.approved.md @@ -18,7 +18,7 @@ Exit code: `0` INFO Dry run mode is enabled, no changes will be made. ▶ called io::invoke git rev-parse HEAD INFO The current version of valet is: 1.2.3. -INFO Found 98 functions with documentation. +INFO Found 100 functions with documentation. ▶ called io::invoke git tag --sort=version:refname --no-color INFO The last tag is: v1.2.3. ▶ called io::invoke git log --pretty=format:%s v1.2.3..HEAD @@ -154,11 +154,13 @@ DEBUG Found function: ⌜io::countArgs⌝ DEBUG Found function: ⌜io::listPaths⌝ DEBUG Found function: ⌜io::listFiles⌝ DEBUG Found function: ⌜io::listDirectories⌝ +DEBUG Found function: ⌜io::isDirectoryWritable⌝ DEBUG Found function: ⌜kurl::toFile⌝ DEBUG Found function: ⌜kurl::toVar⌝ DEBUG Found function: ⌜profiler::enable⌝ DEBUG Found function: ⌜profiler::disable⌝ DEBUG Found function: ⌜string::cutField⌝ +DEBUG Found function: ⌜string::compareSemanticVersion⌝ DEBUG Found function: ⌜string::bumpSemanticVersion⌝ DEBUG Found function: ⌜string::camelCaseToSnakeCase⌝ DEBUG Found function: ⌜string::kebabCaseToSnakeCase⌝ @@ -176,7 +178,7 @@ DEBUG Found function: ⌜system::date⌝ DEBUG Found function: ⌜system::getUndeclaredVariables⌝ DEBUG Found function: ⌜test::commentTest⌝ DEBUG Found function: ⌜test::endTest⌝ -INFO Found 98 functions with documentation. +INFO Found 100 functions with documentation. ▶ called io::invoke rm -f $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/array.md ▶ called io::invoke rm -f $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/codes.md ▶ called io::invoke rm -f $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/core.md @@ -295,6 +297,8 @@ INFO Found 98 functions with documentation. ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/string.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/core.md ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/core.md +▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md +▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/system.md ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/system.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md @@ -379,6 +383,8 @@ INFO Found 98 functions with documentation. ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/core.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md +▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/string.md +▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/string.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/log.md ▶ called io::writeToFile $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/log.md ▶ called io::writeToFileFromRef $GLOBAL_VALET_HOME/docs/content/docs/300.libraries/io.md diff --git a/tests.d/1300-valet-cli/results.approved.md b/tests.d/1300-valet-cli/results.approved.md index 90117e0..2eb935f 100644 --- a/tests.d/1300-valet-cli/results.approved.md +++ b/tests.d/1300-valet-cli/results.approved.md @@ -76,7 +76,7 @@ ARGUMENTS EXAMPLES - self mock2 -o -2 value1 arg1 more1 more2 + valet self mock2 -o -2 value1 arg1 more1 more2 Call command1 with option1, option2 and some arguments. @@ -235,12 +235,12 @@ ARGUMENTS EXAMPLES - help cmd + valet help cmd Shows the help for the command ⌜cmd⌝ - help cmd subCmd + valet help cmd subCmd Shows the help for the sub command ⌜subCmd⌝ of the command ⌜cmd⌝ - help --no-colors --columns 50 + valet help --no-colors --columns 50 Shows the help for the program without any color and with a maximum of 50 columns @@ -1144,7 +1144,7 @@ COMMANDS self test Test your valet custom commands. self update - Update valet using the latest release on GitHub. + Install or update valet using the latest release on GitHub. ``` diff --git a/valet.d/lib-io b/valet.d/lib-io index 51b8926..f374b1f 100644 --- a/valet.d/lib-io +++ b/valet.d/lib-io @@ -844,13 +844,9 @@ function io::listDirectories() { # fi # ``` function io::isDirectoryWritable() { - path="${1:-}/writable-test" - if (: >"${path}") &>/dev/null; then - if ! rm "${path}" 1>/dev/null; then - return 1 - fi - return 0 - else + local path="${1:-}/writable-test-${BASHPID}" + if ! (: >"${path}") &>/dev/null || ! rm "${path}" 1>/dev/null; then return 1 fi + return 0 } \ No newline at end of file diff --git a/valet.d/lib-string b/valet.d/lib-string index 10b050e..d532e0d 100644 --- a/valet.d/lib-string +++ b/valet.d/lib-string @@ -48,6 +48,55 @@ function string::cutField() { RETURNED_VALUE="" } +# ## string::compareSemanticVersion +# +# This function allows to compare two semantic versions formatted like: +# major.minor.patch-prerelease+build +# +# - $1: **version1** _as string_: +# the first version to compare +# - $2: **version2** _as string_: +# the second version to compare +# +# Returns: +# +# - `RETURNED_VALUE`: +# - 0 if the versions are equal, +# - 1 if version1 is greater, +# - -1 if version2 is greater +# +# ```bash +# string::compareSemanticVersion "2.3.4-prerelease+build" "1.2.3-prerelease+build" +# local comparison="${RETURNED_VALUE}" +# ``` +# +# > The prerelease and build are ignored in the comparison. +function string::compareSemanticVersion() { + local version1="${1#v}" + local version2="${2#v}" + + local -i semVerIndex + local semVerNumber1 semVerNumber2 + for semVerIndex in {0..2}; do + string::cutField "${version1}" "${semVerIndex}" "." + semVerNumber1="${RETURNED_VALUE%%-*}" + semVerNumber1="${semVerNumber1%%+*}" + string::cutField "${version2}" "${semVerIndex}" "." + semVerNumber2="${RETURNED_VALUE%%-*}" + semVerNumber2="${semVerNumber2%%+*}" + if [[ ! ${semVerNumber1} =~ ^[0-9]+$ || ! ${semVerNumber2} =~ ^[0-9]+$ ]]; then + core::fail "Failed to compare versions ⌜${version1}⌝ and ⌜${version2}⌝ because they are not valid semantic versions." + elif (( semVerNumber1 > semVerNumber2 )); then + RETURNED_VALUE=1 + return 0 + elif (( semVerNumber1 < semVerNumber2 )); then + RETURNED_VALUE=-1 + return 0 + fi + done + RETURNED_VALUE=0 +} + # ## string::bumpSemanticVersion # # This function allows to bump a semantic version formatted like: @@ -92,7 +141,11 @@ function string::bumpSemanticVersion() { if [[ ${bumpLevel:-} == "minor" ]]; then level=1; fi local newVersion semVerString for semVerIndex in {0..2}; do - string::cutField "${version}" "${semVerIndex}" "." && semVerString="${RETURNED_VALUE%-*}" + string::cutField "${version}" "${semVerIndex}" "." + semVerString="${RETURNED_VALUE%-*}" + if [[ ! ${semVerString} =~ ^[0-9]+$ ]]; then + core::fail "Failed to bump the version ⌜${version}⌝ because it is not valid semantic version." + fi semVerNumber="${semVerString%+}" if [[ semVerIndex -eq level ]]; then semVerNumber=$((semVerNumber + 1)); fi if [[ semVerIndex -gt level ]]; then semVerNumber=0; fi @@ -452,4 +505,4 @@ function string::regexGetFirst() { else RETURNED_VALUE="" fi -} \ No newline at end of file +} diff --git a/valet.d/version b/valet.d/version index 66c0602..2408c26 100644 --- a/valet.d/version +++ b/valet.d/version @@ -1 +1 @@ -0.18.298 \ No newline at end of file +0.18.301 \ No newline at end of file