Rewrite of bash system
+ Implemented new dashboard menu + some fixes for db_assembler + new module installation process with version check via json files + some fixes to modules installer + implemented simple crossplatform worldserver and authserver restarters + new compiler script + client data downloader (beta) + various other fixes
This commit is contained in:
parent
07a451e140
commit
85388901cf
5
acore.json
Normal file
5
acore.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name" : "azerothcore-wotlk",
|
||||||
|
"version" : "2.0.0-dev",
|
||||||
|
"license" : "AGPL3"
|
||||||
|
}
|
||||||
7
acore.sh
Normal file
7
acore.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/apps/installer/main.sh"
|
||||||
23
apps/bash_shared/common.sh
Normal file
23
apps/bash_shared/common.sh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
function registerHooks() { hwc_event_register_hooks "$@"; }
|
||||||
|
function runHooks() { hwc_event_run_hooks "$@"; }
|
||||||
|
|
||||||
|
source "$AC_PATH_CONF/config.sh.dist" # "hack" to avoid missing conf variables
|
||||||
|
|
||||||
|
if [ -f "$AC_PATH_CONF/config.sh" ]; then
|
||||||
|
source "$AC_PATH_CONF/config.sh" # should overwrite previous
|
||||||
|
else
|
||||||
|
echo "NOTICE: file <$AC_PATH_CONF/config.sh> has not been found, you should create and configure it."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load modules
|
||||||
|
#
|
||||||
|
|
||||||
|
for entry in "$AC_PATH_MODULES/"*/include.sh
|
||||||
|
do
|
||||||
|
if [ -e $entry ]; then
|
||||||
|
source $entry
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
ACORE_VERSION=$("$AC_PATH_DEPS/jsonpath/JSONPath.sh" -f $AC_PATH_ROOT/acore.json -b '$.version')
|
||||||
@ -11,25 +11,5 @@ source "$AC_PATH_SHARED/defines.sh"
|
|||||||
|
|
||||||
source "$AC_PATH_DEPS/hw-core/bash-lib-event/src/hooks.sh"
|
source "$AC_PATH_DEPS/hw-core/bash-lib-event/src/hooks.sh"
|
||||||
|
|
||||||
|
source "$AC_PATH_SHARED/common.sh"
|
||||||
|
|
||||||
function registerHooks() { hwc_event_register_hooks "$@"; }
|
|
||||||
function runHooks() { hwc_event_run_hooks "$@"; }
|
|
||||||
|
|
||||||
source "$AC_PATH_CONF/config.sh.dist" # "hack" to avoid missing conf variables
|
|
||||||
|
|
||||||
if [ -f "$AC_PATH_CONF/config.sh" ]; then
|
|
||||||
source "$AC_PATH_CONF/config.sh" # should overwrite previous
|
|
||||||
else
|
|
||||||
echo "NOTICE: file <$AC_PATH_CONF/config.sh> has not been found, you should create and configure it."
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# Load modules
|
|
||||||
#
|
|
||||||
|
|
||||||
for entry in "$AC_PATH_MODULES/"*/include.sh
|
|
||||||
do
|
|
||||||
if [ -e $entry ]; then
|
|
||||||
source $entry
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
bash "$CURRENT_PATH/compiler.sh" 1
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
bash "$CURRENT_PATH/compiler.sh" 2
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
bash "$CURRENT_PATH/compiler.sh" 3
|
|
||||||
@ -4,41 +4,67 @@ CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||||||
|
|
||||||
source "$CURRENT_PATH/includes/includes.sh"
|
source "$CURRENT_PATH/includes/includes.sh"
|
||||||
|
|
||||||
function all() {
|
|
||||||
comp_clean
|
|
||||||
comp_configure
|
|
||||||
comp_build
|
|
||||||
}
|
|
||||||
|
|
||||||
function run_option() {
|
function run_option() {
|
||||||
if test "${comp_functions[$1-1]+'test'}"; then
|
re='^[0-9]+$'
|
||||||
|
if [[ $1 =~ $re ]] && test "${comp_functions[$1-1]+'test'}"; then
|
||||||
${comp_functions[$1-1]}
|
${comp_functions[$1-1]}
|
||||||
|
elif [ -n "$(type -t comp_$1)" ] && [ "$(type -t comp_$1)" = function ]; then
|
||||||
|
fun="comp_$1"
|
||||||
|
$fun
|
||||||
else
|
else
|
||||||
echo "invalid option"
|
echo "invalid option, use --help option for the commands list"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
comp_options=("Clean" "Configure" "Build" "All")
|
function comp_quit() {
|
||||||
comp_functions=("comp_clean" "comp_configure" "comp_build" "all")
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
comp_options=(
|
||||||
|
"build: Configure and compile"
|
||||||
|
"clean: Clean build files"
|
||||||
|
"configure: Run CMake"
|
||||||
|
"compile: Compile only"
|
||||||
|
"all: clean, configure and compile"
|
||||||
|
"quit: Close this menu")
|
||||||
|
comp_functions=(
|
||||||
|
"comp_build"
|
||||||
|
"comp_clean"
|
||||||
|
"comp_configure"
|
||||||
|
"comp_compile"
|
||||||
|
"comp_all"
|
||||||
|
"comp_quit")
|
||||||
|
|
||||||
|
PS3='[ Please enter your choice ]: '
|
||||||
|
|
||||||
runHooks "ON_AFTER_OPTIONS" #you can create your custom options
|
runHooks "ON_AFTER_OPTIONS" #you can create your custom options
|
||||||
|
|
||||||
# push exit after custom options
|
function _switch() {
|
||||||
comp_options+=('Exit')
|
_reply="$1"
|
||||||
comp_functions+=('exit 0')
|
_opt="$2"
|
||||||
|
|
||||||
# run option directly if specified in argument
|
case $_reply in
|
||||||
[ ! -z $1 ] && run_option $1 && exit 0
|
""|"--help")
|
||||||
|
echo "Available commands:"
|
||||||
PS3='[ Please enter your choice ]: '
|
printf '%s\n' "${options[@]}"
|
||||||
select opt in "${comp_options[@]}"
|
|
||||||
do
|
|
||||||
case $opt in
|
|
||||||
'Exit')
|
|
||||||
break
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
run_option $REPLY
|
run_option $_reply $_opt
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
# run option directly if specified in argument
|
||||||
|
[ ! -z $1 ] && _switch $@
|
||||||
|
[ ! -z $1 ] && exit 0
|
||||||
|
|
||||||
|
select opt in "${comp_options[@]}"
|
||||||
|
do
|
||||||
|
echo "==== ACORE COMPILER ===="
|
||||||
|
_switch $REPLY
|
||||||
|
break;
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
@ -39,7 +39,7 @@ function comp_configure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function comp_build() {
|
function comp_compile() {
|
||||||
[ $MTHREADS == 0 ] && MTHREADS=`grep -c ^processor /proc/cpuinfo` && MTHREADS=$(($MTHREADS + 2))
|
[ $MTHREADS == 0 ] && MTHREADS=`grep -c ^processor /proc/cpuinfo` && MTHREADS=$(($MTHREADS + 2))
|
||||||
|
|
||||||
echo "Using $MTHREADS threads"
|
echo "Using $MTHREADS threads"
|
||||||
@ -55,3 +55,13 @@ function comp_build() {
|
|||||||
|
|
||||||
runHooks "ON_AFTER_BUILD"
|
runHooks "ON_AFTER_BUILD"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function comp_build() {
|
||||||
|
comp_configure
|
||||||
|
comp_build
|
||||||
|
}
|
||||||
|
|
||||||
|
function comp_all() {
|
||||||
|
comp_clean
|
||||||
|
comp_build
|
||||||
|
}
|
||||||
@ -6,56 +6,70 @@ source "$CURRENT_PATH/includes/includes.sh"
|
|||||||
|
|
||||||
cmdopt=$1
|
cmdopt=$1
|
||||||
|
|
||||||
while true
|
PS3='[Please enter your choice]: '
|
||||||
do
|
|
||||||
echo "===== DB ASSEMBLER MENU ====="
|
|
||||||
PS3='Please enter your choice: '
|
|
||||||
options=(
|
options=(
|
||||||
"Assemble ALL" "Assemble only bases" "Assemble only updates" "Assemble only customs"
|
"all: Assemble all" # 1
|
||||||
"Quit"
|
"bases: Assemble only bases" # 2
|
||||||
"Assemble & import ALL" "Assemble & import only bases" "Assemble & import only updates" "Assemble & import only customs"
|
"updates: Assemble only updates" # 3
|
||||||
|
"customs: Assemble only customs" # 4
|
||||||
|
"import-all: Assemble & Import all" # 5
|
||||||
|
"import-bases: Assemble & Import only bases" # 6
|
||||||
|
"import-updates: Assemble & Import only updates" # 7
|
||||||
|
"import-customs: Assemble & Import only customs" # 8
|
||||||
|
"quit: Exit from this menu" # 9
|
||||||
)
|
)
|
||||||
|
|
||||||
function _switch() {
|
function _switch() {
|
||||||
case $1 in
|
_reply="$1"
|
||||||
"Assemble ALL")
|
_opt="$2"
|
||||||
|
|
||||||
|
case $_reply in
|
||||||
|
""|"all"|"1")
|
||||||
dbasm_run true true true
|
dbasm_run true true true
|
||||||
;;
|
;;
|
||||||
"Assemble only bases")
|
""|"bases"|"2")
|
||||||
dbasm_run true false false
|
dbasm_run true false false
|
||||||
;;
|
;;
|
||||||
"Assemble only updates")
|
""|"updates"|"3")
|
||||||
dbasm_run false true false
|
dbasm_run false true false
|
||||||
;;
|
;;
|
||||||
"Assemble only customs")
|
""|"customs"|"4")
|
||||||
dbasm_run false false true
|
dbasm_run false false true
|
||||||
;;
|
;;
|
||||||
"Assemble & import ALL")
|
""|"import-all"|"5")
|
||||||
dbasm_import true true true
|
dbasm_import true true true
|
||||||
;;
|
;;
|
||||||
"Assemble & import only bases")
|
""|"import-bases"|"6")
|
||||||
dbasm_import true false false
|
dbasm_import true false false
|
||||||
;;
|
;;
|
||||||
"Assemble & import only updates")
|
""|"import-updates"|"7")
|
||||||
dbasm_import false true false
|
dbasm_import false true false
|
||||||
;;
|
;;
|
||||||
"Assemble & import only customs")
|
""|"import-customs"|"8")
|
||||||
dbasm_import false false true
|
dbasm_import false false true
|
||||||
;;
|
;;
|
||||||
"Quit")
|
""|"quit"|"9")
|
||||||
echo "Goodbye!"
|
echo "Goodbye!"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
*) echo invalid option;;
|
""|"--help")
|
||||||
|
echo "Available commands:"
|
||||||
|
printf '%s\n' "${options[@]}"
|
||||||
|
;;
|
||||||
|
*) echo "invalid option, use --help option for the commands list";;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# run option directly if specified in argument
|
while true
|
||||||
[ ! -z $1 ] && _switch "${options[$cmdopt-1]}" && exit 0
|
|
||||||
|
|
||||||
select opt in "${options[@]}"
|
|
||||||
do
|
do
|
||||||
_switch "$opt"
|
# run option directly if specified in argument
|
||||||
break
|
[ ! -z $1 ] && _switch $@
|
||||||
done
|
[ ! -z $1 ] && exit 0
|
||||||
|
|
||||||
|
select opt in "${options[@]}"
|
||||||
|
do
|
||||||
|
echo "===== DB ASSEMBLER MENU ====="
|
||||||
|
_switch $REPLY
|
||||||
|
break
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
@ -44,10 +44,6 @@ function inst_cleanCompile() {
|
|||||||
inst_compile
|
inst_compile
|
||||||
}
|
}
|
||||||
|
|
||||||
function inst_assembleDb {
|
|
||||||
dbasm_import true true true
|
|
||||||
}
|
|
||||||
|
|
||||||
function inst_allInOne() {
|
function inst_allInOne() {
|
||||||
inst_configureOS
|
inst_configureOS
|
||||||
inst_updateRepo
|
inst_updateRepo
|
||||||
@ -55,19 +51,66 @@ function inst_allInOne() {
|
|||||||
inst_assembleDb
|
inst_assembleDb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inst_getVersionBranch() {
|
||||||
|
local res="master"
|
||||||
|
local v="not-defined"
|
||||||
|
local MODULE_MAJOR=0
|
||||||
|
local MODULE_MINOR=0
|
||||||
|
local MODULE_PATCH=0
|
||||||
|
local MODULE_SPECIAL=0;
|
||||||
|
local ACV_MAJOR=0
|
||||||
|
local ACV_MINOR=0
|
||||||
|
local ACV_PATCH=0
|
||||||
|
local ACV_SPECIAL=0;
|
||||||
|
local curldata=$(curl -f --silent -H 'Cache-Control: no-cache' "$1" || echo "{}")
|
||||||
|
local parsed=$(echo "$curldata" | "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.compatibility.*.[version,branch]')
|
||||||
|
|
||||||
|
semverParseInto "$ACORE_VERSION" ACV_MAJOR ACV_MINOR ACV_PATCH ACV_SPECIAL
|
||||||
|
|
||||||
|
if [[ ! -z "$parsed" ]]; then
|
||||||
|
readarray -t vers < <(echo "$parsed")
|
||||||
|
local idx
|
||||||
|
res="none"
|
||||||
|
# since we've the pair version,branch alternated in not associative and one-dimensional
|
||||||
|
# array, we've to simulate the association with length/2 trick
|
||||||
|
for idx in `seq 0 $((${#vers[*]}/2-1))`; do
|
||||||
|
semverParseInto "${vers[idx*2]}" MODULE_MAJOR MODULE_MINOR MODULE_PATCH MODULE_SPECIAL
|
||||||
|
if [[ $MODULE_MAJOR -eq $ACV_MAJOR && $MODULE_MINOR -le $ACV_MINOR ]]; then
|
||||||
|
res="${vers[idx*2+1]}"
|
||||||
|
v="${vers[idx*2]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$v" "$res"
|
||||||
|
}
|
||||||
|
|
||||||
function inst_module_search {
|
function inst_module_search {
|
||||||
search=""
|
|
||||||
|
local res="$1"
|
||||||
|
local idx=0;
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Type what to search or leave blank for full list"
|
echo "Type what to search or leave blank for full list"
|
||||||
read -p "Insert name: " res
|
read -p "Insert name: " res
|
||||||
|
|
||||||
search="+$res"
|
|
||||||
fi
|
fi
|
||||||
echo "Searching ..."
|
|
||||||
|
local search="+$res"
|
||||||
|
|
||||||
|
echo "Searching $res..."
|
||||||
echo "";
|
echo "";
|
||||||
|
|
||||||
for i in `curl -s "https://api.github.com/search/repositories?q=org%3Aazerothcore${search}+fork%3Atrue+topic%3Acore-module+sort%3Astars&type=" | grep \"name\" | cut -d ':' -f 2-3|tr -d '",'`; do
|
readarray -t MODS < <(curl --silent "https://api.github.com/search/repositories?q=org%3Aazerothcore${search}+fork%3Atrue+topic%3Acore-module+sort%3Astars&type=" \
|
||||||
echo "-> $i";
|
| "$AC_PATH_DEPS/jsonpath/JSONPath.sh" -b '$.items.*.name')
|
||||||
|
while (( ${#MODS[@]} > idx )); do
|
||||||
|
mod="${MODS[idx++]}"
|
||||||
|
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/azerothcore/$mod/master/acore-module.json")
|
||||||
|
|
||||||
|
if [[ "$b" != "none" ]]; then
|
||||||
|
echo "-> $mod (tested with AC v$v)"
|
||||||
|
else
|
||||||
|
echo "-> $mod (no revision available for AC v$AC_VERSION, it could not work!)"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "";
|
echo "";
|
||||||
@ -75,30 +118,50 @@ function inst_module_search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function inst_module_install {
|
function inst_module_install {
|
||||||
|
local res
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Type the name of the module to install"
|
echo "Type the name of the module to install"
|
||||||
read -p "Insert name: " res
|
read -p "Insert name: " res
|
||||||
|
else
|
||||||
|
res="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git clone "https://github.com/azerothcore/$res" "$AC_PATH_ROOT/modules/$res" && echo "Done, please re-run compiling and db assembly. Read instruction on module repository for more information"
|
read v b < <(inst_getVersionBranch "https://raw.githubusercontent.com/azerothcore/$res/master/acore-module.json")
|
||||||
|
|
||||||
|
if [[ "$b" != "none" ]]; then
|
||||||
|
Joiner:add_repo "https://github.com/azerothcore/$res" "$res" "$b" && echo "Done, please re-run compiling and db assembly. Read instruction on module repository for more information"
|
||||||
|
else
|
||||||
|
echo "Cannot install $res module: it doesn't exists or no version compatible with AC v$ACORE_VERSION are available"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "";
|
echo "";
|
||||||
echo "";
|
echo "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function inst_module_update {
|
function inst_module_update {
|
||||||
|
local res;
|
||||||
|
local _tmp;
|
||||||
|
local branch;
|
||||||
|
local p;
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Type the name of the module to update"
|
echo "Type the name of the module to update"
|
||||||
read -p "Insert name: " res
|
read -p "Insert name: " res
|
||||||
|
else
|
||||||
|
res="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$AC_PATH_ROOT/modules/$res"
|
_tmp=$PWD
|
||||||
|
|
||||||
#git reset --hard master
|
if [ -d "$J_PATH_MODULES/$res/" ]; then
|
||||||
#git clean -f
|
cd "$J_PATH_MODULES/$res/"
|
||||||
git pull origin master && echo "Done"
|
branch=`git rev-parse --abbrev-ref HEAD`
|
||||||
|
|
||||||
cd "../../"
|
Joiner:upd_repo "https://github.com/azerothcore/$res" "$res" "$branch" && echo "Done, please re-run compiling and db assembly" || echo "Cannot update"
|
||||||
|
cd $_tmp
|
||||||
|
else
|
||||||
|
echo "Cannot update! Path doesn't exist"
|
||||||
|
fi;
|
||||||
|
|
||||||
echo "";
|
echo "";
|
||||||
echo "";
|
echo "";
|
||||||
@ -108,10 +171,29 @@ function inst_module_remove {
|
|||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Type the name of the module to remove"
|
echo "Type the name of the module to remove"
|
||||||
read -p "Insert name: " res
|
read -p "Insert name: " res
|
||||||
|
else
|
||||||
|
res="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$AC_PATH_ROOT/modules/$res" && echo "Done"
|
Joiner:remove "$res" && echo "Done, please re-run compiling" || echo "Cannot remove"
|
||||||
|
|
||||||
echo "";
|
echo "";
|
||||||
echo "";
|
echo "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function inst_simple_restarter {
|
||||||
|
echo "Running $1 in background..."
|
||||||
|
bash "$AC_PATH_APPS/startup-scripts/simple-restarter" "$BINPATH" "$1" &
|
||||||
|
}
|
||||||
|
|
||||||
|
function inst_download_client_data {
|
||||||
|
path="$BINPATH/data"
|
||||||
|
if [ -e "$path/.git/" ]; then
|
||||||
|
# if exists , update
|
||||||
|
git --git-dir="$path/.git/" rev-parse && git --git-dir="$path/.git/" pull origin master | grep 'Already up-to-date.' && changed="no"
|
||||||
|
else
|
||||||
|
# otherwise clone
|
||||||
|
git clone "https://github.com/wowgaming/client-data" -c advice.detachedHead=0 -b master --depth=1 $path
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
@ -1,9 +1,31 @@
|
|||||||
CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
[[ ${INSTALLER_GUARDYVAR:-} -eq 1 ]] && return || readonly INSTALLER_GUARDYVAR=1 # include it once
|
||||||
|
|
||||||
|
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd )
|
||||||
|
|
||||||
source "$CURRENT_PATH/../../bash_shared/includes.sh"
|
source "$CURRENT_PATH/../../bash_shared/includes.sh"
|
||||||
|
|
||||||
AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
||||||
|
|
||||||
|
|
||||||
|
J_VER_REQ="v0.8.3"
|
||||||
|
J_PATH="$AC_PATH_APPS/drassil/joiner"
|
||||||
|
J_PATH_MODULES="$AC_PATH_MODULES"
|
||||||
|
|
||||||
|
#install/update and include joiner
|
||||||
|
if [ ! -d "$J_PATH/.git" ]; then
|
||||||
|
git clone https://github.com/drassil/joiner "$J_PATH" -b master
|
||||||
|
git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" reset --hard "$J_VER_REQ"
|
||||||
|
else
|
||||||
|
# legacy code, with new rev of joiner the update process is internally handled
|
||||||
|
_cur_branch=`git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" rev-parse --abbrev-ref HEAD`
|
||||||
|
_cur_ver=`git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" name-rev --tags --name-only $_cur_branch`
|
||||||
|
if [ "$_cur_ver" != "$J_VER_REQ" ]; then
|
||||||
|
git --git-dir="$J_PATH/.git" --work-tree="$J_PATH/" rev-parse && git --git-dir="$J_PATH/.git" --work-tree="$J_PATH/" fetch --tags origin master --quiet
|
||||||
|
git --git-dir="$J_PATH/.git/" --work-tree="$J_PATH/" reset --hard "$J_VER_REQ"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
source "$AC_PATH_APPS/drassil/joiner/joiner.sh"
|
||||||
|
|
||||||
if [ -f "$AC_PATH_INSTALLER/config.sh" ]; then
|
if [ -f "$AC_PATH_INSTALLER/config.sh" ]; then
|
||||||
source "$AC_PATH_INSTALLER/config.sh" # should overwrite previous
|
source "$AC_PATH_INSTALLER/config.sh" # should overwrite previous
|
||||||
fi
|
fi
|
||||||
@ -11,4 +33,6 @@ fi
|
|||||||
source "$AC_PATH_APPS/compiler/includes/includes.sh"
|
source "$AC_PATH_APPS/compiler/includes/includes.sh"
|
||||||
source "$AC_PATH_APPS/db_assembler/includes/includes.sh"
|
source "$AC_PATH_APPS/db_assembler/includes/includes.sh"
|
||||||
|
|
||||||
|
source "$AC_PATH_DEPS/semver_bash/semver.sh"
|
||||||
|
|
||||||
source "$AC_PATH_INSTALLER/includes/functions.sh"
|
source "$AC_PATH_INSTALLER/includes/functions.sh"
|
||||||
|
|||||||
@ -4,75 +4,90 @@ CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||||||
|
|
||||||
source "$CURRENT_PATH/includes/includes.sh"
|
source "$CURRENT_PATH/includes/includes.sh"
|
||||||
|
|
||||||
cmdopt=$1
|
PS3='[Please enter your choice]: '
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
echo "===== INSTALLER SCRIPT ====="
|
|
||||||
PS3='Please enter your choice: '
|
|
||||||
options=(
|
options=(
|
||||||
"First Installation" "Configure OS dep" "Update Repository" "Reset & Clean Repository"
|
"init (i): First Installation" # 1
|
||||||
"Compile" "Clean & Compile" "Assemble & Import DB" "Module Search" "Module Install" "Module Update" "Module Remove"
|
"install-deps (d): Configure OS dep" # 2
|
||||||
"Sub Menu >> Compiler" "Sub Menu >> DB Assembler"
|
"pull (u): Update Repository" # 3
|
||||||
"Quit"
|
"reset (r): Reset & Clean Repository" # 4
|
||||||
|
"compiler (c): Run compiler tool" # 5
|
||||||
|
"db-assembler (a): Run db assembler tool" # 6
|
||||||
|
"module-search (ms): Module Search by keyword" # 7
|
||||||
|
"module-install (mi): Module Install by name" # 8
|
||||||
|
"module-update (mu): Module Update by name" # 9
|
||||||
|
"module-remove: (mr): Module Remove by name" # 10
|
||||||
|
"client-data: (gd): download client data from github repository (beta)" # 11
|
||||||
|
"run-worldserver (rw): execute a simple restarter for worldserver" # 12
|
||||||
|
"run-authserver (ra): execute a simple restarter for authserver" # 13
|
||||||
|
"quit: Exit from this menu" # 14
|
||||||
)
|
)
|
||||||
|
|
||||||
function _switch() {
|
function _switch() {
|
||||||
case $1 in
|
_reply="$1"
|
||||||
"First Installation")
|
_opt="$2"
|
||||||
|
|
||||||
|
case $_reply in
|
||||||
|
""|"i"|"init"|"1")
|
||||||
inst_allInOne
|
inst_allInOne
|
||||||
;;
|
;;
|
||||||
"Configure OS dep")
|
""|"d"|"install-deps"|"2")
|
||||||
inst_configureOS
|
inst_configureOS
|
||||||
;;
|
;;
|
||||||
"Update Repository")
|
""|"u"|"pull"|"3")
|
||||||
inst_updateRepo
|
inst_updateRepo
|
||||||
;;
|
;;
|
||||||
"Reset & Clean Repository")
|
""|"r"|"reset"|"4")
|
||||||
inst_resetRepo
|
inst_resetRepo
|
||||||
;;
|
;;
|
||||||
"Compile")
|
""|"c"|"compiler"|"5")
|
||||||
inst_compile
|
bash "$AC_PATH_APPS/compiler/compiler.sh" $_opt
|
||||||
;;
|
;;
|
||||||
"Clean & Compile")
|
""|"a"|"db-assembler"|"6")
|
||||||
inst_cleanCompile
|
bash "$AC_PATH_APPS/db_assembler/db_assembler.sh" $_opt
|
||||||
;;
|
;;
|
||||||
"Assemble & Import DB")
|
""|"ms"|"module-search"|"7")
|
||||||
inst_assembleDb
|
inst_module_search "$_opt"
|
||||||
;;
|
;;
|
||||||
"Module Search")
|
""|"mi"|"module-install"|"8")
|
||||||
inst_module_search $2
|
inst_module_install "$_opt"
|
||||||
;;
|
;;
|
||||||
"Module Install")
|
""|"mu"|"module-update"|"9")
|
||||||
inst_module_install $2
|
inst_module_update "$_opt"
|
||||||
;;
|
;;
|
||||||
"Module Update")
|
""|"mr"|"module-remove"|"10")
|
||||||
inst_module_update $2
|
inst_module_remove "$_opt"
|
||||||
;;
|
;;
|
||||||
"Module Remove")
|
""|"gd"|"client-data"|"11")
|
||||||
inst_module_remove $2
|
inst_download_client_data
|
||||||
;;
|
;;
|
||||||
"Sub Menu >> Compiler")
|
""|"rw"|"run-worldserver"|"12")
|
||||||
bash "$AC_PATH_APPS/compiler/compiler.sh"
|
inst_simple_restarter worldserver
|
||||||
;;
|
;;
|
||||||
"Sub Menu >> DB Assembler")
|
""|"ra"|"run-authserver"|"13")
|
||||||
bash "$AC_PATH_APPS/db_assembler/db_assembler.sh"
|
inst_simple_restarter authserver
|
||||||
;;
|
;;
|
||||||
"Quit")
|
""|"quit"|"14")
|
||||||
echo "Goodbye!"
|
echo "Goodbye!"
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
*) echo invalid option;;
|
""|"--help")
|
||||||
|
echo "Available commands:"
|
||||||
|
printf '%s\n' "${options[@]}"
|
||||||
|
;;
|
||||||
|
*) echo "invalid option, use --help option for the commands list";;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# run option directly if specified in argument
|
while true
|
||||||
[ ! -z $1 ] && _switch "${options[$cmdopt-1]}"
|
|
||||||
[ ! -z $1 ] && exit 0
|
|
||||||
|
|
||||||
select opt in "${options[@]}"
|
|
||||||
do
|
do
|
||||||
_switch "$opt"
|
# run option directly if specified in argument
|
||||||
break
|
[ ! -z $1 ] && _switch $@ # old method: "${options[$cmdopt-1]}"
|
||||||
done
|
[ ! -z $1 ] && exit 0
|
||||||
|
|
||||||
|
select opt in "${options[@]}"
|
||||||
|
do
|
||||||
|
echo "==== ACORE DASHBOARD ===="
|
||||||
|
_switch $REPLY
|
||||||
|
break
|
||||||
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
9
apps/startup-scripts/simple-restarter
Normal file
9
apps/startup-scripts/simple-restarter
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#PARAMETER 1: directory
|
||||||
|
#PARAMETER 2: binary file
|
||||||
|
|
||||||
|
_bin_path=$1
|
||||||
|
_bin_file=$2
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
cd "$_bin_path" && "./$_bin_file" &>/dev/null; echo "$_bin_file crashed (?), restarting..."
|
||||||
|
done
|
||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
source ./acore-installer
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/acore-installer"
|
||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
bash ../apps/compiler/compiler.sh
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/../apps/compiler/compiler.sh"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
bash ../apps/db_assembler/db_assembler.sh
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/../apps/db_assembler/db_assembler.sh"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
bash ../apps/db_exporter/db_exporter.sh
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/../apps/db_exporter/db_exporter.sh"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
bash ../apps/db_pendings/import.sh
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/../apps/db_pendings/import.sh"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
bash ../apps/installer/main.sh
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CUR_PATH/../apps/installer/main.sh"
|
||||||
|
|||||||
5
deps/jsonpath/.gitignore
vendored
Normal file
5
deps/jsonpath/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
test/errlog
|
||||||
|
test/outlog
|
||||||
|
|
||||||
|
# vi .swp files
|
||||||
|
.*.swp
|
||||||
10
deps/jsonpath/.travis.yml
vendored
Normal file
10
deps/jsonpath/.travis.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
language: python
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- bash
|
||||||
|
|
||||||
|
# Whatever the current shebang, replace with hardcoded shell
|
||||||
|
script: >
|
||||||
|
./all-tests.sh
|
||||||
1
deps/jsonpath/CNAME
vendored
Normal file
1
deps/jsonpath/CNAME
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
jsonpath.obdi.io
|
||||||
857
deps/jsonpath/JSONPath.sh
vendored
Normal file
857
deps/jsonpath/JSONPath.sh
vendored
Normal file
@ -0,0 +1,857 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GLOBALS
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DEBUG=0
|
||||||
|
INCLEMPTY=0
|
||||||
|
NOCASE=0
|
||||||
|
WHOLEWORD=0
|
||||||
|
FILE=
|
||||||
|
NO_HEAD=0
|
||||||
|
NORMALIZE_SOLIDUS=0
|
||||||
|
BRIEF=0
|
||||||
|
PASSTHROUGH=0
|
||||||
|
JSON=0
|
||||||
|
PRINT=1
|
||||||
|
MULTIPASS=0
|
||||||
|
FLATTEN=0
|
||||||
|
STDINFILE=/var/tmp/JSONPath.$$.stdin
|
||||||
|
STDINFILE2=/var/tmp/JSONPath.$$.stdin2
|
||||||
|
PASSFILE=/var/tmp/JSONPath.$$.pass1
|
||||||
|
declare -a INDEXMATCH_QUERY
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
main() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# It all starts here
|
||||||
|
|
||||||
|
parse_options "$@"
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
if [[ $QUERY == *'?(@'* ]]; then
|
||||||
|
# This will be a multipass query
|
||||||
|
|
||||||
|
[[ -n $FILE ]] && STDINFILE=$FILE
|
||||||
|
[[ -z $FILE ]] && cat >$STDINFILE
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
tokenize_path
|
||||||
|
create_filter
|
||||||
|
|
||||||
|
cat "$STDINFILE" | tokenize | parse | filter | indexmatcher >$PASSFILE
|
||||||
|
|
||||||
|
[[ $MULTIPASS -eq 1 ]] && {
|
||||||
|
# replace filter expression with index sequence
|
||||||
|
SET=$(sed -rn 's/.*,([0-9]+)[],].*/\1/p' $PASSFILE | tr '\n' ,)
|
||||||
|
SET=${SET%,}
|
||||||
|
QUERY=$(echo $QUERY | sed "s/?(@[^)]\+)/$SET/")
|
||||||
|
[[ $DEBUG -eq 1 ]] && echo "QUERY=$QUERY"
|
||||||
|
reset
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cat $PASSFILE | flatten | json | brief
|
||||||
|
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
tokenize_path
|
||||||
|
create_filter
|
||||||
|
|
||||||
|
if [[ $PASSTHROUGH -eq 1 ]]; then
|
||||||
|
JSON=1
|
||||||
|
flatten | json
|
||||||
|
elif [[ -z $FILE ]]; then
|
||||||
|
tokenize | parse | filter | indexmatcher | flatten | json | brief
|
||||||
|
else
|
||||||
|
cat "$FILE" | tokenize | parse | filter | indexmatcher | flatten | \
|
||||||
|
json | brief
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
reset() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Reset some vars
|
||||||
|
declare -a INDEXMATCH_QUERY
|
||||||
|
PATHTOKENS=
|
||||||
|
FILTER=
|
||||||
|
OPERATOR=
|
||||||
|
RHS=
|
||||||
|
MULTIPASS=0
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
cleanup() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[[ -e "$PASSFILE" ]] && rm -f "$PASSFILE"
|
||||||
|
[[ -e "$STDINFILE2" ]] && rm -f "$STDINFILE2"
|
||||||
|
[[ -z "$FILE" && -e "$STDINFILE" ]] && rm -f "$STDINFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
usage() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Usage: JSONPath.sh [-b] [j] [-h] [-f FILE] [pattern]"
|
||||||
|
echo
|
||||||
|
echo "pattern - the JSONPath query. Defaults to '$.*' if not supplied."
|
||||||
|
#echo "-s - Remove escaping of the solidus symbol (straight slash)."
|
||||||
|
echo "-b - Brief. Only show values."
|
||||||
|
echo "-j - JSON ouput."
|
||||||
|
echo "-u - Strip unnecessary leading path elements."
|
||||||
|
echo "-i - Case insensitive."
|
||||||
|
echo "-p - Pass-through to the JSON parser."
|
||||||
|
echo "-w - Match whole words only (for filter script expression)."
|
||||||
|
echo "-f FILE - Read a FILE instead of stdin."
|
||||||
|
#echo "-n - No-head. Do not show nodes that have no path (lines that start with [])."
|
||||||
|
echo "-h - This help text."
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse_options() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set -- "$@"
|
||||||
|
local ARGN=$#
|
||||||
|
while [ "$ARGN" -ne 0 ]
|
||||||
|
do
|
||||||
|
case $1 in
|
||||||
|
-h) usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-f) shift
|
||||||
|
FILE=$1
|
||||||
|
;;
|
||||||
|
-i) NOCASE=1
|
||||||
|
;;
|
||||||
|
-j) JSON=1
|
||||||
|
;;
|
||||||
|
-n) NO_HEAD=1
|
||||||
|
;;
|
||||||
|
-b) BRIEF=1
|
||||||
|
;;
|
||||||
|
-u) FLATTEN=1
|
||||||
|
;;
|
||||||
|
-p) PASSTHROUGH=1
|
||||||
|
;;
|
||||||
|
-w) WHOLEWORD=1
|
||||||
|
;;
|
||||||
|
-s) NORMALIZE_SOLIDUS=1
|
||||||
|
;;
|
||||||
|
?*) QUERY=$1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift 1
|
||||||
|
ARGN=$((ARGN-1))
|
||||||
|
done
|
||||||
|
[[ -z $QUERY ]] && QUERY='$.*'
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
awk_egrep() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
local pattern_string=$1
|
||||||
|
|
||||||
|
gawk '{
|
||||||
|
while ($0) {
|
||||||
|
start=match($0, pattern);
|
||||||
|
token=substr($0, start, RLENGTH);
|
||||||
|
print token;
|
||||||
|
$0=substr($0, start+RLENGTH);
|
||||||
|
}
|
||||||
|
}' pattern="$pattern_string"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
tokenize() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# json parsing
|
||||||
|
|
||||||
|
local GREP
|
||||||
|
local ESCAPE
|
||||||
|
local CHAR
|
||||||
|
|
||||||
|
if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
GREP='egrep -ao --color=never'
|
||||||
|
else
|
||||||
|
GREP='egrep -ao'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "test string" | egrep -o "test" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
|
||||||
|
CHAR='[^[:cntrl:]"\\]'
|
||||||
|
else
|
||||||
|
GREP=awk_egrep
|
||||||
|
ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
|
||||||
|
CHAR='[^[:cntrl:]"\\\\]'
|
||||||
|
fi
|
||||||
|
|
||||||
|
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
|
||||||
|
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
|
||||||
|
local KEYWORD='null|false|true'
|
||||||
|
local SPACE='[[:space:]]+'
|
||||||
|
|
||||||
|
# Force zsh to expand $A into multiple words
|
||||||
|
local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
|
||||||
|
if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
|
||||||
|
$GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$"
|
||||||
|
if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
tokenize_path () {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
local GREP
|
||||||
|
local ESCAPE
|
||||||
|
local CHAR
|
||||||
|
|
||||||
|
if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
GREP='egrep -ao --color=never'
|
||||||
|
else
|
||||||
|
GREP='egrep -ao'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "test string" | egrep -o "test" >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
CHAR='[^[:cntrl:]"\\]'
|
||||||
|
else
|
||||||
|
GREP=awk_egrep
|
||||||
|
#CHAR='[^[:cntrl:]"\\\\]'
|
||||||
|
fi
|
||||||
|
|
||||||
|
local WILDCARD='\*'
|
||||||
|
local WORD='[ A-Za-z0-9_-]*'
|
||||||
|
local INDEX="\\[$WORD(:$WORD){0,2}\\]"
|
||||||
|
local INDEXALL="\\[\\*\\]"
|
||||||
|
local STRING="[\\\"'][^[:cntrl:]\\\"']*[\\\"']"
|
||||||
|
local SET="\\[($WORD|$STRING)(,($WORD|$STRING))*\\]"
|
||||||
|
local FILTER='\?\(@[^)]+'
|
||||||
|
local DEEPSCAN="\\.\\."
|
||||||
|
local SPACE='[[:space:]]+'
|
||||||
|
|
||||||
|
# Force zsh to expand $A into multiple words
|
||||||
|
local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
|
||||||
|
if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
|
||||||
|
readarray -t PATHTOKENS < <( echo "$QUERY" | \
|
||||||
|
$GREP "$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|." | \
|
||||||
|
egrep -v "^$SPACE$|^\\.$|^\[$|^\]$|^'$|^\\\$$|^\)$")
|
||||||
|
[[ $DEBUG -eq 1 ]] && {
|
||||||
|
echo "egrep -o '$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|.'"
|
||||||
|
echo -n "TOKENISED QUERY="; echo "$QUERY" | \
|
||||||
|
$GREP "$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|." | \
|
||||||
|
egrep -v "^$SPACE$|^\\.$|^\[$|^\]$|^'$|^\\\$$|^\)$"
|
||||||
|
}
|
||||||
|
if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
create_filter() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Creates the filter from the user's query.
|
||||||
|
# Filter works in a single pass through the data, unless a filter (script)
|
||||||
|
# expression is used, in which case two passes are required (MULTIPASS=1).
|
||||||
|
|
||||||
|
local len=${#PATHTOKENS[*]}
|
||||||
|
|
||||||
|
local -i i=0
|
||||||
|
local query="^\[" comma=
|
||||||
|
while [[ i -lt len ]]; do
|
||||||
|
case "${PATHTOKENS[i]}" in
|
||||||
|
'"') :
|
||||||
|
;;
|
||||||
|
'..') query+="$comma[^]]*"
|
||||||
|
comma=
|
||||||
|
;;
|
||||||
|
'[*]') query+="$comma[^,]*"
|
||||||
|
comma=","
|
||||||
|
;;
|
||||||
|
'*') query+="$comma(\"[^\"]*\"|[0-9]+[^],]*)"
|
||||||
|
comma=","
|
||||||
|
;;
|
||||||
|
'?(@'*) a=${PATHTOKENS[i]#?(@.}
|
||||||
|
elem="${a%%[<>=!]*}"
|
||||||
|
rhs="${a##*[<>=!]}"
|
||||||
|
a="${a#$elem}"
|
||||||
|
elem="${elem//./[\",.]+}" # Allows child node matching
|
||||||
|
operator="${a%$rhs}"
|
||||||
|
[[ -z $operator ]] && { operator="=="; rhs=; }
|
||||||
|
if [[ $rhs == *'"'* || $rhs == *"'"* ]]; then
|
||||||
|
case $operator in
|
||||||
|
'=='|'=') OPERATOR=
|
||||||
|
if [[ $elem == '?(@' ]]; then
|
||||||
|
# To allow search on @.property such as:
|
||||||
|
# $..book[?(@.title==".*Book 1.*")]
|
||||||
|
query+="$comma[0-9]+[],][[:space:]\"]*${rhs//\"/}"
|
||||||
|
else
|
||||||
|
# To allow search on @ (this node) such as:
|
||||||
|
# $..reviews[?(@==".*Fant.*")]
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*${rhs//\"/}"
|
||||||
|
fi
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'>='|'>') OPERATOR=">"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'<='|'<') OPERATOR="<"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
case $operator in
|
||||||
|
'=='|'=') OPERATOR=
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*$rhs"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'>=') OPERATOR="-ge"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'>') OPERATOR="-gt"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'<=') OPERATOR="-le"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
;;
|
||||||
|
'<') OPERATOR="-lt"
|
||||||
|
RHS="$rhs"
|
||||||
|
query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
|
||||||
|
FILTER="$query"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
MULTIPASS=1
|
||||||
|
;;
|
||||||
|
"["*) if [[ ${PATHTOKENS[i]} =~ , ]]; then
|
||||||
|
a=${PATHTOKENS[i]#[}
|
||||||
|
a=${a%]}
|
||||||
|
if [[ $a =~ [[:alpha:]] ]]; then
|
||||||
|
# converts only one comma: s/("[^"]+),([^"]+")/\1`\2/g;s/"//g
|
||||||
|
#a=$(echo $a | sed 's/\([[:alpha:]]*\)/"\1"/g')
|
||||||
|
a=$(echo $a | sed -r "s/[\"']//g;s/([^,]*)/\"\1\"/g")
|
||||||
|
fi
|
||||||
|
query+="$comma(${a//,/|})"
|
||||||
|
elif [[ ${PATHTOKENS[i]} =~ : ]]; then
|
||||||
|
if ! [[ ${PATHTOKENS[i]} =~ [0-9][0-9] || ${PATHTOKENS[i]} =~ :] ]]
|
||||||
|
then
|
||||||
|
if [[ ${PATHTOKENS[i]#*:} =~ : ]]; then
|
||||||
|
INDEXMATCH_QUERY+=("${PATHTOKENS[i]}")
|
||||||
|
query+="$comma[^,]*"
|
||||||
|
else
|
||||||
|
# Index in the range of 0-9 can be handled by regex
|
||||||
|
query+="${comma}$(echo ${PATHTOKENS[i]} | \
|
||||||
|
awk '/:/ { a=substr($0,0,index($0,":")-1);
|
||||||
|
b=substr($0,index($0,":")+1,index($0,"]")-index($0,":")-1);
|
||||||
|
if(b>0) { print a ":" b-1 "]" };
|
||||||
|
if(b<=0) { print a ":]" } }' | \
|
||||||
|
sed 's/\([0-9]\):\([0-9]\)/\1-\2/;
|
||||||
|
s/\[:\([0-9]\)/[0-\1/;
|
||||||
|
s/\([0-9]\):\]/\1-9999999]/')"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
INDEXMATCH_QUERY+=("${PATHTOKENS[i]}")
|
||||||
|
query+="$comma[^,]*"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
a=${PATHTOKENS[i]#[}
|
||||||
|
a=${a%]}
|
||||||
|
if [[ $a =~ [[:alpha:]] ]]; then
|
||||||
|
a=$(echo $a | sed -r "s/[\"']//g;s/([^,]*)/\"\1\"/g")
|
||||||
|
else
|
||||||
|
[[ $i -gt 0 ]] && comma=","
|
||||||
|
fi
|
||||||
|
#idx=$(echo "${PATHTOKENS[i]}" | tr -d "[]")
|
||||||
|
query+="$comma$a"
|
||||||
|
fi
|
||||||
|
comma=","
|
||||||
|
;;
|
||||||
|
*) PATHTOKENS[i]=${PATHTOKENS[i]//\'/\"}
|
||||||
|
query+="$comma\"${PATHTOKENS[i]//\"/}\""
|
||||||
|
comma=","
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
i=i+1
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z $FILTER ]] && FILTER="$query[],]"
|
||||||
|
[[ $DEBUG -eq 1 ]] && echo "FILTER=$FILTER"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse_array () {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# json parsing
|
||||||
|
|
||||||
|
local index=0
|
||||||
|
local ary=''
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
']')
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
parse_value "$1" "$index"
|
||||||
|
index=$((index+1))
|
||||||
|
ary="$ary""$value"
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
']') break ;;
|
||||||
|
',') ary="$ary," ;;
|
||||||
|
*) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
|
||||||
|
esac
|
||||||
|
read -r token
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
value=
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse_object () {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# json parsing
|
||||||
|
|
||||||
|
local key
|
||||||
|
local obj=''
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
'}')
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
case "$token" in
|
||||||
|
'"'*'"') key=$token ;;
|
||||||
|
*) throw "EXPECTED string GOT ${token:-EOF}" ;;
|
||||||
|
esac
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
':') ;;
|
||||||
|
*) throw "EXPECTED : GOT ${token:-EOF}" ;;
|
||||||
|
esac
|
||||||
|
read -r token
|
||||||
|
parse_value "$1" "$key"
|
||||||
|
obj="$obj$key:$value"
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
'}') break ;;
|
||||||
|
',') obj="$obj," ;;
|
||||||
|
*) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
|
||||||
|
esac
|
||||||
|
read -r token
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
value=
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse_value () {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# json parsing
|
||||||
|
|
||||||
|
local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0
|
||||||
|
case "$token" in
|
||||||
|
'{') parse_object "$jpath" ;;
|
||||||
|
'[') parse_array "$jpath" ;;
|
||||||
|
# At this point, the only valid single-character tokens are digits.
|
||||||
|
''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
|
||||||
|
*) value=$token
|
||||||
|
# if asked, replace solidus ("\/") in json strings with normalized value: "/"
|
||||||
|
[ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g')
|
||||||
|
isleaf=1
|
||||||
|
[ "$value" = '""' ] && isempty=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
[[ -z INCLEMPTY ]] && [ "$value" = '' ] && return
|
||||||
|
[ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return
|
||||||
|
|
||||||
|
[ "$isleaf" -eq 1 ] && [ $isempty -eq 0 ] && print=1
|
||||||
|
[ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value"
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
flatten() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Take out
|
||||||
|
|
||||||
|
local path a prevpath pathlen
|
||||||
|
|
||||||
|
if [[ $FLATTEN -eq 1 ]]; then
|
||||||
|
cat >"$STDINFILE2"
|
||||||
|
|
||||||
|
highest=9999
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
a=${line#[};a=${a%%]*}
|
||||||
|
readarray -t path < <(grep -o "[^,]*"<<<"$a")
|
||||||
|
[[ -z $prevpath ]] && {
|
||||||
|
prevpath=("${path[@]}")
|
||||||
|
highest=$((${#path[*]}-1))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
pathlen=$((${#path[*]}-1))
|
||||||
|
|
||||||
|
for i in `seq 0 $pathlen`; do
|
||||||
|
[[ ${path[i]} != ${prevpath[i]} ]] && {
|
||||||
|
high=$i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $high -lt $highest ]] && highest=$high
|
||||||
|
|
||||||
|
prevpath=("${path[@]}")
|
||||||
|
done <"$STDINFILE2"
|
||||||
|
|
||||||
|
if [[ $highest -gt 0 ]]; then
|
||||||
|
sed -r 's/\[(([0-9]+|"[^"]+")[],]){'$((highest))'}(.*)/[\3/' \
|
||||||
|
"$STDINFILE2"
|
||||||
|
else
|
||||||
|
cat "$STDINFILE2"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
indexmatcher() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# For double digit or greater indexes match each line individually
|
||||||
|
# Single digit indexes are handled more efficiently by regex
|
||||||
|
|
||||||
|
local a b
|
||||||
|
|
||||||
|
[[ $DEBUG -eq 1 ]] && {
|
||||||
|
for i in `seq 0 $((${#INDEXMATCH_QUERY[*]}-1))`; do
|
||||||
|
echo "INDEXMATCH_QUERY[$i]=${INDEXMATCH_QUERY[i]}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
matched=1
|
||||||
|
|
||||||
|
step=
|
||||||
|
if [[ ${#INDEXMATCH_QUERY[*]} -gt 0 ]]; then
|
||||||
|
while read -r line; do
|
||||||
|
for i in `seq 0 $((${#INDEXMATCH_QUERY[*]}-1))`; do
|
||||||
|
[[ ${INDEXMATCH_QUERY[i]#*:} =~ : ]] && {
|
||||||
|
step=${INDEXMATCH_QUERY[i]##*:}
|
||||||
|
step=${step%]}
|
||||||
|
INDEXMATCH_QUERY[i]="${INDEXMATCH_QUERY[i]%:*}]"
|
||||||
|
}
|
||||||
|
q=${INDEXMATCH_QUERY[i]:1:-1} # <- strip '[' and ']'
|
||||||
|
a=${q%:*} # <- number before ':'
|
||||||
|
b=${q#*:} # <- number after ':'
|
||||||
|
[[ -z $b ]] && b=99999999999
|
||||||
|
readarray -t num < <( (grep -Eo ',[0-9]+[],]' | tr -d ,])<<<$line )
|
||||||
|
if [[ ${num[i]} -ge $a && ${num[i]} -lt $b && matched -eq 1 ]]; then
|
||||||
|
matched=1
|
||||||
|
[[ $i -eq $((${#INDEXMATCH_QUERY[*]}-1)) ]] && {
|
||||||
|
if [[ $step -gt 1 ]]; then
|
||||||
|
[[ $(((num[i]-a)%step)) -eq 0 ]] && {
|
||||||
|
[[ $DEBUG -eq 1 ]] && echo -n "($a,$b,${num[i]}) "
|
||||||
|
echo "$line"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[[ $DEBUG -eq 1 ]] && echo -n "($a,$b,${num[i]}) "
|
||||||
|
echo "$line"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
else
|
||||||
|
matched=0
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
matched=1
|
||||||
|
done
|
||||||
|
else
|
||||||
|
cat -
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
brief() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Only show the value
|
||||||
|
|
||||||
|
if [[ $BRIEF -eq 1 ]]; then
|
||||||
|
sed 's/^[^\t]*\t//;s/^"//;s/"$//;'
|
||||||
|
else
|
||||||
|
cat
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
json() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Turn output into JSON
|
||||||
|
|
||||||
|
local a tab=$(echo -e "\t")
|
||||||
|
local UP=1 DOWN=2 SAME=3
|
||||||
|
local prevpathlen=-1 prevpath=() path a
|
||||||
|
declare -a closers
|
||||||
|
|
||||||
|
if [[ $JSON -eq 0 ]]; then
|
||||||
|
cat -
|
||||||
|
else
|
||||||
|
while read -r line; do
|
||||||
|
a=${line#[};a=${a%%]*}
|
||||||
|
readarray -t path < <(grep -o "[^,]*"<<<"$a")
|
||||||
|
value=${line#*$tab}
|
||||||
|
|
||||||
|
# Not including the object itself (last item)
|
||||||
|
pathlen=$((${#path[*]}-1))
|
||||||
|
|
||||||
|
# General direction
|
||||||
|
|
||||||
|
direction=$SAME
|
||||||
|
[[ $pathlen -gt $prevpathlen ]] && direction=$DOWN
|
||||||
|
[[ $pathlen -lt $prevpathlen ]] && direction=$UP
|
||||||
|
|
||||||
|
# Handle jumps UP the tree (close previous paths)
|
||||||
|
|
||||||
|
[[ $prevpathlen != -1 ]] && {
|
||||||
|
for i in `seq 0 $((pathlen-1))`; do
|
||||||
|
[[ ${prevpath[i]} == ${path[i]} ]] && continue
|
||||||
|
[[ ${path[i]} != '"'* ]] && {
|
||||||
|
a=(${!arrays[*]})
|
||||||
|
[[ -n $a ]] && {
|
||||||
|
for k in `seq $((i+1)) ${a[-1]}`; do
|
||||||
|
arrays[k]=
|
||||||
|
done
|
||||||
|
}
|
||||||
|
a=(${!comma[*]})
|
||||||
|
[[ -n $a ]] && {
|
||||||
|
for k in `seq $((i+1)) ${a[-1]}`; do
|
||||||
|
comma[k]=
|
||||||
|
done
|
||||||
|
}
|
||||||
|
for j in `seq $((prevpathlen)) -1 $((i+2))`
|
||||||
|
do
|
||||||
|
arrays[j]=
|
||||||
|
[[ -n ${closers[j]} ]] && {
|
||||||
|
let indent=j*4
|
||||||
|
printf "\n%0${indent}s${closers[j]}" ""
|
||||||
|
unset closers[j]
|
||||||
|
comma[j]=
|
||||||
|
}
|
||||||
|
done
|
||||||
|
direction=$DOWN
|
||||||
|
break
|
||||||
|
}
|
||||||
|
direction=$DOWN
|
||||||
|
for j in `seq $((prevpathlen)) -1 $((i+1))`
|
||||||
|
do
|
||||||
|
arrays[j]=
|
||||||
|
[[ -n ${closers[j]} ]] && {
|
||||||
|
let indent=j*4
|
||||||
|
printf "\n%0${indent}s${closers[j]}" ""
|
||||||
|
unset closers[j]
|
||||||
|
comma[j]=
|
||||||
|
}
|
||||||
|
done
|
||||||
|
a=(${!arrays[*]})
|
||||||
|
[[ -n $a ]] && {
|
||||||
|
for k in `seq $i ${a[-1]}`; do
|
||||||
|
arrays[k]=
|
||||||
|
done
|
||||||
|
}
|
||||||
|
break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ $direction -eq $UP ]] && {
|
||||||
|
[[ $prevpathlen != -1 ]] && comma[prevpathlen]=
|
||||||
|
for i in `seq $((prevpathlen+1)) -1 $((pathlen+1))`
|
||||||
|
do
|
||||||
|
arrays[i]=
|
||||||
|
[[ -n ${closers[i]} ]] && {
|
||||||
|
let indent=i*4
|
||||||
|
printf "\n%0${indent}s${closers[i]}" ""
|
||||||
|
unset closers[i]
|
||||||
|
comma[i]=
|
||||||
|
}
|
||||||
|
done
|
||||||
|
a=(${!arrays[*]})
|
||||||
|
[[ -n $a ]] && {
|
||||||
|
for k in `seq $i ${a[-1]}`; do
|
||||||
|
arrays[k]=
|
||||||
|
done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Opening braces (the path leading up to the key)
|
||||||
|
|
||||||
|
broken=
|
||||||
|
for i in `seq 0 $((pathlen-1))`; do
|
||||||
|
[[ -z $broken && ${prevpath[i]} == ${path[i]} ]] && continue
|
||||||
|
[[ -z $broken ]] && {
|
||||||
|
broken=$i
|
||||||
|
[[ $prevpathlen -ne -1 ]] && broken=$((i+1))
|
||||||
|
}
|
||||||
|
if [[ ${path[i]} == '"'* ]]; then
|
||||||
|
# Object
|
||||||
|
[[ $i -ge $broken ]] && {
|
||||||
|
let indent=i*4
|
||||||
|
printf "${comma[i]}%0${indent}s{\n" ""
|
||||||
|
closers[i]='}'
|
||||||
|
comma[i]=
|
||||||
|
}
|
||||||
|
let indent=(i+1)*4
|
||||||
|
printf "${comma[i]}%0${indent}s${path[i]}:\n" ""
|
||||||
|
comma[i]=",\n"
|
||||||
|
else
|
||||||
|
# Array
|
||||||
|
if [[ ${arrays[i]} != 1 ]]; then
|
||||||
|
let indent=i*4
|
||||||
|
printf "%0${indent}s" ""
|
||||||
|
echo "["
|
||||||
|
closers[i]=']'
|
||||||
|
arrays[i]=1
|
||||||
|
comma[i]=
|
||||||
|
else
|
||||||
|
let indent=(i+1)*4
|
||||||
|
printf "\n%0${indent}s${closers[i-1]}" ""
|
||||||
|
direction=$DOWN
|
||||||
|
comma[i+1]=",\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# keys & values
|
||||||
|
|
||||||
|
if [[ ${path[-1]} == '"'* ]]; then
|
||||||
|
# Object
|
||||||
|
[[ $direction -eq $DOWN ]] && {
|
||||||
|
let indent=pathlen*4
|
||||||
|
printf "${comma[pathlen]}%0${indent}s{\n" ""
|
||||||
|
closers[pathlen]='}'
|
||||||
|
comma[pathlen]=
|
||||||
|
}
|
||||||
|
let indent=(pathlen+1)*4
|
||||||
|
printf "${comma[pathlen]}%0${indent}s" ""
|
||||||
|
echo -n "${path[-1]}:$value"
|
||||||
|
comma[pathlen]=",\n"
|
||||||
|
else
|
||||||
|
# Array
|
||||||
|
[[ ${arrays[i]} != 1 ]] && {
|
||||||
|
let indent=(pathlen-0)*4
|
||||||
|
printf "%0${indent}s[\n" ""
|
||||||
|
closers[pathlen]=']'
|
||||||
|
comma[pathlen]=
|
||||||
|
arrays[i]=1
|
||||||
|
}
|
||||||
|
let indent=(pathlen+1)*4
|
||||||
|
printf "${comma[pathlen]}%0${indent}s" ""
|
||||||
|
echo -n "$value"
|
||||||
|
comma[pathlen]=",\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
prevpath=("${path[@]}")
|
||||||
|
prevpathlen=$pathlen
|
||||||
|
done
|
||||||
|
|
||||||
|
# closing braces
|
||||||
|
|
||||||
|
for i in `seq $((pathlen)) -1 0`
|
||||||
|
do
|
||||||
|
let indent=i*4
|
||||||
|
printf "\n%0${indent}s${closers[i]}" ""
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
filter() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Apply the query filter
|
||||||
|
|
||||||
|
local a tab=$(echo -e "\t") v
|
||||||
|
|
||||||
|
[[ $NOCASE -eq 1 ]] && opts+="-i"
|
||||||
|
[[ $WHOLEWORD -eq 1 ]] && opts+=" -w"
|
||||||
|
if [[ -z $OPERATOR ]]; then
|
||||||
|
egrep $opts "$FILTER"
|
||||||
|
else
|
||||||
|
egrep $opts "$FILTER" | \
|
||||||
|
while read line; do
|
||||||
|
v=${line#*$tab}
|
||||||
|
case $OPERATOR in
|
||||||
|
'-ge') if awk '{exit !($1>=$2)}'<<<"$v $RHS";then echo "$line"; fi
|
||||||
|
;;
|
||||||
|
'-gt') if awk '{exit !($1>$2) }'<<<"$v $RHS";then echo "$line"; fi
|
||||||
|
;;
|
||||||
|
'-le') if awk '{exit !($1<=$2) }'<<<"$v $RHS";then echo "$line"; fi
|
||||||
|
;;
|
||||||
|
'-lt') if awk '{exit !($1<$2) }'<<<"$v $RHS";then echo "$line"; fi
|
||||||
|
;;
|
||||||
|
'>') v=${v#\"};v=${v%\"}
|
||||||
|
RHS=${RHS#\"};RHS=${RHS%\"}
|
||||||
|
[[ "$v" > "$RHS" ]] && echo "$line"
|
||||||
|
;;
|
||||||
|
'<') v=${v#\"};v=${v%\"}
|
||||||
|
RHS=${RHS#\"};RHS=${RHS%\"}
|
||||||
|
[[ "$v" < "$RHS" ]] && echo "$line"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done #< <(egrep $opts "$FILTER")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse () {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Parses json
|
||||||
|
|
||||||
|
read -r token
|
||||||
|
parse_value
|
||||||
|
read -r token
|
||||||
|
case "$token" in
|
||||||
|
'') ;;
|
||||||
|
*) throw "EXPECTED EOF GOT $token"
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
throw() {
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]);
|
||||||
|
then
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# vi: expandtab sw=2 ts=2
|
||||||
15
deps/jsonpath/LICENSE.APACHE2
vendored
Normal file
15
deps/jsonpath/LICENSE.APACHE2
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Apache License, Version 2.0
|
||||||
|
|
||||||
|
Copyright (c) 2011 Dominic Tarr
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
24
deps/jsonpath/LICENSE.MIT
vendored
Normal file
24
deps/jsonpath/LICENSE.MIT
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2011 Dominic Tarr
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge,
|
||||||
|
to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the "Software"), to
|
||||||
|
deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify,
|
||||||
|
merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom
|
||||||
|
the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||||
|
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
3
deps/jsonpath/MANIFEST.in
vendored
Normal file
3
deps/jsonpath/MANIFEST.in
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
include README.md
|
||||||
|
include LICENSE.MIT
|
||||||
|
include LICENSE.APACHE2
|
||||||
491
deps/jsonpath/README.md
vendored
Normal file
491
deps/jsonpath/README.md
vendored
Normal file
@ -0,0 +1,491 @@
|
|||||||
|
# JSONPath.sh
|
||||||
|
|
||||||
|
yo, so it's a JSONPath implementation written in Bash - and it probably only works in Bash.
|
||||||
|
|
||||||
|
[](https://travis-ci.org/mclarkson/JSONPath.sh)
|
||||||
|
|
||||||
|
## Invocation
|
||||||
|
|
||||||
|
JSONPath.sh [-b] [-i] [-j] [-h] [-p] [-u] [-f FILE] [pattern]
|
||||||
|
|
||||||
|
pattern
|
||||||
|
> the JSONPath query. Defaults to '$.\*' if not supplied.
|
||||||
|
|
||||||
|
-b
|
||||||
|
> Brief output. Only show the values, not the path and key.
|
||||||
|
|
||||||
|
-f FILE
|
||||||
|
> Read a FILE instead of reading from standard input.
|
||||||
|
|
||||||
|
-i
|
||||||
|
> Case insensitive searching.
|
||||||
|
|
||||||
|
-j
|
||||||
|
> Output in JSON format, instead of JSON.sh format.
|
||||||
|
|
||||||
|
-u
|
||||||
|
> Strip unnecessary leading path elements.
|
||||||
|
|
||||||
|
-p
|
||||||
|
> Pass JSON.sh formatted data through to the JSON parser only. Useful after
|
||||||
|
> JSON.sh data has been manipulated.
|
||||||
|
|
||||||
|
-h
|
||||||
|
> Show help text.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
JSONPath.sh is a Bash script that uses the standard GNU tools: *bash*, *cat*, *sed*, *awk*, *grep*, and *seq*.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install with pip:
|
||||||
|
|
||||||
|
* `sudo pip install git+https://github.com/mclarkson/JSONPath.sh#egg=JSONPath.sh`
|
||||||
|
|
||||||
|
Install with npm:
|
||||||
|
|
||||||
|
* `sudo npm install -g jsonpath.sh`
|
||||||
|
|
||||||
|
Or copy the `JSONPath.sh` script to your PATH, for example:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
curl -O https://raw.githubusercontent.com/mclarkson/JSONPath.sh/master/JSONPath.sh
|
||||||
|
chmod +x JSONPath.sh
|
||||||
|
mv JSONPath.sh ~/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
$ ./JSONPath.sh < package.json
|
||||||
|
["name"] "JSONPath.sh"
|
||||||
|
["version"] "0.0.0"
|
||||||
|
["description"] "JSONPath implementation written in Bash"
|
||||||
|
["homepage"] "http://github.com/mclarkson/JSONPath.sh"
|
||||||
|
["repository","type"] "git"
|
||||||
|
["repository","url"] "https://github.com/mclarkson/JSONPath.sh.git"
|
||||||
|
["bin","JSONPath.sh"] "./JSONPath.sh"
|
||||||
|
["author"] "Mark Clarkson <mark.clarkson@smorg.co.uk>"
|
||||||
|
["scripts","test"] "./all-tests.sh"
|
||||||
|
```
|
||||||
|
|
||||||
|
more complex examples:
|
||||||
|
|
||||||
|
*NPMJS.ORG EXAMPLES*
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Number of downloads yesterday
|
||||||
|
curl -s https://api.npmjs.org/downloads/point/last-day/jsonpath.sh | \
|
||||||
|
JSONPath.sh '$.downloads' -b
|
||||||
|
|
||||||
|
# Show all versions
|
||||||
|
curl registry.npmjs.org/express | ./JSONPath.sh '$.versions.*.version'
|
||||||
|
|
||||||
|
# Show version 2.2.0
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/npmjs.org.json \
|
||||||
|
'$.versions.["2.2.0"]'
|
||||||
|
|
||||||
|
# Find versions 2.2.x (using a regular expression)
|
||||||
|
# and show version and contributors
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/npmjs.org.json \
|
||||||
|
'$..["2.2.*"].[version,contributors]'
|
||||||
|
```
|
||||||
|
*JSONPATH.ORG EXAMPLES*
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# The default query
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/jsonpath.com.json \
|
||||||
|
'$.phoneNumbers[:1].type'
|
||||||
|
|
||||||
|
# The same, but using a filter (script) expression
|
||||||
|
# (This takes 2 passes through the data)
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/jsonpath.com.json \
|
||||||
|
'$.phoneNumbers[?(@.type=iPhone)]'
|
||||||
|
```
|
||||||
|
|
||||||
|
*KUBERNETES EXAMPLES*
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Show the NodePort of a service named bob
|
||||||
|
# from a list of all services
|
||||||
|
kubectl get svc -o json | JSONPath.sh \
|
||||||
|
'$..items[?(@.metadata.name==bob)].spec.ports[0].nodePort' -b
|
||||||
|
|
||||||
|
# Or, more simply, show the NodePort of the service
|
||||||
|
kubectl get svc bob -o json | JSONPath.sh '$..nodePort' -b
|
||||||
|
|
||||||
|
# Get the port of the kubernetes-dashboard and output as json:
|
||||||
|
kubectl get svc --all-namespaces -o json | JSONPath.sh -j -u \
|
||||||
|
'$.items[?(@.spec.selector.app=".*dashboard")]..ports[*].nodePort'
|
||||||
|
```
|
||||||
|
|
||||||
|
*DOCKER EXAMPLES*
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Show Everything
|
||||||
|
./JSONPath.sh -f test/valid/docker_stopped.json '$.*'
|
||||||
|
|
||||||
|
# Look for an ip address (using case insensitive searching to start)
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/docker_running.json \
|
||||||
|
/valid/docker_running.json -i '$..".*ip.*"'
|
||||||
|
|
||||||
|
# Now get the IP address exactly
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/docker_running.json \
|
||||||
|
'$.*.NetworkSettings.IPAddress' -b
|
||||||
|
|
||||||
|
# Show all Mounts
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/docker_stopped.json \
|
||||||
|
'$.[*].Mounts'
|
||||||
|
|
||||||
|
# Show sources and destinations for all mounts
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/docker_stopped.json \
|
||||||
|
'$.[*].Mounts[*].[Source,Destination]'
|
||||||
|
|
||||||
|
# Use brief (-b) output to store mounts in an array for use in a loop
|
||||||
|
readarray -t MNTS \
|
||||||
|
< <(./JSONPath.sh -b -f test/valid/docker_stopped.json '$.*.Mounts[*].[Source,Destination]')
|
||||||
|
|
||||||
|
# the loop:
|
||||||
|
for idx in `seq 0 $((${#MNTS[*]}/2-1))`; do
|
||||||
|
echo "'${MNTS[idx*2]}' is mounted on the host at '${MNTS[idx*2+1]}'"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
*GOESSNER.NET (EXPANDED) EXAMPLES*
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# dot-notation (my latest favourite book)
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
'$.store.book[16].title'
|
||||||
|
|
||||||
|
# dot-notation with a node set
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
'$.store.book[4,6,16,22].title'
|
||||||
|
|
||||||
|
# bracket-notation ('$[' needs escaping at the
|
||||||
|
# command line, so bash doesn't think it's an
|
||||||
|
# arithmetic expression)
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
"\$['store']['book'][16]['title']"
|
||||||
|
|
||||||
|
# bracket-notation with an array slice and a set
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
"\$['store']['book'][14:25:2]['title','reviews']"
|
||||||
|
|
||||||
|
# Mixed bracket- and dot- notation
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
"\$['store'].book[16].title"
|
||||||
|
|
||||||
|
# Show all titles
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
'$..book[*].title'
|
||||||
|
|
||||||
|
# All books with 'Book 1' somewhere in the title
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
-i '$..book[?(@.title==".*Book 1.*")].title'
|
||||||
|
|
||||||
|
# All books with a price less than or equal to 4.20
|
||||||
|
# Show both the title and the price and output in
|
||||||
|
# JSON format but without redundant path elements.
|
||||||
|
./JSONPath.sh -j -u \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
'$.store.book[?(@.price<4.20)].[title,price]'
|
||||||
|
|
||||||
|
# The following does not work yet (TODO)
|
||||||
|
./JSONPath.sh \
|
||||||
|
-f test/valid/goessner.net.expanded.json \
|
||||||
|
'$.store.book[(@.length-1)].title'
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSONPath patterns and extensions
|
||||||
|
|
||||||
|
### Supported JSONPath options
|
||||||
|
|
||||||
|
| JSONPath | Supported | Comment |
|
||||||
|
| -----------------------|-----------|---------------------------------------------------------|
|
||||||
|
| $ | Y | the root object/element (optional) |
|
||||||
|
| @ | Y | the current object/element |
|
||||||
|
| . or [] | Y | child operator. |
|
||||||
|
| .. | Y | recusive descent. |
|
||||||
|
| * | Y | wildcard. All objects/elements regardless their names. |
|
||||||
|
| [] | Y | subscript operator. |
|
||||||
|
| [,] | Y | node sets. |
|
||||||
|
| ```[start:end:step]``` | Y | array slice operator. |
|
||||||
|
| ?() | Y | applies a filter (script) expressions |
|
||||||
|
| () | Y | script expression, using the underlying script engine. |
|
||||||
|
|
||||||
|
### Searching for things
|
||||||
|
|
||||||
|
"regex"
|
||||||
|
|
||||||
|
Use a regular expression inside the JSONPath pattern.<br>
|
||||||
|
Combine with '-i' for case insensitive search.<br>
|
||||||
|
Combine with '-w' to match whole words only.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Find every node key starting with 'ip':
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# These are all equivalent
|
||||||
|
./JSONPath.sh -f test/valid/docker_running.json -i "$..['ip.*']"
|
||||||
|
./JSONPath.sh -f test/valid/docker_running.json -i '$..["ip.*"]'
|
||||||
|
./JSONPath.sh -f test/valid/docker_running.json -i '$.."ip.*"'
|
||||||
|
./JSONPath.sh -f test/valid/docker_running.json -i "$..'ip.*'"
|
||||||
|
```
|
||||||
|
|
||||||
|
Restrict the previous search to the bridge object.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
./JSONPath.sh -f test/valid/docker_running.json -i "$..bridge.'ip.*'"
|
||||||
|
```
|
||||||
|
|
||||||
|
Show all book titles by authors starting with 'Doug'.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# Show the title
|
||||||
|
./JSONPath.sh -f test/valid/goessner.net.expanded.json -i \
|
||||||
|
"$..book[?(@.author==Doug)].title"
|
||||||
|
|
||||||
|
# Show the author, title and rating (can be with or without double quotes)
|
||||||
|
./JSONPath.sh -f test/valid/goessner.net.expanded.json -i \
|
||||||
|
'$..book[?(@.author="Doug")].["author","title",rating]'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modification
|
||||||
|
|
||||||
|
A common task is to modify JSON data on-the-fly. Unix style 'one-liners' can be
|
||||||
|
created to easily and logically modify JSON data.
|
||||||
|
|
||||||
|
The key to data modification (that is: add, modify or deletion of data) is to
|
||||||
|
modify the *JSON.sh* formatted data, then use the passthrough, '-p', option to
|
||||||
|
output again as JSON. Sequence is:
|
||||||
|
|
||||||
|
1. Read JSON data and output as *JSON.sh* data.
|
||||||
|
2. Modify *JSON.sh* data using standard Unix tools.
|
||||||
|
3. Pipe modified *JSON.sh* data to JSONPath.sh with passthrough option producing
|
||||||
|
JSON data again.
|
||||||
|
|
||||||
|
For example: The following 'one-liner' will read a kubernetes deployment
|
||||||
|
configuration (using 'kubectl get ...'), output it in *JSON.sh* format (using
|
||||||
|
'JSONPath.sh'), change the number of replicas from the existing value to 5
|
||||||
|
(using *sed*), output again in JSON (using 'JSONPath.sh -p'), then replace the
|
||||||
|
original deployment with the newly changed one (using 'kubectl replace ...').
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get deployment sample-deployment -o json | \
|
||||||
|
JSONPath.sh | \
|
||||||
|
sed 's/\["spec","replicas"\].*/["spec","replicas"]\t5/' | \
|
||||||
|
JSONPath.sh -p | \
|
||||||
|
kubectl replace deployment sample-deployment -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to reuse your Unix skills rather than learn new terse syntax
|
||||||
|
or Domain Specific Language.
|
||||||
|
|
||||||
|
### Re-injection
|
||||||
|
|
||||||
|
This tool, JSONPath.sh, is really handy for handing json formatted
|
||||||
|
data to other tools, and using pass-through mode (-p) comes in quite
|
||||||
|
handy for creating complex queries and outputting in json.
|
||||||
|
|
||||||
|
**Re-injection** allows the user to overcome the limitation
|
||||||
|
of a single filter expression per invocation. To do this the first
|
||||||
|
query, or set of queries, should output in JSON format using the
|
||||||
|
'-j' option.
|
||||||
|
|
||||||
|
**Usage Example**
|
||||||
|
|
||||||
|
Show all books with a price greater than 4 that also have a 5 star
|
||||||
|
rating (note that the first process in the pipeline outputs in json):
|
||||||
|
|
||||||
|
```
|
||||||
|
./JSONPath.sh -j -f test/valid/goessner.net.expanded.json \
|
||||||
|
'$..book[?(@.price>4)]' | ./JSONPath.sh \
|
||||||
|
'$..book[?(@.rating==5)].title'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pass-through mode** reads the standard output JSONPath.sh (or JSON.sh)
|
||||||
|
produces and outputs JSON. This gives the user an opportunity to filter
|
||||||
|
or modify the results:
|
||||||
|
|
||||||
|
**Filtering Usage Example**
|
||||||
|
|
||||||
|
Show all authors, without showing duplicates and output in JSON format.
|
||||||
|
|
||||||
|
All authors with duplicates:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author'
|
||||||
|
... omitted ...
|
||||||
|
["store","book",9,"author"] "James S. A. Corey"
|
||||||
|
["store","book",10,"author"] "James S. A. Corey"
|
||||||
|
["store","book",11,"author"] "James S. A. Corey"
|
||||||
|
... 25 lines of output ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use standard unix tools to remove duplicates:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author' \
|
||||||
|
| sort -k2 | uniq -f 1
|
||||||
|
... 11 lines of output ...
|
||||||
|
```
|
||||||
|
|
||||||
|
And pipe (re-inject - 'cos it sounds cool) the output into JSONPath.sh:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author' \
|
||||||
|
| sort -k2 | uniq -f 1 \
|
||||||
|
| ./JSONPath.sh -p
|
||||||
|
{
|
||||||
|
"store":
|
||||||
|
{
|
||||||
|
"book":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"author":"Douglas E. Richards"
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
"author":"Evelyn Waugh"
|
||||||
|
}
|
||||||
|
... JSON output with unique data ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the '-u' option to flatten the output:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json \
|
||||||
|
'$..author' \
|
||||||
|
| sort -k2 | uniq -f 1 \
|
||||||
|
| ./JSONPath.sh -p -u
|
||||||
|
... JSON flattened output ...
|
||||||
|
{
|
||||||
|
"book":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"author":"Douglas E. Richards"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author":"Evelyn Waugh"
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
**Filter and Merge Usage Example**
|
||||||
|
|
||||||
|
Different parts of JSON input, or entirely different JSON input, can be merged
|
||||||
|
together with Unix 'sort' and output in json format.
|
||||||
|
|
||||||
|
This is a complex kubernetes example that uses JSONPath.sh and standard Unix
|
||||||
|
tools to output just the command, pod mounts, and container mounts (output from
|
||||||
|
different parts of the tree) for the first matched kube-proxy pod.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Get details of all pods
|
||||||
|
kubectl get -n kube-system pods -o json >/tmp/kpod
|
||||||
|
|
||||||
|
# Get the index of the first pod with name starting 'kube-proxy'
|
||||||
|
idx=`JSONPath.sh -f /tmp/kpod '$.items[?(@.metadata.name=="kube-proxy.*")].apiVersion' \
|
||||||
|
| head -n1 | grep -o ',[0-9]\+,' | tr -d ,`
|
||||||
|
|
||||||
|
# Get three subtrees using the index and merge them using sort
|
||||||
|
# and then output in json format
|
||||||
|
( JSONPath.sh -f /tmp/kpod '$.items['$idx'].spec.volumes'; \
|
||||||
|
JSONPath.sh -f /tmp/kpod '$.items['$idx']..volumeMounts'; \
|
||||||
|
JSONPath.sh -f /tmp/kpod '$.items['$idx']..containers[*].command'
|
||||||
|
) | sort | JSONPath.sh -p -u
|
||||||
|
```
|
||||||
|
|
||||||
|
, which produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"containers":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"command":
|
||||||
|
[
|
||||||
|
"/usr/local/bin/kube-proxy",
|
||||||
|
"--kubeconfig=/var/lib/kube-proxy/kubeconfig.conf"
|
||||||
|
],
|
||||||
|
"volumeMounts":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"mountPath":"/var/lib/kube-proxy",
|
||||||
|
"name":"kube-proxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount",
|
||||||
|
"name":"kube-proxy-token-m9b6j",
|
||||||
|
"readOnly":true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"volumes":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"configMap":
|
||||||
|
{
|
||||||
|
"defaultMode":420,
|
||||||
|
"name":"kube-proxy"
|
||||||
|
},
|
||||||
|
"name":"kube-proxy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"kube-proxy-token-m9b6j",
|
||||||
|
"secret":
|
||||||
|
{
|
||||||
|
"defaultMode":420,
|
||||||
|
"secretName":"kube-proxy-token-m9b6j"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cool Links
|
||||||
|
|
||||||
|
* [dominictarr/JSON.sh](https://github.com/dominictarr/JSON.sh) The original, the best, JSON.sh.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
* Performance is acceptable for small data sizes
|
||||||
|
* Worse when using:
|
||||||
|
* large data files (hundreds of kilobytes).
|
||||||
|
* filter (script) expressions (An extra pass is required).
|
||||||
|
* Indexes greater than 9.
|
||||||
|
* Indexes with steps even with indexes less than 10.
|
||||||
|
* Better with:
|
||||||
|
* Small data files (A few kilobytes).
|
||||||
|
* Indexes less than 10 (then matching is done by regex, unless a step is used).
|
||||||
|
* No filter (script) expressions (so no extra pass through the data).
|
||||||
|
|
||||||
|
## Limitations (todo)
|
||||||
|
|
||||||
|
* Only one filter expression, '?(@', per query.
|
||||||
|
Use re-injection, detailed above, to overcome this limitation.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This software is available under the following licenses:
|
||||||
|
|
||||||
|
* MIT
|
||||||
|
* Apache 2
|
||||||
|
|
||||||
1
deps/jsonpath/_config.yml
vendored
Normal file
1
deps/jsonpath/_config.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-slate
|
||||||
33
deps/jsonpath/all-tests.sh
vendored
Normal file
33
deps/jsonpath/all-tests.sh
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd ${0%/*}
|
||||||
|
|
||||||
|
#set -e
|
||||||
|
fail=0
|
||||||
|
tests=0
|
||||||
|
#all_tests=${__dirname:}
|
||||||
|
#echo PLAN ${#all_tests}
|
||||||
|
for test in test/*.sh ;
|
||||||
|
do
|
||||||
|
tests=$((tests+1))
|
||||||
|
echo TEST: $test
|
||||||
|
./$test
|
||||||
|
ret=$?
|
||||||
|
if [ $ret -eq 0 ] ; then
|
||||||
|
echo OK: ---- $test
|
||||||
|
passed=$((passed+1))
|
||||||
|
else
|
||||||
|
echo FAIL: $test $fail
|
||||||
|
fail=$((fail+ret))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $fail -eq 0 ]; then
|
||||||
|
echo -n 'SUCCESS '
|
||||||
|
exitcode=0
|
||||||
|
else
|
||||||
|
echo -n 'FAILURE '
|
||||||
|
exitcode=1
|
||||||
|
fi
|
||||||
|
echo $passed / $tests
|
||||||
|
exit $exitcode
|
||||||
19
deps/jsonpath/package.json
vendored
Normal file
19
deps/jsonpath/package.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "jsonpath.sh",
|
||||||
|
"version": "0.0.14",
|
||||||
|
"description": "JSONPath implementation written in Bash",
|
||||||
|
"homepage": "http://github.com/mclarkson/JSONPath.sh",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mclarkson/JSONPath.sh.git"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"JSONPath.sh": "./JSONPath.sh"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {},
|
||||||
|
"author": "Mark Clarkson <mark.clarkson@smorg.co.uk>",
|
||||||
|
"scripts": {
|
||||||
|
"test": "./all-tests.sh"
|
||||||
|
}
|
||||||
|
}
|
||||||
31
deps/jsonpath/setup.py
vendored
Normal file
31
deps/jsonpath/setup.py
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Allow setup.py to be run from any path
|
||||||
|
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='JSONPath.sh',
|
||||||
|
scripts=[
|
||||||
|
'JSONPath.sh',
|
||||||
|
],
|
||||||
|
version='0.0.14',
|
||||||
|
description="JSONPath implementation written in Bash",
|
||||||
|
long_description="",
|
||||||
|
author='Mark Clarkson',
|
||||||
|
author_email='mark.clarkson@smorg.co.uk',
|
||||||
|
url='https://github.com/mclarkson/JSONPath.sh',
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Unix Shell",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"License :: OSI Approved :: Apache Software License",
|
||||||
|
"Intended Audience :: System Administrators",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Operating System :: POSIX :: Linux",
|
||||||
|
"Topic :: Utilities",
|
||||||
|
"Topic :: Software Development :: Libraries",
|
||||||
|
],
|
||||||
|
)
|
||||||
4
deps/semver_bash/.gitignore
vendored
Normal file
4
deps/semver_bash/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
*~
|
||||||
|
*tmp
|
||||||
|
*swp
|
||||||
|
|
||||||
26
deps/semver_bash/LICENSE
vendored
Normal file
26
deps/semver_bash/LICENSE
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Copyright (c) 2013, Ray Bejjani
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of the FreeBSD Project.
|
||||||
31
deps/semver_bash/README.md
vendored
Normal file
31
deps/semver_bash/README.md
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
semver_bash is a bash parser for semantic versioning
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
[Semantic Versioning](http://semver.org/) is a set of guidelines that help keep
|
||||||
|
version and version management sane. This is a bash based parser to help manage
|
||||||
|
a project's versions. Use it from a Makefile or any scripts you use in your
|
||||||
|
project.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
semver_bash can be used from the command line as:
|
||||||
|
|
||||||
|
$ ./semver.sh "3.2.1" "3.2.1-alpha"
|
||||||
|
3.2.1 -> M: 3 m:2 p:1 s:
|
||||||
|
3.2.1-alpha -> M: 3 m:2 p:1 s:-alpha
|
||||||
|
3.2.1 == 3.2.1-alpha -> 1.
|
||||||
|
3.2.1 < 3.2.1-alpha -> 1.
|
||||||
|
3.2.1 > 3.2.1-alpha -> 0.
|
||||||
|
|
||||||
|
|
||||||
|
Alternatively, you can source it from within a script:
|
||||||
|
|
||||||
|
. ./semver.sh
|
||||||
|
|
||||||
|
local MAJOR=0
|
||||||
|
local MINOR=0
|
||||||
|
local PATCH=0
|
||||||
|
local SPECIAL=""
|
||||||
|
|
||||||
|
semverParseInto "1.2.3" MAJOR MINOR PATCH SPECIAL
|
||||||
|
semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL
|
||||||
130
deps/semver_bash/semver.sh
vendored
Normal file
130
deps/semver_bash/semver.sh
vendored
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
function semverParseInto() {
|
||||||
|
local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)'
|
||||||
|
#MAJOR
|
||||||
|
eval $2=`echo $1 | sed -e "s#$RE#\1#"`
|
||||||
|
#MINOR
|
||||||
|
eval $3=`echo $1 | sed -e "s#$RE#\2#"`
|
||||||
|
#MINOR
|
||||||
|
eval $4=`echo $1 | sed -e "s#$RE#\3#"`
|
||||||
|
#SPECIAL
|
||||||
|
eval $5=`echo $1 | sed -e "s#$RE#\4#"`
|
||||||
|
}
|
||||||
|
|
||||||
|
function semverEQ() {
|
||||||
|
local MAJOR_A=0
|
||||||
|
local MINOR_A=0
|
||||||
|
local PATCH_A=0
|
||||||
|
local SPECIAL_A=0
|
||||||
|
|
||||||
|
local MAJOR_B=0
|
||||||
|
local MINOR_B=0
|
||||||
|
local PATCH_B=0
|
||||||
|
local SPECIAL_B=0
|
||||||
|
|
||||||
|
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
|
||||||
|
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
|
||||||
|
|
||||||
|
if [ $MAJOR_A -ne $MAJOR_B ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $MINOR_A -ne $MINOR_B ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $PATCH_A -ne $PATCH_B ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function semverLT() {
|
||||||
|
local MAJOR_A=0
|
||||||
|
local MINOR_A=0
|
||||||
|
local PATCH_A=0
|
||||||
|
local SPECIAL_A=0
|
||||||
|
|
||||||
|
local MAJOR_B=0
|
||||||
|
local MINOR_B=0
|
||||||
|
local PATCH_B=0
|
||||||
|
local SPECIAL_B=0
|
||||||
|
|
||||||
|
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
|
||||||
|
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
|
||||||
|
|
||||||
|
if [ $MAJOR_A -lt $MAJOR_B ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function semverGT() {
|
||||||
|
semverEQ $1 $2
|
||||||
|
local EQ=$?
|
||||||
|
|
||||||
|
semverLT $1 $2
|
||||||
|
local LT=$?
|
||||||
|
|
||||||
|
if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "___semver.sh" == "___`basename $0`" ]; then
|
||||||
|
|
||||||
|
MAJOR=0
|
||||||
|
MINOR=0
|
||||||
|
PATCH=0
|
||||||
|
SPECIAL=""
|
||||||
|
|
||||||
|
semverParseInto $1 MAJOR MINOR PATCH SPECIAL
|
||||||
|
echo "$1 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
|
||||||
|
|
||||||
|
semverParseInto $2 MAJOR MINOR PATCH SPECIAL
|
||||||
|
echo "$2 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
|
||||||
|
|
||||||
|
semverEQ $1 $2
|
||||||
|
echo "$1 == $2 -> $?."
|
||||||
|
|
||||||
|
semverLT $1 $2
|
||||||
|
echo "$1 < $2 -> $?."
|
||||||
|
|
||||||
|
semverGT $1 $2
|
||||||
|
echo "$1 > $2 -> $?."
|
||||||
|
|
||||||
|
fi
|
||||||
151
deps/semver_bash/semver_test.sh
vendored
Normal file
151
deps/semver_bash/semver_test.sh
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
. ./semver.sh
|
||||||
|
|
||||||
|
semverTest() {
|
||||||
|
local A=R1.3.2
|
||||||
|
local B=R2.3.2
|
||||||
|
local C=R1.4.2
|
||||||
|
local D=R1.3.3
|
||||||
|
local E=R1.3.2a
|
||||||
|
local F=R1.3.2b
|
||||||
|
local G=R1.2.3
|
||||||
|
|
||||||
|
local MAJOR=0
|
||||||
|
local MINOR=0
|
||||||
|
local PATCH=0
|
||||||
|
local SPECIAL=""
|
||||||
|
|
||||||
|
semverParseInto $A MAJOR MINOR PATCH SPECIAL
|
||||||
|
echo "$A -> M:$MAJOR m:$MINOR p:$PATCH s:$SPECIAL. Expect M:1 m:3 p:2 s:"
|
||||||
|
semverParseInto $E MAJOR MINOR PATCH SPECIAL
|
||||||
|
echo "$E -> M:$MAJOR m:$MINOR p:$PATCH s:$SPECIAL. Expect M:1 m:3 p:2 s:a"
|
||||||
|
|
||||||
|
echo "Equality comparisions"
|
||||||
|
semverEQ $A $A
|
||||||
|
echo "$A == $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverLT $A $A
|
||||||
|
echo "$A < $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $A $A
|
||||||
|
echo "$A > $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
|
||||||
|
echo "Major number comparisions"
|
||||||
|
semverEQ $A $B
|
||||||
|
echo "$A == $B -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $A $B
|
||||||
|
echo "$A < $B -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $A $B
|
||||||
|
echo "$A > $B -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverEQ $B $A
|
||||||
|
echo "$B == $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $B $A
|
||||||
|
echo "$B < $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $B $A
|
||||||
|
echo "$B > $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
|
||||||
|
echo "Minor number comparisions"
|
||||||
|
semverEQ $A $C
|
||||||
|
echo "$A == $C -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $A $C
|
||||||
|
echo "$A < $C -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $A $C
|
||||||
|
echo "$A > $C -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverEQ $C $A
|
||||||
|
echo "$C == $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $C $A
|
||||||
|
echo "$C < $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $C $A
|
||||||
|
echo "$C > $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
echo "patch number comparisions"
|
||||||
|
semverEQ $A $D
|
||||||
|
echo "$A == $D -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $A $D
|
||||||
|
echo "$A < $D -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $A $D
|
||||||
|
echo "$A > $D -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverEQ $D $A
|
||||||
|
echo "$D == $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $D $A
|
||||||
|
echo "$D < $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $D $A
|
||||||
|
echo "$D > $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
echo "special section vs no special comparisions"
|
||||||
|
semverEQ $A $E
|
||||||
|
echo "$A == $E -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $A $E
|
||||||
|
echo "$A < $E -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $A $E
|
||||||
|
echo "$A > $E -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverEQ $E $A
|
||||||
|
echo "$E == $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $E $A
|
||||||
|
echo "$E < $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $E $A
|
||||||
|
echo "$E > $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
echo "special section vs special comparisions"
|
||||||
|
semverEQ $E $F
|
||||||
|
echo "$E == $F -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $E $F
|
||||||
|
echo "$E < $F -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $E $F
|
||||||
|
echo "$E > $F -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverEQ $F $E
|
||||||
|
echo "$F == $E -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $F $E
|
||||||
|
echo "$F < $E -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $F $E
|
||||||
|
echo "$F > $E -> $?. Expect 0."
|
||||||
|
|
||||||
|
echo "Minor and patch number comparisons"
|
||||||
|
semverEQ $A $G
|
||||||
|
echo "$A == $G -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $A $G
|
||||||
|
echo "$A < $G -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverGT $A $G
|
||||||
|
echo "$A > $G -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverEQ $G $A
|
||||||
|
echo "$G == $A -> $?. Expect 1."
|
||||||
|
|
||||||
|
semverLT $G $A
|
||||||
|
echo "$G < $A -> $?. Expect 0."
|
||||||
|
|
||||||
|
semverGT $G $A
|
||||||
|
echo "$G > $A -> $?. Expect 1."
|
||||||
|
}
|
||||||
|
|
||||||
|
semverTest
|
||||||
12
install.sh
12
install.sh
@ -3,16 +3,8 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
PATH_APPS="$CUR_PATH/apps/"
|
|
||||||
PATH_MODULES="$CUR_PATH/modules/"
|
source "$CUR_PATH/apps/installer/includes/includes.sh"
|
||||||
[ ! -d $PATH_APPS/drassil/joiner ] && git clone https://github.com/drassil/joiner $PATH_APPS/drassil/joiner -b master
|
|
||||||
source "$PATH_APPS/drassil/joiner/joiner.sh"
|
|
||||||
|
|
||||||
|
|
||||||
# installing repository dependencies
|
|
||||||
if [[ $1 == "dev" ]]; then
|
|
||||||
git submodule update --init "$CUR_PATH/data/doc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
source "$CUR_PATH/apps/installer/main.sh"
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user