diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index b9496822..0c64883f 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -34,33 +34,33 @@ jobs: include: - vendor: ubuntu bashImage: ubuntu:20.04 - batsOptions: -j 5 + batsOptions: -j 30 bashTarVersion: 4.4 runPrecommitTests: false - vendor: ubuntu bashImage: ubuntu:20.04 bashTarVersion: 5.0 - batsOptions: -j 5 + batsOptions: -j 30 runPrecommitTests: false - vendor: ubuntu bashImage: ubuntu:20.04 bashTarVersion: 5.1 - batsOptions: -j 5 + batsOptions: -j 30 runPrecommitTests: true - vendor: alpine bashTarVersion: 4.4 bashImage: amd64/bash:4.4-alpine3.18 - batsOptions: -j 5 + batsOptions: -j 30 runPrecommitTests: false - vendor: alpine bashTarVersion: 5.0 bashImage: amd64/bash:5.0-alpine3.18 - batsOptions: -j 5 + batsOptions: -j 30 runPrecommitTests: false - vendor: alpine bashTarVersion: 5.1 bashImage: amd64/bash:5.1-alpine3.18 - batsOptions: -j 5 + batsOptions: -j 30 runPrecommitTests: false steps: - name: Checkout @@ -116,6 +116,7 @@ jobs: name: linter-reports path: | megalinter-reports/** + bin/** - name: Create Pull Request if: matrix.runPrecommitTests && failure() diff --git a/bin/cli b/bin/cli index f6f44efb..b0abddf5 100755 --- a/bin/cli +++ b/bin/cli @@ -1646,7 +1646,7 @@ cliCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/dbImport b/bin/dbImport index acedf753..39e8f151 100755 --- a/bin/dbImport +++ b/bin/dbImport @@ -264,6 +264,36 @@ Assert::commandExists() { return 0 } +# @description ignore exit code 141 from simple command pipes +# @example use with: +# local resultingStatus=0 +# local -a originalPipeStatus=() +# cmd1 | cmd2 || Bash::handlePipelineFailure resultingStatus originalPipeStatus || true +# [[ "${resultingStatus}" = "0" ]] +# @arg $1 resultingStatusCode:&int (passed by reference) (optional) resulting status code +# @arg $2 originalStatus:int[] (passed by reference) (optional) copy of original PIPESTATUS array +# @env PIPESTATUS assuming that this function is called like in the example provided +# @see https://unix.stackexchange.com/a/709880/582856 +Bash::handlePipelineFailure() { + local -a pipeStatusBackup=("${PIPESTATUS[@]}") + local -n handlePipelineFailure_resultingStatusCode=$1 + local -n handlePipelineFailure_originalStatus=$2 + # shellcheck disable=SC2034 + handlePipelineFailure_originalStatus=("${pipeStatusBackup[@]}") + handlePipelineFailure_resultingStatusCode=0 + local statusCode + for statusCode in "${pipeStatusBackup[@]}"; do + if ((statusCode == 141)); then + return 0 + elif ((statusCode > 0)); then + # shellcheck disable=SC2034 + handlePipelineFailure_resultingStatusCode="${statusCode}" + break + fi + done + return "${handlePipelineFailure_resultingStatusCode}" +} + # @description get absolute conf file from specified conf folder deduced using these rules # * from absolute file (ignores and ) # * relative to where script is executed (ignores and ) @@ -2202,7 +2232,7 @@ dbImportCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray @@ -2488,9 +2518,13 @@ run() { Log::displayInfo "avoid to create db structure" else Log::displayInfo "create db structure from ${remoteDbStructureDumpTempFile}" + # shellcheck disable=SC2034 + local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() time ( pv "${remoteDbStructureDumpTempFile}" | zcat | - Database::query dbTargetDatabase "" "${targetDbName}" + Database::query dbTargetDatabase "" "${targetDbName}" || Bash::handlePipelineFailure status pipeStatus ) fi fi diff --git a/bin/dbImportProfile b/bin/dbImportProfile index be0dc3ce..a9564c9d 100755 --- a/bin/dbImportProfile +++ b/bin/dbImportProfile @@ -1781,7 +1781,7 @@ dbImportProfileCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/dbImportStream b/bin/dbImportStream index 6da59309..8caaa9f9 100755 --- a/bin/dbImportStream +++ b/bin/dbImportStream @@ -264,6 +264,36 @@ Assert::commandExists() { return 0 } +# @description ignore exit code 141 from simple command pipes +# @example use with: +# local resultingStatus=0 +# local -a originalPipeStatus=() +# cmd1 | cmd2 || Bash::handlePipelineFailure resultingStatus originalPipeStatus || true +# [[ "${resultingStatus}" = "0" ]] +# @arg $1 resultingStatusCode:&int (passed by reference) (optional) resulting status code +# @arg $2 originalStatus:int[] (passed by reference) (optional) copy of original PIPESTATUS array +# @env PIPESTATUS assuming that this function is called like in the example provided +# @see https://unix.stackexchange.com/a/709880/582856 +Bash::handlePipelineFailure() { + local -a pipeStatusBackup=("${PIPESTATUS[@]}") + local -n handlePipelineFailure_resultingStatusCode=$1 + local -n handlePipelineFailure_originalStatus=$2 + # shellcheck disable=SC2034 + handlePipelineFailure_originalStatus=("${pipeStatusBackup[@]}") + handlePipelineFailure_resultingStatusCode=0 + local statusCode + for statusCode in "${pipeStatusBackup[@]}"; do + if ((statusCode == 141)); then + return 0 + elif ((statusCode > 0)); then + # shellcheck disable=SC2034 + handlePipelineFailure_resultingStatusCode="${statusCode}" + break + fi + done + return "${handlePipelineFailure_resultingStatusCode}" +} + # @description get absolute conf file from specified conf folder deduced using these rules # * from absolute file (ignores and ) # * relative to where script is executed (ignores and ) @@ -2014,7 +2044,7 @@ dbImportStreamCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray @@ -2157,7 +2187,7 @@ run() { Version::checkMinimal "gawk" "--version" "5.0.1" # create db instances - declare -Agx dbTargetInstance + local -Agx dbTargetInstance Database::newInstance dbTargetInstance "${optionTargetDsn}" Database::setQueryOptions dbTargetInstance "${dbTargetInstance[QUERY_OPTIONS]} --connect-timeout=5" @@ -2166,7 +2196,11 @@ run() { initializeDefaultTargetMysqlOptions dbTargetInstance "${argTargetDbName}" # TODO character set should be retrieved from dump files if possible - declare remoteCharacterSet="${optionCharacterSet:-${defaultRemoteCharacterSet}}" + local remoteCharacterSet="${optionCharacterSet:-${defaultRemoteCharacterSet}}" + + local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() # shellcheck disable=2086 ( @@ -2175,19 +2209,19 @@ run() { elif [[ "${argDumpFile}" =~ \.gz$ ]]; then zcat "${argDumpFile}" fi - # zcat will continue to write to stdout whereas awk has finished if table has been found - # we detect this case because zcat will return code 141 because pipe closed - status=$? - if [[ "${status}" -eq "141" ]]; then true; else exit "${status}"; fi ) | awk \ -v PROFILE_COMMAND="${profileCommandFile}" \ -v CHARACTER_SET="${remoteCharacterSet}" \ --source "${awkScript}" \ - - | mysql \ - "--defaults-extra-file=${dbTargetInstance['AUTH_FILE']}" \ - ${dbTargetInstance['DB_IMPORT_OPTIONS']} \ - "${argTargetDbName}" || exit $? + - | + mysql \ + "--defaults-extra-file=${dbTargetInstance['AUTH_FILE']}" \ + ${dbTargetInstance['DB_IMPORT_OPTIONS']} \ + "${argTargetDbName}" || + # zcat will continue to write to stdout whereas awk has finished if table has been found + # we detect this case because zcat will return code 141 because pipe closed + Bash::handlePipelineFailure status pipeStatus } if [[ "${BASH_FRAMEWORK_QUIET_MODE:-0}" = "1" ]]; then diff --git a/bin/dbQueryAllDatabases b/bin/dbQueryAllDatabases index 67517317..b26beb15 100755 --- a/bin/dbQueryAllDatabases +++ b/bin/dbQueryAllDatabases @@ -8,7 +8,6 @@ # BIN_FILE=${BASH_TOOLS_ROOT_DIR}/bin/dbQueryAllDatabases # VAR_RELATIVE_FRAMEWORK_DIR_TO_CURRENT_DIR=.. # FACADE -# EMBED Db::queryOneDatabase as dbQueryOneDatabase # ensure that no user aliases could interfere with # commands used in this script @@ -249,32 +248,6 @@ Assert::commandExists() { return 0 } -# @description convert base64 encoded back to target file -# if target file is executable prepend dir of target -# file to PATH to make binary available everywhere -# it is advised to include in the path of the target file -# the md5sum of the binFile -# -# @arg $1 targetFile:String the file to write -# @arg $2 binFileBase64:String the base64 encoded file -# @arg $3 fileMode:String the chmod to set on the file -# @set PATH String prepend target embedded file binary directory to PATH variable if binary executable -Compiler::Embed::extractFileFromBase64() { - local targetFile="$1" - local binFileBase64="$2" - local fileMode="${3:-+x}" - - if [[ ! -f "${targetFile}" ]]; then - mkdir -p "$(dirname "${targetFile}")" - base64 -d >"${targetFile}" <<<"${binFileBase64}" - chmod "${fileMode}" "${targetFile}" - fi - - if [[ -x "${targetFile}" ]]; then - Env::pathPrepend "$(dirname "${targetFile}")" - fi -} - # @description get absolute conf file from specified conf folder deduced using these rules # * from absolute file (ignores and ) # * relative to where script is executed (ignores and ) @@ -454,6 +427,32 @@ Database::setQueryOptions() { instanceSetQueryOptions['QUERY_OPTIONS']="$2" } +# @description used to execute given query when using +# dbScriptAllDatabases +# @arg $1 dsn:String +# @arg $2 db:String +# @env query String +# @env optionSeparator String +# @require Linux::requireExecutedAsUser +Db::queryOneDatabase() { + # query and optionSeparator are passed via export + local dsn="$1" + local db="$2" + + local -A dbInstance + Database::newInstance dbInstance "${dsn}" + Database::setQueryOptions dbInstance "${dbInstance[QUERY_OPTIONS]} --connect-timeout=5" + + # identify columns header + echo -n "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" + Database::skipColumnNames dbInstance 0 + + # shellcheck disable=SC2154 + if ! Database::query dbInstance "${query}" "${db}" | sed "s/\t/${optionSeparator}/g"; then + Log::fatal "database ${db} error" 1>&2 + fi +} + # @description ensure env files are loaded # @arg $@ list of default files to load at the end # @exitcode 1 if one of env files fails to load @@ -493,6 +492,15 @@ Framework::createTempFile() { mktemp -p "${TMPDIR:-/tmp}" -t "${1:-}.XXXXXXXXXXXX" } +# @description ensure running user is not root +# @exitcode 1 if current user is root +# @stderr diagnostics information is displayed +Linux::requireExecutedAsUser() { + if [[ "$(id -u)" = "0" ]]; then + Log::fatal "this script should be executed as normal user" + fi +} + # @description Log namespace provides 2 kind of functions # - Log::display* allows to display given message with # given display level @@ -742,20 +750,6 @@ Version::checkMinimal() { } -# @description ensure tmpdir/bin exists and -# is added to PATH to make embed being executed automatically -# @noargs -# @exitcode 1 if cannot create tmp bin directory -# @set PATH string add tmp bin directory where to find embed binaries -# @stderr diagnostics information is displayed -Compiler::Embed::requireEmbedBinDir() { - mkdir -p "${TMPDIR:-/tmp}/bin" || { - Log::displayError "unable to create directory ${TMPDIR:-/tmp}/bin" - return 1 - } - Env::pathPrepend "${TMPDIR:-/tmp}/bin" -} - bashToolsDefaultConfigTemplate="${bashToolsDefaultConfigTemplate:-$( cat <<'EOF' # shellcheck disable=SC2034 @@ -856,15 +850,6 @@ Compiler::Facade::requireCommandBinDir() { Env::pathPrepend "${COMMAND_BIN_DIR}" } -# @description ensure running user is not root -# @exitcode 1 if current user is root -# @stderr diagnostics information is displayed -Linux::requireExecutedAsUser() { - if [[ "$(id -u)" = "0" ]]; then - Log::fatal "this script should be executed as normal user" - fi -} - # @description check if tty (interactive mode) is active # @noargs # @exitcode 1 if tty not active @@ -1036,6 +1021,18 @@ Database::query() { fi } +# @description by default we skip the column names +# but sometimes we need column names to display some results +# disable this option temporarily and then restore it to true +# +# @arg $1 instanceSetQueryOptions:&Map (passed by reference) database instance to use +# @arg $2 skipColumnNames:Boolean 0 to disable, 1 to enable (hide column names) +Database::skipColumnNames() { + local -n instanceSkipColumnNames=$1 + # shellcheck disable=SC2034 + instanceSkipColumnNames['SKIP_COLUMN_NAMES']="$2" +} + # @description prepend directories to the PATH environment variable # @arg $@ args:String[] list of directories to prepend # @set PATH update PATH with the directories prepended @@ -1222,15 +1219,6 @@ Log::logSkipped() { # FUNCTIONS -# @require Compiler::Embed::requireEmbedBinDir - -declare -gx embed_function_DbQueryOneDatabase="${PERSISTENT_TMPDIR:-/tmp}/bin/812e3ceaf05a68bbee12d5603a3400be/dbQueryOneDatabase" -declare -gx encoded_binary_file_DbQueryOneDatabase="IyEvdXNyL2Jpbi9lbnYgYmFzaAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgR0VORVJBVEVEIEZBQ0FERSBGUk9NIGh0dHBzOi8vZ2l0aHViLmNvbS9mY2hhc3RhbmV0L2Jhc2gtdG9vbHMvdHJlZS9tYXN0ZXIvaG9tZS93c2wvZmNoYXN0YW5ldC9iYXNoLWRldi1lbnYvdmVuZG9yL2Jhc2gtdG9vbHMtZnJhbWV3b3JrL3NyYy9Db21waWxlci9FbWJlZC9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uLmJpbkZpbGUudHBsCiMgRE8gTk9UIEVESVQgSVQKIyBAZ2VuZXJhdGVkCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMjg4LFNDMjAzNAojIEJJTl9GSUxFPSR7QklOX0ZJTEV9CiMgRkFDQURFCgojIGVuc3VyZSB0aGF0IG5vIHVzZXIgYWxpYXNlcyBjb3VsZCBpbnRlcmZlcmUgd2l0aAojIGNvbW1hbmRzIHVzZWQgaW4gdGhpcyBzY3JpcHQKdW5hbGlhcyAtYSB8fCB0cnVlCnNob3B0IC11IGV4cGFuZF9hbGlhc2VzCgojIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwMzQKKChmYWlsdXJlcyA9IDApKSB8fCB0cnVlCgojIEJhc2ggd2lsbCByZW1lbWJlciAmIHJldHVybiB0aGUgaGlnaGVzdCBleGl0IGNvZGUgaW4gYSBjaGFpbiBvZiBwaXBlcy4KIyBUaGlzIHdheSB5b3UgY2FuIGNhdGNoIHRoZSBlcnJvciBpbnNpZGUgcGlwZXMsIGUuZy4gbXlzcWxkdW1wIHwgZ3ppcApzZXQgLW8gcGlwZWZhaWwKc2V0IC1vIGVycmV4aXQKCiMgQ29tbWFuZCBTdWJzdGl0dXRpb24gY2FuIGluaGVyaXQgZXJyZXhpdCBvcHRpb24gc2luY2UgYmFzaCB2NC40CnNob3B0IC1zIGluaGVyaXRfZXJyZXhpdCB8fCB0cnVlCgojIGlmIHNldCwgYW5kIGpvYiBjb250cm9sIGlzIG5vdCBhY3RpdmUsIHRoZSBzaGVsbCBydW5zIHRoZSBsYXN0IGNvbW1hbmQKIyBvZiBhIHBpcGVsaW5lIG5vdCBleGVjdXRlZCBpbiB0aGUgYmFja2dyb3VuZCBpbiB0aGUgY3VycmVudCBzaGVsbAojIGVudmlyb25tZW50LgpzaG9wdCAtcyBsYXN0cGlwZQoKIyBhIGxvZyBpcyBnZW5lcmF0ZWQgd2hlbiBhIGNvbW1hbmQgZmFpbHMKc2V0IC1vIGVycnRyYWNlCgojIHVzZSBudWxsZ2xvYiBzbyB0aGF0IChmaWxlKi5waHApIHdpbGwgcmV0dXJuIGFuIGVtcHR5IGFycmF5IGlmIG5vIGZpbGUKIyBtYXRjaGVzIHRoZSB3aWxkY2FyZApzaG9wdCAtcyBudWxsZ2xvYgoKIyBlbnN1cmUgcmVnZXhwIGFyZSBpbnRlcnByZXRlZCB3aXRob3V0IGFjY2VudHVhdGVkIGNoYXJhY3RlcnMKZXhwb3J0IExDX0FMTD1QT1NJWAoKZXhwb3J0IFRFUk09eHRlcm0tMjU2Y29sb3IKCiMgYXZvaWQgaW50ZXJhY3RpdmUgaW5zdGFsbApleHBvcnQgREVCSUFOX0ZST05URU5EPW5vbmludGVyYWN0aXZlCmV4cG9ydCBERUJDT05GX05PTklOVEVSQUNUSVZFX1NFRU49dHJ1ZQoKIyBzdG9yZSBjb21tYW5kIGFyZ3VtZW50cyBmb3IgbGF0ZXIgdXNhZ2UKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0CmRlY2xhcmUgLWEgQkFTSF9GUkFNRVdPUktfQVJHVj0oIiRAIikKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0CmRlY2xhcmUgLWEgT1JJR0lOQUxfQkFTSF9GUkFNRVdPUktfQVJHVj0oIiRAIikKCiMgQHNlZSBodHRwczovL3VuaXguc3RhY2tleGNoYW5nZS5jb20vYS8zODY4NTYKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMzE3CmludGVycnVwdE1hbmFnZW1lbnQoKSB7CiAgIyByZXN0b3JlIFNJR0lOVCBoYW5kbGVyCiAgdHJhcCAtIElOVAogICMgZW5zdXJlIHRoYXQgQ3RybC1DIGlzIHRyYXBwZWQgYnkgdGhpcyBzY3JpcHQgYW5kIG5vdCBieSBzdWIgcHJvY2VzcwogICMgcmVwb3J0IHRvIHRoZSBwYXJlbnQgdGhhdCB3ZSBoYXZlIGluZGVlZCBiZWVuIGludGVycnVwdGVkCiAga2lsbCAtcyBJTlQgIiQkIgp9CnRyYXAgaW50ZXJydXB0TWFuYWdlbWVudCBJTlQKU0NSSVBUX05BTUU9JHswIyMqL30KUkVBTF9TQ1JJUFRfRklMRT0iJChyZWFkbGluayAtZSAiJChyZWFscGF0aCAiJHtCQVNIX1NPVVJDRVswXX0iKSIpIgppZiBbWyAtbiAiJHtFTUJFRF9DVVJSRU5UX0RJUn0iIF1dOyB0aGVuCiAgQ1VSUkVOVF9ESVI9IiR7RU1CRURfQ1VSUkVOVF9ESVJ9IgplbHNlCiAgQ1VSUkVOVF9ESVI9IiQoY2QgIiQocmVhZGxpbmsgLWUgIiR7UkVBTF9TQ1JJUFRfRklMRSUvKn0iKSIgJiYgcHdkIC1QKSIKZmkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFRlbXAgZGlyIG1hbmFnZW1lbnQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpLRUVQX1RFTVBfRklMRVM9IiR7S0VFUF9URU1QX0ZJTEVTOi0wfSIKZXhwb3J0IEtFRVBfVEVNUF9GSUxFUwoKIyBQRVJTSVNURU5UX1RNUERJUiBpcyBub3QgZGVsZXRlZCBieSB0cmFwcwpQRVJTSVNURU5UX1RNUERJUj0iJHtUTVBESVI6LS90bXB9L2Jhc2gtZnJhbWV3b3JrIgpleHBvcnQgUEVSU0lTVEVOVF9UTVBESVIKbWtkaXIgLXAgIiR7UEVSU0lTVEVOVF9UTVBESVJ9IgoKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0ClRNUERJUj0iJChta3RlbXAgLWQgLXAgIiR7UEVSU0lTVEVOVF9UTVBESVI6LS90bXB9IiAtdCBiYXNoLWZyYW1ld29yay0kJC1YWFhYWFgpIgpleHBvcnQgVE1QRElSCgojIHRlbXAgZGlyIGNsZWFuaW5nCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjMxNwpjbGVhbk9uRXhpdCgpIHsKICBpZiBbWyAiJHtLRUVQX1RFTVBfRklMRVM6LTB9IiA9ICIxIiBdXTsgdGhlbgogICAgTG9nOjpkaXNwbGF5SW5mbyAiS0VFUF9URU1QX0ZJTEVTPTEgdGVtcCBmaWxlcyBrZXB0IGhlcmUgJyR7VE1QRElSfSciCiAgZWxpZiBbWyAtbiAiJHtUTVBESVIreHh4fSIgXV07IHRoZW4KICAgIExvZzo6ZGlzcGxheURlYnVnICJLRUVQX1RFTVBfRklMRVM9MCByZW1vdmluZyB0ZW1wIGZpbGVzICcke1RNUERJUn0nIgogICAgcm0gLVJmICIke1RNUERJUjotL3RtcC9mYWtlfSIgPi9kZXYvbnVsbCAyPiYxCiAgZmkKfQp0cmFwIGNsZWFuT25FeGl0IEVYSVQgSFVQIFFVSVQgQUJSVCBURVJNCgojIFZBUl9NQUlOX0ZVTkNUSU9OX1ZBUl9OQU1FPWRiUXVlcnlBbGxEYXRhYmFzZXNGYWNhZGUKCiMgQGRlc2NyaXB0aW9uIHVzZWQgdG8gZXhlY3V0ZSBnaXZlbiBxdWVyeSB3aGVuIHVzaW5nCiMgZGJTY3JpcHRBbGxEYXRhYmFzZXMKIyBAYXJnICQxIGRzbjpTdHJpbmcKIyBAYXJnICQyIGRiOlN0cmluZwojIEBlbnYgcXVlcnkgU3RyaW5nCiMgQGVudiBvcHRpb25TZXBhcmF0b3IgU3RyaW5nCiMgQHJlcXVpcmUgTGludXg6OnJlcXVpcmVFeGVjdXRlZEFzVXNlcgpEYjo6cXVlcnlPbmVEYXRhYmFzZSgpIHsKICAjIHF1ZXJ5IGFuZCBvcHRpb25TZXBhcmF0b3IgYXJlIHBhc3NlZCB2aWEgZXhwb3J0CiAgbG9jYWwgZHNuPSIkMSIKICBsb2NhbCBkYj0iJDIiCgogIGxvY2FsIC1BIGRiSW5zdGFuY2UKICBEYXRhYmFzZTo6bmV3SW5zdGFuY2UgZGJJbnN0YW5jZSAiJHtkc259IgogIERhdGFiYXNlOjpzZXRRdWVyeU9wdGlvbnMgZGJJbnN0YW5jZSAiJHtkYkluc3RhbmNlW1FVRVJZX09QVElPTlNdfSAtLWNvbm5lY3QtdGltZW91dD01IgoKICAjIGlkZW50aWZ5IGNvbHVtbnMgaGVhZGVyCiAgZWNobyAtbiAiQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAiCiAgRGF0YWJhc2U6OnNraXBDb2x1bW5OYW1lcyBkYkluc3RhbmNlIDAKCiAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTU0CiAgaWYgISBEYXRhYmFzZTo6cXVlcnkgZGJJbnN0YW5jZSAiJHtxdWVyeX0iICIke2RifSIgfCBzZWQgInMvXHQvJHtvcHRpb25TZXBhcmF0b3J9L2ciOyB0aGVuCiAgICBMb2c6OmZhdGFsICJkYXRhYmFzZSAke2RifSBlcnJvciIgMT4mMgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIExvZyBuYW1lc3BhY2UgcHJvdmlkZXMgMiBraW5kIG9mIGZ1bmN0aW9ucwojIC0gTG9nOjpkaXNwbGF5KiBhbGxvd3MgdG8gZGlzcGxheSBnaXZlbiBtZXNzYWdlIHdpdGgKIyAgIGdpdmVuIGRpc3BsYXkgbGV2ZWwKIyAtIExvZzo6bG9nKiBhbGxvd3MgdG8gbG9nIGdpdmVuIG1lc3NhZ2Ugd2l0aAojICAgZ2l2ZW4gbG9nIGxldmVsCiMgTG9nOjpkaXNwbGF5KiBmdW5jdGlvbnMgYXV0b21hdGljYWxseSBsb2cgdGhlIG1lc3NhZ2UgdG9vCiMgQHNlZSBFbnY6OnJlcXVpcmVMb2FkIHRvIGxvYWQgdGhlIGRpc3BsYXkgYW5kIGxvZyBsZXZlbCBmcm9tIC5lbnYgZmlsZQoKIyBAZGVzY3JpcHRpb24gbG9nIGxldmVsIG9mZgpleHBvcnQgX19MRVZFTF9PRkY9MAojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgZXJyb3IKZXhwb3J0IF9fTEVWRUxfRVJST1I9MQojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgd2FybmluZwpleHBvcnQgX19MRVZFTF9XQVJOSU5HPTIKIyBAZGVzY3JpcHRpb24gbG9nIGxldmVsIGluZm8KZXhwb3J0IF9fTEVWRUxfSU5GTz0zCiMgQGRlc2NyaXB0aW9uIGxvZyBsZXZlbCBzdWNjZXNzCmV4cG9ydCBfX0xFVkVMX1NVQ0NFU1M9MwojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgZGVidWcKZXhwb3J0IF9fTEVWRUxfREVCVUc9NAoKIyBAZGVzY3JpcHRpb24gdmVyYm9zZSBsZXZlbCBvZmYKZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9PRkY9MAojIEBkZXNjcmlwdGlvbiB2ZXJib3NlIGxldmVsIGluZm8KZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9JTkZPPTEKIyBAZGVzY3JpcHRpb24gdmVyYm9zZSBsZXZlbCBpbmZvCmV4cG9ydCBfX1ZFUkJPU0VfTEVWRUxfREVCVUc9MgojIEBkZXNjcmlwdGlvbiB2ZXJib3NlIGxldmVsIGluZm8KZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9UUkFDRT0zCgojIEBkZXNjcmlwdGlvbiBEaXNwbGF5IG1lc3NhZ2UgdXNpbmcgZGVidWcgY29sb3IgKGdyZXkpCiMgQGFyZyAkMSBtZXNzYWdlOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CkxvZzo6ZGlzcGxheURlYnVnKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCA+PSBfX0xFVkVMX0RFQlVHKSk7IHRoZW4KICAgIGVjaG8gLWUgIiR7X19ERUJVR19DT0xPUn1ERUJVRyAgIC0gJHsxfSR7X19SRVNFVF9DT0xPUn0iID4mMgogIGZpCiAgTG9nOjpsb2dEZWJ1ZyAiJDEiCn0KCiMgQGRlc2NyaXB0aW9uIERpc3BsYXkgbWVzc2FnZSB1c2luZyBpbmZvIGNvbG9yIChiZyBsaWdodCBibHVlL2ZnIHdoaXRlKQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlJbmZvKCkgewogIGxvY2FsIHR5cGU9IiR7MjotSU5GT30iCiAgaWYgKChCQVNIX0ZSQU1FV09SS19ESVNQTEFZX0xFVkVMID49IF9fTEVWRUxfSU5GTykpOyB0aGVuCiAgICBlY2hvIC1lICIke19fSU5GT19DT0xPUn0ke3R5cGV9ICAgIC0gJHsxfSR7X19SRVNFVF9DT0xPUn0iID4mMgogIGZpCiAgTG9nOjpsb2dJbmZvICIkMSIgIiR7dHlwZX0iCn0KCiMgQGRlc2NyaXB0aW9uIGVuc3VyZSBDT01NQU5EX0JJTl9ESVIgZW52IHZhciBpcyBzZXQKIyBhbmQgUEFUSCBjb3JyZWN0bHkgcHJlcGFyZWQKIyBAbm9hcmdzCiMgQHNldCBDT01NQU5EX0JJTl9ESVIgc3RyaW5nIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdG8gZmluZCB0aGlzIGNvbW1hbmQKIyBAc2V0IFBBVEggc3RyaW5nIGFkZCBkaXJlY3Rvcnkgd2hlcmUgdG8gZmluZCB0aGlzIGNvbW1hbmQgYmluYXJ5CkNvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyKCkgewogIENPTU1BTkRfQklOX0RJUj0iJHtDVVJSRU5UX0RJUn0iCiAgRW52OjpwYXRoUHJlcGVuZCAiJHtDT01NQU5EX0JJTl9ESVJ9Igp9CgojIEBkZXNjcmlwdGlvbiBjcmVhdGUgYSBuZXcgZGIgaW5zdGFuY2UKIyBSZXR1cm5zIGltbWVkaWF0ZWx5IGlmIHRoZSBpbnN0YW5jZSBpcyBhbHJlYWR5IGluaXRpYWxpemVkCiMKIyBAYXJnICQxIGluc3RhbmNlTmV3SW5zdGFuY2U6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBkc246U3RyaW5nIGRzbiBwcm9maWxlIC0gbG9hZCB0aGUgZHNuLmVudiBwcm9maWxlIGRlZHVjZWQgdXNpbmcgcnVsZXMgZGVmaW5lZCBpbiBDb25mOjpnZXRBYnNvbHV0ZUZpbGUKIwojIEBleGFtcGxlCiMgICBkZWNsYXJlIC1BZ3ggZGJJbnN0YW5jZQojICAgRGF0YWJhc2U6Om5ld0luc3RhbmNlIGRiSW5zdGFuY2UgImRlZmF1bHQubG9jYWwiCiMKIyBAZXhpdGNvZGUgMSBpZiBkbnMgZmlsZSBub3QgYWJsZSB0byBsb2FkZWQKRGF0YWJhc2U6Om5ld0luc3RhbmNlKCkgewogIGxvY2FsIC1uIGluc3RhbmNlTmV3SW5zdGFuY2U9JDEKICBsb2NhbCBkc249IiQyIgogIGxvY2FsIERTTl9GSUxFCgogIGlmIFtbIC12IGluc3RhbmNlTmV3SW5zdGFuY2VbJ0lOSVRJQUxJWkVEJ10gJiYgIiR7aW5zdGFuY2VOZXdJbnN0YW5jZVsnSU5JVElBTElaRUQnXTotMH0iID09ICIxIiBdXTsgdGhlbgogICAgcmV0dXJuCiAgZmkKCiAgIyBmaW5hbCBhdXRoIGZpbGUgZ2VuZXJhdGVkIGZyb20gZG5zIGZpbGUKICBpbnN0YW5jZU5ld0luc3RhbmNlWydBVVRIX0ZJTEUnXT0iIgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0RTTl9GSUxFJ109IiIKCiAgIyBjaGVjayBkc24gZmlsZQogIERTTl9GSUxFPSIkKENvbmY6OmdldEFic29sdXRlRmlsZSAiZHNuIiAiJHtkc259IiAiZW52IikiIHx8IHJldHVybiAxCiAgRGF0YWJhc2U6OmNoZWNrRHNuRmlsZSAiJHtEU05fRklMRX0iIHx8IHJldHVybiAxCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnRFNOX0ZJTEUnXT0iJHtEU05fRklMRX0iCgogICMgc2hlbGxjaGVjayBzb3VyY2U9L3NyYy9EYXRhYmFzZS90ZXN0c0RhdGEvZHNuX3ZhbGlkLmVudgogIHNvdXJjZSAiJHtpbnN0YW5jZU5ld0luc3RhbmNlWydEU05fRklMRSddfSIKCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnVVNFUiddPSIke1VTRVJ9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ1BBU1NXT1JEJ109IiR7UEFTU1dPUkR9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0hPU1ROQU1FJ109IiR7SE9TVE5BTUV9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ1BPUlQnXT0iJHtQT1JUfSIKCiAgIyBnZW5lcmF0ZSBhdXRoRmlsZSBmb3IgZWFzeSBhdXRoZW50aWNhdGlvbgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0FVVEhfRklMRSddPSQobWt0ZW1wIC1wICIke1RNUERJUjotL3RtcH0iIC10ICJteXNxbC5YWFhYWFhYWFhYWFgiKQogICgKICAgIGVjaG8gIltjbGllbnRdIgogICAgZWNobyAidXNlciA9ICR7VVNFUn0iCiAgICBlY2hvICJwYXNzd29yZCA9ICR7UEFTU1dPUkR9IgogICAgZWNobyAiaG9zdCA9ICR7SE9TVE5BTUV9IgogICAgZWNobyAicG9ydCA9ICR7UE9SVH0iCiAgKSA+IiR7aW5zdGFuY2VOZXdJbnN0YW5jZVsnQVVUSF9GSUxFJ119IgoKICAjIHNvbWUgb2YgdGhvc2UgdmFsdWVzIGNhbiBiZSBvdmVycmlkZGVuIHVzaW5nIHRoZSBkc24gZmlsZQogICMgU0tJUF9DT0xVTU5fTkFNRVMgZW5hYmxlZCBieSBkZWZhdWx0CiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnU0tJUF9DT0xVTU5fTkFNRVMnXT0iJHtTS0lQX0NPTFVNTl9OQU1FUzotMX0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnU1NMX09QVElPTlMnXT0iJHtNWVNRTF9TU0xfT1BUSU9OUzotLS1zc2wtbW9kZT1ESVNBQkxFRH0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnUVVFUllfT1BUSU9OUyddPSIke01ZU1FMX1FVRVJZX09QVElPTlM6LS0tYmF0Y2ggLS1yYXcgLS1kZWZhdWx0LWNoYXJhY3Rlci1zZXQ9dXRmOH0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnRFVNUF9PUFRJT05TJ109IiR7TVlTUUxfRFVNUF9PUFRJT05TOi0tLWRlZmF1bHQtY2hhcmFjdGVyLXNldD11dGY4IC0tY29tcHJlc3MgLS1oZXgtYmxvYiAtLXJvdXRpbmVzIC0tdHJpZ2dlcnMgLS1zaW5nbGUtdHJhbnNhY3Rpb24gLS1zZXQtZ3RpZC1wdXJnZWQ9T0ZGIC0tY29sdW1uLXN0YXRpc3RpY3M9MCAke2luc3RhbmNlTmV3SW5zdGFuY2VbJ1NTTF9PUFRJT05TJ119fSIKICBpbnN0YW5jZU5ld0luc3RhbmNlWydEQl9JTVBPUlRfT1BUSU9OUyddPSIke0RCX0lNUE9SVF9PUFRJT05TOi0tLWNvbm5lY3QtdGltZW91dD01IC0tYmF0Y2ggLS1yYXcgLS1kZWZhdWx0LWNoYXJhY3Rlci1zZXQ9dXRmOH0iCgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0lOSVRJQUxJWkVEJ109MQp9CgojIEBkZXNjcmlwdGlvbiBteXNxbCBxdWVyeSBvbiBhIGdpdmVuIGRiCiMgQHdhcm5pbmcgY291bGQgdXNlIFFVRVJZX09QVElPTlMgdmFyaWFibGUgZnJvbSBkc24gaWYgZGVmaW5lZAojIEBleGFtcGxlCiMgICBjYXQgZmlsZS5zcWwgfCBEYXRhYmFzZTo6cXVlcnkgLi4uCiMgQGFyZyAkMSBpbnN0YW5jZVF1ZXJ5OiZNYXA8U3RyaW5nLFN0cmluZz4gKHBhc3NlZCBieSByZWZlcmVuY2UpIGRhdGFiYXNlIGluc3RhbmNlIHRvIHVzZQojIEBhcmcgJDIgc3FsUXVlcnk6U3RyaW5nIChvcHRpb25hbCkgc3FsIHF1ZXJ5IG9yIHNxbCBmaWxlIHRvIGV4ZWN1dGUuIGlmIG5vdCBwcm92aWRlZCBvciBlbXB0eSwgdGhlIGNvbW1hbmQgY2FuIGJlIHBpcGVkCiMgQGFyZyAkMyBkYk5hbWU6U3RyaW5nIChvcHRpb25hbCkgdGhlIGRiIG5hbWUKIwojIEBleGl0Y29kZSBteXNxbCBjb21tYW5kIHN0YXR1cyBjb2RlCkRhdGFiYXNlOjpxdWVyeSgpIHsKICBsb2NhbCAtbiBpbnN0YW5jZVF1ZXJ5PSQxCiAgbG9jYWwgLWEgbXlzcWxDb21tYW5kPSgpCiAgbG9jYWwgLWEgcXVlcnlPcHRpb25zCgogIG15c3FsQ29tbWFuZCs9KG15c3FsKQogIG15c3FsQ29tbWFuZCs9KCItLWRlZmF1bHRzLWV4dHJhLWZpbGU9JHtpbnN0YW5jZVF1ZXJ5WydBVVRIX0ZJTEUnXX0iKQogIElGUz0nICcgcmVhZCAtciAtYSBxdWVyeU9wdGlvbnMgPDw8IiR7aW5zdGFuY2VRdWVyeVsnUVVFUllfT1BUSU9OUyddfSIKICBteXNxbENvbW1hbmQrPSgiJHtxdWVyeU9wdGlvbnNbQF19IikKICBpZiBbWyAiJHtpbnN0YW5jZVF1ZXJ5WydTS0lQX0NPTFVNTl9OQU1FUyddfSIgPSAiMSIgXV07IHRoZW4KICAgIG15c3FsQ29tbWFuZCs9KCItcyIgIi0tc2tpcC1jb2x1bW4tbmFtZXMiKQogIGZpCiAgIyBhZGQgb3B0aW9uYWwgZGIgbmFtZQogIGlmIFtbIC1uICIkezMreH0iIF1dOyB0aGVuCiAgICBteXNxbENvbW1hbmQrPSgiJDMiKQogIGZpCiAgIyBhZGQgb3B0aW9uYWwgc3FsIHF1ZXJ5CiAgaWYgW1sgLW4gIiR7Mit4fSIgJiYgLW4gIiQyIiAmJiAhIC1mICIkMiIgXV07IHRoZW4KICAgIG15c3FsQ29tbWFuZCs9KCItZSIpCiAgICBteXNxbENvbW1hbmQrPSgiJDIiKQogIGZpCiAgTG9nOjpkaXNwbGF5RGVidWcgIiQocHJpbnRmICJleGVjdXRlIGNvbW1hbmQ6ICclcyciICIke215c3FsQ29tbWFuZFsqXX0iKSIKCiAgaWYgW1sgLWYgIiQyIiBdXTsgdGhlbgogICAgIiR7bXlzcWxDb21tYW5kW0BdfSIgPCIkMiIKICBlbHNlCiAgICAiJHtteXNxbENvbW1hbmRbQF19IgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIHNldCB0aGUgZ2VuZXJhbCBvcHRpb25zIHRvIHVzZSBvbiBteXNxbCBjb21tYW5kIHRvIHF1ZXJ5IHRoZSBkYXRhYmFzZQojIERpZmZlcnMgdGhhbiBzZXRPcHRpb25zIGluIHRoZSB3YXkgdGhhdCB0aGVzZSBvcHRpb25zIGNvdWxkIGNoYW5nZSBlYWNoIHRpbWUKIwojIEBhcmcgJDEgaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBvcHRpb25zTGlzdDpTdHJpbmcgcXVlcnkgb3B0aW9ucyBsaXN0CkRhdGFiYXNlOjpzZXRRdWVyeU9wdGlvbnMoKSB7CiAgbG9jYWwgLW4gaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM9JDEKICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwMzQKICBpbnN0YW5jZVNldFF1ZXJ5T3B0aW9uc1snUVVFUllfT1BUSU9OUyddPSIkMiIKfQoKIyBAZGVzY3JpcHRpb24gYnkgZGVmYXVsdCB3ZSBza2lwIHRoZSBjb2x1bW4gbmFtZXMKIyBidXQgc29tZXRpbWVzIHdlIG5lZWQgY29sdW1uIG5hbWVzIHRvIGRpc3BsYXkgc29tZSByZXN1bHRzCiMgZGlzYWJsZSB0aGlzIG9wdGlvbiB0ZW1wb3JhcmlseSBhbmQgdGhlbiByZXN0b3JlIGl0IHRvIHRydWUKIwojIEBhcmcgJDEgaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBza2lwQ29sdW1uTmFtZXM6Qm9vbGVhbiAwIHRvIGRpc2FibGUsIDEgdG8gZW5hYmxlIChoaWRlIGNvbHVtbiBuYW1lcykKRGF0YWJhc2U6OnNraXBDb2x1bW5OYW1lcygpIHsKICBsb2NhbCAtbiBpbnN0YW5jZVNraXBDb2x1bW5OYW1lcz0kMQogICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjAzNAogIGluc3RhbmNlU2tpcENvbHVtbk5hbWVzWydTS0lQX0NPTFVNTl9OQU1FUyddPSIkMiIKfQoKIyBAZGVzY3JpcHRpb24gcHJlcGVuZCBkaXJlY3RvcmllcyB0byB0aGUgUEFUSCBlbnZpcm9ubWVudCB2YXJpYWJsZQojIEBhcmcgJEAgYXJnczpTdHJpbmdbXSBsaXN0IG9mIGRpcmVjdG9yaWVzIHRvIHByZXBlbmQKIyBAc2V0IFBBVEggdXBkYXRlIFBBVEggd2l0aCB0aGUgZGlyZWN0b3JpZXMgcHJlcGVuZGVkCkVudjo6cGF0aFByZXBlbmQoKSB7CiAgbG9jYWwgYXJnCiAgZm9yIGFyZyBpbiAiJEAiOyBkbwogICAgaWYgW1sgLWQgIiR7YXJnfSIgJiYgIjoke1BBVEh9OiIgIT0gKiI6JHthcmd9OiIqIF1dOyB0aGVuCiAgICAgIFBBVEg9IiQocmVhbHBhdGggIiR7YXJnfSIpOiR7UEFUSH0iCiAgICBmaQogIGRvbmUKfQoKIyBAZGVzY3JpcHRpb24gRGlzcGxheSBtZXNzYWdlIHVzaW5nIGVycm9yIGNvbG9yIChyZWQpIGFuZCBleGl0IGltbWVkaWF0ZWx5IHdpdGggZXJyb3Igc3RhdHVzIDEKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpmYXRhbCgpIHsKICBlY2hvIC1lICIke19fRVJST1JfQ09MT1J9RkFUQUwgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBMb2c6OmxvZ0ZhdGFsICIkMSIKICBleGl0IDEKfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ0RlYnVnKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID49IF9fTEVWRUxfREVCVUcpKTsgdGhlbgogICAgTG9nOjpsb2dNZXNzYWdlICIkezI6LURFQlVHfSIgIiQxIgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIGxvZyBtZXNzYWdlIHRvIGZpbGUKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpsb2dJbmZvKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID49IF9fTEVWRUxfSU5GTykpOyB0aGVuCiAgICBMb2c6OmxvZ01lc3NhZ2UgIiR7MjotSU5GT30iICIkMSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBlbnN1cmUgcnVubmluZyB1c2VyIGlzIG5vdCByb290CiMgQGV4aXRjb2RlIDEgaWYgY3VycmVudCB1c2VyIGlzIHJvb3QKIyBAc3RkZXJyIGRpYWdub3N0aWNzIGluZm9ybWF0aW9uIGlzIGRpc3BsYXllZApMaW51eDo6cmVxdWlyZUV4ZWN1dGVkQXNVc2VyKCkgewogIGlmIFtbICIkKGlkIC11KSIgPSAiMCIgXV07IHRoZW4KICAgIExvZzo6ZmF0YWwgInRoaXMgc2NyaXB0IHNob3VsZCBiZSBleGVjdXRlZCBhcyBub3JtYWwgdXNlciIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBnZXQgYWJzb2x1dGUgY29uZiBmaWxlIGZyb20gc3BlY2lmaWVkIGNvbmYgZm9sZGVyIGRlZHVjZWQgdXNpbmcgdGhlc2UgcnVsZXMKIyAgICogZnJvbSBhYnNvbHV0ZSBmaWxlIChpZ25vcmVzIDxjb25mRm9sZGVyPiBhbmQgPGV4dGVuc2lvbj4pCiMgICAqIHJlbGF0aXZlIHRvIHdoZXJlIHNjcmlwdCBpcyBleGVjdXRlZCAoaWdub3JlcyA8Y29uZkZvbGRlcj4gYW5kIDxleHRlbnNpb24+KQojICAgKiBmcm9tIGhvbWUvLmJhc2gtdG9vbHMvPGNvbmZGb2xkZXI+CiMgICAqIGZyb20gZnJhbWV3b3JrIGNvbmYvPGNvbmZGb2xkZXI+CiMKIyBAYXJnICQxIGNvbmZGb2xkZXI6U3RyaW5nIHRoZSBkaXJlY3RvcnkgbmFtZSAobm90IHRoZSBwYXRoKSB0byBsaXN0CiMgQGFyZyAkMiBjb25mOlN0cmluZyBmaWxlIHRvIHVzZSB3aXRob3V0IGV4dGVuc2lvbgojIEBhcmcgJDMgZXh0ZW5zaW9uOlN0cmluZyB0aGUgZXh0ZW5zaW9uICguc2ggYnkgZGVmYXVsdCkKIwojIEBzdGRvdXQgYWJzb2x1dGUgY29uZiBmaWxlbmFtZQojIEBleGl0Y29kZSAxIGlmIGZpbGUgaXMgbm90IGZvdW5kIGluIGFueSBsb2NhdGlvbgpDb25mOjpnZXRBYnNvbHV0ZUZpbGUoKSB7CiAgbG9jYWwgY29uZkZvbGRlcj0iJDEiCiAgbG9jYWwgY29uZj0iJDIiCiAgbG9jYWwgZXh0ZW5zaW9uPSIkezMtLnNofSIKICBpZiBbWyAtbiAiJHtleHRlbnNpb259IiAmJiAiJHtleHRlbnNpb246MDoxfSIgIT0gIi4iIF1dOyB0aGVuCiAgICBleHRlbnNpb249Ii4ke2V4dGVuc2lvbn0iCiAgZmkKCiAgdGVzdEFicygpIHsKICAgIGxvY2FsIHJlc3VsdAogICAgcmVzdWx0PSIkKHJlYWxwYXRoIC1lICIkMSIgMj4vZGV2L251bGwpIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTgxCiAgICBpZiBbWyAiJD8iID0gIjAiICYmIC1mICIke3Jlc3VsdH0iIF1dOyB0aGVuCiAgICAgIGVjaG8gIiR7cmVzdWx0fSIKICAgICAgcmV0dXJuIDAKICAgIGZpCiAgICByZXR1cm4gMQogIH0KCiAgIyBjb25mIGlzIGFic29sdXRlIGZpbGUgKGluY2x1ZGluZyBleHRlbnNpb24pCiAgdGVzdEFicyAiJHtjb25mRm9sZGVyfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICAjIGNvbmYgaXMgYWJzb2x1dGUgZmlsZQogIHRlc3RBYnMgIiR7Y29uZkZvbGRlcn0iICYmIHJldHVybiAwCiAgIyBjb25mIGlzIGFic29sdXRlIGZpbGUgKGluY2x1ZGluZyBleHRlbnNpb24pCiAgdGVzdEFicyAiJHtjb25mfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICAjIGNvbmYgaXMgYWJzb2x1dGUgZmlsZQogIHRlc3RBYnMgIiR7Y29uZn0iICYmIHJldHVybiAwCgogICMgcmVsYXRpdmUgdG8gd2hlcmUgc2NyaXB0IGlzIGV4ZWN1dGVkIChpbmNsdWRpbmcgZXh0ZW5zaW9uKQogIGlmIFtbIC1uICIke0NVUlJFTlRfRElSK3h4eH0iIF1dOyB0aGVuCiAgICB0ZXN0QWJzICIkKEZpbGU6OmNvbmNhdGVuYXRlUGF0aCAiJHtDVVJSRU5UX0RJUn0iICIke2NvbmZGb2xkZXJ9IikvJHtjb25mfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICBmaQogICMgZnJvbSBob21lLy5iYXNoLXRvb2xzLzxjb25mRm9sZGVyPgogIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0hPTUV9Ly5iYXNoLXRvb2xzIiAiJHtjb25mRm9sZGVyfSIpLyR7Y29uZn0ke2V4dGVuc2lvbn0iICYmIHJldHVybiAwCgogIGlmIFtbIC1uICIke0ZSQU1FV09SS19ST09UX0RJUit4eHh9IiBdXTsgdGhlbgogICAgIyBmcm9tIGZyYW1ld29yayBjb25mLzxjb25mRm9sZGVyPiAoaW5jbHVkaW5nIGV4dGVuc2lvbikKICAgIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0ZSQU1FV09SS19ST09UX0RJUn0vY29uZiIgIiR7Y29uZkZvbGRlcn0iKS8ke2NvbmZ9JHtleHRlbnNpb259IiAmJiByZXR1cm4gMAoKICAgICMgZnJvbSBmcmFtZXdvcmsgY29uZi88Y29uZkZvbGRlcj4KICAgIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0ZSQU1FV09SS19ST09UX0RJUn0vY29uZiIgIiR7Y29uZkZvbGRlcn0iKS8ke2NvbmZ9IiAmJiByZXR1cm4gMAogIGZpCgogICMgZmlsZSBub3QgZm91bmQKICBMb2c6OmRpc3BsYXlFcnJvciAiY29uZiBmaWxlICcke2NvbmZ9JyBub3QgZm91bmQiCgogIHJldHVybiAxCn0KCiMgQGRlc2NyaXB0aW9uIGNoZWNrIGlmIGRzbiBmaWxlIGhhcyBhbGwgdGhlIG1hbmRhdG9yeSB2YXJpYWJsZXMgc2V0CiMgTWFuZGF0b3J5IHZhcmlhYmxlcyBhcmU6IEhPU1ROQU1FLCBVU0VSLCBQQVNTV09SRCwgUE9SVAojCiMgQGFyZyAkMSBkc25GaWxlTmFtZTpTdHJpbmcgZHNuIGFic29sdXRlIGZpbGVuYW1lCiMgQHNldCBIT1NUTkFNRSBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgUE9SVCBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgVVNFUiBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgUEFTU1dPUkQgbG9hZGVkIGZyb20gZHNuIGZpbGUKIyBAZXhpdGNvZGUgMCBvbiB2YWxpZCBmaWxlCiMgQGV4aXRjb2RlIDEgaWYgb25lIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBjb25mIGZpbGUgaXMgaW52YWxpZCBvciBpZiBmaWxlIG5vdCBmb3VuZAojIEBzdGRlcnIgbG9nIG91dHB1dCBpZiBlcnJvciBmb3VuZCBpbiBjb25mIGZpbGUKRGF0YWJhc2U6OmNoZWNrRHNuRmlsZSgpIHsKICBsb2NhbCBkc25GaWxlTmFtZT0iJDEiCiAgaWYgW1sgISAtZiAiJHtkc25GaWxlTmFtZX0iIF1dOyB0aGVuCiAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gbm90IGZvdW5kIgogICAgcmV0dXJuIDEKICBmaQoKICAoCiAgICB1bnNldCBIT1NUTkFNRSBQT1JUIFBBU1NXT1JEIFVTRVIKICAgICMgc2hlbGxjaGVjayBzb3VyY2U9L3NyYy9EYXRhYmFzZS90ZXN0c0RhdGEvZHNuX3ZhbGlkLmVudgogICAgc291cmNlICIke2RzbkZpbGVOYW1lfSIKICAgIGlmIFtbIC16ICR7SE9TVE5BTUUreH0gXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5RXJyb3IgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogSE9TVE5BTUUgbm90IHByb3ZpZGVkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke0hPU1ROQU1FfSIgXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5V2FybmluZyAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBIT1NUTkFNRSB2YWx1ZSBub3QgcHJvdmlkZWQiCiAgICBmaQogICAgaWYgW1sgIiR7SE9TVE5BTUV9IiA9ICJsb2NhbGhvc3QiIF1dOyB0aGVuCiAgICAgIExvZzo6ZGlzcGxheVdhcm5pbmcgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogY2hlY2sgdGhhdCBIT1NUTkFNRSBzaG91bGQgbm90IGJlIDEyNy4wLjAuMSBpbnN0ZWFkIG9mIGxvY2FsaG9zdCIKICAgIGZpCiAgICBpZiBbWyAteiAiJHtQT1JUK3h9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBQT1JUIG5vdCBwcm92aWRlZCIKICAgICAgcmV0dXJuIDEKICAgIGZpCiAgICBpZiAhIFtbICR7UE9SVH0gPX4gXlswLTldKyQgXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5RXJyb3IgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogUE9SVCBpbnZhbGlkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke1VTRVIreH0iIF1dOyB0aGVuCiAgICAgIExvZzo6ZGlzcGxheUVycm9yICJkc24gZmlsZSAke2RzbkZpbGVOYW1lfSA6IFVTRVIgbm90IHByb3ZpZGVkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke1BBU1NXT1JEK3h9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBQQVNTV09SRCBub3QgcHJvdmlkZWQiCiAgICAgIHJldHVybiAxCiAgICBmaQogICkKfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ0ZhdGFsKCkgewogIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1GQVRBTH0iICIkMSIKfQoKIyBAZGVzY3JpcHRpb24gSW50ZXJuYWw6IGNvbW1vbiBsb2cgbWVzc2FnZQojIEBleGFtcGxlIHRleHQKIyAgIFtkYXRlXXxbbGV2ZWxNc2ddfG1lc3NhZ2UKIwojIEBleGFtcGxlIHRleHQKIyAgIDIwMjAtMDEtMTkgMTk6MjA6MjF8RVJST1IgIHxsb2cgZXJyb3IKIyAgIDIwMjAtMDEtMTkgMTk6MjA6MjF8U0tJUFBFRHxsb2cgc2tpcHBlZAojCiMgQGFyZyAkMSBsZXZlbE1zZzpTdHJpbmcgbWVzc2FnZSdzIGxldmVsIGRlc2NyaXB0aW9uIChlZzogU1RBVFVTLCBFUlJPUiwgLi4uKQojIEBhcmcgJDIgbXNnOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CiMgQGVudiBCQVNIX0ZSQU1FV09SS19MT0dfRklMRSBTdHJpbmcgbG9nIGZpbGUgdG8gdXNlLCBkbyBub3RoaW5nIGlmIGVtcHR5CiMgQGVudiBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwgaW50IGxvZyBsZXZlbCBsb2cgb25seSBpZiA+IE9GRiBvciBmYXRhbCBtZXNzYWdlcwojIEBzdGRlcnIgZGlhZ25vc3RpY3MgaW5mb3JtYXRpb24gaXMgZGlzcGxheWVkCiMgQHJlcXVpcmUgRW52OjpyZXF1aXJlTG9hZAojIEByZXF1aXJlIExvZzo6cmVxdWlyZUxvYWQKTG9nOjpsb2dNZXNzYWdlKCkgewogIGxvY2FsIGxldmVsTXNnPSIkMSIKICBsb2NhbCBtc2c9IiQyIgogIGxvY2FsIGRhdGUKCiAgaWYgW1sgLW4gIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiBdXSAmJiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+IF9fTEVWRUxfT0ZGKSk7IHRoZW4KICAgIGRhdGU9IiQoZGF0ZSAnKyVZLSVtLSVkICVIOiVNOiVTJykiCiAgICB0b3VjaCAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iCiAgICBwcmludGYgIiVzfCU3c3wlc1xuIiAiJHtkYXRlfSIgIiR7bGV2ZWxNc2d9IiAiJHttc2d9IiA+PiIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBjb25jYXRlbmF0ZSAyIHBhdGhzIGFuZCBlbnN1cmUgdGhlIHBhdGggaXMgY29ycmVjdCB1c2luZyByZWFscGF0aCAtbQojIEBhcmcgJDEgYmFzZVBhdGg6U3RyaW5nCiMgQGFyZyAkMiBzdWJQYXRoOlN0cmluZwojIEByZXF1aXJlIExpbnV4OjpyZXF1aXJlUmVhbHBhdGhDb21tYW5kCkZpbGU6OmNvbmNhdGVuYXRlUGF0aCgpIHsKICBsb2NhbCBiYXNlUGF0aD0iJDEiCiAgbG9jYWwgc3ViUGF0aD0iJDIiCiAgbG9jYWwgZnVsbFBhdGg9IiR7YmFzZVBhdGg6KyR7YmFzZVBhdGh9L30ke3N1YlBhdGh9IgoKICByZWFscGF0aCAtbSAiJHtmdWxsUGF0aH0iIDI+L2Rldi9udWxsCn0KCiMgQGRlc2NyaXB0aW9uIERpc3BsYXkgbWVzc2FnZSB1c2luZyBlcnJvciBjb2xvciAocmVkKQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlFcnJvcigpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0RJU1BMQVlfTEVWRUwgPj0gX19MRVZFTF9FUlJPUikpOyB0aGVuCiAgICBlY2hvIC1lICIke19fRVJST1JfQ09MT1J9RVJST1IgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBmaQogIExvZzo6bG9nRXJyb3IgIiQxIgp9CgojIEBkZXNjcmlwdGlvbiBEaXNwbGF5IG1lc3NhZ2UgdXNpbmcgd2FybmluZyBjb2xvciAoeWVsbG93KQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlXYXJuaW5nKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCA+PSBfX0xFVkVMX1dBUk5JTkcpKTsgdGhlbgogICAgZWNobyAtZSAiJHtfX1dBUk5JTkdfQ09MT1J9V0FSTiAgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBmaQogIExvZzo6bG9nV2FybmluZyAiJDEiCn0KCiMgQGRlc2NyaXB0aW9uIGVuc3VyZSBlbnYgZmlsZXMgYXJlIGxvYWRlZAojIEBhcmcgJEAgbGlzdCBvZiBkZWZhdWx0IGZpbGVzIHRvIGxvYWQgYXQgdGhlIGVuZAojIEBleGl0Y29kZSAxIGlmIG9uZSBvZiBlbnYgZmlsZXMgZmFpbHMgdG8gbG9hZAojIEBzdGRlcnIgZGlhZ25vc3RpY3MgaW5mb3JtYXRpb24gaXMgZGlzcGxheWVkCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjEyMApFbnY6OnJlcXVpcmVMb2FkKCkgewogIGxvY2FsIC1hIGRlZmF1bHRGaWxlcz0oIiRAIikKICAjIGdldCBsaXN0IG9mIHBvc3NpYmxlIGNvbmZpZyBmaWxlcwogIGxvY2FsIC1hIGNvbmZpZ0ZpbGVzPSgpCiAgaWYgW1sgLW4gIiR7QkFTSF9GUkFNRVdPUktfRU5WX0ZJTEVTWzBdKzF9IiBdXTsgdGhlbgogICAgIyBCQVNIX0ZSQU1FV09SS19FTlZfRklMRVMgaXMgYW4gYXJyYXkKICAgIGNvbmZpZ0ZpbGVzKz0oIiR7QkFTSF9GUkFNRVdPUktfRU5WX0ZJTEVTW0BdfSIpCiAgZmkKICBpZiBbWyAtZiAiJChwd2QpLy5mcmFtZXdvcmstY29uZmlnIiBdXTsgdGhlbgogICAgY29uZmlnRmlsZXMrPSgiJChwd2QpLy5mcmFtZXdvcmstY29uZmlnIikKICBmaQogIGlmIFtbIC1mICIke0ZSQU1FV09SS19ST09UX0RJUn0vLmZyYW1ld29yay1jb25maWciIF1dOyB0aGVuCiAgICBjb25maWdGaWxlcys9KCIke0ZSQU1FV09SS19ST09UX0RJUn0vLmZyYW1ld29yay1jb25maWciKQogIGZpCiAgY29uZmlnRmlsZXMrPSgiJHtvcHRpb25FbnZGaWxlc1tAXX0iKQogIGNvbmZpZ0ZpbGVzKz0oIiR7ZGVmYXVsdEZpbGVzW0BdfSIpCgogIGZvciBmaWxlIGluICIke2NvbmZpZ0ZpbGVzW0BdfSI7IGRvCiAgICAjIHNoZWxsY2hlY2sgc291cmNlPS8uZnJhbWV3b3JrLWNvbmZpZwogICAgQ1VSUkVOVF9MT0FERURfRU5WX0ZJTEU9IiR7ZmlsZX0iIHNvdXJjZSAiJHtmaWxlfSIgfHwgewogICAgICBMb2c6OmRpc3BsYXlFcnJvciAid2hpbGUgbG9hZGluZyBjb25maWcgZmlsZTogJHtmaWxlfSIKICAgICAgcmV0dXJuIDEKICAgIH0KICBkb25lCn0KCiMgQGRlc2NyaXB0aW9uIGFjdGl2YXRlIG9yIG5vdCBMb2c6OmRpc3BsYXkqIGFuZCBMb2c6OmxvZyogZnVuY3Rpb25zCiMgYmFzZWQgb24gQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCBhbmQgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMCiMgZW52aXJvbm1lbnQgdmFyaWFibGVzIGxvYWRlZCBieSBFbnY6OnJlcXVpcmVMb2FkCiMgdHJ5IHRvIGNyZWF0ZSBsb2cgZmlsZSBhbmQgcm90YXRlIGl0IGlmIG5lY2Vzc2FyeQojIEBub2FyZ3MKIyBAc2V0IEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCBpbnQgdG8gT0ZGIGxldmVsIGlmIEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFIGlzIGVtcHR5IG9yIG5vdCB3cml0YWJsZQojIEBlbnYgQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCBpbnQKIyBAZW52IEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCBpbnQKIyBAZW52IEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFIFN0cmluZwojIEBlbnYgQkFTSF9GUkFNRVdPUktfTE9HX0ZJTEVfTUFYX1JPVEFUSU9OIGludCBkbyBsb2cgcm90YXRpb24gaWYgPiAwCiMgQGV4aXRjb2RlIDAgYWx3YXlzIHN1Y2Nlc3NmdWwKIyBAc3RkZXJyIGRpYWdub3N0aWNzIGluZm9ybWF0aW9uIGFib3V0IGxvZyBmaWxlIGlzIGRpc3BsYXllZAojIEByZXF1aXJlIEVudjo6cmVxdWlyZUxvYWQKIyBAcmVxdWlyZSBVSTo6cmVxdWlyZVRoZW1lCkxvZzo6cmVxdWlyZUxvYWQoKSB7CiAgaWYgW1sgLXogIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEU6LX0iIF1dOyB0aGVuCiAgICBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUw9JHtfX0xFVkVMX09GRn0KICAgIGV4cG9ydCBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwKICBmaQoKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+IF9fTEVWRUxfT0ZGKSk7IHRoZW4KICAgIGlmIFtbICEgLWYgIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiBdXTsgdGhlbgogICAgICBpZgogICAgICAgICEgbWtkaXIgLXAgIiQoZGlybmFtZSAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iKSIgMj4vZGV2L251bGwgfHwKICAgICAgICAgICEgdG91Y2ggLS1uby1jcmVhdGUgIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiAyPi9kZXYvbnVsbAogICAgICB0aGVuCiAgICAgICAgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMPSR7X19MRVZFTF9PRkZ9CiAgICAgICAgZWNobyAtZSAiJHtfX0VSUk9SX0NPTE9SfUVSUk9SICAgLSBGaWxlICR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IGlzIG5vdCB3cml0YWJsZSR7X19SRVNFVF9DT0xPUn0iID4mMgogICAgICBmaQogICAgZWxpZiBbWyAhIC13ICIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSIgXV07IHRoZW4KICAgICAgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMPSR7X19MRVZFTF9PRkZ9CiAgICAgIGVjaG8gLWUgIiR7X19FUlJPUl9DT0xPUn1FUlJPUiAgIC0gRmlsZSAke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSBpcyBub3Qgd3JpdGFibGUke19fUkVTRVRfQ09MT1J9IiA+JjIKICAgIGZpCgogIGZpCgogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID4gX19MRVZFTF9PRkYpKTsgdGhlbgogICAgIyB3aWxsIGFsd2F5cyBiZSBjcmVhdGVkIGV2ZW4gaWYgbm90IGluIGluZm8gbGV2ZWwKICAgIExvZzo6bG9nTWVzc2FnZSAiSU5GTyIgIkxvZ2dpbmcgdG8gZmlsZSAke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSAtIExvZyBsZXZlbCAke0JBU0hfRlJBTUVXT1JLX0xPR19MRVZFTH0iCiAgICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFX01BWF9ST1RBVElPTiA+IDApKTsgdGhlbgogICAgICBMb2c6OnJvdGF0ZSAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iICIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFX01BWF9ST1RBVElPTn0iCiAgICBmaQogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIGxvZyBtZXNzYWdlIHRvIGZpbGUKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpsb2dFcnJvcigpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+PSBfX0xFVkVMX0VSUk9SKSk7IHRoZW4KICAgIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1FUlJPUn0iICIkMSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBsb2cgbWVzc2FnZSB0byBmaWxlCiMgQGFyZyAkMSBtZXNzYWdlOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CkxvZzo6bG9nV2FybmluZygpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+PSBfX0xFVkVMX1dBUk5JTkcpKTsgdGhlbgogICAgTG9nOjpsb2dNZXNzYWdlICIkezI6LVdBUk5JTkd9IiAiJDEiCiAgZmkKfQoKIyBAZGVzY3JpcHRpb24gVG8gYmUgY2FsbGVkIGJlZm9yZSBsb2dnaW5nIGluIHRoZSBsb2cgZmlsZQojIEBhcmcgJDEgZmlsZTpzdHJpbmcgbG9nIGZpbGUgbmFtZQojIEBhcmcgJDIgbWF4TG9nRmlsZXNDb3VudDppbnQgbWF4aW11bSBudW1iZXIgb2YgbG9nIGZpbGVzCkxvZzo6cm90YXRlKCkgewogIGxvY2FsIGZpbGU9IiQxIgogIGxvY2FsIG1heExvZ0ZpbGVzQ291bnQ9IiR7MjotNX0iCgogIGlmIFtbICEgLWYgIiR7ZmlsZX0iIF1dOyB0aGVuCiAgICBMb2c6OmRpc3BsYXlTa2lwcGVkICJMb2cgZmlsZSAke2ZpbGV9IGRvZXNuJ3QgZXhpc3QgeWV0IgogICAgcmV0dXJuIDAKICBmaQogIGZvciBpIGluICQoc2VxICQoKG1heExvZ0ZpbGVzQ291bnQgLSAxKSkgLTEgMSk7IGRvCiAgICBMb2c6OmRpc3BsYXlJbmZvICJMb2cgcm90YXRpb24gJHtmaWxlfS4ke2l9IHRvICR7ZmlsZX0uJCgoaSArIDEpKSIKICAgIG12ICIke2ZpbGV9LiJ7IiR7aX0iLCIkKChpICsgMSkpIn0gJj4vZGV2L251bGwgfHwgdHJ1ZQogIGRvbmUKICBpZiBjcCAiJHtmaWxlfSIgIiR7ZmlsZX0uMSIgJj4vZGV2L251bGw7IHRoZW4KICAgIGVjaG8gPiIke2ZpbGV9IiAjIHJlc2V0IGxvZyBmaWxlCiAgICBMb2c6OmRpc3BsYXlJbmZvICJMb2cgcm90YXRpb24gJHtmaWxlfSB0byAke2ZpbGV9LjEiCiAgZmkKfQoKIyBAZGVzY3JpcHRpb24gZW5zdXJlIGNvbW1hbmQgcmVhbHBhdGggaXMgYXZhaWxhYmxlCiMgQGV4aXRjb2RlIDEgaWYgcmVhbHBhdGggY29tbWFuZCBub3QgYXZhaWxhYmxlCiMgQHN0ZGVyciBkaWFnbm9zdGljcyBpbmZvcm1hdGlvbiBpcyBkaXNwbGF5ZWQKTGludXg6OnJlcXVpcmVSZWFscGF0aENvbW1hbmQoKSB7CiAgQXNzZXJ0Ojpjb21tYW5kRXhpc3RzIHJlYWxwYXRoCn0KCiMgQGRlc2NyaXB0aW9uIGxvYWQgY29sb3IgdGhlbWUKIyBAbm9hcmdzCiMgQGVudiBCQVNIX0ZSQU1FV09SS19USEVNRSBTdHJpbmcgdGhlbWUgdG8gdXNlCiMgQGV4aXRjb2RlIDAgYWx3YXlzIHN1Y2Nlc3NmdWwKVUk6OnJlcXVpcmVUaGVtZSgpIHsKICBVSTo6dGhlbWUgIiR7QkFTSF9GUkFNRVdPUktfVEhFTUUtZGVmYXVsdH0iCn0KCiMgQGRlc2NyaXB0aW9uIGNoZWNrIGlmIGNvbW1hbmQgc3BlY2lmaWVkIGV4aXN0cyBvciByZXR1cm4gMQojIHdpdGggZXJyb3IgYW5kIG1lc3NhZ2UgaWYgbm90CiMKIyBAYXJnICQxIGNvbW1hbmROYW1lOlN0cmluZyBvbiB3aGljaCBleGlzdGVuY2UgbXVzdCBiZSBjaGVja2VkCiMgQGFyZyAkMiBoZWxwSWZOb3RFeGlzdHM6U3RyaW5nIGEgaGVscCBjb21tYW5kIHRvIGRpc3BsYXkgaWYgdGhlIGNvbW1hbmQgZG9lcyBub3QgZXhpc3QKIwojIEBleGl0Y29kZSAxIGlmIHRoZSBjb21tYW5kIHNwZWNpZmllZCBkb2VzIG5vdCBleGlzdAojIEBzdGRlcnIgZGlhZ25vc3RpYyBpbmZvcm1hdGlvbiArIGhlbHAgaWYgc2Vjb25kIGFyZ3VtZW50IGlzIHByb3ZpZGVkCkFzc2VydDo6Y29tbWFuZEV4aXN0cygpIHsKICBsb2NhbCBjb21tYW5kTmFtZT0iJDEiCiAgbG9jYWwgaGVscElmTm90RXhpc3RzPSIkMiIKCiAgIiR7QkFTSF9GUkFNRVdPUktfQ09NTUFORDotY29tbWFuZH0iIC12ICIke2NvbW1hbmROYW1lfSIgPi9kZXYvbnVsbCAyPi9kZXYvbnVsbCB8fCB7CiAgICBMb2c6OmRpc3BsYXlFcnJvciAiJHtjb21tYW5kTmFtZX0gaXMgbm90IGluc3RhbGxlZCwgcGxlYXNlIGluc3RhbGwgaXQiCiAgICBpZiBbWyAtbiAiJHtoZWxwSWZOb3RFeGlzdHN9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlJbmZvICIke2hlbHBJZk5vdEV4aXN0c30iCiAgICBmaQogICAgcmV0dXJuIDEKICB9CiAgcmV0dXJuIDAKfQoKIyBAZGVzY3JpcHRpb24gRGlzcGxheSBtZXNzYWdlIHVzaW5nIHNraXAgY29sb3IgKHllbGxvdykKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpkaXNwbGF5U2tpcHBlZCgpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0RJU1BMQVlfTEVWRUwgPj0gX19MRVZFTF9JTkZPKSk7IHRoZW4KICAgIGVjaG8gLWUgIiR7X19TS0lQUEVEX0NPTE9SfVNLSVBQRUQgLSAkezF9JHtfX1JFU0VUX0NPTE9SfSIgPiYyCiAgZmkKICBMb2c6OmxvZ1NraXBwZWQgIiQxIgp9CgojIEBkZXNjcmlwdGlvbiBsb2FkIGNvbG9ycyB0aGVtZSBjb25zdGFudHMKIyBAd2FybmluZyBpZiB0dHkgbm90IG9wZW5lZCwgbm9Db2xvciB0aGVtZSB3aWxsIGJlIGNob3NlbgojIEBhcmcgJDEgdGhlbWU6U3RyaW5nIHRoZSB0aGVtZSB0byB1c2UgKGRlZmF1bHQsIG5vQ29sb3IpCiMgQGFyZyAkQCBhcmdzOlN0cmluZ1tdCiMgQHNldCBfX0VSUk9SX0NPTE9SIFN0cmluZyBpbmRpY2F0ZSBlcnJvciBzdGF0dXMKIyBAc2V0IF9fSU5GT19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgaW5mbyBzdGF0dXMKIyBAc2V0IF9fU1VDQ0VTU19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgc3VjY2VzcyBzdGF0dXMKIyBAc2V0IF9fV0FSTklOR19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgd2FybmluZyBzdGF0dXMKIyBAc2V0IF9fU0tJUFBFRF9DT0xPUiBTdHJpbmcgaW5kaWNhdGUgc2tpcHBlZCBzdGF0dXMKIyBAc2V0IF9fREVCVUdfQ09MT1IgU3RyaW5nIGluZGljYXRlIGRlYnVnIHN0YXR1cwojIEBzZXQgX19IRUxQX0NPTE9SIFN0cmluZyBpbmRpY2F0ZSBoZWxwIHN0YXR1cwojIEBzZXQgX19URVNUX0NPTE9SIFN0cmluZyBub3QgdXNlZAojIEBzZXQgX19URVNUX0VSUk9SX0NPTE9SIFN0cmluZyBub3QgdXNlZAojIEBzZXQgX19IRUxQX1RJVExFX0NPTE9SIFN0cmluZyB1c2VkIHRvIGRpc3BsYXkgaGVscCB0aXRsZSBpbiBoZWxwIHN0cmluZ3MKIyBAc2V0IF9fSEVMUF9PUFRJT05fQ09MT1IgU3RyaW5nIHVzZWQgdG8gZGlzcGxheSBoaWdobGlnaHQgb3B0aW9ucyBpbiBoZWxwIHN0cmluZ3MKIwojIEBzZXQgX19SRVNFVF9DT0xPUiBTdHJpbmcgcmVzZXQgZGVmYXVsdCBjb2xvcgojCiMgQHNldCBfX0hFTFBfRVhBTVBMRSBTdHJpbmcgdG8gcmVtb3ZlCiMgQHNldCBfX0hFTFBfVElUTEUgU3RyaW5nIHRvIHJlbW92ZQojIEBzZXQgX19IRUxQX05PUk1BTCBTdHJpbmcgdG8gcmVtb3ZlCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjAzNApVSTo6dGhlbWUoKSB7CiAgbG9jYWwgdGhlbWU9IiR7MS1kZWZhdWx0fSIKICBpZiBbWyAhICIke3RoZW1lfSIgPX4gLWZvcmNlJCBdXSAmJiAhIEFzc2VydDo6dHR5OyB0aGVuCiAgICB0aGVtZT0ibm9Db2xvciIKICBmaQogIGNhc2UgIiR7dGhlbWV9IiBpbgogICAgZGVmYXVsdCB8IGRlZmF1bHQtZm9yY2UpCiAgICAgIHRoZW1lPSJkZWZhdWx0IgogICAgICA7OwogICAgbm9Db2xvcikgOzsKICAgICopCiAgICAgIExvZzo6ZmF0YWwgImludmFsaWQgdGhlbWUgcHJvdmlkZWQiCiAgICAgIDs7CiAgZXNhYwogIGlmIFtbICIke3RoZW1lfSIgPSAiZGVmYXVsdCIgXV07IHRoZW4KICAgIEJBU0hfRlJBTUVXT1JLX1RIRU1FPSJkZWZhdWx0IgogICAgIyBjaGVjayBjb2xvcnMgYXBwbGljYWJsZSBodHRwczovL21pc2MuZmxvZ2lzb2Z0LmNvbS9iYXNoL3RpcF9jb2xvcnNfYW5kX2Zvcm1hdHRpbmcKICAgIF9fRVJST1JfQ09MT1I9J1xlWzMxbScgICAgICAgICAjIFJlZAogICAgX19JTkZPX0NPTE9SPSdcZVs0NG0nICAgICAgICAgICMgd2hpdGUgb24gbGlnaHRCbHVlCiAgICBfX1NVQ0NFU1NfQ09MT1I9J1xlWzMybScgICAgICAgIyBHcmVlbgogICAgX19XQVJOSU5HX0NPTE9SPSdcZVszM20nICAgICAgICMgWWVsbG93CiAgICBfX1NLSVBQRURfQ09MT1I9J1xlWzMzbScgICAgICAgIyBZZWxsb3cKICAgIF9fREVCVUdfQ09MT1I9J1xlWzM3bScgICAgICAgICAjIEdyZXkKICAgIF9fSEVMUF9DT0xPUj0nXGVbNzs0OTszM20nICAgICAjIEJsYWNrIG9uIEdvbGQKICAgIF9fVEVTVF9DT0xPUj0nXGVbMTAwbScgICAgICAgICAjIExpZ2h0IG1hZ2VudGEKICAgIF9fVEVTVF9FUlJPUl9DT0xPUj0nXGVbNDFtJyAgICAjIHdoaXRlIG9uIHJlZAogICAgX19IRUxQX1RJVExFX0NPTE9SPSJcZVsxOzM3bSIgICMgQm9sZAogICAgX19IRUxQX09QVElPTl9DT0xPUj0iXGVbMTszNG0iICMgQmx1ZQogICAgIyBJbnRlcm5hbDogcmVzZXQgY29sb3IKICAgIF9fUkVTRVRfQ09MT1I9J1xlWzBtJyAjIFJlc2V0IENvbG9yCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTUsU0MyMDM0CiAgICBfX0hFTFBfRVhBTVBMRT0iJChlY2hvIC1lICJcZVsyOzk3bSIpIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTU1LFNDMjAzNAogICAgX19IRUxQX1RJVExFPSIkKGVjaG8gLWUgIlxlWzE7MzdtIikiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTUsU0MyMDM0CiAgICBfX0hFTFBfTk9STUFMPSIkKGVjaG8gLWUgIlwwMzNbMG0iKSIKICBlbHNlCiAgICBCQVNIX0ZSQU1FV09SS19USEVNRT0ibm9Db2xvciIKICAgICMgY2hlY2sgY29sb3JzIGFwcGxpY2FibGUgaHR0cHM6Ly9taXNjLmZsb2dpc29mdC5jb20vYmFzaC90aXBfY29sb3JzX2FuZF9mb3JtYXR0aW5nCiAgICBfX0VSUk9SX0NPTE9SPScnCiAgICBfX0lORk9fQ09MT1I9JycKICAgIF9fU1VDQ0VTU19DT0xPUj0nJwogICAgX19XQVJOSU5HX0NPTE9SPScnCiAgICBfX1NLSVBQRURfQ09MT1I9JycKICAgIF9fREVCVUdfQ09MT1I9JycKICAgIF9fSEVMUF9DT0xPUj0nJwogICAgX19URVNUX0NPTE9SPScnCiAgICBfX1RFU1RfRVJST1JfQ09MT1I9JycKICAgIF9fSEVMUF9USVRMRV9DT0xPUj0nJwogICAgX19IRUxQX09QVElPTl9DT0xPUj0nJwogICAgIyBJbnRlcm5hbDogcmVzZXQgY29sb3IKICAgIF9fUkVTRVRfQ09MT1I9JycKICAgIF9fSEVMUF9FWEFNUExFPScnCiAgICBfX0hFTFBfVElUTEU9JycKICAgIF9fSEVMUF9OT1JNQUw9JycKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBjaGVjayBpZiB0dHkgKGludGVyYWN0aXZlIG1vZGUpIGlzIGFjdGl2ZQojIEBub2FyZ3MKIyBAZXhpdGNvZGUgMSBpZiB0dHkgbm90IGFjdGl2ZQojIEBlbnYgTk9OX0lOVEVSQUNUSVZFIGlmIDEgY29uc2lkZXIgYXMgbm90IGludGVyYWN0aXZlIGV2ZW4gaWYgZW52aXJvbm1lbnQgaXMgaW50ZXJhY3RpdmUKIyBAZW52IElOVEVSQUNUSVZFIGlmIDEgY29uc2lkZXIgYXMgaW50ZXJhY3RpdmUgZXZlbiBpZiBlbnZpcm9ubWVudCBpcyBub3QgaW50ZXJhY3RpdmUKIyBAc3RkZXJyIGRpYWdub3N0aWMgaW5mb3JtYXRpb24gKyBoZWxwIGlmIHNlY29uZCBhcmd1bWVudCBpcyBwcm92aWRlZApBc3NlcnQ6OnR0eSgpIHsKICBpZiBbWyAiJHtOT05fSU5URVJBQ1RJVkU6LTB9IiA9ICIxIiBdXTsgdGhlbgogICAgcmV0dXJuIDEKICBmaQogIGlmIFtbICIke0lOVEVSQUNUSVZFOi0wfSIgPSAiMSIgXV07IHRoZW4KICAgIHJldHVybiAwCiAgZmkKICBbWyAtdCAxIHx8IC10IDIgXV0KfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ1NraXBwZWQoKSB7CiAgaWYgKChCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwgPj0gX19MRVZFTF9JTkZPKSk7IHRoZW4KICAgIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1TS0lQUEVEfSIgIiQxIgogIGZpCn0KCiMgRlVOQ1RJT05TCgpmYWNhZGVfbWFpbl9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uYmluRmlsZXRwbCgpIHsKIyBSRVFVSVJFUwpMaW51eDo6cmVxdWlyZUV4ZWN1dGVkQXNVc2VyCkVudjo6cmVxdWlyZUxvYWQKTG9nOjpyZXF1aXJlTG9hZApMaW51eDo6cmVxdWlyZVJlYWxwYXRoQ29tbWFuZApVSTo6cmVxdWlyZVRoZW1lCkNvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyCgojIEByZXF1aXJlIENvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyCgojIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTQsU0MyMDE2CmZ1bmN0aW9uVG9DYWxsPSdEYjo6cXVlcnlPbmVEYXRhYmFzZScKIiR7ZnVuY3Rpb25Ub0NhbGx9IiAiJEAiCgp9CgpmYWNhZGVfbWFpbl9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uYmluRmlsZXRwbCAiJEAiCg==" - -Compiler::Embed::extractFileFromBase64 \ - "${embed_function_DbQueryOneDatabase}" \ - "${encoded_binary_file_DbQueryOneDatabase}" - facade_main_dbQueryAllDatabasessh() { BASH_TOOLS_ROOT_DIR="$(cd "${CURRENT_DIR}/.." && pwd -P)" if [[ -d "${BASH_TOOLS_ROOT_DIR}/vendor/bash-tools-framework/" ]]; then @@ -1249,18 +1237,25 @@ if [[ -f "${HOME}/.bash-tools/.env" ]]; then export BASH_FRAMEWORK_ENV_FILES=("${HOME}/.bash-tools/.env") fi # REQUIRES +Linux::requireExecutedAsUser Env::requireLoad UI::requireTheme Linux::requireRealpathCommand Log::requireLoad -Compiler::Embed::requireEmbedBinDir BashTools::Conf::requireLoad Compiler::Facade::requireCommandBinDir -Linux::requireExecutedAsUser # @require Compiler::Facade::requireCommandBinDir # shellcheck disable=SC2034 +# later on, parallel calls this script(inception) +if [[ "$1" = "DbQueryOneDatabase" ]]; then + shift || true + Linux::requireExecutedAsUser + Db::queryOneDatabase "$@" + exit 0 +fi + #default values # default value for FROM_DSN if from-aws not set declare queryIsFile="0" @@ -1932,7 +1927,7 @@ dbQueryAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(specify\ the\ number\ of\ db\ to\ query\ in\ parallel) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: 1" + echo ' Default value: 1' echo -e " ${__HELP_OPTION_COLOR}--bar${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-b${__HELP_NORMAL} {single}" local -a helpArray # shellcheck disable=SC2054 @@ -1943,7 +1938,7 @@ dbQueryAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(character\ to\ use\ to\ separate\ mysql\ column) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: |" + echo ' Default value: |' echo echo -e "${__HELP_TITLE_COLOR}QUERY OPTIONS:${__RESET_COLOR}" echo -e " ${__HELP_OPTION_COLOR}--from-dsn${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-f ${__HELP_NORMAL} {single}" @@ -1993,7 +1988,7 @@ dbQueryAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray @@ -2160,8 +2155,8 @@ run() { export optionFromDsn # shellcheck disable=SC2154 echo "${allDbs}" | - SHELL=$(type -p bash) parallel --eta --progress "${PARALLEL_OPTIONS[@]}" \ - "${embed_function_DbQueryOneDatabase}" "${optionFromDsn}" | + SHELL=$(type -p bash) parallel --eta --progress -m "${PARALLEL_OPTIONS[@]}" \ + ::: "$0" "DbQueryOneDatabase" "${optionFromDsn}" | awk --source "${awkScript}" - } diff --git a/bin/dbScriptAllDatabases b/bin/dbScriptAllDatabases index 790ebf4f..99c7e4ac 100755 --- a/bin/dbScriptAllDatabases +++ b/bin/dbScriptAllDatabases @@ -8,7 +8,6 @@ # BIN_FILE=${BASH_TOOLS_ROOT_DIR}/bin/dbScriptAllDatabases # VAR_RELATIVE_FRAMEWORK_DIR_TO_CURRENT_DIR=.. # FACADE -# EMBED Db::queryOneDatabase as dbQueryOneDatabase # ensure that no user aliases could interfere with # commands used in this script @@ -249,32 +248,6 @@ Assert::commandExists() { return 0 } -# @description convert base64 encoded back to target file -# if target file is executable prepend dir of target -# file to PATH to make binary available everywhere -# it is advised to include in the path of the target file -# the md5sum of the binFile -# -# @arg $1 targetFile:String the file to write -# @arg $2 binFileBase64:String the base64 encoded file -# @arg $3 fileMode:String the chmod to set on the file -# @set PATH String prepend target embedded file binary directory to PATH variable if binary executable -Compiler::Embed::extractFileFromBase64() { - local targetFile="$1" - local binFileBase64="$2" - local fileMode="${3:-+x}" - - if [[ ! -f "${targetFile}" ]]; then - mkdir -p "$(dirname "${targetFile}")" - base64 -d >"${targetFile}" <<<"${binFileBase64}" - chmod "${fileMode}" "${targetFile}" - fi - - if [[ -x "${targetFile}" ]]; then - Env::pathPrepend "$(dirname "${targetFile}")" - fi -} - # @description get absolute conf file from specified conf folder deduced using these rules # * from absolute file (ignores and ) # * relative to where script is executed (ignores and ) @@ -700,20 +673,6 @@ UI::theme() { fi } -# @description ensure tmpdir/bin exists and -# is added to PATH to make embed being executed automatically -# @noargs -# @exitcode 1 if cannot create tmp bin directory -# @set PATH string add tmp bin directory where to find embed binaries -# @stderr diagnostics information is displayed -Compiler::Embed::requireEmbedBinDir() { - mkdir -p "${TMPDIR:-/tmp}/bin" || { - Log::displayError "unable to create directory ${TMPDIR:-/tmp}/bin" - return 1 - } - Env::pathPrepend "${TMPDIR:-/tmp}/bin" -} - bashToolsDefaultConfigTemplate="${bashToolsDefaultConfigTemplate:-$( cat <<'EOF' # shellcheck disable=SC2034 @@ -1108,15 +1067,6 @@ Log::logSkipped() { # FUNCTIONS -# @require Compiler::Embed::requireEmbedBinDir - -declare -gx embed_function_DbQueryOneDatabase="${PERSISTENT_TMPDIR:-/tmp}/bin/812e3ceaf05a68bbee12d5603a3400be/dbQueryOneDatabase" -declare -gx encoded_binary_file_DbQueryOneDatabase="IyEvdXNyL2Jpbi9lbnYgYmFzaAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgR0VORVJBVEVEIEZBQ0FERSBGUk9NIGh0dHBzOi8vZ2l0aHViLmNvbS9mY2hhc3RhbmV0L2Jhc2gtdG9vbHMvdHJlZS9tYXN0ZXIvaG9tZS93c2wvZmNoYXN0YW5ldC9iYXNoLWRldi1lbnYvdmVuZG9yL2Jhc2gtdG9vbHMtZnJhbWV3b3JrL3NyYy9Db21waWxlci9FbWJlZC9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uLmJpbkZpbGUudHBsCiMgRE8gTk9UIEVESVQgSVQKIyBAZ2VuZXJhdGVkCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMjg4LFNDMjAzNAojIEJJTl9GSUxFPSR7QklOX0ZJTEV9CiMgRkFDQURFCgojIGVuc3VyZSB0aGF0IG5vIHVzZXIgYWxpYXNlcyBjb3VsZCBpbnRlcmZlcmUgd2l0aAojIGNvbW1hbmRzIHVzZWQgaW4gdGhpcyBzY3JpcHQKdW5hbGlhcyAtYSB8fCB0cnVlCnNob3B0IC11IGV4cGFuZF9hbGlhc2VzCgojIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwMzQKKChmYWlsdXJlcyA9IDApKSB8fCB0cnVlCgojIEJhc2ggd2lsbCByZW1lbWJlciAmIHJldHVybiB0aGUgaGlnaGVzdCBleGl0IGNvZGUgaW4gYSBjaGFpbiBvZiBwaXBlcy4KIyBUaGlzIHdheSB5b3UgY2FuIGNhdGNoIHRoZSBlcnJvciBpbnNpZGUgcGlwZXMsIGUuZy4gbXlzcWxkdW1wIHwgZ3ppcApzZXQgLW8gcGlwZWZhaWwKc2V0IC1vIGVycmV4aXQKCiMgQ29tbWFuZCBTdWJzdGl0dXRpb24gY2FuIGluaGVyaXQgZXJyZXhpdCBvcHRpb24gc2luY2UgYmFzaCB2NC40CnNob3B0IC1zIGluaGVyaXRfZXJyZXhpdCB8fCB0cnVlCgojIGlmIHNldCwgYW5kIGpvYiBjb250cm9sIGlzIG5vdCBhY3RpdmUsIHRoZSBzaGVsbCBydW5zIHRoZSBsYXN0IGNvbW1hbmQKIyBvZiBhIHBpcGVsaW5lIG5vdCBleGVjdXRlZCBpbiB0aGUgYmFja2dyb3VuZCBpbiB0aGUgY3VycmVudCBzaGVsbAojIGVudmlyb25tZW50LgpzaG9wdCAtcyBsYXN0cGlwZQoKIyBhIGxvZyBpcyBnZW5lcmF0ZWQgd2hlbiBhIGNvbW1hbmQgZmFpbHMKc2V0IC1vIGVycnRyYWNlCgojIHVzZSBudWxsZ2xvYiBzbyB0aGF0IChmaWxlKi5waHApIHdpbGwgcmV0dXJuIGFuIGVtcHR5IGFycmF5IGlmIG5vIGZpbGUKIyBtYXRjaGVzIHRoZSB3aWxkY2FyZApzaG9wdCAtcyBudWxsZ2xvYgoKIyBlbnN1cmUgcmVnZXhwIGFyZSBpbnRlcnByZXRlZCB3aXRob3V0IGFjY2VudHVhdGVkIGNoYXJhY3RlcnMKZXhwb3J0IExDX0FMTD1QT1NJWAoKZXhwb3J0IFRFUk09eHRlcm0tMjU2Y29sb3IKCiMgYXZvaWQgaW50ZXJhY3RpdmUgaW5zdGFsbApleHBvcnQgREVCSUFOX0ZST05URU5EPW5vbmludGVyYWN0aXZlCmV4cG9ydCBERUJDT05GX05PTklOVEVSQUNUSVZFX1NFRU49dHJ1ZQoKIyBzdG9yZSBjb21tYW5kIGFyZ3VtZW50cyBmb3IgbGF0ZXIgdXNhZ2UKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0CmRlY2xhcmUgLWEgQkFTSF9GUkFNRVdPUktfQVJHVj0oIiRAIikKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0CmRlY2xhcmUgLWEgT1JJR0lOQUxfQkFTSF9GUkFNRVdPUktfQVJHVj0oIiRAIikKCiMgQHNlZSBodHRwczovL3VuaXguc3RhY2tleGNoYW5nZS5jb20vYS8zODY4NTYKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMzE3CmludGVycnVwdE1hbmFnZW1lbnQoKSB7CiAgIyByZXN0b3JlIFNJR0lOVCBoYW5kbGVyCiAgdHJhcCAtIElOVAogICMgZW5zdXJlIHRoYXQgQ3RybC1DIGlzIHRyYXBwZWQgYnkgdGhpcyBzY3JpcHQgYW5kIG5vdCBieSBzdWIgcHJvY2VzcwogICMgcmVwb3J0IHRvIHRoZSBwYXJlbnQgdGhhdCB3ZSBoYXZlIGluZGVlZCBiZWVuIGludGVycnVwdGVkCiAga2lsbCAtcyBJTlQgIiQkIgp9CnRyYXAgaW50ZXJydXB0TWFuYWdlbWVudCBJTlQKU0NSSVBUX05BTUU9JHswIyMqL30KUkVBTF9TQ1JJUFRfRklMRT0iJChyZWFkbGluayAtZSAiJChyZWFscGF0aCAiJHtCQVNIX1NPVVJDRVswXX0iKSIpIgppZiBbWyAtbiAiJHtFTUJFRF9DVVJSRU5UX0RJUn0iIF1dOyB0aGVuCiAgQ1VSUkVOVF9ESVI9IiR7RU1CRURfQ1VSUkVOVF9ESVJ9IgplbHNlCiAgQ1VSUkVOVF9ESVI9IiQoY2QgIiQocmVhZGxpbmsgLWUgIiR7UkVBTF9TQ1JJUFRfRklMRSUvKn0iKSIgJiYgcHdkIC1QKSIKZmkKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFRlbXAgZGlyIG1hbmFnZW1lbnQKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpLRUVQX1RFTVBfRklMRVM9IiR7S0VFUF9URU1QX0ZJTEVTOi0wfSIKZXhwb3J0IEtFRVBfVEVNUF9GSUxFUwoKIyBQRVJTSVNURU5UX1RNUERJUiBpcyBub3QgZGVsZXRlZCBieSB0cmFwcwpQRVJTSVNURU5UX1RNUERJUj0iJHtUTVBESVI6LS90bXB9L2Jhc2gtZnJhbWV3b3JrIgpleHBvcnQgUEVSU0lTVEVOVF9UTVBESVIKbWtkaXIgLXAgIiR7UEVSU0lTVEVOVF9UTVBESVJ9IgoKIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDM0ClRNUERJUj0iJChta3RlbXAgLWQgLXAgIiR7UEVSU0lTVEVOVF9UTVBESVI6LS90bXB9IiAtdCBiYXNoLWZyYW1ld29yay0kJC1YWFhYWFgpIgpleHBvcnQgVE1QRElSCgojIHRlbXAgZGlyIGNsZWFuaW5nCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjMxNwpjbGVhbk9uRXhpdCgpIHsKICBpZiBbWyAiJHtLRUVQX1RFTVBfRklMRVM6LTB9IiA9ICIxIiBdXTsgdGhlbgogICAgTG9nOjpkaXNwbGF5SW5mbyAiS0VFUF9URU1QX0ZJTEVTPTEgdGVtcCBmaWxlcyBrZXB0IGhlcmUgJyR7VE1QRElSfSciCiAgZWxpZiBbWyAtbiAiJHtUTVBESVIreHh4fSIgXV07IHRoZW4KICAgIExvZzo6ZGlzcGxheURlYnVnICJLRUVQX1RFTVBfRklMRVM9MCByZW1vdmluZyB0ZW1wIGZpbGVzICcke1RNUERJUn0nIgogICAgcm0gLVJmICIke1RNUERJUjotL3RtcC9mYWtlfSIgPi9kZXYvbnVsbCAyPiYxCiAgZmkKfQp0cmFwIGNsZWFuT25FeGl0IEVYSVQgSFVQIFFVSVQgQUJSVCBURVJNCgojIFZBUl9NQUlOX0ZVTkNUSU9OX1ZBUl9OQU1FPWRiUXVlcnlBbGxEYXRhYmFzZXNGYWNhZGUKCiMgQGRlc2NyaXB0aW9uIHVzZWQgdG8gZXhlY3V0ZSBnaXZlbiBxdWVyeSB3aGVuIHVzaW5nCiMgZGJTY3JpcHRBbGxEYXRhYmFzZXMKIyBAYXJnICQxIGRzbjpTdHJpbmcKIyBAYXJnICQyIGRiOlN0cmluZwojIEBlbnYgcXVlcnkgU3RyaW5nCiMgQGVudiBvcHRpb25TZXBhcmF0b3IgU3RyaW5nCiMgQHJlcXVpcmUgTGludXg6OnJlcXVpcmVFeGVjdXRlZEFzVXNlcgpEYjo6cXVlcnlPbmVEYXRhYmFzZSgpIHsKICAjIHF1ZXJ5IGFuZCBvcHRpb25TZXBhcmF0b3IgYXJlIHBhc3NlZCB2aWEgZXhwb3J0CiAgbG9jYWwgZHNuPSIkMSIKICBsb2NhbCBkYj0iJDIiCgogIGxvY2FsIC1BIGRiSW5zdGFuY2UKICBEYXRhYmFzZTo6bmV3SW5zdGFuY2UgZGJJbnN0YW5jZSAiJHtkc259IgogIERhdGFiYXNlOjpzZXRRdWVyeU9wdGlvbnMgZGJJbnN0YW5jZSAiJHtkYkluc3RhbmNlW1FVRVJZX09QVElPTlNdfSAtLWNvbm5lY3QtdGltZW91dD01IgoKICAjIGlkZW50aWZ5IGNvbHVtbnMgaGVhZGVyCiAgZWNobyAtbiAiQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAiCiAgRGF0YWJhc2U6OnNraXBDb2x1bW5OYW1lcyBkYkluc3RhbmNlIDAKCiAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTU0CiAgaWYgISBEYXRhYmFzZTo6cXVlcnkgZGJJbnN0YW5jZSAiJHtxdWVyeX0iICIke2RifSIgfCBzZWQgInMvXHQvJHtvcHRpb25TZXBhcmF0b3J9L2ciOyB0aGVuCiAgICBMb2c6OmZhdGFsICJkYXRhYmFzZSAke2RifSBlcnJvciIgMT4mMgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIExvZyBuYW1lc3BhY2UgcHJvdmlkZXMgMiBraW5kIG9mIGZ1bmN0aW9ucwojIC0gTG9nOjpkaXNwbGF5KiBhbGxvd3MgdG8gZGlzcGxheSBnaXZlbiBtZXNzYWdlIHdpdGgKIyAgIGdpdmVuIGRpc3BsYXkgbGV2ZWwKIyAtIExvZzo6bG9nKiBhbGxvd3MgdG8gbG9nIGdpdmVuIG1lc3NhZ2Ugd2l0aAojICAgZ2l2ZW4gbG9nIGxldmVsCiMgTG9nOjpkaXNwbGF5KiBmdW5jdGlvbnMgYXV0b21hdGljYWxseSBsb2cgdGhlIG1lc3NhZ2UgdG9vCiMgQHNlZSBFbnY6OnJlcXVpcmVMb2FkIHRvIGxvYWQgdGhlIGRpc3BsYXkgYW5kIGxvZyBsZXZlbCBmcm9tIC5lbnYgZmlsZQoKIyBAZGVzY3JpcHRpb24gbG9nIGxldmVsIG9mZgpleHBvcnQgX19MRVZFTF9PRkY9MAojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgZXJyb3IKZXhwb3J0IF9fTEVWRUxfRVJST1I9MQojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgd2FybmluZwpleHBvcnQgX19MRVZFTF9XQVJOSU5HPTIKIyBAZGVzY3JpcHRpb24gbG9nIGxldmVsIGluZm8KZXhwb3J0IF9fTEVWRUxfSU5GTz0zCiMgQGRlc2NyaXB0aW9uIGxvZyBsZXZlbCBzdWNjZXNzCmV4cG9ydCBfX0xFVkVMX1NVQ0NFU1M9MwojIEBkZXNjcmlwdGlvbiBsb2cgbGV2ZWwgZGVidWcKZXhwb3J0IF9fTEVWRUxfREVCVUc9NAoKIyBAZGVzY3JpcHRpb24gdmVyYm9zZSBsZXZlbCBvZmYKZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9PRkY9MAojIEBkZXNjcmlwdGlvbiB2ZXJib3NlIGxldmVsIGluZm8KZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9JTkZPPTEKIyBAZGVzY3JpcHRpb24gdmVyYm9zZSBsZXZlbCBpbmZvCmV4cG9ydCBfX1ZFUkJPU0VfTEVWRUxfREVCVUc9MgojIEBkZXNjcmlwdGlvbiB2ZXJib3NlIGxldmVsIGluZm8KZXhwb3J0IF9fVkVSQk9TRV9MRVZFTF9UUkFDRT0zCgojIEBkZXNjcmlwdGlvbiBEaXNwbGF5IG1lc3NhZ2UgdXNpbmcgZGVidWcgY29sb3IgKGdyZXkpCiMgQGFyZyAkMSBtZXNzYWdlOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CkxvZzo6ZGlzcGxheURlYnVnKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCA+PSBfX0xFVkVMX0RFQlVHKSk7IHRoZW4KICAgIGVjaG8gLWUgIiR7X19ERUJVR19DT0xPUn1ERUJVRyAgIC0gJHsxfSR7X19SRVNFVF9DT0xPUn0iID4mMgogIGZpCiAgTG9nOjpsb2dEZWJ1ZyAiJDEiCn0KCiMgQGRlc2NyaXB0aW9uIERpc3BsYXkgbWVzc2FnZSB1c2luZyBpbmZvIGNvbG9yIChiZyBsaWdodCBibHVlL2ZnIHdoaXRlKQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlJbmZvKCkgewogIGxvY2FsIHR5cGU9IiR7MjotSU5GT30iCiAgaWYgKChCQVNIX0ZSQU1FV09SS19ESVNQTEFZX0xFVkVMID49IF9fTEVWRUxfSU5GTykpOyB0aGVuCiAgICBlY2hvIC1lICIke19fSU5GT19DT0xPUn0ke3R5cGV9ICAgIC0gJHsxfSR7X19SRVNFVF9DT0xPUn0iID4mMgogIGZpCiAgTG9nOjpsb2dJbmZvICIkMSIgIiR7dHlwZX0iCn0KCiMgQGRlc2NyaXB0aW9uIGVuc3VyZSBDT01NQU5EX0JJTl9ESVIgZW52IHZhciBpcyBzZXQKIyBhbmQgUEFUSCBjb3JyZWN0bHkgcHJlcGFyZWQKIyBAbm9hcmdzCiMgQHNldCBDT01NQU5EX0JJTl9ESVIgc3RyaW5nIHRoZSBkaXJlY3Rvcnkgd2hlcmUgdG8gZmluZCB0aGlzIGNvbW1hbmQKIyBAc2V0IFBBVEggc3RyaW5nIGFkZCBkaXJlY3Rvcnkgd2hlcmUgdG8gZmluZCB0aGlzIGNvbW1hbmQgYmluYXJ5CkNvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyKCkgewogIENPTU1BTkRfQklOX0RJUj0iJHtDVVJSRU5UX0RJUn0iCiAgRW52OjpwYXRoUHJlcGVuZCAiJHtDT01NQU5EX0JJTl9ESVJ9Igp9CgojIEBkZXNjcmlwdGlvbiBjcmVhdGUgYSBuZXcgZGIgaW5zdGFuY2UKIyBSZXR1cm5zIGltbWVkaWF0ZWx5IGlmIHRoZSBpbnN0YW5jZSBpcyBhbHJlYWR5IGluaXRpYWxpemVkCiMKIyBAYXJnICQxIGluc3RhbmNlTmV3SW5zdGFuY2U6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBkc246U3RyaW5nIGRzbiBwcm9maWxlIC0gbG9hZCB0aGUgZHNuLmVudiBwcm9maWxlIGRlZHVjZWQgdXNpbmcgcnVsZXMgZGVmaW5lZCBpbiBDb25mOjpnZXRBYnNvbHV0ZUZpbGUKIwojIEBleGFtcGxlCiMgICBkZWNsYXJlIC1BZ3ggZGJJbnN0YW5jZQojICAgRGF0YWJhc2U6Om5ld0luc3RhbmNlIGRiSW5zdGFuY2UgImRlZmF1bHQubG9jYWwiCiMKIyBAZXhpdGNvZGUgMSBpZiBkbnMgZmlsZSBub3QgYWJsZSB0byBsb2FkZWQKRGF0YWJhc2U6Om5ld0luc3RhbmNlKCkgewogIGxvY2FsIC1uIGluc3RhbmNlTmV3SW5zdGFuY2U9JDEKICBsb2NhbCBkc249IiQyIgogIGxvY2FsIERTTl9GSUxFCgogIGlmIFtbIC12IGluc3RhbmNlTmV3SW5zdGFuY2VbJ0lOSVRJQUxJWkVEJ10gJiYgIiR7aW5zdGFuY2VOZXdJbnN0YW5jZVsnSU5JVElBTElaRUQnXTotMH0iID09ICIxIiBdXTsgdGhlbgogICAgcmV0dXJuCiAgZmkKCiAgIyBmaW5hbCBhdXRoIGZpbGUgZ2VuZXJhdGVkIGZyb20gZG5zIGZpbGUKICBpbnN0YW5jZU5ld0luc3RhbmNlWydBVVRIX0ZJTEUnXT0iIgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0RTTl9GSUxFJ109IiIKCiAgIyBjaGVjayBkc24gZmlsZQogIERTTl9GSUxFPSIkKENvbmY6OmdldEFic29sdXRlRmlsZSAiZHNuIiAiJHtkc259IiAiZW52IikiIHx8IHJldHVybiAxCiAgRGF0YWJhc2U6OmNoZWNrRHNuRmlsZSAiJHtEU05fRklMRX0iIHx8IHJldHVybiAxCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnRFNOX0ZJTEUnXT0iJHtEU05fRklMRX0iCgogICMgc2hlbGxjaGVjayBzb3VyY2U9L3NyYy9EYXRhYmFzZS90ZXN0c0RhdGEvZHNuX3ZhbGlkLmVudgogIHNvdXJjZSAiJHtpbnN0YW5jZU5ld0luc3RhbmNlWydEU05fRklMRSddfSIKCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnVVNFUiddPSIke1VTRVJ9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ1BBU1NXT1JEJ109IiR7UEFTU1dPUkR9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0hPU1ROQU1FJ109IiR7SE9TVE5BTUV9IgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ1BPUlQnXT0iJHtQT1JUfSIKCiAgIyBnZW5lcmF0ZSBhdXRoRmlsZSBmb3IgZWFzeSBhdXRoZW50aWNhdGlvbgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0FVVEhfRklMRSddPSQobWt0ZW1wIC1wICIke1RNUERJUjotL3RtcH0iIC10ICJteXNxbC5YWFhYWFhYWFhYWFgiKQogICgKICAgIGVjaG8gIltjbGllbnRdIgogICAgZWNobyAidXNlciA9ICR7VVNFUn0iCiAgICBlY2hvICJwYXNzd29yZCA9ICR7UEFTU1dPUkR9IgogICAgZWNobyAiaG9zdCA9ICR7SE9TVE5BTUV9IgogICAgZWNobyAicG9ydCA9ICR7UE9SVH0iCiAgKSA+IiR7aW5zdGFuY2VOZXdJbnN0YW5jZVsnQVVUSF9GSUxFJ119IgoKICAjIHNvbWUgb2YgdGhvc2UgdmFsdWVzIGNhbiBiZSBvdmVycmlkZGVuIHVzaW5nIHRoZSBkc24gZmlsZQogICMgU0tJUF9DT0xVTU5fTkFNRVMgZW5hYmxlZCBieSBkZWZhdWx0CiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnU0tJUF9DT0xVTU5fTkFNRVMnXT0iJHtTS0lQX0NPTFVNTl9OQU1FUzotMX0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnU1NMX09QVElPTlMnXT0iJHtNWVNRTF9TU0xfT1BUSU9OUzotLS1zc2wtbW9kZT1ESVNBQkxFRH0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnUVVFUllfT1BUSU9OUyddPSIke01ZU1FMX1FVRVJZX09QVElPTlM6LS0tYmF0Y2ggLS1yYXcgLS1kZWZhdWx0LWNoYXJhY3Rlci1zZXQ9dXRmOH0iCiAgaW5zdGFuY2VOZXdJbnN0YW5jZVsnRFVNUF9PUFRJT05TJ109IiR7TVlTUUxfRFVNUF9PUFRJT05TOi0tLWRlZmF1bHQtY2hhcmFjdGVyLXNldD11dGY4IC0tY29tcHJlc3MgLS1oZXgtYmxvYiAtLXJvdXRpbmVzIC0tdHJpZ2dlcnMgLS1zaW5nbGUtdHJhbnNhY3Rpb24gLS1zZXQtZ3RpZC1wdXJnZWQ9T0ZGIC0tY29sdW1uLXN0YXRpc3RpY3M9MCAke2luc3RhbmNlTmV3SW5zdGFuY2VbJ1NTTF9PUFRJT05TJ119fSIKICBpbnN0YW5jZU5ld0luc3RhbmNlWydEQl9JTVBPUlRfT1BUSU9OUyddPSIke0RCX0lNUE9SVF9PUFRJT05TOi0tLWNvbm5lY3QtdGltZW91dD01IC0tYmF0Y2ggLS1yYXcgLS1kZWZhdWx0LWNoYXJhY3Rlci1zZXQ9dXRmOH0iCgogIGluc3RhbmNlTmV3SW5zdGFuY2VbJ0lOSVRJQUxJWkVEJ109MQp9CgojIEBkZXNjcmlwdGlvbiBteXNxbCBxdWVyeSBvbiBhIGdpdmVuIGRiCiMgQHdhcm5pbmcgY291bGQgdXNlIFFVRVJZX09QVElPTlMgdmFyaWFibGUgZnJvbSBkc24gaWYgZGVmaW5lZAojIEBleGFtcGxlCiMgICBjYXQgZmlsZS5zcWwgfCBEYXRhYmFzZTo6cXVlcnkgLi4uCiMgQGFyZyAkMSBpbnN0YW5jZVF1ZXJ5OiZNYXA8U3RyaW5nLFN0cmluZz4gKHBhc3NlZCBieSByZWZlcmVuY2UpIGRhdGFiYXNlIGluc3RhbmNlIHRvIHVzZQojIEBhcmcgJDIgc3FsUXVlcnk6U3RyaW5nIChvcHRpb25hbCkgc3FsIHF1ZXJ5IG9yIHNxbCBmaWxlIHRvIGV4ZWN1dGUuIGlmIG5vdCBwcm92aWRlZCBvciBlbXB0eSwgdGhlIGNvbW1hbmQgY2FuIGJlIHBpcGVkCiMgQGFyZyAkMyBkYk5hbWU6U3RyaW5nIChvcHRpb25hbCkgdGhlIGRiIG5hbWUKIwojIEBleGl0Y29kZSBteXNxbCBjb21tYW5kIHN0YXR1cyBjb2RlCkRhdGFiYXNlOjpxdWVyeSgpIHsKICBsb2NhbCAtbiBpbnN0YW5jZVF1ZXJ5PSQxCiAgbG9jYWwgLWEgbXlzcWxDb21tYW5kPSgpCiAgbG9jYWwgLWEgcXVlcnlPcHRpb25zCgogIG15c3FsQ29tbWFuZCs9KG15c3FsKQogIG15c3FsQ29tbWFuZCs9KCItLWRlZmF1bHRzLWV4dHJhLWZpbGU9JHtpbnN0YW5jZVF1ZXJ5WydBVVRIX0ZJTEUnXX0iKQogIElGUz0nICcgcmVhZCAtciAtYSBxdWVyeU9wdGlvbnMgPDw8IiR7aW5zdGFuY2VRdWVyeVsnUVVFUllfT1BUSU9OUyddfSIKICBteXNxbENvbW1hbmQrPSgiJHtxdWVyeU9wdGlvbnNbQF19IikKICBpZiBbWyAiJHtpbnN0YW5jZVF1ZXJ5WydTS0lQX0NPTFVNTl9OQU1FUyddfSIgPSAiMSIgXV07IHRoZW4KICAgIG15c3FsQ29tbWFuZCs9KCItcyIgIi0tc2tpcC1jb2x1bW4tbmFtZXMiKQogIGZpCiAgIyBhZGQgb3B0aW9uYWwgZGIgbmFtZQogIGlmIFtbIC1uICIkezMreH0iIF1dOyB0aGVuCiAgICBteXNxbENvbW1hbmQrPSgiJDMiKQogIGZpCiAgIyBhZGQgb3B0aW9uYWwgc3FsIHF1ZXJ5CiAgaWYgW1sgLW4gIiR7Mit4fSIgJiYgLW4gIiQyIiAmJiAhIC1mICIkMiIgXV07IHRoZW4KICAgIG15c3FsQ29tbWFuZCs9KCItZSIpCiAgICBteXNxbENvbW1hbmQrPSgiJDIiKQogIGZpCiAgTG9nOjpkaXNwbGF5RGVidWcgIiQocHJpbnRmICJleGVjdXRlIGNvbW1hbmQ6ICclcyciICIke215c3FsQ29tbWFuZFsqXX0iKSIKCiAgaWYgW1sgLWYgIiQyIiBdXTsgdGhlbgogICAgIiR7bXlzcWxDb21tYW5kW0BdfSIgPCIkMiIKICBlbHNlCiAgICAiJHtteXNxbENvbW1hbmRbQF19IgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIHNldCB0aGUgZ2VuZXJhbCBvcHRpb25zIHRvIHVzZSBvbiBteXNxbCBjb21tYW5kIHRvIHF1ZXJ5IHRoZSBkYXRhYmFzZQojIERpZmZlcnMgdGhhbiBzZXRPcHRpb25zIGluIHRoZSB3YXkgdGhhdCB0aGVzZSBvcHRpb25zIGNvdWxkIGNoYW5nZSBlYWNoIHRpbWUKIwojIEBhcmcgJDEgaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBvcHRpb25zTGlzdDpTdHJpbmcgcXVlcnkgb3B0aW9ucyBsaXN0CkRhdGFiYXNlOjpzZXRRdWVyeU9wdGlvbnMoKSB7CiAgbG9jYWwgLW4gaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM9JDEKICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwMzQKICBpbnN0YW5jZVNldFF1ZXJ5T3B0aW9uc1snUVVFUllfT1BUSU9OUyddPSIkMiIKfQoKIyBAZGVzY3JpcHRpb24gYnkgZGVmYXVsdCB3ZSBza2lwIHRoZSBjb2x1bW4gbmFtZXMKIyBidXQgc29tZXRpbWVzIHdlIG5lZWQgY29sdW1uIG5hbWVzIHRvIGRpc3BsYXkgc29tZSByZXN1bHRzCiMgZGlzYWJsZSB0aGlzIG9wdGlvbiB0ZW1wb3JhcmlseSBhbmQgdGhlbiByZXN0b3JlIGl0IHRvIHRydWUKIwojIEBhcmcgJDEgaW5zdGFuY2VTZXRRdWVyeU9wdGlvbnM6Jk1hcDxTdHJpbmcsU3RyaW5nPiAocGFzc2VkIGJ5IHJlZmVyZW5jZSkgZGF0YWJhc2UgaW5zdGFuY2UgdG8gdXNlCiMgQGFyZyAkMiBza2lwQ29sdW1uTmFtZXM6Qm9vbGVhbiAwIHRvIGRpc2FibGUsIDEgdG8gZW5hYmxlIChoaWRlIGNvbHVtbiBuYW1lcykKRGF0YWJhc2U6OnNraXBDb2x1bW5OYW1lcygpIHsKICBsb2NhbCAtbiBpbnN0YW5jZVNraXBDb2x1bW5OYW1lcz0kMQogICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjAzNAogIGluc3RhbmNlU2tpcENvbHVtbk5hbWVzWydTS0lQX0NPTFVNTl9OQU1FUyddPSIkMiIKfQoKIyBAZGVzY3JpcHRpb24gcHJlcGVuZCBkaXJlY3RvcmllcyB0byB0aGUgUEFUSCBlbnZpcm9ubWVudCB2YXJpYWJsZQojIEBhcmcgJEAgYXJnczpTdHJpbmdbXSBsaXN0IG9mIGRpcmVjdG9yaWVzIHRvIHByZXBlbmQKIyBAc2V0IFBBVEggdXBkYXRlIFBBVEggd2l0aCB0aGUgZGlyZWN0b3JpZXMgcHJlcGVuZGVkCkVudjo6cGF0aFByZXBlbmQoKSB7CiAgbG9jYWwgYXJnCiAgZm9yIGFyZyBpbiAiJEAiOyBkbwogICAgaWYgW1sgLWQgIiR7YXJnfSIgJiYgIjoke1BBVEh9OiIgIT0gKiI6JHthcmd9OiIqIF1dOyB0aGVuCiAgICAgIFBBVEg9IiQocmVhbHBhdGggIiR7YXJnfSIpOiR7UEFUSH0iCiAgICBmaQogIGRvbmUKfQoKIyBAZGVzY3JpcHRpb24gRGlzcGxheSBtZXNzYWdlIHVzaW5nIGVycm9yIGNvbG9yIChyZWQpIGFuZCBleGl0IGltbWVkaWF0ZWx5IHdpdGggZXJyb3Igc3RhdHVzIDEKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpmYXRhbCgpIHsKICBlY2hvIC1lICIke19fRVJST1JfQ09MT1J9RkFUQUwgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBMb2c6OmxvZ0ZhdGFsICIkMSIKICBleGl0IDEKfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ0RlYnVnKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID49IF9fTEVWRUxfREVCVUcpKTsgdGhlbgogICAgTG9nOjpsb2dNZXNzYWdlICIkezI6LURFQlVHfSIgIiQxIgogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIGxvZyBtZXNzYWdlIHRvIGZpbGUKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpsb2dJbmZvKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID49IF9fTEVWRUxfSU5GTykpOyB0aGVuCiAgICBMb2c6OmxvZ01lc3NhZ2UgIiR7MjotSU5GT30iICIkMSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBlbnN1cmUgcnVubmluZyB1c2VyIGlzIG5vdCByb290CiMgQGV4aXRjb2RlIDEgaWYgY3VycmVudCB1c2VyIGlzIHJvb3QKIyBAc3RkZXJyIGRpYWdub3N0aWNzIGluZm9ybWF0aW9uIGlzIGRpc3BsYXllZApMaW51eDo6cmVxdWlyZUV4ZWN1dGVkQXNVc2VyKCkgewogIGlmIFtbICIkKGlkIC11KSIgPSAiMCIgXV07IHRoZW4KICAgIExvZzo6ZmF0YWwgInRoaXMgc2NyaXB0IHNob3VsZCBiZSBleGVjdXRlZCBhcyBub3JtYWwgdXNlciIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBnZXQgYWJzb2x1dGUgY29uZiBmaWxlIGZyb20gc3BlY2lmaWVkIGNvbmYgZm9sZGVyIGRlZHVjZWQgdXNpbmcgdGhlc2UgcnVsZXMKIyAgICogZnJvbSBhYnNvbHV0ZSBmaWxlIChpZ25vcmVzIDxjb25mRm9sZGVyPiBhbmQgPGV4dGVuc2lvbj4pCiMgICAqIHJlbGF0aXZlIHRvIHdoZXJlIHNjcmlwdCBpcyBleGVjdXRlZCAoaWdub3JlcyA8Y29uZkZvbGRlcj4gYW5kIDxleHRlbnNpb24+KQojICAgKiBmcm9tIGhvbWUvLmJhc2gtdG9vbHMvPGNvbmZGb2xkZXI+CiMgICAqIGZyb20gZnJhbWV3b3JrIGNvbmYvPGNvbmZGb2xkZXI+CiMKIyBAYXJnICQxIGNvbmZGb2xkZXI6U3RyaW5nIHRoZSBkaXJlY3RvcnkgbmFtZSAobm90IHRoZSBwYXRoKSB0byBsaXN0CiMgQGFyZyAkMiBjb25mOlN0cmluZyBmaWxlIHRvIHVzZSB3aXRob3V0IGV4dGVuc2lvbgojIEBhcmcgJDMgZXh0ZW5zaW9uOlN0cmluZyB0aGUgZXh0ZW5zaW9uICguc2ggYnkgZGVmYXVsdCkKIwojIEBzdGRvdXQgYWJzb2x1dGUgY29uZiBmaWxlbmFtZQojIEBleGl0Y29kZSAxIGlmIGZpbGUgaXMgbm90IGZvdW5kIGluIGFueSBsb2NhdGlvbgpDb25mOjpnZXRBYnNvbHV0ZUZpbGUoKSB7CiAgbG9jYWwgY29uZkZvbGRlcj0iJDEiCiAgbG9jYWwgY29uZj0iJDIiCiAgbG9jYWwgZXh0ZW5zaW9uPSIkezMtLnNofSIKICBpZiBbWyAtbiAiJHtleHRlbnNpb259IiAmJiAiJHtleHRlbnNpb246MDoxfSIgIT0gIi4iIF1dOyB0aGVuCiAgICBleHRlbnNpb249Ii4ke2V4dGVuc2lvbn0iCiAgZmkKCiAgdGVzdEFicygpIHsKICAgIGxvY2FsIHJlc3VsdAogICAgcmVzdWx0PSIkKHJlYWxwYXRoIC1lICIkMSIgMj4vZGV2L251bGwpIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTgxCiAgICBpZiBbWyAiJD8iID0gIjAiICYmIC1mICIke3Jlc3VsdH0iIF1dOyB0aGVuCiAgICAgIGVjaG8gIiR7cmVzdWx0fSIKICAgICAgcmV0dXJuIDAKICAgIGZpCiAgICByZXR1cm4gMQogIH0KCiAgIyBjb25mIGlzIGFic29sdXRlIGZpbGUgKGluY2x1ZGluZyBleHRlbnNpb24pCiAgdGVzdEFicyAiJHtjb25mRm9sZGVyfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICAjIGNvbmYgaXMgYWJzb2x1dGUgZmlsZQogIHRlc3RBYnMgIiR7Y29uZkZvbGRlcn0iICYmIHJldHVybiAwCiAgIyBjb25mIGlzIGFic29sdXRlIGZpbGUgKGluY2x1ZGluZyBleHRlbnNpb24pCiAgdGVzdEFicyAiJHtjb25mfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICAjIGNvbmYgaXMgYWJzb2x1dGUgZmlsZQogIHRlc3RBYnMgIiR7Y29uZn0iICYmIHJldHVybiAwCgogICMgcmVsYXRpdmUgdG8gd2hlcmUgc2NyaXB0IGlzIGV4ZWN1dGVkIChpbmNsdWRpbmcgZXh0ZW5zaW9uKQogIGlmIFtbIC1uICIke0NVUlJFTlRfRElSK3h4eH0iIF1dOyB0aGVuCiAgICB0ZXN0QWJzICIkKEZpbGU6OmNvbmNhdGVuYXRlUGF0aCAiJHtDVVJSRU5UX0RJUn0iICIke2NvbmZGb2xkZXJ9IikvJHtjb25mfSR7ZXh0ZW5zaW9ufSIgJiYgcmV0dXJuIDAKICBmaQogICMgZnJvbSBob21lLy5iYXNoLXRvb2xzLzxjb25mRm9sZGVyPgogIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0hPTUV9Ly5iYXNoLXRvb2xzIiAiJHtjb25mRm9sZGVyfSIpLyR7Y29uZn0ke2V4dGVuc2lvbn0iICYmIHJldHVybiAwCgogIGlmIFtbIC1uICIke0ZSQU1FV09SS19ST09UX0RJUit4eHh9IiBdXTsgdGhlbgogICAgIyBmcm9tIGZyYW1ld29yayBjb25mLzxjb25mRm9sZGVyPiAoaW5jbHVkaW5nIGV4dGVuc2lvbikKICAgIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0ZSQU1FV09SS19ST09UX0RJUn0vY29uZiIgIiR7Y29uZkZvbGRlcn0iKS8ke2NvbmZ9JHtleHRlbnNpb259IiAmJiByZXR1cm4gMAoKICAgICMgZnJvbSBmcmFtZXdvcmsgY29uZi88Y29uZkZvbGRlcj4KICAgIHRlc3RBYnMgIiQoRmlsZTo6Y29uY2F0ZW5hdGVQYXRoICIke0ZSQU1FV09SS19ST09UX0RJUn0vY29uZiIgIiR7Y29uZkZvbGRlcn0iKS8ke2NvbmZ9IiAmJiByZXR1cm4gMAogIGZpCgogICMgZmlsZSBub3QgZm91bmQKICBMb2c6OmRpc3BsYXlFcnJvciAiY29uZiBmaWxlICcke2NvbmZ9JyBub3QgZm91bmQiCgogIHJldHVybiAxCn0KCiMgQGRlc2NyaXB0aW9uIGNoZWNrIGlmIGRzbiBmaWxlIGhhcyBhbGwgdGhlIG1hbmRhdG9yeSB2YXJpYWJsZXMgc2V0CiMgTWFuZGF0b3J5IHZhcmlhYmxlcyBhcmU6IEhPU1ROQU1FLCBVU0VSLCBQQVNTV09SRCwgUE9SVAojCiMgQGFyZyAkMSBkc25GaWxlTmFtZTpTdHJpbmcgZHNuIGFic29sdXRlIGZpbGVuYW1lCiMgQHNldCBIT1NUTkFNRSBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgUE9SVCBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgVVNFUiBsb2FkZWQgZnJvbSBkc24gZmlsZQojIEBzZXQgUEFTU1dPUkQgbG9hZGVkIGZyb20gZHNuIGZpbGUKIyBAZXhpdGNvZGUgMCBvbiB2YWxpZCBmaWxlCiMgQGV4aXRjb2RlIDEgaWYgb25lIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBjb25mIGZpbGUgaXMgaW52YWxpZCBvciBpZiBmaWxlIG5vdCBmb3VuZAojIEBzdGRlcnIgbG9nIG91dHB1dCBpZiBlcnJvciBmb3VuZCBpbiBjb25mIGZpbGUKRGF0YWJhc2U6OmNoZWNrRHNuRmlsZSgpIHsKICBsb2NhbCBkc25GaWxlTmFtZT0iJDEiCiAgaWYgW1sgISAtZiAiJHtkc25GaWxlTmFtZX0iIF1dOyB0aGVuCiAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gbm90IGZvdW5kIgogICAgcmV0dXJuIDEKICBmaQoKICAoCiAgICB1bnNldCBIT1NUTkFNRSBQT1JUIFBBU1NXT1JEIFVTRVIKICAgICMgc2hlbGxjaGVjayBzb3VyY2U9L3NyYy9EYXRhYmFzZS90ZXN0c0RhdGEvZHNuX3ZhbGlkLmVudgogICAgc291cmNlICIke2RzbkZpbGVOYW1lfSIKICAgIGlmIFtbIC16ICR7SE9TVE5BTUUreH0gXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5RXJyb3IgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogSE9TVE5BTUUgbm90IHByb3ZpZGVkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke0hPU1ROQU1FfSIgXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5V2FybmluZyAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBIT1NUTkFNRSB2YWx1ZSBub3QgcHJvdmlkZWQiCiAgICBmaQogICAgaWYgW1sgIiR7SE9TVE5BTUV9IiA9ICJsb2NhbGhvc3QiIF1dOyB0aGVuCiAgICAgIExvZzo6ZGlzcGxheVdhcm5pbmcgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogY2hlY2sgdGhhdCBIT1NUTkFNRSBzaG91bGQgbm90IGJlIDEyNy4wLjAuMSBpbnN0ZWFkIG9mIGxvY2FsaG9zdCIKICAgIGZpCiAgICBpZiBbWyAteiAiJHtQT1JUK3h9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBQT1JUIG5vdCBwcm92aWRlZCIKICAgICAgcmV0dXJuIDEKICAgIGZpCiAgICBpZiAhIFtbICR7UE9SVH0gPX4gXlswLTldKyQgXV07IHRoZW4KICAgICAgTG9nOjpkaXNwbGF5RXJyb3IgImRzbiBmaWxlICR7ZHNuRmlsZU5hbWV9IDogUE9SVCBpbnZhbGlkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke1VTRVIreH0iIF1dOyB0aGVuCiAgICAgIExvZzo6ZGlzcGxheUVycm9yICJkc24gZmlsZSAke2RzbkZpbGVOYW1lfSA6IFVTRVIgbm90IHByb3ZpZGVkIgogICAgICByZXR1cm4gMQogICAgZmkKICAgIGlmIFtbIC16ICIke1BBU1NXT1JEK3h9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlFcnJvciAiZHNuIGZpbGUgJHtkc25GaWxlTmFtZX0gOiBQQVNTV09SRCBub3QgcHJvdmlkZWQiCiAgICAgIHJldHVybiAxCiAgICBmaQogICkKfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ0ZhdGFsKCkgewogIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1GQVRBTH0iICIkMSIKfQoKIyBAZGVzY3JpcHRpb24gSW50ZXJuYWw6IGNvbW1vbiBsb2cgbWVzc2FnZQojIEBleGFtcGxlIHRleHQKIyAgIFtkYXRlXXxbbGV2ZWxNc2ddfG1lc3NhZ2UKIwojIEBleGFtcGxlIHRleHQKIyAgIDIwMjAtMDEtMTkgMTk6MjA6MjF8RVJST1IgIHxsb2cgZXJyb3IKIyAgIDIwMjAtMDEtMTkgMTk6MjA6MjF8U0tJUFBFRHxsb2cgc2tpcHBlZAojCiMgQGFyZyAkMSBsZXZlbE1zZzpTdHJpbmcgbWVzc2FnZSdzIGxldmVsIGRlc2NyaXB0aW9uIChlZzogU1RBVFVTLCBFUlJPUiwgLi4uKQojIEBhcmcgJDIgbXNnOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CiMgQGVudiBCQVNIX0ZSQU1FV09SS19MT0dfRklMRSBTdHJpbmcgbG9nIGZpbGUgdG8gdXNlLCBkbyBub3RoaW5nIGlmIGVtcHR5CiMgQGVudiBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwgaW50IGxvZyBsZXZlbCBsb2cgb25seSBpZiA+IE9GRiBvciBmYXRhbCBtZXNzYWdlcwojIEBzdGRlcnIgZGlhZ25vc3RpY3MgaW5mb3JtYXRpb24gaXMgZGlzcGxheWVkCiMgQHJlcXVpcmUgRW52OjpyZXF1aXJlTG9hZAojIEByZXF1aXJlIExvZzo6cmVxdWlyZUxvYWQKTG9nOjpsb2dNZXNzYWdlKCkgewogIGxvY2FsIGxldmVsTXNnPSIkMSIKICBsb2NhbCBtc2c9IiQyIgogIGxvY2FsIGRhdGUKCiAgaWYgW1sgLW4gIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiBdXSAmJiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+IF9fTEVWRUxfT0ZGKSk7IHRoZW4KICAgIGRhdGU9IiQoZGF0ZSAnKyVZLSVtLSVkICVIOiVNOiVTJykiCiAgICB0b3VjaCAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iCiAgICBwcmludGYgIiVzfCU3c3wlc1xuIiAiJHtkYXRlfSIgIiR7bGV2ZWxNc2d9IiAiJHttc2d9IiA+PiIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBjb25jYXRlbmF0ZSAyIHBhdGhzIGFuZCBlbnN1cmUgdGhlIHBhdGggaXMgY29ycmVjdCB1c2luZyByZWFscGF0aCAtbQojIEBhcmcgJDEgYmFzZVBhdGg6U3RyaW5nCiMgQGFyZyAkMiBzdWJQYXRoOlN0cmluZwojIEByZXF1aXJlIExpbnV4OjpyZXF1aXJlUmVhbHBhdGhDb21tYW5kCkZpbGU6OmNvbmNhdGVuYXRlUGF0aCgpIHsKICBsb2NhbCBiYXNlUGF0aD0iJDEiCiAgbG9jYWwgc3ViUGF0aD0iJDIiCiAgbG9jYWwgZnVsbFBhdGg9IiR7YmFzZVBhdGg6KyR7YmFzZVBhdGh9L30ke3N1YlBhdGh9IgoKICByZWFscGF0aCAtbSAiJHtmdWxsUGF0aH0iIDI+L2Rldi9udWxsCn0KCiMgQGRlc2NyaXB0aW9uIERpc3BsYXkgbWVzc2FnZSB1c2luZyBlcnJvciBjb2xvciAocmVkKQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlFcnJvcigpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0RJU1BMQVlfTEVWRUwgPj0gX19MRVZFTF9FUlJPUikpOyB0aGVuCiAgICBlY2hvIC1lICIke19fRVJST1JfQ09MT1J9RVJST1IgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBmaQogIExvZzo6bG9nRXJyb3IgIiQxIgp9CgojIEBkZXNjcmlwdGlvbiBEaXNwbGF5IG1lc3NhZ2UgdXNpbmcgd2FybmluZyBjb2xvciAoeWVsbG93KQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmRpc3BsYXlXYXJuaW5nKCkgewogIGlmICgoQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCA+PSBfX0xFVkVMX1dBUk5JTkcpKTsgdGhlbgogICAgZWNobyAtZSAiJHtfX1dBUk5JTkdfQ09MT1J9V0FSTiAgICAtICR7MX0ke19fUkVTRVRfQ09MT1J9IiA+JjIKICBmaQogIExvZzo6bG9nV2FybmluZyAiJDEiCn0KCiMgQGRlc2NyaXB0aW9uIGVuc3VyZSBlbnYgZmlsZXMgYXJlIGxvYWRlZAojIEBhcmcgJEAgbGlzdCBvZiBkZWZhdWx0IGZpbGVzIHRvIGxvYWQgYXQgdGhlIGVuZAojIEBleGl0Y29kZSAxIGlmIG9uZSBvZiBlbnYgZmlsZXMgZmFpbHMgdG8gbG9hZAojIEBzdGRlcnIgZGlhZ25vc3RpY3MgaW5mb3JtYXRpb24gaXMgZGlzcGxheWVkCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjEyMApFbnY6OnJlcXVpcmVMb2FkKCkgewogIGxvY2FsIC1hIGRlZmF1bHRGaWxlcz0oIiRAIikKICAjIGdldCBsaXN0IG9mIHBvc3NpYmxlIGNvbmZpZyBmaWxlcwogIGxvY2FsIC1hIGNvbmZpZ0ZpbGVzPSgpCiAgaWYgW1sgLW4gIiR7QkFTSF9GUkFNRVdPUktfRU5WX0ZJTEVTWzBdKzF9IiBdXTsgdGhlbgogICAgIyBCQVNIX0ZSQU1FV09SS19FTlZfRklMRVMgaXMgYW4gYXJyYXkKICAgIGNvbmZpZ0ZpbGVzKz0oIiR7QkFTSF9GUkFNRVdPUktfRU5WX0ZJTEVTW0BdfSIpCiAgZmkKICBpZiBbWyAtZiAiJChwd2QpLy5mcmFtZXdvcmstY29uZmlnIiBdXTsgdGhlbgogICAgY29uZmlnRmlsZXMrPSgiJChwd2QpLy5mcmFtZXdvcmstY29uZmlnIikKICBmaQogIGlmIFtbIC1mICIke0ZSQU1FV09SS19ST09UX0RJUn0vLmZyYW1ld29yay1jb25maWciIF1dOyB0aGVuCiAgICBjb25maWdGaWxlcys9KCIke0ZSQU1FV09SS19ST09UX0RJUn0vLmZyYW1ld29yay1jb25maWciKQogIGZpCiAgY29uZmlnRmlsZXMrPSgiJHtvcHRpb25FbnZGaWxlc1tAXX0iKQogIGNvbmZpZ0ZpbGVzKz0oIiR7ZGVmYXVsdEZpbGVzW0BdfSIpCgogIGZvciBmaWxlIGluICIke2NvbmZpZ0ZpbGVzW0BdfSI7IGRvCiAgICAjIHNoZWxsY2hlY2sgc291cmNlPS8uZnJhbWV3b3JrLWNvbmZpZwogICAgQ1VSUkVOVF9MT0FERURfRU5WX0ZJTEU9IiR7ZmlsZX0iIHNvdXJjZSAiJHtmaWxlfSIgfHwgewogICAgICBMb2c6OmRpc3BsYXlFcnJvciAid2hpbGUgbG9hZGluZyBjb25maWcgZmlsZTogJHtmaWxlfSIKICAgICAgcmV0dXJuIDEKICAgIH0KICBkb25lCn0KCiMgQGRlc2NyaXB0aW9uIGFjdGl2YXRlIG9yIG5vdCBMb2c6OmRpc3BsYXkqIGFuZCBMb2c6OmxvZyogZnVuY3Rpb25zCiMgYmFzZWQgb24gQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCBhbmQgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMCiMgZW52aXJvbm1lbnQgdmFyaWFibGVzIGxvYWRlZCBieSBFbnY6OnJlcXVpcmVMb2FkCiMgdHJ5IHRvIGNyZWF0ZSBsb2cgZmlsZSBhbmQgcm90YXRlIGl0IGlmIG5lY2Vzc2FyeQojIEBub2FyZ3MKIyBAc2V0IEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCBpbnQgdG8gT0ZGIGxldmVsIGlmIEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFIGlzIGVtcHR5IG9yIG5vdCB3cml0YWJsZQojIEBlbnYgQkFTSF9GUkFNRVdPUktfRElTUExBWV9MRVZFTCBpbnQKIyBAZW52IEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCBpbnQKIyBAZW52IEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFIFN0cmluZwojIEBlbnYgQkFTSF9GUkFNRVdPUktfTE9HX0ZJTEVfTUFYX1JPVEFUSU9OIGludCBkbyBsb2cgcm90YXRpb24gaWYgPiAwCiMgQGV4aXRjb2RlIDAgYWx3YXlzIHN1Y2Nlc3NmdWwKIyBAc3RkZXJyIGRpYWdub3N0aWNzIGluZm9ybWF0aW9uIGFib3V0IGxvZyBmaWxlIGlzIGRpc3BsYXllZAojIEByZXF1aXJlIEVudjo6cmVxdWlyZUxvYWQKIyBAcmVxdWlyZSBVSTo6cmVxdWlyZVRoZW1lCkxvZzo6cmVxdWlyZUxvYWQoKSB7CiAgaWYgW1sgLXogIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEU6LX0iIF1dOyB0aGVuCiAgICBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUw9JHtfX0xFVkVMX09GRn0KICAgIGV4cG9ydCBCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwKICBmaQoKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+IF9fTEVWRUxfT0ZGKSk7IHRoZW4KICAgIGlmIFtbICEgLWYgIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiBdXTsgdGhlbgogICAgICBpZgogICAgICAgICEgbWtkaXIgLXAgIiQoZGlybmFtZSAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iKSIgMj4vZGV2L251bGwgfHwKICAgICAgICAgICEgdG91Y2ggLS1uby1jcmVhdGUgIiR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IiAyPi9kZXYvbnVsbAogICAgICB0aGVuCiAgICAgICAgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMPSR7X19MRVZFTF9PRkZ9CiAgICAgICAgZWNobyAtZSAiJHtfX0VSUk9SX0NPTE9SfUVSUk9SICAgLSBGaWxlICR7QkFTSF9GUkFNRVdPUktfTE9HX0ZJTEV9IGlzIG5vdCB3cml0YWJsZSR7X19SRVNFVF9DT0xPUn0iID4mMgogICAgICBmaQogICAgZWxpZiBbWyAhIC13ICIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSIgXV07IHRoZW4KICAgICAgQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMPSR7X19MRVZFTF9PRkZ9CiAgICAgIGVjaG8gLWUgIiR7X19FUlJPUl9DT0xPUn1FUlJPUiAgIC0gRmlsZSAke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSBpcyBub3Qgd3JpdGFibGUke19fUkVTRVRfQ09MT1J9IiA+JjIKICAgIGZpCgogIGZpCgogIGlmICgoQkFTSF9GUkFNRVdPUktfTE9HX0xFVkVMID4gX19MRVZFTF9PRkYpKTsgdGhlbgogICAgIyB3aWxsIGFsd2F5cyBiZSBjcmVhdGVkIGV2ZW4gaWYgbm90IGluIGluZm8gbGV2ZWwKICAgIExvZzo6bG9nTWVzc2FnZSAiSU5GTyIgIkxvZ2dpbmcgdG8gZmlsZSAke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFfSAtIExvZyBsZXZlbCAke0JBU0hfRlJBTUVXT1JLX0xPR19MRVZFTH0iCiAgICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19GSUxFX01BWF9ST1RBVElPTiA+IDApKTsgdGhlbgogICAgICBMb2c6OnJvdGF0ZSAiJHtCQVNIX0ZSQU1FV09SS19MT0dfRklMRX0iICIke0JBU0hfRlJBTUVXT1JLX0xPR19GSUxFX01BWF9ST1RBVElPTn0iCiAgICBmaQogIGZpCn0KCiMgQGRlc2NyaXB0aW9uIGxvZyBtZXNzYWdlIHRvIGZpbGUKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpsb2dFcnJvcigpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+PSBfX0xFVkVMX0VSUk9SKSk7IHRoZW4KICAgIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1FUlJPUn0iICIkMSIKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBsb2cgbWVzc2FnZSB0byBmaWxlCiMgQGFyZyAkMSBtZXNzYWdlOlN0cmluZyB0aGUgbWVzc2FnZSB0byBkaXNwbGF5CkxvZzo6bG9nV2FybmluZygpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0xPR19MRVZFTCA+PSBfX0xFVkVMX1dBUk5JTkcpKTsgdGhlbgogICAgTG9nOjpsb2dNZXNzYWdlICIkezI6LVdBUk5JTkd9IiAiJDEiCiAgZmkKfQoKIyBAZGVzY3JpcHRpb24gVG8gYmUgY2FsbGVkIGJlZm9yZSBsb2dnaW5nIGluIHRoZSBsb2cgZmlsZQojIEBhcmcgJDEgZmlsZTpzdHJpbmcgbG9nIGZpbGUgbmFtZQojIEBhcmcgJDIgbWF4TG9nRmlsZXNDb3VudDppbnQgbWF4aW11bSBudW1iZXIgb2YgbG9nIGZpbGVzCkxvZzo6cm90YXRlKCkgewogIGxvY2FsIGZpbGU9IiQxIgogIGxvY2FsIG1heExvZ0ZpbGVzQ291bnQ9IiR7MjotNX0iCgogIGlmIFtbICEgLWYgIiR7ZmlsZX0iIF1dOyB0aGVuCiAgICBMb2c6OmRpc3BsYXlTa2lwcGVkICJMb2cgZmlsZSAke2ZpbGV9IGRvZXNuJ3QgZXhpc3QgeWV0IgogICAgcmV0dXJuIDAKICBmaQogIGZvciBpIGluICQoc2VxICQoKG1heExvZ0ZpbGVzQ291bnQgLSAxKSkgLTEgMSk7IGRvCiAgICBMb2c6OmRpc3BsYXlJbmZvICJMb2cgcm90YXRpb24gJHtmaWxlfS4ke2l9IHRvICR7ZmlsZX0uJCgoaSArIDEpKSIKICAgIG12ICIke2ZpbGV9LiJ7IiR7aX0iLCIkKChpICsgMSkpIn0gJj4vZGV2L251bGwgfHwgdHJ1ZQogIGRvbmUKICBpZiBjcCAiJHtmaWxlfSIgIiR7ZmlsZX0uMSIgJj4vZGV2L251bGw7IHRoZW4KICAgIGVjaG8gPiIke2ZpbGV9IiAjIHJlc2V0IGxvZyBmaWxlCiAgICBMb2c6OmRpc3BsYXlJbmZvICJMb2cgcm90YXRpb24gJHtmaWxlfSB0byAke2ZpbGV9LjEiCiAgZmkKfQoKIyBAZGVzY3JpcHRpb24gZW5zdXJlIGNvbW1hbmQgcmVhbHBhdGggaXMgYXZhaWxhYmxlCiMgQGV4aXRjb2RlIDEgaWYgcmVhbHBhdGggY29tbWFuZCBub3QgYXZhaWxhYmxlCiMgQHN0ZGVyciBkaWFnbm9zdGljcyBpbmZvcm1hdGlvbiBpcyBkaXNwbGF5ZWQKTGludXg6OnJlcXVpcmVSZWFscGF0aENvbW1hbmQoKSB7CiAgQXNzZXJ0Ojpjb21tYW5kRXhpc3RzIHJlYWxwYXRoCn0KCiMgQGRlc2NyaXB0aW9uIGxvYWQgY29sb3IgdGhlbWUKIyBAbm9hcmdzCiMgQGVudiBCQVNIX0ZSQU1FV09SS19USEVNRSBTdHJpbmcgdGhlbWUgdG8gdXNlCiMgQGV4aXRjb2RlIDAgYWx3YXlzIHN1Y2Nlc3NmdWwKVUk6OnJlcXVpcmVUaGVtZSgpIHsKICBVSTo6dGhlbWUgIiR7QkFTSF9GUkFNRVdPUktfVEhFTUUtZGVmYXVsdH0iCn0KCiMgQGRlc2NyaXB0aW9uIGNoZWNrIGlmIGNvbW1hbmQgc3BlY2lmaWVkIGV4aXN0cyBvciByZXR1cm4gMQojIHdpdGggZXJyb3IgYW5kIG1lc3NhZ2UgaWYgbm90CiMKIyBAYXJnICQxIGNvbW1hbmROYW1lOlN0cmluZyBvbiB3aGljaCBleGlzdGVuY2UgbXVzdCBiZSBjaGVja2VkCiMgQGFyZyAkMiBoZWxwSWZOb3RFeGlzdHM6U3RyaW5nIGEgaGVscCBjb21tYW5kIHRvIGRpc3BsYXkgaWYgdGhlIGNvbW1hbmQgZG9lcyBub3QgZXhpc3QKIwojIEBleGl0Y29kZSAxIGlmIHRoZSBjb21tYW5kIHNwZWNpZmllZCBkb2VzIG5vdCBleGlzdAojIEBzdGRlcnIgZGlhZ25vc3RpYyBpbmZvcm1hdGlvbiArIGhlbHAgaWYgc2Vjb25kIGFyZ3VtZW50IGlzIHByb3ZpZGVkCkFzc2VydDo6Y29tbWFuZEV4aXN0cygpIHsKICBsb2NhbCBjb21tYW5kTmFtZT0iJDEiCiAgbG9jYWwgaGVscElmTm90RXhpc3RzPSIkMiIKCiAgIiR7QkFTSF9GUkFNRVdPUktfQ09NTUFORDotY29tbWFuZH0iIC12ICIke2NvbW1hbmROYW1lfSIgPi9kZXYvbnVsbCAyPi9kZXYvbnVsbCB8fCB7CiAgICBMb2c6OmRpc3BsYXlFcnJvciAiJHtjb21tYW5kTmFtZX0gaXMgbm90IGluc3RhbGxlZCwgcGxlYXNlIGluc3RhbGwgaXQiCiAgICBpZiBbWyAtbiAiJHtoZWxwSWZOb3RFeGlzdHN9IiBdXTsgdGhlbgogICAgICBMb2c6OmRpc3BsYXlJbmZvICIke2hlbHBJZk5vdEV4aXN0c30iCiAgICBmaQogICAgcmV0dXJuIDEKICB9CiAgcmV0dXJuIDAKfQoKIyBAZGVzY3JpcHRpb24gRGlzcGxheSBtZXNzYWdlIHVzaW5nIHNraXAgY29sb3IgKHllbGxvdykKIyBAYXJnICQxIG1lc3NhZ2U6U3RyaW5nIHRoZSBtZXNzYWdlIHRvIGRpc3BsYXkKTG9nOjpkaXNwbGF5U2tpcHBlZCgpIHsKICBpZiAoKEJBU0hfRlJBTUVXT1JLX0RJU1BMQVlfTEVWRUwgPj0gX19MRVZFTF9JTkZPKSk7IHRoZW4KICAgIGVjaG8gLWUgIiR7X19TS0lQUEVEX0NPTE9SfVNLSVBQRUQgLSAkezF9JHtfX1JFU0VUX0NPTE9SfSIgPiYyCiAgZmkKICBMb2c6OmxvZ1NraXBwZWQgIiQxIgp9CgojIEBkZXNjcmlwdGlvbiBsb2FkIGNvbG9ycyB0aGVtZSBjb25zdGFudHMKIyBAd2FybmluZyBpZiB0dHkgbm90IG9wZW5lZCwgbm9Db2xvciB0aGVtZSB3aWxsIGJlIGNob3NlbgojIEBhcmcgJDEgdGhlbWU6U3RyaW5nIHRoZSB0aGVtZSB0byB1c2UgKGRlZmF1bHQsIG5vQ29sb3IpCiMgQGFyZyAkQCBhcmdzOlN0cmluZ1tdCiMgQHNldCBfX0VSUk9SX0NPTE9SIFN0cmluZyBpbmRpY2F0ZSBlcnJvciBzdGF0dXMKIyBAc2V0IF9fSU5GT19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgaW5mbyBzdGF0dXMKIyBAc2V0IF9fU1VDQ0VTU19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgc3VjY2VzcyBzdGF0dXMKIyBAc2V0IF9fV0FSTklOR19DT0xPUiBTdHJpbmcgaW5kaWNhdGUgd2FybmluZyBzdGF0dXMKIyBAc2V0IF9fU0tJUFBFRF9DT0xPUiBTdHJpbmcgaW5kaWNhdGUgc2tpcHBlZCBzdGF0dXMKIyBAc2V0IF9fREVCVUdfQ09MT1IgU3RyaW5nIGluZGljYXRlIGRlYnVnIHN0YXR1cwojIEBzZXQgX19IRUxQX0NPTE9SIFN0cmluZyBpbmRpY2F0ZSBoZWxwIHN0YXR1cwojIEBzZXQgX19URVNUX0NPTE9SIFN0cmluZyBub3QgdXNlZAojIEBzZXQgX19URVNUX0VSUk9SX0NPTE9SIFN0cmluZyBub3QgdXNlZAojIEBzZXQgX19IRUxQX1RJVExFX0NPTE9SIFN0cmluZyB1c2VkIHRvIGRpc3BsYXkgaGVscCB0aXRsZSBpbiBoZWxwIHN0cmluZ3MKIyBAc2V0IF9fSEVMUF9PUFRJT05fQ09MT1IgU3RyaW5nIHVzZWQgdG8gZGlzcGxheSBoaWdobGlnaHQgb3B0aW9ucyBpbiBoZWxwIHN0cmluZ3MKIwojIEBzZXQgX19SRVNFVF9DT0xPUiBTdHJpbmcgcmVzZXQgZGVmYXVsdCBjb2xvcgojCiMgQHNldCBfX0hFTFBfRVhBTVBMRSBTdHJpbmcgdG8gcmVtb3ZlCiMgQHNldCBfX0hFTFBfVElUTEUgU3RyaW5nIHRvIHJlbW92ZQojIEBzZXQgX19IRUxQX05PUk1BTCBTdHJpbmcgdG8gcmVtb3ZlCiMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjAzNApVSTo6dGhlbWUoKSB7CiAgbG9jYWwgdGhlbWU9IiR7MS1kZWZhdWx0fSIKICBpZiBbWyAhICIke3RoZW1lfSIgPX4gLWZvcmNlJCBdXSAmJiAhIEFzc2VydDo6dHR5OyB0aGVuCiAgICB0aGVtZT0ibm9Db2xvciIKICBmaQogIGNhc2UgIiR7dGhlbWV9IiBpbgogICAgZGVmYXVsdCB8IGRlZmF1bHQtZm9yY2UpCiAgICAgIHRoZW1lPSJkZWZhdWx0IgogICAgICA7OwogICAgbm9Db2xvcikgOzsKICAgICopCiAgICAgIExvZzo6ZmF0YWwgImludmFsaWQgdGhlbWUgcHJvdmlkZWQiCiAgICAgIDs7CiAgZXNhYwogIGlmIFtbICIke3RoZW1lfSIgPSAiZGVmYXVsdCIgXV07IHRoZW4KICAgIEJBU0hfRlJBTUVXT1JLX1RIRU1FPSJkZWZhdWx0IgogICAgIyBjaGVjayBjb2xvcnMgYXBwbGljYWJsZSBodHRwczovL21pc2MuZmxvZ2lzb2Z0LmNvbS9iYXNoL3RpcF9jb2xvcnNfYW5kX2Zvcm1hdHRpbmcKICAgIF9fRVJST1JfQ09MT1I9J1xlWzMxbScgICAgICAgICAjIFJlZAogICAgX19JTkZPX0NPTE9SPSdcZVs0NG0nICAgICAgICAgICMgd2hpdGUgb24gbGlnaHRCbHVlCiAgICBfX1NVQ0NFU1NfQ09MT1I9J1xlWzMybScgICAgICAgIyBHcmVlbgogICAgX19XQVJOSU5HX0NPTE9SPSdcZVszM20nICAgICAgICMgWWVsbG93CiAgICBfX1NLSVBQRURfQ09MT1I9J1xlWzMzbScgICAgICAgIyBZZWxsb3cKICAgIF9fREVCVUdfQ09MT1I9J1xlWzM3bScgICAgICAgICAjIEdyZXkKICAgIF9fSEVMUF9DT0xPUj0nXGVbNzs0OTszM20nICAgICAjIEJsYWNrIG9uIEdvbGQKICAgIF9fVEVTVF9DT0xPUj0nXGVbMTAwbScgICAgICAgICAjIExpZ2h0IG1hZ2VudGEKICAgIF9fVEVTVF9FUlJPUl9DT0xPUj0nXGVbNDFtJyAgICAjIHdoaXRlIG9uIHJlZAogICAgX19IRUxQX1RJVExFX0NPTE9SPSJcZVsxOzM3bSIgICMgQm9sZAogICAgX19IRUxQX09QVElPTl9DT0xPUj0iXGVbMTszNG0iICMgQmx1ZQogICAgIyBJbnRlcm5hbDogcmVzZXQgY29sb3IKICAgIF9fUkVTRVRfQ09MT1I9J1xlWzBtJyAjIFJlc2V0IENvbG9yCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTUsU0MyMDM0CiAgICBfX0hFTFBfRVhBTVBMRT0iJChlY2hvIC1lICJcZVsyOzk3bSIpIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMTU1LFNDMjAzNAogICAgX19IRUxQX1RJVExFPSIkKGVjaG8gLWUgIlxlWzE7MzdtIikiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTUsU0MyMDM0CiAgICBfX0hFTFBfTk9STUFMPSIkKGVjaG8gLWUgIlwwMzNbMG0iKSIKICBlbHNlCiAgICBCQVNIX0ZSQU1FV09SS19USEVNRT0ibm9Db2xvciIKICAgICMgY2hlY2sgY29sb3JzIGFwcGxpY2FibGUgaHR0cHM6Ly9taXNjLmZsb2dpc29mdC5jb20vYmFzaC90aXBfY29sb3JzX2FuZF9mb3JtYXR0aW5nCiAgICBfX0VSUk9SX0NPTE9SPScnCiAgICBfX0lORk9fQ09MT1I9JycKICAgIF9fU1VDQ0VTU19DT0xPUj0nJwogICAgX19XQVJOSU5HX0NPTE9SPScnCiAgICBfX1NLSVBQRURfQ09MT1I9JycKICAgIF9fREVCVUdfQ09MT1I9JycKICAgIF9fSEVMUF9DT0xPUj0nJwogICAgX19URVNUX0NPTE9SPScnCiAgICBfX1RFU1RfRVJST1JfQ09MT1I9JycKICAgIF9fSEVMUF9USVRMRV9DT0xPUj0nJwogICAgX19IRUxQX09QVElPTl9DT0xPUj0nJwogICAgIyBJbnRlcm5hbDogcmVzZXQgY29sb3IKICAgIF9fUkVTRVRfQ09MT1I9JycKICAgIF9fSEVMUF9FWEFNUExFPScnCiAgICBfX0hFTFBfVElUTEU9JycKICAgIF9fSEVMUF9OT1JNQUw9JycKICBmaQp9CgojIEBkZXNjcmlwdGlvbiBjaGVjayBpZiB0dHkgKGludGVyYWN0aXZlIG1vZGUpIGlzIGFjdGl2ZQojIEBub2FyZ3MKIyBAZXhpdGNvZGUgMSBpZiB0dHkgbm90IGFjdGl2ZQojIEBlbnYgTk9OX0lOVEVSQUNUSVZFIGlmIDEgY29uc2lkZXIgYXMgbm90IGludGVyYWN0aXZlIGV2ZW4gaWYgZW52aXJvbm1lbnQgaXMgaW50ZXJhY3RpdmUKIyBAZW52IElOVEVSQUNUSVZFIGlmIDEgY29uc2lkZXIgYXMgaW50ZXJhY3RpdmUgZXZlbiBpZiBlbnZpcm9ubWVudCBpcyBub3QgaW50ZXJhY3RpdmUKIyBAc3RkZXJyIGRpYWdub3N0aWMgaW5mb3JtYXRpb24gKyBoZWxwIGlmIHNlY29uZCBhcmd1bWVudCBpcyBwcm92aWRlZApBc3NlcnQ6OnR0eSgpIHsKICBpZiBbWyAiJHtOT05fSU5URVJBQ1RJVkU6LTB9IiA9ICIxIiBdXTsgdGhlbgogICAgcmV0dXJuIDEKICBmaQogIGlmIFtbICIke0lOVEVSQUNUSVZFOi0wfSIgPSAiMSIgXV07IHRoZW4KICAgIHJldHVybiAwCiAgZmkKICBbWyAtdCAxIHx8IC10IDIgXV0KfQoKIyBAZGVzY3JpcHRpb24gbG9nIG1lc3NhZ2UgdG8gZmlsZQojIEBhcmcgJDEgbWVzc2FnZTpTdHJpbmcgdGhlIG1lc3NhZ2UgdG8gZGlzcGxheQpMb2c6OmxvZ1NraXBwZWQoKSB7CiAgaWYgKChCQVNIX0ZSQU1FV09SS19MT0dfTEVWRUwgPj0gX19MRVZFTF9JTkZPKSk7IHRoZW4KICAgIExvZzo6bG9nTWVzc2FnZSAiJHsyOi1TS0lQUEVEfSIgIiQxIgogIGZpCn0KCiMgRlVOQ1RJT05TCgpmYWNhZGVfbWFpbl9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uYmluRmlsZXRwbCgpIHsKIyBSRVFVSVJFUwpMaW51eDo6cmVxdWlyZUV4ZWN1dGVkQXNVc2VyCkVudjo6cmVxdWlyZUxvYWQKTG9nOjpyZXF1aXJlTG9hZApMaW51eDo6cmVxdWlyZVJlYWxwYXRoQ29tbWFuZApVSTo6cmVxdWlyZVRoZW1lCkNvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyCgojIEByZXF1aXJlIENvbXBpbGVyOjpGYWNhZGU6OnJlcXVpcmVDb21tYW5kQmluRGlyCgojIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIxNTQsU0MyMDE2CmZ1bmN0aW9uVG9DYWxsPSdEYjo6cXVlcnlPbmVEYXRhYmFzZScKIiR7ZnVuY3Rpb25Ub0NhbGx9IiAiJEAiCgp9CgpmYWNhZGVfbWFpbl9lbWJlZEZyYW1ld29ya0Z1bmN0aW9uYmluRmlsZXRwbCAiJEAiCg==" - -Compiler::Embed::extractFileFromBase64 \ - "${embed_function_DbQueryOneDatabase}" \ - "${encoded_binary_file_DbQueryOneDatabase}" - facade_main_dbScriptAllDatabasessh() { BASH_TOOLS_ROOT_DIR="$(cd "${CURRENT_DIR}/.." && pwd -P)" if [[ -d "${BASH_TOOLS_ROOT_DIR}/vendor/bash-tools-framework/" ]]; then @@ -1139,7 +1089,6 @@ Env::requireLoad UI::requireTheme Linux::requireRealpathCommand Log::requireLoad -Compiler::Embed::requireEmbedBinDir BashTools::Conf::requireLoad Compiler::Facade::requireCommandBinDir Linux::requireExecutedAsUser @@ -1865,7 +1814,7 @@ dbScriptAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(specify\ the\ number\ of\ db\ to\ query\ in\ parallel) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: 1" + echo ' Default value: 1' echo -e " ${__HELP_OPTION_COLOR}--bar${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-b${__HELP_NORMAL} {single}" local -a helpArray # shellcheck disable=SC2054 @@ -1893,7 +1842,7 @@ dbScriptAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(if\ output\ dir\ provided\,\ will\ log\ each\ db\ result\ to\ log\ file) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: none" + echo ' Default value: none' echo ' Possible values: none|log' echo echo -e "${__HELP_TITLE_COLOR}GLOBAL OPTIONS:${__RESET_COLOR}" @@ -1937,7 +1886,7 @@ dbScriptAllDatabasesCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/doc b/bin/doc index b6455457..17f60051 100755 --- a/bin/doc +++ b/bin/doc @@ -1624,7 +1624,7 @@ docCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray @@ -1732,7 +1732,7 @@ run() { "${DOC_DIR}/Commands.md" \ "${BASH_TOOLS_ROOT_DIR}/bin" \ TOKEN_NOT_FOUND_COUNT \ - '(bash-tpl|plantuml|definitionLint|compile|installFacadeExample)$' + '(test)$' # inject plantuml diagram source code into command sed -E -i \ diff --git a/bin/gitIsAncestorOf b/bin/gitIsAncestorOf index e06cffdb..3c659635 100755 --- a/bin/gitIsAncestorOf +++ b/bin/gitIsAncestorOf @@ -1374,7 +1374,7 @@ gitIsAncestorOfCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/gitIsBranch b/bin/gitIsBranch index ca046c09..d0fae218 100755 --- a/bin/gitIsBranch +++ b/bin/gitIsBranch @@ -1352,7 +1352,7 @@ gitIsBranchCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/gitRenameBranch b/bin/gitRenameBranch index 40a9f301..f6471c78 100755 --- a/bin/gitRenameBranch +++ b/bin/gitRenameBranch @@ -1458,7 +1458,7 @@ gitRenameBranchCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/installRequirements b/bin/installRequirements index b5d0f779..1c5bb714 100755 --- a/bin/installRequirements +++ b/bin/installRequirements @@ -1423,7 +1423,7 @@ installRequirementsCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/mysql2puml b/bin/mysql2puml index aaa106cb..c5c6a79f 100755 --- a/bin/mysql2puml +++ b/bin/mysql2puml @@ -1525,7 +1525,7 @@ mysql2pumlCommand() { # shellcheck disable=SC2054 helpArray=(header\ configuration\ of\ the\ plant\ uml\ file) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo echo -e "${__HELP_TITLE_COLOR}GLOBAL OPTIONS:${__RESET_COLOR}" echo -e " ${__HELP_OPTION_COLOR}--bash-framework-config ${__HELP_NORMAL} {single}" @@ -1568,7 +1568,7 @@ mysql2pumlCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/postmanCli b/bin/postmanCli index b360eab6..09f6440d 100755 --- a/bin/postmanCli +++ b/bin/postmanCli @@ -1152,6 +1152,8 @@ Postman::api() { responseFile="$(Framework::createTempFile)" local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() getCollectionDataFromFile "${collectionFile}" | curl \ --request POST https://api.getpostman.com/collections \ @@ -1160,7 +1162,7 @@ Postman::api() { --header 'Accept: application/json' \ --header "X-Api-Key: ${POSTMAN_API_KEY}" \ --data @- \ - --fail --silent --show-error || status=$? + --fail --silent --show-error || Bash::handlePipelineFailure status pipeStatus Postman::displayResponse "createCollectionFromFile" "${responseFile}" @@ -1174,6 +1176,8 @@ Postman::api() { responseFile="$(Framework::createTempFile)" local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() getCollectionDataFromFile "${collectionFile}" | curl \ --request PUT "https://api.getpostman.com/collections/${collectionId}" \ @@ -1182,7 +1186,7 @@ Postman::api() { --header 'Accept: application/json' \ --header "X-Api-Key: ${POSTMAN_API_KEY}" \ --data @- \ - --fail --silent --show-error || status=$? + --fail --silent --show-error || Bash::handlePipelineFailure status pipeStatus Postman::displayResponse "updateCollectionFromFile" "${responseFile}" @@ -1217,6 +1221,36 @@ Postman::api() { esac } +# @description ignore exit code 141 from simple command pipes +# @example use with: +# local resultingStatus=0 +# local -a originalPipeStatus=() +# cmd1 | cmd2 || Bash::handlePipelineFailure resultingStatus originalPipeStatus || true +# [[ "${resultingStatus}" = "0" ]] +# @arg $1 resultingStatusCode:&int (passed by reference) (optional) resulting status code +# @arg $2 originalStatus:int[] (passed by reference) (optional) copy of original PIPESTATUS array +# @env PIPESTATUS assuming that this function is called like in the example provided +# @see https://unix.stackexchange.com/a/709880/582856 +Bash::handlePipelineFailure() { + local -a pipeStatusBackup=("${PIPESTATUS[@]}") + local -n handlePipelineFailure_resultingStatusCode=$1 + local -n handlePipelineFailure_originalStatus=$2 + # shellcheck disable=SC2034 + handlePipelineFailure_originalStatus=("${pipeStatusBackup[@]}") + handlePipelineFailure_resultingStatusCode=0 + local statusCode + for statusCode in "${pipeStatusBackup[@]}"; do + if ((statusCode == 141)); then + return 0 + elif ((statusCode > 0)); then + # shellcheck disable=SC2034 + handlePipelineFailure_resultingStatusCode="${statusCode}" + break + fi + done + return "${handlePipelineFailure_resultingStatusCode}" +} + # @description log message to file # @arg $1 message:String the message to display Log::logSkipped() { @@ -1588,6 +1622,14 @@ commandOptionParseFinished() { displayConfig fi } +NBSP="\xc2\xa0" +NBSP2="${NBSP}${NBSP}" +argCommandHelp() { + echo -e "${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}" + echo -e "${NBSP2}Pull collections from Postman back to repositories.\r" + echo -e "${__HELP_OPTION_COLOR}push${__HELP_NORMAL}" + echo -e "${NBSP2}Push repositories collections to Postman." +} postmanCliCommand() { local options_parse_cmd="$1" @@ -1921,8 +1963,8 @@ postmanCliCommand() { echo -e "${__HELP_TITLE_COLOR}ARGUMENTS:${__RESET_COLOR}" echo -e " [${__HELP_OPTION_COLOR}command${__HELP_NORMAL} {single}]" local -a helpArray - # shellcheck disable=SC2054 - helpArray=($'\e[1;34mpull\n\n \xc2\xa0\xc2\xa0Pull collections from Postman back to repositories.\n\n \e[1;34mpush\n\n \xc2\xa0\xc2\xa0Push repositories collections to Postman.\n') + # shellcheck disable=SC2054,SC2206 + mapfile -t helpArray < <(argCommandHelp) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" echo -e " [${__HELP_OPTION_COLOR}commandArgs${__HELP_NORMAL} {list} (optional)]" local -a helpArray @@ -1978,7 +2020,7 @@ postmanCliCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray @@ -2032,6 +2074,7 @@ postmanCliCommand() { fi } declare optionPostmanModelConfig="$(pwd -P)/postmanCli.collections.json" +declare copyrightBeginYear="2023" # shellcheck disable=SC2317 # if function is overridden unknownOption() { diff --git a/bin/upgradeGithubRelease b/bin/upgradeGithubRelease index a62e0ce6..fe69d18d 100755 --- a/bin/upgradeGithubRelease +++ b/bin/upgradeGithubRelease @@ -1733,7 +1733,7 @@ upgradeGithubReleaseCommand() { # shellcheck disable=SC2054 helpArray=($'The argument that will be provided to the currently installed binary\n\n to check the version of the software. \n\n See options constraints below.') echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: --version" + echo ' Default value: --version' echo -e " ${__HELP_OPTION_COLOR}--current-version${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-c ${__HELP_NORMAL} {single}" local -a helpArray # shellcheck disable=SC2054 @@ -1791,7 +1791,7 @@ upgradeGithubReleaseCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/waitForIt b/bin/waitForIt index 2f525963..8bb49f99 100755 --- a/bin/waitForIt +++ b/bin/waitForIt @@ -1451,7 +1451,7 @@ waitForItCommand() { # shellcheck disable=SC2054 helpArray=(Timeout\ in\ seconds\,\ zero\ for\ no\ timeout.) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: 15" + echo ' Default value: 15' echo -e " ${__HELP_OPTION_COLOR}--host${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-i ${__HELP_NORMAL} {single} (mandatory)" local -a helpArray # shellcheck disable=SC2054 @@ -1514,7 +1514,7 @@ waitForItCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/bin/waitForMysql b/bin/waitForMysql index 4b7d479a..6f601176 100755 --- a/bin/waitForMysql +++ b/bin/waitForMysql @@ -1427,7 +1427,7 @@ waitForMysqlCommand() { # shellcheck disable=SC2054 helpArray=(Timeout\ in\ seconds\,\ zero\ for\ no\ timeout.) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: 15" + echo ' Default value: 15' echo echo -e "${__HELP_TITLE_COLOR}GLOBAL OPTIONS:${__RESET_COLOR}" echo -e " ${__HELP_OPTION_COLOR}--bash-framework-config ${__HELP_NORMAL} {single}" @@ -1470,7 +1470,7 @@ waitForMysqlCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/conf/dbImportProfiles/default.sh b/conf/dbImportProfiles/default.sh index b88c5445..70c55437 100755 --- a/conf/dbImportProfiles/default.sh +++ b/conf/dbImportProfiles/default.sh @@ -8,4 +8,8 @@ cat | grep -v '.*stats' | grep -v '.*history.*' | # always finish by a cat to be sure the command does not return exit code != 0 - cat + cat || { + declare exitCode=$? + if ((exitCode == 141)); then exit 0; fi + exit "${exitCode}" +} diff --git a/install b/install index 2cf9a935..b6784644 100755 --- a/install +++ b/install @@ -1325,7 +1325,7 @@ installCommand() { # shellcheck disable=SC2054 helpArray=(choose\ color\ theme\ -\ default-force\ means\ colors\ will\ be\ produced\ even\ if\ command\ is\ piped) echo -e " $(Array::wrap2 " " 76 4 "${helpArray[@]}")" - echo " Default value: default" + echo ' Default value: default' echo ' Possible values: default|default-force|noColor' echo -e " ${__HELP_OPTION_COLOR}--help${__HELP_NORMAL}, ${__HELP_OPTION_COLOR}-h${__HELP_NORMAL} {single}" local -a helpArray diff --git a/src/Db/queryOneDatabase.sh b/src/Db/queryOneDatabase.sh index 6905fb6b..e39441f4 100755 --- a/src/Db/queryOneDatabase.sh +++ b/src/Db/queryOneDatabase.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# VAR_MAIN_FUNCTION_VAR_NAME=dbQueryAllDatabasesFacade # @description used to execute given query when using # dbScriptAllDatabases diff --git a/src/Postman/Model/validate.bats b/src/Postman/Model/validate.bats index 77255f80..4747f4a3 100755 --- a/src/Postman/Model/validate.bats +++ b/src/Postman/Model/validate.bats @@ -11,6 +11,10 @@ setup() { export BASH_FRAMEWORK_THEME="noColor" } +teardown() { + chmod -R u+w "${BATS_TEST_TMPDIR}/pullMode" 2>/dev/null || true +} + function Postman::Model::validate::missingMode { #@test run Postman::Model::validate \ "fileNotFound.json" "invalidMode" @@ -89,17 +93,20 @@ function Postman::Model::validate::pushModeCollectionsWithErrors { #@test } function Postman::Model::validate::pullModeCollectionsWithErrors { #@test + cp -R "${BATS_TEST_DIRNAME}/testsData/pullMode" "${BATS_TEST_TMPDIR}" + chmod -w "${BATS_TEST_TMPDIR}/pullMode/GithubAPI/notWritableFile.json" + chmod -w "${BATS_TEST_TMPDIR}/pullMode" Postman::Model::getRelativeConfigDirectory() { - echo "${BATS_TEST_DIRNAME}/testsData/pullMode" + echo "${BATS_TEST_TMPDIR}/pullMode" } - local file="${BATS_TEST_DIRNAME}/testsData/pullMode/getCollectionRefs-collectionsWithErrors.json" + local file="${BATS_TEST_TMPDIR}/pullMode/getCollectionRefs-collectionsWithErrors.json" run Postman::Model::validate \ "${file}" "pull" assert_failure 1 assert_line --index 0 "ERROR - File '${file}' - collection 0 - missing file property" - assert_line --index 1 "ERROR - File '${file}' - collection fileNotWritable - collection file ${BATS_TEST_DIRNAME}/testsData/pullMode/GithubAPI/notWritableFile.json is not writable" - assert_line --index 2 "ERROR - File '${file}' - collection dirNotWritable - config directory ${BATS_TEST_DIRNAME}/testsData/pullMode is not writable" + assert_line --index 1 "ERROR - File '${file}' - collection fileNotWritable - collection file ${BATS_TEST_TMPDIR}/pullMode/GithubAPI/notWritableFile.json is not writable" + assert_line --index 2 "ERROR - File '${file}' - collection dirNotWritable - config directory ${BATS_TEST_TMPDIR}/pullMode is not writable" assert_lines_count 3 } diff --git a/src/Postman/api.bats b/src/Postman/api.bats index add09791..43e3b429 100755 --- a/src/Postman/api.bats +++ b/src/Postman/api.bats @@ -4,6 +4,8 @@ source "$(cd "${BATS_TEST_DIRNAME}/.." && pwd)/batsHeaders.sh" # shellcheck source=src/Postman/api.sh source "${rootDir}/src/Postman/api.sh" +# shellcheck source=vendor/bash-tools-framework/src/Bash/handlePipelineFailure.sh +source "${FRAMEWORK_ROOT_DIR}/src/Bash/handlePipelineFailure.sh" setup() { export BASH_FRAMEWORK_THEME="noColor" diff --git a/src/Postman/api.sh b/src/Postman/api.sh index 817f46bc..f3980587 100755 --- a/src/Postman/api.sh +++ b/src/Postman/api.sh @@ -30,6 +30,8 @@ Postman::api() { responseFile="$(Framework::createTempFile)" local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() getCollectionDataFromFile "${collectionFile}" | curl \ --request POST https://api.getpostman.com/collections \ @@ -38,7 +40,7 @@ Postman::api() { --header 'Accept: application/json' \ --header "X-Api-Key: ${POSTMAN_API_KEY}" \ --data @- \ - --fail --silent --show-error || status=$? + --fail --silent --show-error || Bash::handlePipelineFailure status pipeStatus Postman::displayResponse "createCollectionFromFile" "${responseFile}" @@ -52,6 +54,8 @@ Postman::api() { responseFile="$(Framework::createTempFile)" local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() getCollectionDataFromFile "${collectionFile}" | curl \ --request PUT "https://api.getpostman.com/collections/${collectionId}" \ @@ -60,7 +64,7 @@ Postman::api() { --header 'Accept: application/json' \ --header "X-Api-Key: ${POSTMAN_API_KEY}" \ --data @- \ - --fail --silent --show-error || status=$? + --fail --silent --show-error || Bash::handlePipelineFailure status pipeStatus Postman::displayResponse "updateCollectionFromFile" "${responseFile}" diff --git a/src/_binaries/DbImport/dbImport.bats b/src/_binaries/DbImport/dbImport.bats index c8b72c00..aad66a92 100755 --- a/src/_binaries/DbImport/dbImport.bats +++ b/src/_binaries/DbImport/dbImport.bats @@ -173,13 +173,13 @@ function Database::dbImport::remote_db_fully_functional_from_mysql { #@test export BASH_FRAMEWORK_ENV_FILEPATH="${BATS_TEST_DIRNAME}/testsData/.env" run "${binDir}/dbImport" --verbose -f default.local fromDb toDb 2>&1 - unstub_all assert_output --partial "Import database duration : " assert_output --partial "begin insert emptyTable" assert_output --partial "begin insert dataTable" assert_output --partial "begin insert otherTable" [[ -f "${HOME}/.bash-tools/dbImportDumps/fromDb_default.sql.gz" ]] [[ -f "${HOME}/.bash-tools/dbImportDumps/fromDb_default_structure.sql.gz" ]] + unstub_all [[ "$(zcat "${HOME}/.bash-tools/dbImportDumps/fromDb_default.sql.gz" | grep '####data####')" = "####data####" ]] [[ "$(zcat "${HOME}/.bash-tools/dbImportDumps/fromDb_default_structure.sql.gz" | grep '####structure####')" = "####structure####" ]] } @@ -283,10 +283,12 @@ function Database::dbImport::import_local_dump_not_aws_with_tables_filter { #@te $'* --connect-timeout=5 --batch --raw --default-character-set=utf8 toDb : i=0 ; while read line; do ((i=i+1)); echo "line $i"; done < /dev/stdin' run "${binDir}/dbImport" --verbose -f default.local fromDb toDb --tables dataTable,otherTable 2>&1 - assert_output --partial "Import database duration : " + assert_output --partial "db created" + assert_output --partial "import structure dump" assert_output --partial "ignore table emptyTable" - assert_output --partial "begin insert dataTable" + assert_output --partial "Import database duration : " assert_output --partial "begin insert otherTable" + assert_output --partial "begin insert dataTable" [[ -f "${HOME}/.bash-tools/dbImportDumps/fromDb_default.sql.gz" ]] [[ -f "${HOME}/.bash-tools/dbImportDumps/fromDb_default_structure.sql.gz" ]] # check files have been touched diff --git a/src/_binaries/DbImport/dbImport.sh b/src/_binaries/DbImport/dbImport.sh index 13a0b5ab..a8dbe33a 100755 --- a/src/_binaries/DbImport/dbImport.sh +++ b/src/_binaries/DbImport/dbImport.sh @@ -190,9 +190,13 @@ run() { Log::displayInfo "avoid to create db structure" else Log::displayInfo "create db structure from ${remoteDbStructureDumpTempFile}" + # shellcheck disable=SC2034 + local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() time ( pv "${remoteDbStructureDumpTempFile}" | zcat | - Database::query dbTargetDatabase "" "${targetDbName}" + Database::query dbTargetDatabase "" "${targetDbName}" || Bash::handlePipelineFailure status pipeStatus ) fi fi diff --git a/src/_binaries/DbImport/dbImportStream.sh b/src/_binaries/DbImport/dbImportStream.sh index e716c4eb..896892ea 100755 --- a/src/_binaries/DbImport/dbImportStream.sh +++ b/src/_binaries/DbImport/dbImportStream.sh @@ -37,7 +37,7 @@ run() { Version::checkMinimal "gawk" "--version" "5.0.1" # create db instances - declare -Agx dbTargetInstance + local -Agx dbTargetInstance Database::newInstance dbTargetInstance "${optionTargetDsn}" Database::setQueryOptions dbTargetInstance "${dbTargetInstance[QUERY_OPTIONS]} --connect-timeout=5" @@ -46,7 +46,11 @@ run() { initializeDefaultTargetMysqlOptions dbTargetInstance "${argTargetDbName}" # TODO character set should be retrieved from dump files if possible - declare remoteCharacterSet="${optionCharacterSet:-${defaultRemoteCharacterSet}}" + local remoteCharacterSet="${optionCharacterSet:-${defaultRemoteCharacterSet}}" + + local status=0 + # shellcheck disable=SC2034 + local -a pipeStatus=() # shellcheck disable=2086 ( @@ -55,19 +59,19 @@ run() { elif [[ "${argDumpFile}" =~ \.gz$ ]]; then zcat "${argDumpFile}" fi - # zcat will continue to write to stdout whereas awk has finished if table has been found - # we detect this case because zcat will return code 141 because pipe closed - status=$? - if [[ "${status}" -eq "141" ]]; then true; else exit "${status}"; fi ) | awk \ -v PROFILE_COMMAND="${profileCommandFile}" \ -v CHARACTER_SET="${remoteCharacterSet}" \ --source "${awkScript}" \ - - | mysql \ - "--defaults-extra-file=${dbTargetInstance['AUTH_FILE']}" \ - ${dbTargetInstance['DB_IMPORT_OPTIONS']} \ - "${argTargetDbName}" || exit $? + - | + mysql \ + "--defaults-extra-file=${dbTargetInstance['AUTH_FILE']}" \ + ${dbTargetInstance['DB_IMPORT_OPTIONS']} \ + "${argTargetDbName}" || + # zcat will continue to write to stdout whereas awk has finished if table has been found + # we detect this case because zcat will return code 141 because pipe closed + Bash::handlePipelineFailure status pipeStatus } if [[ "${BASH_FRAMEWORK_QUIET_MODE:-0}" = "1" ]]; then diff --git a/src/_binaries/DbImport/testsData/dbImportProfiles/default.sh b/src/_binaries/DbImport/testsData/dbImportProfiles/default.sh index 68138349..8cf9b92b 100755 --- a/src/_binaries/DbImport/testsData/dbImportProfiles/default.sh +++ b/src/_binaries/DbImport/testsData/dbImportProfiles/default.sh @@ -8,4 +8,8 @@ cat | grep -v '.*stats' | grep -v '.*history.*' | # always finish by a cat to be sure the command does not return exit code != 0 - cat + cat || { + # avoid failure on premature process close (check Bash::handlePipelineFailure) + declare exitCode=$?; if (( exitCode == 141 )); then exit 0; fi + exit "${exitCode}" + } diff --git a/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.bats b/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.bats index 5a91c5ac..7b6ad94c 100755 --- a/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.bats +++ b/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.bats @@ -55,7 +55,7 @@ function Database::dbQueryAllDatabases::providingEnvFileChangeDbConnectionParame # shellcheck disable=SC2016 stub parallel \ - '--eta --progress --linebuffer -j 1 * * : while IFS= read -r db; do "$6" "$7" "${db}"; done' + '--eta --progress -m --linebuffer -j 1 ::: * DbQueryOneDatabase * * : while IFS= read -r db; do "$8" "$9" "${10}" "${db}"; done' f() { # shellcheck disable=SC2317 @@ -88,7 +88,7 @@ function Database::dbQueryAllDatabases::multipleJobs { #@test # shellcheck disable=SC2016 stub parallel \ - '--eta --progress --linebuffer -j 8 * * : while IFS= read -r db; do "$6" "$7" "${db}"; done' + '--eta --progress -m --linebuffer -j 8 ::: * DbQueryOneDatabase * * : while IFS= read -r db; do "$8" "$9" "${10}" "${db}"; done' f() { # shellcheck disable=SC2317 diff --git a/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.sh b/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.sh index 1d5af64d..22b031a9 100755 --- a/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.sh +++ b/src/_binaries/DbQueryAllDatabases/dbQueryAllDatabases.sh @@ -2,9 +2,16 @@ # BIN_FILE=${BASH_TOOLS_ROOT_DIR}/bin/dbQueryAllDatabases # VAR_RELATIVE_FRAMEWORK_DIR_TO_CURRENT_DIR=.. # FACADE -# EMBED Db::queryOneDatabase as dbQueryOneDatabase # shellcheck disable=SC2034 +# later on, parallel calls this script(inception) +if [[ "$1" = "DbQueryOneDatabase" ]]; then + shift || true + Linux::requireExecutedAsUser + Db::queryOneDatabase "$@" + exit 0 +fi + #default values # default value for FROM_DSN if from-aws not set declare queryIsFile="0" @@ -58,8 +65,8 @@ run() { export optionFromDsn # shellcheck disable=SC2154 echo "${allDbs}" | - SHELL=$(type -p bash) parallel --eta --progress "${PARALLEL_OPTIONS[@]}" \ - "${embed_function_DbQueryOneDatabase}" "${optionFromDsn}" | + SHELL=$(type -p bash) parallel --eta --progress -m "${PARALLEL_OPTIONS[@]}" \ + ::: "$0" "DbQueryOneDatabase" "${optionFromDsn}" | awk --source "${awkScript}" - } diff --git a/src/_binaries/DbScriptAllDatabases/dbScriptAllDatabases.sh b/src/_binaries/DbScriptAllDatabases/dbScriptAllDatabases.sh index eb9f508d..775d0ef8 100755 --- a/src/_binaries/DbScriptAllDatabases/dbScriptAllDatabases.sh +++ b/src/_binaries/DbScriptAllDatabases/dbScriptAllDatabases.sh @@ -2,7 +2,6 @@ # BIN_FILE=${BASH_TOOLS_ROOT_DIR}/bin/dbScriptAllDatabases # VAR_RELATIVE_FRAMEWORK_DIR_TO_CURRENT_DIR=.. # FACADE -# EMBED Db::queryOneDatabase as dbQueryOneDatabase # shellcheck disable=SC2034 # default values diff --git a/src/_binaries/Postman/command.postmanCli.tpl b/src/_binaries/Postman/command.postmanCli.tpl index 6f5a9151..eb87dccf 100644 --- a/src/_binaries/Postman/command.postmanCli.tpl +++ b/src/_binaries/Postman/command.postmanCli.tpl @@ -2,15 +2,21 @@ declare versionNumber="1.0" declare commandFunctionName="postmanCliCommand" declare help="Push/Pull postman collections of all the configured repositories" -declare copyrightBeginYear="2023" # shellcheck disable=SC2016 % .INCLUDE "$(dynamicTemplateDir _binaries/options/options.base.tpl)" -% - NBSP="\xc2\xa0" NBSP2="${NBSP}${NBSP}" +argCommandHelp() { + echo -e "${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}" + echo -e "${NBSP2}Pull collections from Postman back to repositories." $'\r' + echo -e "${__HELP_OPTION_COLOR}push${__HELP_NORMAL}" + echo -e "${NBSP2}Push repositories collections to Postman." +} + +% + # shellcheck source=/dev/null source <( Options::generateGroup \ @@ -28,17 +34,14 @@ source <( --variable-name "optionPostmanModelConfig" \ --function-name optionPostmanModelConfigFunction + argCommandHelp() { :; } Options::generateArg \ --variable-name "argCommand" \ --min 0 \ --max 1 \ --name "command" \ --authorized-values 'pull|push' \ - --help \ - $'${__HELP_OPTION_COLOR}pull${__HELP_NORMAL}\n - ${NBSP2}Pull collections from Postman back to repositories.\n - ${__HELP_OPTION_COLOR}push${__HELP_NORMAL}\n - ${NBSP2}Push repositories collections to Postman.\n' \ + --help argCommandHelp \ --function-name argCommandFunction Options::generateArg \ @@ -63,6 +66,7 @@ options+=( Options::generateCommand "${options[@]}" % declare optionPostmanModelConfig="$(pwd -P)/postmanCli.collections.json" +declare copyrightBeginYear="2023" # shellcheck disable=SC2317 # if function is overridden unknownOption() { diff --git a/src/_binaries/Postman/testsData/postmanCli.help.txt b/src/_binaries/Postman/testsData/postmanCli.help.txt index 17c44e0e..04c6028a 100644 --- a/src/_binaries/Postman/testsData/postmanCli.help.txt +++ b/src/_binaries/Postman/testsData/postmanCli.help.txt @@ -10,10 +10,8 @@ Push/Pull postman collections of all the configured repositories ARGUMENTS: [command {single}] - pull -   Pull collections from Postman back to repositories. - push -   Push repositories collections to Postman. + pull   Pull collections from Postman back to repositories. + push   Push repositories collections to Postman. [commandArgs {list} (optional)] list of postman collection's references to pull or push or no argument to pull or push all the collections @@ -70,4 +68,4 @@ https://github.com/fchastanet/bash-tools/tree/master/src/_binaries/Postman/postm LICENSE: MIT License -Copyright (c) 2024-now François Chastanet +Copyright (c) 2023-now François Chastanet diff --git a/src/_binaries/build/doc.sh b/src/_binaries/build/doc.sh index a01c80c2..ff820cbd 100755 --- a/src/_binaries/build/doc.sh +++ b/src/_binaries/build/doc.sh @@ -61,7 +61,7 @@ run() { "${DOC_DIR}/Commands.md" \ "${BASH_TOOLS_ROOT_DIR}/bin" \ TOKEN_NOT_FOUND_COUNT \ - '(bash-tpl|plantuml|definitionLint|compile|installFacadeExample)$' + '(test)$' # inject plantuml diagram source code into command sed -E -i \