diff --git a/objects.tar.gz b/objects.tar.gz index 1d6241e01..313d36673 100644 Binary files a/objects.tar.gz and b/objects.tar.gz differ diff --git a/sherpa-manager.tar.gz b/sherpa-manager.tar.gz index 15ea45787..8df8ab984 100644 Binary files a/sherpa-manager.tar.gz and b/sherpa-manager.tar.gz differ diff --git a/support/build-objects.sh b/support/build-objects.sh index 82b21073f..13ff13d27 100755 --- a/support/build-objects.sh +++ b/support/build-objects.sh @@ -4,6 +4,8 @@ echo -n "building 'objects' file ... " +objects_epoch=$(date +%s) + target=$support_path/$objects_file # These are used internally by sherpa. Must maintain separate lists for sherpa internal-use, and what user has requested. @@ -123,7 +125,7 @@ echo $public_function_name':Add() } [[ -e $target ]] && rm -f "$target" -echo "r_objects_version=''" > "$target" +echo "r_objects_epoch=''" > "$target" echo "#* " >> "$target" # package action flag objects. diff --git a/support/sherpa-manager.source b/support/sherpa-manager.source index 847e3bb8b..6ef9cbab2 100755 --- a/support/sherpa-manager.source +++ b/support/sherpa-manager.source @@ -767,6 +767,7 @@ CreatePaths() MakePath "$r_reports_path" reports || return MakePath "$r_qpkg_bu_path" 'QPKG backup' || return MakePath "$r_qpkg_download_path" 'QPKG download' || return + MakePath "$r_qpkg_states_path" states || return } @@ -867,9 +868,13 @@ DebugLogEnv() # DebugUserspace ok '$PATH (LHS-only)' "${PATH:0:$((r_debug_log_third_column_width-${#r_chars_ellipsis}))}${r_chars_ellipsis}" # fi - DebugScript 'git branch' "$useropt_branch" + DebugScript 'QPKG version' "$(ConvertDateTimeAutoExpand "$r_this_package_ver")" + DebugScript 'manager epoch' "$(ConvertDateTimeAutoExpand "$r_this_script_epoch")" + DebugScript 'manager version' "$r_this_script_ver" + DebugScript 'loader version' "$(ConvertDateTimeAutoExpand "${LOADER_SCRIPT_VERSION:=undefined}")" + DebugScript 'objects epoch' "$(ConvertDateTimeAutoExpand "${r_objects_epoch:-not loaded}")" + DebugScript 'packages epoch' "$(ConvertDateTimeAutoExpand "${r_packages_epoch:-not loaded}")" DebugScript 'logs path' "$r_logs_path" - DebugScript 'action concurrency' "$r_concurrency" DebugScript "'sqlite3' binary" "$sqlite_cmd" if OsIsSupportUnofficialPackages; then @@ -1741,10 +1746,18 @@ ProcAction() OpenActionMsgPipe() { + # Inputs: (global) + # $r_action_msg_pipe + + # Outputs: (global) + # $action_msg_pipe_fd + # $backup_stdin_fd + # Create a message pipe, so action forks can send data back to parent. [[ -p $r_action_msg_pipe ]] && rm -f "$r_action_msg_pipe" 2> /dev/null - [[ ! -p $r_action_msg_pipe ]] && mknod "$r_action_msg_pipe" p + [[ ! -d $($DIRNAME_CMD "$r_action_msg_pipe") ]] && mkdir -p "$($DIRNAME_CMD "$r_action_msg_pipe")" + [[ ! -p $r_action_msg_pipe ]] && $MKNOD_CMD "$r_action_msg_pipe" p # Create a file descriptor to store original stdin FD. @@ -1769,6 +1782,11 @@ OpenActionMsgPipe() CloseActionMsgPipe() { + # Inputs: (global) + # $action_msg_pipe_fd + # $backup_stdin_fd + # $r_action_msg_pipe + # Restore original file descriptors, and remove message pipe. if [[ -n ${backup_stdin_fd:-} ]]; then @@ -2320,6 +2338,7 @@ ParseShowArgs() show) case $group in about) + LoadPackages action='' awaiting_group=false get_qpkg_states=false @@ -5771,7 +5790,7 @@ GenerateFeaturesReportTitleLine() printf "%-$((r_report_qpkg_tier_column_width+2+$(LenANSIDiff "$a")))s" "$a" # column 8: NAS arch is compatible? - a='Compat?' + a='ArchCompat?' printf "%-$((r_report_qpkg_is_compatible_column_width+2+$(LenANSIDiff "$a")))s" "$a" # column 9: QPKG is sherpa-compatible? @@ -5797,14 +5816,14 @@ GenerateFeaturesReportDataLine() local active_test=false local active_test_msg=$r_chars_blank - local autoupdate=false + local autoupdate=false # Tri-state: true, false, N/A local autoupdate_msg=$r_chars_blank local backup=false local backup_msg=$r_chars_blank local clean=false local clean_msg=$r_chars_blank - local compatible=false - local compatible_msg=$r_chars_blank + local arch_compatible=false + local arch_compatible_msg=$r_chars_blank local mode='' local name_msg=$r_chars_blank local req_alert=false @@ -5856,7 +5875,7 @@ GenerateFeaturesReportDataLine() autoupdate=N/A backup=N/A clean=N/A - compatible=N/A + arch_compatible=N/A restart_to_update=N/A sherpa_compatible=N/A tier=N/A @@ -5867,7 +5886,7 @@ GenerateFeaturesReportDataLine() autoupdate_msg+=$autoupdate backup_msg+=$backup clean_msg+=$clean - compatible_msg+=$compatible + arch_compatible_msg+=$arch_compatible restart_to_update_msg+=$restart_to_update sherpa_compatible_msg+=$sherpa_compatible tier_msg+=$tier @@ -5878,7 +5897,7 @@ GenerateFeaturesReportDataLine() autoupdate_msg=$(TextDarkGrey "$autoupdate_msg") backup_msg=$(TextDarkGrey "$backup_msg") clean_msg=$(TextDarkGrey "$clean_msg") - compatible_msg=$(TextDarkGrey "$compatible_msg") + arch_compatible_msg=$(TextDarkGrey "$arch_compatible_msg") restart_to_update_msg=$(TextDarkGrey "$restart_to_update_msg") sherpa_compatible_msg=$(TextDarkGrey "$sherpa_compatible_msg") tier_msg=$(TextDarkGrey "$tier_msg") @@ -5901,7 +5920,7 @@ GenerateFeaturesReportDataLine() QpkgIsDatabaseCanBackup && backup=true QpkgIsDatabaseCanClean && clean=true - QpkgIsDatabaseArchOK && compatible=true + QpkgIsDatabaseArchOK && arch_compatible=true if QpkgIsDatabaseCanRestartToUpdate; then restart_to_update=true @@ -5918,7 +5937,7 @@ GenerateFeaturesReportDataLine() autoupdate_msg+=$autoupdate backup_msg+=$backup clean_msg+=$clean - compatible_msg+=$compatible + arch_compatible_msg+=$arch_compatible restart_to_update_msg+=$restart_to_update sherpa_compatible_msg+=$sherpa_compatible tier_msg+=$tier @@ -5927,33 +5946,52 @@ GenerateFeaturesReportDataLine() # Highlight field messages. if [[ $active_test = true ]]; then - active_test_msg=$(TextBrightGreen "$active_test_msg") + : # active_test_msg=$(TextBrightGreen "$active_test_msg") else active_test_msg=$(TextBrightOrange "$active_test_msg") fi - if [[ $autoupdate = true ]]; then - autoupdate_msg=$(TextBrightGreen "$autoupdate_msg") + if [[ $autoupdate = true ]]; then # Tri-state. + : # autoupdate_msg=$(TextBrightGreen "$autoupdate_msg") elif [[ $autoupdate = false ]]; then autoupdate_msg=$(TextBrightOrange "$autoupdate_msg") fi - [[ $backup = true ]] && backup_msg=$(TextBrightGreen "$backup_msg") - [[ $clean = true ]] && clean_msg=$(TextBrightGreen "$clean_msg") + if [[ $backup = true ]]; then + : # backup_msg=$(TextBrightGreen "$backup_msg") + else + backup_msg=$(TextBrightOrange "$backup_msg") + fi - if [[ $compatible = true ]]; then - compatible_msg=$(TextBrightGreen "$compatible_msg") + if [[ $clean = true ]]; then + : # clean_msg=$(TextBrightGreen "$clean_msg") else - compatible_msg=$(TextBrightRed "$compatible_msg") + clean_msg=$(TextBrightOrange "$clean_msg") fi - [[ $restart_to_update = true ]] && restart_to_update_msg=$(TextBrightGreen "$restart_to_update_msg") + if [[ $arch_compatible = true ]]; then + : # arch_compatible_msg=$(TextBrightGreen "$arch_compatible_msg") + else + arch_compatible_msg=$(TextBrightRed "$arch_compatible_msg") + fi + + if [[ $restart_to_update = true ]]; then + : # restart_to_update_msg=$(TextBrightGreen "$restart_to_update_msg") + else + restart_to_update_msg=$(TextBrightOrange "$restart_to_update_msg") + fi if [[ $sherpa_compatible = true ]]; then - sherpa_compatible_msg=$(TextBrightGreen "$sherpa_compatible_msg") + : # sherpa_compatible_msg=$(TextBrightGreen "$sherpa_compatible_msg") else sherpa_compatible_msg=$(TextBrightOrange "$sherpa_compatible_msg") fi + + if [[ $uniqueunpack = true ]]; then + : # uniqueunpack_msg=$(TextBrightGreen "$uniqueunpack_msg") + else + uniqueunpack_msg=$(TextBrightOrange "$uniqueunpack_msg") + fi esac if [[ $req_alert = true ]]; then @@ -5969,7 +6007,7 @@ GenerateFeaturesReportDataLine() fi if OsIsSupportAutowidthTableColumns; then - echo "$name_msg|$backup_msg|$clean_msg|$restart_to_update_msg|$autoupdate_msg|$active_test_msg|$tier_msg|$compatible_msg|$sherpa_compatible_msg|$uniqueunpack_msg" + echo "$name_msg|$backup_msg|$clean_msg|$restart_to_update_msg|$autoupdate_msg|$active_test_msg|$tier_msg|$arch_compatible_msg|$sherpa_compatible_msg|$uniqueunpack_msg" else # column 1: package name. printf "%-$((r_report_qpkg_name_column_width+$(LenANSIDiff "$name_msg")))s" "$name_msg" @@ -6000,7 +6038,7 @@ GenerateFeaturesReportDataLine() # column 8: NAS arch is compatible? printf "%$((r_report_column_spacing))s" - printf "%-$((r_report_qpkg_is_compatible_column_width+$(LenANSIDiff "$compatible_msg")))s" "$compatible_msg" + printf "%-$((r_report_qpkg_is_compatible_column_width+$(LenANSIDiff "$arch_compatible_msg")))s" "$arch_compatible_msg" # column 9: QPKG is sherpa-compatible? printf "%$((r_report_column_spacing))s" @@ -7395,8 +7433,6 @@ BuildQPKGsStates() ShowAsProc 'QPKG states' - MakePath "$r_qpkg_states_path" states || return - # Faster to launch several concurrent loops async, than a single loop. Launch those requiring more processing-time first. # This one should only be run when actioning 'installable' QPKGs. @@ -7859,7 +7895,7 @@ ShowReportFeatures() ResetReportsPath &> /dev/null if OsIsSupportAutowidthTableColumns; then - printf -v a '\n%s\n' 'QPKG name:|CanBack?|CanClean?|StartUpd?|AutoUpd?|LiveTest?|Indep?|Compat?|Enhanced?|UniqueUnpack?' + printf -v a '\n%s\n' 'QPKG name:|CanBack?|CanClean?|StartUpd?|AutoUpd?|LiveTest?|Indep?|ArchCompat?|Enhanced?|UniqueUnpack?' else printf -v a '\n%s\n' "$(GenerateFeaturesReportTitleLine)" fi @@ -8378,8 +8414,9 @@ GenerateReportHeadingsFooter() DisplayAsIndentQuotedInfoItem 'AutoUpd?' 'application restart-to-update is enabled' DisplayAsIndentQuotedInfoItem 'LiveTest?' "has a built-in 'status' check, and can test for daemon live status" DisplayAsIndentQuotedInfoItem 'Indep?' 'is independent of other QPKGs' - DisplayAsIndentQuotedInfoItem 'Compat?' 'has a release compatible with this NAS architecture' + DisplayAsIndentQuotedInfoItem 'ArchCompat?' 'has a release compatible with this NAS architecture' DisplayAsIndentQuotedInfoItem 'Enhanced?' "$(ShowAsTitleName) enhanced service actions are supported" + DisplayAsIndentQuotedInfoItem 'UniqueUnpack?' 'QPKG unpacks itself to a unique path' }) if [[ -n $a ]]; then @@ -8413,11 +8450,11 @@ ShowVersionsList() DisableDebugToArchiveAndFile EraseThisLine - Display "QPKG: ${r_this_package_ver:-undefined}$([[ $r_this_package_ver != undefined ]] && printf '%s' " ($(ConvertDateCodeToExtendedDate "$r_this_package_ver"))")" - Display "manager: ${r_this_script_ver:-undefined}$([[ $r_this_script_ver != undefined ]] && printf '%s' " ($(ConvertSecondsToFullDate "$r_this_script_epoch"))")" - Display "loader: ${LOADER_SCRIPT_VERSION:=undefined}$([[ $LOADER_SCRIPT_VERSION != undefined ]] && printf '%s' " ($(ConvertDateCodeToExtendedDate "$LOADER_SCRIPT_VERSION"))")" - Display "objects: ${r_objects_version:-undefined}$([[ $r_objects_version != undefined ]] && printf '%s' " ($(ConvertDateCodeToExtendedDate "$r_objects_version"))")" - Display "packages: ${r_packages_epoch:-undefined}$([[ $r_packages_epoch != undefined ]] && printf '%s' " ($(ConvertSecondsToFullDate "$r_packages_epoch"))")" + Display "QPKG: $(ConvertDateTimeAutoExpand "$r_this_package_ver")" + Display "manager: $(ConvertDateTimeAutoExpand "$r_this_script_epoch")" + Display "loader: $(ConvertDateTimeAutoExpand "${LOADER_SCRIPT_VERSION:=undefined}")" + Display "objects: $(ConvertDateTimeAutoExpand "${r_objects_epoch:-not loaded}")" + Display "packages: $(ConvertDateTimeAutoExpand "${r_packages_epoch:-not loaded}")" return 0 @@ -12568,7 +12605,7 @@ ClearPath() { # Clear (empty) an existing directory, but don't delete the directory. - # Delete files in a relatively safe manner. Parent of directory MUST be specified to avoid an 'rm -rf /*' situation through empty args. + # Delete files in a relatively safe manner. Parent of directory MUST be specified to avoid an `rm -rf /*` situation because of empty args. # Inputs: (local) # $1 = full path to parent of directory name to clear. @@ -12746,7 +12783,7 @@ FormatAsThous() # Inputs: (local) # $1 = integer value - local a=$($SED_CMD 's/[^0-9]*//g' <<< "${1:-}") # Strip everything not a numeral. + local a=$($SED_CMD 's/[^0-9]*//g' <<< "${1:-}") # Strip non-numerals. local b='' local c='' @@ -13388,7 +13425,7 @@ ConvertSecondsToDatecode() [[ -n ${1:-} ]] || return - local a=$($SED_CMD 's/[^0-9]*//g' <<< "${1:-}") # Strip everything not a numeral. + local a=$($SED_CMD 's/[^0-9]*//g' <<< "${1:-}") # Strip non-numerals. if [[ ${#a} -ne 10 ]]; then printf 000000 @@ -13492,25 +13529,47 @@ ConvertNanosecondsToMilliseconds() } 2> /dev/null -ConvertDateCodeToExtendedDate() +ConvertDateTimeAutoExpand() { + # Convert a datecode or epoch time to an extended date format, or a full date format for epoch time. + # Inputs: (local) # $1 = datecode in the format 'YYMMDD'. Example: '240928' + # $1 = epoch time. Example: '1234567890'. Since 9th September 2001, epoch time has-been 10 numerals and will remain-so until 21st November 2286. # Outputs: (local) - # stdout = extended date format without time. Example: 'Sun 28 Sep 2024' + # stdout = formatted datetime string. [[ -n ${1:-} ]] || return - local a=$($SED_CMD 's/[^0-9]*//g' <<< "${1:-}") # Strip everything not a numeral. + local a=$($SED_CMD 's/[^0-9]*//g' <<< "$1") # Strip non-numerals. + local b='' + local c='' + + case ${#a} in + 6) # Assume input is a datecode, so convert to extended date format. + b=extended + ;; + 10) # Assume input is epoch time, so convert to full date format. + b=full + esac + + case $b in + extended) + c=$(/bin/date -d ${a::2}-${a:2:2}-${a:4:2} '+%a %d %b %Y') # (shortdayname, daynum, monthname, shortyearnum) + ;; + full) + c=$(/bin/date -d @"$a" +%c | tr -s ' ') # (shortdayname, daynum, monthname, yearnum, time, TZname) TODO: hardcode this format instead of relying on the locale default '%c'. + esac - if [[ ${#a} -ne 6 ]]; then + if [[ -n $c ]]; then + printf '%s (%s)' "$a" "$c" + else printf '%s' "$1" - return 1 fi - /bin/date -d ${a::2}-${a:2:2}-${a:4:2} '+%a %d %b %Y' + return } 2> /dev/null @@ -14406,11 +14465,14 @@ LoadObjects() ShowAsProc objects + unset r_objects_epoch + r_objects_epoch=undefined + . "$r_objects_pathfile" objects_loaded=true - readonly r_objects_version - DebugVar r_objects_version + readonly r_objects_epoch + DebugVar r_objects_epoch FuncExit @@ -14480,6 +14542,7 @@ LoadPackages() unset r_qpkg_version unset r_qpkg_will_log + unset r_packages_epoch r_packages_epoch=undefined # Second, create an index 0 element for each array. This element is used to indicate no matching QPKG when searching array. diff --git a/support/vars.source b/support/vars.source index c76ffd155..a55a58f08 100644 --- a/support/vars.source +++ b/support/vars.source @@ -3,6 +3,7 @@ build_date=$(date '+%y%m%d') build_year=$(date '+%Y') manager_epoch=0 # Only update before building `sherpa-manager.sh` file. +objects_epoch=0 # Only update before building `objects` file. packages_epoch=0 # Only update before building `packages` file. colourful=true title_description='a mini-package-manager for QNAP NAS' @@ -112,6 +113,7 @@ SwapTags() buffer=$(sed "s||$build_date|g" <<< "$buffer") buffer=$(sed "s||$build_year|g" <<< "$buffer") buffer=$(sed "s||$manager_epoch|g" <<< "$buffer") + buffer=$(sed "s||$objects_epoch|g" <<< "$buffer") buffer=$(sed "s||$packages_epoch|g" <<< "$buffer") buffer=$(sed "s||$email|g" <<< "$buffer") buffer=$(sed "s||$cdn_sherpa_base_url|g" <<< "$buffer") diff --git a/workshop/issues.txt b/workshop/issues.txt index 57525e56c..65e185760 100644 --- a/workshop/issues.txt +++ b/workshop/issues.txt @@ -1,5 +1,19 @@ Observed issues: + * Extra derp when running actions with no matching packages after reset: + ------------------------------------------------------------------- + [/share/Public] # sherpa follow unstable + done: user setting 'Git_Branch = unstable' has been saved. + done: package cache cleared. + done: reports cleared. + done: logs cleared. + [/share/Public] # sherpa upgrade new + sherpa v241002-unstable + warn: unable to find any 'upgradable' QPKGs to 'upgrade'. + done: actions complete. + derp: previous report results not found. + ------------------------------------------------------------------- + * Packages report (with 'report-footer off') has 3 linespaces between last QPKG name and abbreviations reminder text. * If IPK install stalls, seconds stalled display is not accurate.