diff --git a/objects.tar.gz b/objects.tar.gz index 739ad01c0..1d3875f91 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 6ec499539..d443912e9 100644 Binary files a/sherpa-manager.tar.gz and b/sherpa-manager.tar.gz differ diff --git a/support/sherpa-manager.source b/support/sherpa-manager.source index 1f530b006..e3f817667 100755 --- a/support/sherpa-manager.source +++ b/support/sherpa-manager.source @@ -258,7 +258,6 @@ LoadConsts() readonly r_chars_blank=' ' readonly r_chars_bullet='• ' readonly r_chars_dropend='└─ ' - readonly r_chars_ellipsis='...' readonly r_chars_normal='- ' readonly r_chars_note='* ' readonly r_chars_regular_prompt='$ ' @@ -1340,7 +1339,7 @@ QPKGsAssignToActions() QPKGs-ACuninstall-to:Remove sherpa if QPKGs-ACsign-to.IsAny || QPKGs-ACinstall-to.IsAny; then - LoadQpkgSigning + LoadQpkgSigningCertDetails fi [[ $useropt_debug = true ]] && ListQPKGsActionsAll #devdebug @@ -5363,6 +5362,7 @@ GenerateDepsReportTitleLine() # $r_report_qpkg_min_os_version_column_width # $r_report_qpkg_min_ram_column_width # $r_report_qpkg_name_column_width + # $r_report_qpkg_opt_dependencies_column_width if IsOsSupportAutowidthTableColumns; then printf 'QPKG name:|Dependencies:|Optionals:|Installed?|Enabled?|Managed?|Min. RAM:|Min. OS:|Max. OS:|Supported arch?|Installed QPKG author:' @@ -5507,6 +5507,7 @@ _GenerateDepsReportDataLine_() max_os_msg=$(GenerateReportField "$max_os" mute) else max_os_msg=$(GenerateReportField "$max_os" attention) + req_attention=true fi if IsQpkgDatabaseMinOSVerOk "$qpkg_name"; then @@ -5799,7 +5800,7 @@ _GenerateFeaturesReportDataLine_() for a in "${column_vars[@]}"; do case ${!a} in - true) + true|N/A) local ${a}_msg="$(GenerateReportField "${!a}")" ;; *) @@ -7526,8 +7527,25 @@ BuildQPKGsStates() LoadPackages InitQPKGsStates - IsOsStartingPackages && ShowAsNote "$(GetOsName) is starting all enabled QPKGs $r_chars_ellipsis check again in a few minutes" - IsOsStoppingPackages && ShowAsNote "$(GetOsName) is shutting-down and all QPKGs are stopping" + if IsOsSupportAsyncQpkgActions; then + if IsOsStarting; then + ShowAsNote "$(GetOsName) is still booting ... check again in a few minutes" + elif IsOsStartingPackages; then + ShowAsNote "$(GetOsName) is starting QPKGs ... check again in a few minutes" + fi + else # Must check older QTS (< 5.2.0) differently as it remains in boot mode while launching QPKGs. + if IsOsStartingPackages; then + ShowAsNote "$(GetOsName) is starting QPKGs ... check again in a few minutes" + elif IsOsStarting; then + ShowAsNote "$(GetOsName) is still booting ... check again in a few minutes" + fi + fi + + if IsOsStopping; then + ShowAsNote "$(GetOsName) is shutting-down" + elif IsOsStoppingPackages; then + ShowAsNote "$(GetOsName) is stopping QPKGs" + fi if IsOsLoadAverageInsane; then ShowAsWarn 'the NAS has an exceptionally-high system-load, recommend aborting and trying again later' @@ -9121,7 +9139,7 @@ GetOsFirmwareDate() GetOsName() { - if /bin/grep -q zfs /proc/filesystems; then + if IsQuTS; then printf 'QuTS hero' else printf QTS @@ -9212,8 +9230,12 @@ GetUserSudoUID() GetOsState() { - if IsOsStartingPackages; then + if IsOsStarting; then + printf 'booting' + elif IsOsStartingPackages; then printf 'starting QPKGs' + elif IsOsStopping; then + printf 'shutting-down' elif IsOsStoppingPackages; then printf 'stopping QPKGs' else @@ -9250,7 +9272,21 @@ IsOsQNAP() [[ -e /etc/init.d/functions ]] - } + } &> /dev/null + +IsQuTS() + { + + /bin/grep -q zfs /proc/filesystems + + } &> /dev/null + +IsQTS() + { + + ! IsQuTS + + } &> /dev/null IsOsSupported() { @@ -9262,7 +9298,17 @@ IsOsSupported() [[ ${r_nas_firmware_version//.} -ge 400 ]] - } + } &> /dev/null + +IsOsSupportAsyncQpkgActions() + { + + # Inputs: (global) + # $r_nas_firmware_version + + [[ ${r_nas_firmware_version//.} -ge 520 ]] + + } &> /dev/null IsOsSupportSecureDownload() { @@ -9281,7 +9327,7 @@ IsOsSupportSecureDownload() [[ ${r_nas_firmware_version//.} -ge 500 ]] - } + } &> /dev/null IsOsSupportQpkgTimeout() { @@ -9291,7 +9337,7 @@ IsOsSupportQpkgTimeout() [[ ${r_nas_firmware_version//.} -ge 430 ]] - } + } &> /dev/null IsOsSupportSignedPackages() { @@ -9303,7 +9349,7 @@ IsOsSupportSignedPackages() [[ ${r_nas_firmware_version//.} -ge 440 ]] - } + } &> /dev/null IsOsCompatibleWithSigned() { @@ -9315,7 +9361,7 @@ IsOsCompatibleWithSigned() [[ $r_nas_firmware_date -lt 20201015 || $r_nas_firmware_date -gt 20201020 ]] - } + } &> /dev/null IsOsSupportUnofficialPackages() { @@ -9327,14 +9373,14 @@ IsOsSupportUnofficialPackages() [[ ${r_nas_firmware_version//.} -gt 426 && ${r_nas_firmware_version//.} -le 436 ]] - } + } &> /dev/null IsOsSupportSudo() { [[ -e /usr/bin/sudo ]] - } + } &> /dev/null IsOsSupportSedExtRegex() { @@ -9380,20 +9426,42 @@ IsOsAllowUnofficialPackages() } -IsOsStartingPackages() +IsOsStarting() { /bin/ps | /bin/grep '/bin/sh /etc/init.d/rcS' | /bin/grep -v grep } &> /dev/null -IsOsStoppingPackages() +IsOsStopping() { /bin/ps | /bin/grep '/bin/sh /etc/init.d/rcK' | /bin/grep -v grep } &> /dev/null +IsOsStartingPackages() + { + + if IsOsSupportAsyncQpkgActions; then + /bin/ps | /bin/grep '/usr/local/sbin/qpkg_service start' | /bin/grep -v grep + else + IsOsStarting + fi + + } &> /dev/null + +IsOsStoppingPackages() + { + + if IsOsSupportAsyncQpkgActions; then + /bin/ps | /bin/grep '/usr/local/sbin/qpkg_service stop' | /bin/grep -v grep + else + IsOsStopping + fi + + } &> /dev/null + IsOsStdKernelPageSize() { @@ -12288,16 +12356,18 @@ IsQpkgInstallable() # Can this QPKG be installed? + # Inputs: (local) + # $1 (optional) = QPKG name. + # Inputs: (global) - # $qpkg_default_index - # $qpkg_index + # $qpkg_name (default) # Outputs: (local) # $? = true/false - [[ $qpkg_index -gt 0 && $qpkg_default_index -gt 0 ]] || return + local a=${1:-${qpkg_name:?${FUNCNAME[0]}'()': undefined package name}} - IsNtQpkgReallyInstalled && IsQpkgDatabaseArchOK && IsQpkgDatabaseMinOSVerOk && IsQpkgDatabaseMaxOSVerOk && IsQpkgDatabaseMinRAMOk + IsNtQpkgReallyInstalled "$a" && IsQpkgDatabaseArchOK "$a" && IsQpkgDatabaseMinOSVerOk "$a" && IsQpkgDatabaseMaxOSVerOk "$a" && IsQpkgDatabaseMinRAMOk "$a" } @@ -12859,7 +12929,7 @@ RemovePidFile() } -LoadQpkgSigning() +LoadQpkgSigningCertDetails() { # Outputs: (global) @@ -12869,34 +12939,38 @@ LoadQpkgSigning() r_qpkg_certificate='' r_qpkg_signature='' - # This certificate block is the same used by QNAP for LicenseCenter. + # This certificate block is the same used by QNAP for Download Station 5.9.0.272 + # Expires 11th October 2027. + read -r -d '' r_qpkg_certificate << EOB -----BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIFALhDVuwwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYT -AlRXMQ8wDQYDVQQIDAZUYWl3YW4xDzANBgNVBAcMBlRhaXBlaTENMAsGA1UECgwE -UU5BUDEMMAoGA1UECwwDTkFTMRAwDgYDVQQDDAdRTkFQX0NBMSAwHgYJKoZIhvcN -AQkBFhFzZWN1cml0eUBxbmFwLmNvbTAeFw0yMjAzMTgwNzM5MTRaFw0yNTAzMTcw -NzM5MTRaMIGGMQswCQYDVQQGEwJUVzEPMA0GA1UECAwGVGFpd2FuMQ8wDQYDVQQH -DAZUYWlwZWkxDTALBgNVBAoMBFFOQVAxDDAKBgNVBAsMA05BUzEWMBQGA1UEAwwN -TGljZW5zZUNlbnRlcjEgMB4GCSqGSIb3DQEJARYRc2VjdXJpdHlAcW5hcC5jb20w -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/bAgbZryVvBXfpBHNUKQV -sAkAfvDXjKnxa7lKHrRIcFcOnf+voUZcP1Ly9qWb782gB2eUHsUS1Xqj4CF/dUJf -FEnOBrQUo9+Q9B3x4oTRpMdky7acP4dxAbt4T92swgaReQXAewy9s9//a52HIBca -1dAA4JPwplqiZ/oh18GDCKxh84Iu9Gcu2J5e+VXEI/KUxCwKUd22aDTpv128MSoq -dYexCerCJtQbgM3cwkkMiDnFpjrsta5iFpyrNKdLoBJ7YbY3d5Onkqy4DjE8hwR7 -0j7Qd+3xbMqv3FOCKeLLLn6N03IXHKP/big/MdXKY1dJQVA3/ks/knPH8mhcOM0d -AgMBAAGjPDA6MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6Ly9kb3dubG9hZC5xbmFw -LmNvbS9jcmwvcXRzX3YxLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAWlT1GDH6v8G3 -laIAs2/RdxhPgtKX4aL+fnTEFNF5V2yH0G4luyq5tHQw+VCHtDM6Z3GXWhciKPAR -upbRcHq744JCFaUb6i8z1w1KVJDaQ38EVE5+JtpoPMrrnb+hKB/gGmi4PoMSpnvX -VCxLbCbBnwi19o6t/MnPbz0shvUB2NDngnal6lYQFw/F8Sr6cSjV6GAY4TOZotdu -+gunwqQtYUycEVfNyiWVk/flgED8R8oxTPl9ZoDGen+OgjkZrvgynKnqPLHyxZSd -hYSoWyWcZWkMCQ+69kOgJVvrRa7z9F9y30uAHXIUrsLV2d/dImVjApMHbZ60iALG -AVIlas0e4g== +MIIDxDCCAqygAwIBAgIEFQDq5zANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMC +VFcxDzANBgNVBAgMBlRhaXdhbjEPMA0GA1UEBwwGVGFpcGVpMQ0wCwYDVQQKDARR +TkFQMQwwCgYDVQQLDANOQVMxEDAOBgNVBAMMB1FOQVBfQ0ExIDAeBgkqhkiG9w0B +CQEWEXNlY3VyaXR5QHFuYXAuY29tMB4XDTI0MTAxMTA0MTgzOFoXDTI3MTAxMTA0 +MTgzOFowgYgxCzAJBgNVBAYTAlRXMQ8wDQYDVQQIDAZUYWl3YW4xDzANBgNVBAcM +BlRhaXBlaTENMAsGA1UECgwEUU5BUDEMMAoGA1UECwwDTkFTMRgwFgYDVQQDDA9E +b3dubG9hZFN0YXRpb24xIDAeBgkqhkiG9w0BCQEWEXNlY3VyaXR5QHFuYXAuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/Qkj1D64xGrzhK5bAI18 +CBCCd8fC4xYKbjn6wtUEFprZqhazDAlL+FOH/VdwolqnXnhleJY6/GujMTqc0cjr +cZNNZi+vYH4HKQEZP9jCRrIe1xEqDPSnyn7/cT6VpWoFxFy6Bi44Rp8Y92SUDXac +rpGFzwhxxKJ8y+7XxcCfkNdbP6cgZBDcToxKPL41ffhja58oNmWiy9+d7N7dGQiE +tm5vWlRDLwz91vjYRqTgdUZh+41esh+KQP+NwXXufc4wcgYBpqJ9/qisuSrjG2hm +h1GlX3rFDw6UIwAKwJIzFB5fqZ1ry4D21BenNzdyX/a76a9oePqZsaCVPlct7emg +lwIDAQABozwwOjA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vZG93bmxvYWQucW5h +cC5jb20vY3JsL3F0c192MS5jcmwwDQYJKoZIhvcNAQELBQADggEBADplp152NaL+ +Ov1rBztUSPt6EecPvTC4EMg1+uziqPz54LUuufvVjDHp+rEhKR9mBLPoPHYK2Pc5 +85iJ5fRcCSr+PNwH2ksfHUqbY0K2p2gFMTpsGYrXPVxmcS/t1l9IA0jFlCHkMHR6 +oKdbLHzxGrKFNXxhagbobdw65OUvwP5lJDnk4aInfkWqXPV5Mh/+ZchPaCaD5IE4 +GZFqR1gAlktHAhvwBJhurozMbd92mQt6AVHDWt1ump/qiUgkdz2VJrdCWRd51nJJ +Ij1A6hFRu9wdulkzQlp43rmD30Eloq7mJFlgXX3mSfAa6DyWuYych75cnSbNn5VP +/txPu6xSOp4= -----END CERTIFICATE----- EOB - # This digital signature block is the same used by QNAP for LicenseCenter. + # This digital signature block is the same used by QNAP for Download Station 5.9.0.272 + # Expires 11th October 2027. + read -r -d '' r_qpkg_signature << EOB MIME-Version: 1.0 Content-Disposition: attachment; filename=\"smime.p7m\" @@ -12904,41 +12978,41 @@ Content-Type: application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\" Content-Transfer-Encoding: base64 MIIGtAYJKoZIhvcNAQcCoIIGpTCCBqECAQExDTALBglghkgBZQMEAgEwIwYJKoZI -hvcNAQcBoBYEFAkoseBaFir08zCz63r2YA82DXzxoIIDxzCCA8MwggKroAMCAQIC -BQC4Q1bsMA0GCSqGSIb3DQEBCwUAMIGAMQswCQYDVQQGEwJUVzEPMA0GA1UECAwG -VGFpd2FuMQ8wDQYDVQQHDAZUYWlwZWkxDTALBgNVBAoMBFFOQVAxDDAKBgNVBAsM -A05BUzEQMA4GA1UEAwwHUU5BUF9DQTEgMB4GCSqGSIb3DQEJARYRc2VjdXJpdHlA -cW5hcC5jb20wHhcNMjIwMzE4MDczOTE0WhcNMjUwMzE3MDczOTE0WjCBhjELMAkG -A1UEBhMCVFcxDzANBgNVBAgMBlRhaXdhbjEPMA0GA1UEBwwGVGFpcGVpMQ0wCwYD -VQQKDARRTkFQMQwwCgYDVQQLDANOQVMxFjAUBgNVBAMMDUxpY2Vuc2VDZW50ZXIx -IDAeBgkqhkiG9w0BCQEWEXNlY3VyaXR5QHFuYXAuY29tMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEAv2wIG2a8lbwV36QRzVCkFbAJAH7w14yp8Wu5Sh60 -SHBXDp3/r6FGXD9S8valm+/NoAdnlB7FEtV6o+Ahf3VCXxRJzga0FKPfkPQd8eKE -0aTHZMu2nD+HcQG7eE/drMIGkXkFwHsMvbPf/2udhyAXGtXQAOCT8KZaomf6IdfB -gwisYfOCLvRnLtieXvlVxCPylMQsClHdtmg06b9dvDEqKnWHsQnqwibUG4DN3MJJ -DIg5xaY67LWuYhacqzSnS6ASe2G2N3eTp5KsuA4xPIcEe9I+0Hft8WzKr9xTgini -yy5+jdNyFxyj/24oPzHVymNXSUFQN/5LP5Jzx/JoXDjNHQIDAQABozwwOjA4BgNV -HR8EMTAvMC2gK6AphidodHRwOi8vZG93bmxvYWQucW5hcC5jb20vY3JsL3F0c192 -MS5jcmwwDQYJKoZIhvcNAQELBQADggEBAFpU9Rgx+r/Bt5WiALNv0XcYT4LSl+Gi -/n50xBTReVdsh9BuJbsqubR0MPlQh7QzOmdxl1oXIijwEbqW0XB6u+OCQhWlG+ov -M9cNSlSQ2kN/BFROfibaaDzK652/oSgf4BpouD6DEqZ711QsS2wmwZ8ItfaOrfzJ -z289LIb1AdjQ54J2pepWEBcPxfEq+nEo1ehgGOEzmaLXbvoLp8KkLWFMnBFXzcol -lZP35YBA/EfKMUz5fWaAxnp/joI5Ga74Mpyp6jyx8sWUnYWEqFslnGVpDAkPuvZD -oCVb60Wu8/Rfct9LgB1yFK7C1dnf3SJlYwKTB22etIgCxgFSJWrNHuIxggKbMIIC -lwIBATCBijCBgDELMAkGA1UEBhMCVFcxDzANBgNVBAgMBlRhaXdhbjEPMA0GA1UE -BwwGVGFpcGVpMQ0wCwYDVQQKDARRTkFQMQwwCgYDVQQLDANOQVMxEDAOBgNVBAMM -B1FOQVBfQ0ExIDAeBgkqhkiG9w0BCQEWEXNlY3VyaXR5QHFuYXAuY29tAgUAuENW -7DALBglghkgBZQMEAgGggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq -hkiG9w0BCQUxDxcNMjIxMjAyMDMwOTE3WjAvBgkqhkiG9w0BCQQxIgQgvtdZSm+m -c7QevdJma9Em5ycFr3I7Wo4aG40Vcx/mT5IweQYJKoZIhvcNAQkPMWwwajALBglg +hvcNAQcBoBYEFAQ/j77EF9kxli2d24Kj8bRyX+1GoIIDyDCCA8QwggKsoAMCAQIC +BBUA6ucwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlRXMQ8wDQYDVQQIDAZU +YWl3YW4xDzANBgNVBAcMBlRhaXBlaTENMAsGA1UECgwEUU5BUDEMMAoGA1UECwwD +TkFTMRAwDgYDVQQDDAdRTkFQX0NBMSAwHgYJKoZIhvcNAQkBFhFzZWN1cml0eUBx +bmFwLmNvbTAeFw0yNDEwMTEwNDE4MzhaFw0yNzEwMTEwNDE4MzhaMIGIMQswCQYD +VQQGEwJUVzEPMA0GA1UECAwGVGFpd2FuMQ8wDQYDVQQHDAZUYWlwZWkxDTALBgNV +BAoMBFFOQVAxDDAKBgNVBAsMA05BUzEYMBYGA1UEAwwPRG93bmxvYWRTdGF0aW9u +MSAwHgYJKoZIhvcNAQkBFhFzZWN1cml0eUBxbmFwLmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAP0JI9Q+uMRq84SuWwCNfAgQgnfHwuMWCm45+sLV +BBaa2aoWswwJS/hTh/1XcKJap154ZXiWOvxrozE6nNHI63GTTWYvr2B+BykBGT/Y +wkayHtcRKgz0p8p+/3E+laVqBcRcugYuOEafGPdklA12nK6Rhc8IccSifMvu18XA +n5DXWz+nIGQQ3E6MSjy+NX34Y2ufKDZlosvfneze3RkIhLZub1pUQy8M/db42Eak +4HVGYfuNXrIfikD/jcF17n3OMHIGAaaiff6orLkq4xtoZodRpV96xQ8OlCMACsCS +MxQeX6mda8uA9tQXpzc3cl/2u+mvaHj6mbGglT5XLe3poJcCAwEAAaM8MDowOAYD +VR0fBDEwLzAtoCugKYYnaHR0cDovL2Rvd25sb2FkLnFuYXAuY29tL2NybC9xdHNf +djEuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA6ZadedjWi/jr9awc7VEj7ehHnD70w +uBDINfrs4qj8+eC1Lrn71Ywx6fqxISkfZgSz6Dx2Ctj3OfOYieX0XAkq/jzcB9pL +Hx1Km2NCtqdoBTE6bBmK1z1cZnEv7dZfSANIxZQh5DB0eqCnWyx88RqyhTV8YWoG +6G3cOuTlL8D+ZSQ55OGiJ35Fqlz1eTIf/mXIT2gmg+SBOBmRakdYAJZLRwIb8ASY +bq6MzG3fdpkLegFRw1rdbpqf6olIJHc9lSa3QlkXedZySSI9QOoRUbvcHbpZM0Ja +eN65g99BJaKu5iRZYF195knwGug8lrmMnIe+XJ0mzZ+VT/7cT7usUjqeMYICmjCC +ApYCAQEwgYkwgYAxCzAJBgNVBAYTAlRXMQ8wDQYDVQQIDAZUYWl3YW4xDzANBgNV +BAcMBlRhaXBlaTENMAsGA1UECgwEUU5BUDEMMAoGA1UECwwDTkFTMRAwDgYDVQQD +DAdRTkFQX0NBMSAwHgYJKoZIhvcNAQkBFhFzZWN1cml0eUBxbmFwLmNvbQIEFQDq +5zALBglghkgBZQMEAgGggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq +hkiG9w0BCQUxDxcNMjQxMDE2MDgxNzQ0WjAvBgkqhkiG9w0BCQQxIgQggJireFTx +DlvBWly/Q5HA1BSoAikTAPk0XVMmIIZ93yQweQYJKoZIhvcNAQkPMWwwajALBglg hkgBZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAO BggqhkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcN -AwICASgwDQYJKoZIhvcNAQEBBQAEggEAuInAOUj+ebOkTqlqg3cf7v2FdKeCvZZn -cunx1xRnHJRVAAvcH/UZ3t7RF6MV5NmEQdVN79NBZl0KU1x7K3zyvcXnkacNuHnI -t+6neKKKkxJmB4hh4ljeYtx9a1RBgwH+PiYyH8+58S7+MF3MVhSH8jEiomgSbvsK -BroOCFQDoYWk14K/VIXW1scmvpNvFNBWwm19pYwi977rF+lPWzMHx/0jVXspFSEd -U48h9xKvPg6CsIlyfuKetHBjZZI6iSCvh2FZOWsD1/W2oGYkkY9Hdff24B34/res -cKXk/K9/JFAONWBbXUpxtzpBCeVJlZS1wQgu4Q+Fr6imaBXJkiyiNg== +AwICASgwDQYJKoZIhvcNAQEBBQAEggEA+rY8b+0bWHR5IENsfxZHEr1ya5ue4fGM +imlmR0BjABr3KP9gTGYbLR+dDQNkCtw9Fy1TLOCSuxxm1gdlBLOC8+uDE86jTh5D +RNyMsL/cNAdtGxmTVS2JsCE4zaI2IvlNsnJ4zZOnO1Hl4jBbJAlt7y0dQvbDbc/+ +Cy54p/JW3IS9NqJ2QYTQdeLptRSXDHglLNjyQV5xK+qq/4DrJ+ALoesmfS/2aHar +1hBRm/B3nWXlh61rd4mMcSEU+rfOHaisa9OW97steR9TOb/xoyWI06qvSrBxoAxo +x+auuROm7C3dgpY7klCWav/j95cGdSacac30zlEhndA/UeOj9JImQw== EOB readonly r_qpkg_certificate @@ -14249,7 +14323,6 @@ ShowAsProc() # $2 = trailing task (after the ellipsis) (optional). If specified, $useropt_terse will be ignored. # Inputs: (global) - # $r_chars_ellipsis # $r_inhibit_display_pathfile # $useropt_terse # $useropt_verbose @@ -14259,7 +14332,7 @@ ShowAsProc() local a=$1 local b='' [[ -n ${2:-} ]] && b=$2 - local c="$a $r_chars_ellipsis $b" + local c="$a ... $b" if [[ -n ${r_inhibit_display_pathfile:-} && ! -e $r_inhibit_display_pathfile ]]; then if [[ ${useropt_verbose:=false} = false && ${useropt_terse:=true} = true ]] || [[ ${useropt_verbose:=false} = false && -n ${2:-} ]]; then diff --git a/workshop/dep-manipulator.sh b/workshop/dep-manipulator.sh deleted file mode 100755 index 6dcb3cc4c..000000000 --- a/workshop/dep-manipulator.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash - -GetQPKGPostInstallDeps() - { - - # Inputs: (local) - # $1 = target QPKG name - - # Outputs: (local) - # stdout = target QPKG dependency list, colon-separated. - - # Layout: - # 'Dependency = packageA:packageB:packageC' - - [[ -n ${1:-} ]] || return - - /sbin/getcfg "$1" Dependency -f /etc/config/qpkg.conf - - } - -AddToQPKGPostInstallDeps() - { - - # Inputs: (local) - # $1 = target QPKG name. - # $2 = QPKG to add as a post-install dependency. - - # Layout: - # 'Dependency = packageA:packageB:packageC' - - [[ -n ${1:-} && -n ${2:-} ]] || return - - local a='' - - a=$(GetQPKGPostInstallDeps "$1") - - # First, check if entry already exists. - /bin/grep -qw "$2" <<< "$a" && return - - # Then, append entry to existing 'Dependency' string. - /sbin/setcfg "$1" Dependency "$a:$2" -f /etc/config/qpkg.conf - - } - -RemoveFromQPKGPostInstallDeps() - { - - # Inputs: (local) - # $1 = target QPKG name. - # $2 = QPKG to remove as a post-install dependency. - - # Layout: - # 'Dependency = packageA:packageB:packageC' - - [[ -n ${1:-} && -n ${2:-} ]] || return - - local a='' - local re='' - - re=\\b${2}\\b - a=$(/bin/sed "s|${re}||" <<< "$(/sbin/getcfg "$1" Dependency -f /etc/config/qpkg.conf)") - a=$(/bin/tr -s ':' <<< "$a") - - if [[ -n $a ]]; then - /sbin/setcfg "$1" Dependency "$a" -f /etc/config/qpkg.conf - else - /sbin/setcfg -e "$1" Dependency -f /etc/config/qpkg.conf - fi - - } - -RemoveFromQPKGPostInstallDeps OTransmission test1 - diff --git a/workshop/ideas.txt b/workshop/ideas.txt index d88b6bc47..b1a75f809 100644 --- a/workshop/ideas.txt +++ b/workshop/ideas.txt @@ -1,14 +1,10 @@ * Include option to display alternating line highlighting on reports? - $alternating_report_lines -* Add new QPKG field: r_qpkg_is_plugin+=(true) - - If true, then this QPKG is a plugin. This QPKG is optional and manually installed, is started before dependent QPKGs, and stopped after dependent QPKGs. - - Also add this QPKG as post-install dependency of listed QPKGs. Needed to ensure correct startup sequence in QTS 5.2.0+ - * Include QPKG signing method via default QTS Python and modules. - - Won't require an sqlite binary. + - Won't require an 'sqlite3' binary. -* Display warning when sherpa QPKG is not signed, and QTS App Center requires signed packages only. +* Display a warning when sherpa QPKG is not signed, and QTS App Center requires signed packages only. * Put 'sherpa about' display into a report window. @@ -17,6 +13,7 @@ * Takes 3.5 to 6 seconds to build QPKG states on Laura. - Should be able to do this quicker. - Calculate QPKG features separate to states and cache/load these from file next time? + - It's checking for upgradable QPKGs that takes most of the time. * Disable same-line display updates when not in a user terminal. - No-need to record every progress message change in logs. @@ -26,7 +23,7 @@ * Default dependency report should only show installed QPKGs. - ... but should allow 'sherpa d all' to see all QPKGs. - - Do the same for repository report. + - Same for repository and repo reports. - Add new $QPKG_ACTIONS element: 'report' * When running 'sherpa rebuild sab', SAB is installed and auto-updates as usual. Then when 'restore' action runs, auto-update runs again. diff --git a/workshop/issues.txt b/workshop/issues.txt index b51efd1aa..7051abea2 100644 --- a/workshop/issues.txt +++ b/workshop/issues.txt @@ -19,8 +19,6 @@ Observed issues: - active git branch: 'master' -------------------------------------------------------------------------------------------------- - * Will need a new method to detect if QTS 5.2.0 is starting/stopping QPKGs due to async starts/stops. - * Near the end of installing IPKs, monitored download path can remain at non-zero size while packages complete installation. - Include a separate progress message when dir size stops increasing and shrinks instead? - Maybe force increase to "100%" and stop monitoring? diff --git a/workshop/progress-display.sh b/workshop/progress-display.sh deleted file mode 100755 index 35b969dc0..000000000 --- a/workshop/progress-display.sh +++ /dev/null @@ -1,510 +0,0 @@ -#!/usr/bin/env bash - -# Fault-finding the single-line updating display. 2023-01-23 - -# When running on helga and sarah, QPKG progress shows large on-screen whitespaces between the displayed counts. -# Might be related to 'sed' handling of extended regexes when striping ANSI codes. - -readonly SCRIPT_STARTSECONDS=$(/bin/date +%s) -# GNU_SED_CMD=/usr/bin/sed -GNU_SED_CMD=/opt/bin/sed -# GNU_SED_CMD=/bin/sed -[[ -e $GNU_SED_CMD ]] && colourful=true || colourful=false - -LaunchQPKGActionForks() - { - - # Execute actions concurrently, but only as many as $max_forks will allow given the circumstances - - - # inputs: (local) - # $1 = the target function action to be applied to each QPKG in $target_packages() - # $2 = an array of QPKG names to process with $1 - - # inputs: (global) - # $fork_count = number of currently running forks - # $max_forks = maximum number of permitted concurrent forks given the current environment - - ShowAsProc "fake package action" - - UpdateForkProgress - - # all action forks have launched, just need to wait for them to exit - - while [[ $fork_count -gt 0 ]]; do - UpdateForkProgress # update display while running forks complete - sleep 1 - done - - # all forks have exited - - EraseThisLine - - } - -ShowAsProc() - { - - local suffix='' - [[ -n ${2:-} ]] && suffix=": $2" - - EraseThisLine - WriteToDisplayWait "$(ColourTextBrightOrange proc)" "${1:-}${suffix}" - - } - -UpdateInPlace() - { - - # input: - # $1 = message to display - - local -i this_length=0 - local -i blanking_length=0 - local this_squeezed_msg=$(tr -s ' ' <<< "${1:-}") - local this_clean_msg=$(StripANSI "$this_squeezed_msg") - - if [[ $this_clean_msg != "$previous_clean_msg" ]]; then - this_length=$((${#this_clean_msg})) - - if [[ $this_length -lt $previous_length ]]; then - blanking_length=$((this_length-previous_length)) - # backspace to start of previous msg, print new msg, add additional spaces, then backspace to end of new msg - printf "%${previous_length}s" | tr ' ' '\b'; echo -en "$this_squeezed_msg"; printf "%${blanking_length}s"; printf "%${blanking_length}s" | tr ' ' '\b' - else - # backspace to start of previous msg, print new msg - printf "%${previous_length}s" | tr ' ' '\b'; echo -en "$this_squeezed_msg" - fi - - previous_length=$this_length - previous_clean_msg=$this_clean_msg - fi - - } - -EraseThisLine() - { - - # reset cursor to start-of-line, erasing entire line - - echo -en "\033[2K\r" - - } - -Display() - { - - echo -e "${1:-}" - - } - -DisplayWait() - { - - echo -en "${1:-}" - - } - -InitForkCounts() - { - - # create directories so background processes can be monitored - - InitProgress - - } - -IncForkProgressIndex() - { - - ((progress_index++)) - local formatted_index="$(printf '%02d' "$progress_index")" - - } - -RefreshForkCounts() - { - - fork_count="$(($(/bin/date +%s)-SCRIPT_STARTSECONDS+1))" - ok_count="$(($(/bin/date +%s)-SCRIPT_STARTSECONDS+6))" - skip_count="$(($(/bin/date +%s)-SCRIPT_STARTSECONDS+11))" - fail_count="$(($(/bin/date +%s)-SCRIPT_STARTSECONDS+18))" - - total_count=$((ok_count+skip_count+fail_count+100)) - - } - -InitProgress() - { - - progress_index=0 - previous_length=0 - previous_clean_msg='' - - RefreshForkCounts - - } - -UpdateForkProgress() - { - - # all input vars are global - - local progress_message=': ' - - RefreshForkCounts - - progress_message+="$(PercFrac "$ok_count" "$skip_count" "$fail_count" "$total_count")" - - if [[ $fork_count -gt 0 ]]; then - [[ -n $progress_message ]] && progress_message+=': ' - progress_message+="$(ColourTextBrightOrange "$fork_count") in-progress" - fi - - if [[ $ok_count -gt 0 ]]; then - [[ -n $progress_message ]] && progress_message+=': ' - progress_message+="$(ColourTextBrightGreen "$ok_count") OK" - fi - - if [[ $skip_count -gt 0 ]]; then - [[ -n $progress_message ]] && progress_message+=': ' - progress_message+="$(ColourTextBrightOrange "$skip_count") skipped" - fi - - if [[ $fail_count -gt 0 ]]; then - [[ -n $progress_message ]] && progress_message+=': ' - progress_message+="$(ColourTextBrightRed "$fail_count") failed" - fi - - [[ -n $progress_message ]] && UpdateInPlace "$progress_message " - - return 0 - - } - -ShowAsProcLong() - { - - ShowAsProc "${1:-} (might take a while)" "${2:-}" - - } 2>/dev/null - -ShowAsProc() - { - - local suffix='' - [[ -n ${2:-} ]] && suffix=": $2" - - EraseThisLine - WriteToDisplayWait "$(ColourTextBrightOrange proc)" "${1:-}${suffix}" - WriteToLog proc "${1:-}${suffix}" - - } 2>/dev/null - -ShowAsDone() - { - - # process completed OK - - EraseThisLine - WriteToDisplayNew "$(ColourTextBrightGreen 'done')" "${1:-}" - WriteToLog 'done' "$1" - - } - -ShowAsWarn() - { - - # warning only - - EraseThisLine - WriteToDisplayNew "$(ColourTextBrightOrange warn)" "${1:-}" - WriteToLog warn "$1" - - } 2>/dev/null - -PercFrac() - { - - # calculate percent-complete and a fraction of the total - - # $1 = ok count - # $2 = skip count - # $3 = fail count - # $4 = total count - - declare -i -r OK_COUNT=${1:-0} - declare -i -r SKIP_COUNT=${2:-0} - declare -i -r FAIL_COUNT=${3:-0} - declare -i -r TOTAL_COUNT=${4:-0} - local -i progress_count="$((OK_COUNT+SKIP_COUNT+FAIL_COUNT))" - local percent='' - - [[ $TOTAL_COUNT -gt 0 ]] || return # no-point calculating a fraction of zero - - if [[ $progress_count -gt $TOTAL_COUNT ]]; then - progress_count=$TOTAL_COUNT - percent='100%' - else - percent="$((200*(progress_count+1)/(TOTAL_COUNT+1)%2+100*(progress_count+1)/(TOTAL_COUNT+1)))%" - fi - - echo "$percent ($(ColourTextBrightWhite "$progress_count")/$(ColourTextBrightWhite "$TOTAL_COUNT"))" - - return 0 - - } 2>/dev/null - -ShowAsActionResult() - { - - # $1 = tier (optional) e.g. `Standalone`, `Dependent`, `Addon`, `All` - # $2 = package type: `QPKG`, `IPK`, `PIP`, etc ... - # $3 = ok count - # $4 = skip count - # $5 = fail count - # $6 = total count - # $7 = verb (past) - - if [[ -n $1 && $1 != All ]]; then - local -r TIER=" $(Lowercase "$1")" - else - local -r TIER='' - fi - - local -r PACKAGE_TYPE=${2:?null} - declare -i -r OK_COUNT=${3:-0} - declare -i -r SKIP_COUNT=${4:-0} - declare -i -r FAIL_COUNT=${5:-0} - declare -i -r TOTAL_COUNT=${6:-0} - local result_message="${7:?null} " - - if [[ $OK_COUNT -gt 0 ]]; then - result_message+="${OK_COUNT}${TIER} ${PACKAGE_TYPE}$(Pluralise "$OK_COUNT") OK" - fi - - if [[ $SKIP_COUNT -gt 0 ]]; then - [[ $OK_COUNT -gt 0 ]] && result_message+=', ' - result_message+="${SKIP_COUNT}${TIER} ${PACKAGE_TYPE}$(Pluralise "$SKIP_COUNT") skipped" - fi - - if [[ $FAIL_COUNT -gt 0 ]]; then - [[ $OK_COUNT -gt 0 || $SKIP_COUNT -gt 0 ]] && result_message+=' and ' - result_message+="${FAIL_COUNT}${TIER} ${PACKAGE_TYPE}$(Pluralise "$FAIL_COUNT") failed" - fi - - case $TOTAL_COUNT in - 0) - DebugAsDone "no${TIER} ${PACKAGE_TYPE}s processed" - ;; - "$FAIL_COUNT") - ShowAsWarn "$result_message" - ;; - *) - ShowAsDone "$result_message" - esac - - return 0 - - } - -WriteToDisplayWait() - { - - # Writes a new message without newline - - # input: - # $1 = pass/fail - # $2 = message - - # output: - # $previous_msg = global and will be used again later - - if [[ $colourful = true ]]; then - previous_msg=$(printf '%-10s: %s' "${1:-}" "${2:-}") # allow extra length for ANSI codes - else - previous_msg=$(printf '%-4s: %s' "${1:-}" "${2:-}") - fi - - DisplayWait "$previous_msg" - - return 0 - - } - -WriteToDisplayNew() - { - - # Updates the previous message - - # input: - # $1 = pass/fail - # $2 = message - - # output: - # stdout = overwrites previous message with updated message - # $previous_length - - local this_message='' - local strbuffer='' - local -i this_length=0 - local -i blanking_length=0 - - if [[ $colourful = true ]]; then - this_message=$(printf '%-10s: %s' "${1:-}" "${2:-}") # allow extra length for ANSI codes - else - this_message=$(printf '%-4s: %s' "${1:-}" "${2:-}") - fi - - if [[ $this_message != "${previous_msg:=''}" ]]; then - previous_length=$((${#previous_msg}+1)) - this_length=$((${#this_message}+1)) - - # jump to start of line, print new msg - strbuffer=$(echo -en "\r$this_message ") - - # if new msg is shorter then add spaces to end to cover previous msg - if [[ $this_length -lt $previous_length ]]; then - blanking_length=$((this_length-previous_length)) - strbuffer+=$(printf "%${blanking_length}s") - fi - - Display "$strbuffer" - fi - - return 0 - - } - -WriteToLog() - { - - # input: - # $1 = pass/fail - # $2 = message - - [[ -n ${sess_active_pathfile:-} ]] && printf '%-4s: %s\n' "$(StripANSI "${1:-}")" "$(StripANSI "${2:-}")" >> "$sess_active_pathfile" - - } - -ColourTextBrightGreen() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;32m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightYellow() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;33m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightOrange() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;38;5;214m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightOrangeBlink() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;5;38;5;214m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightRed() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;31m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightRedBlink() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;5;31m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextUnderlinedCyan() - { - - if [[ $colourful = true ]]; then - echo -en '\033[4;36m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBlackOnCyan() - { - - if [[ $colourful = true ]]; then - echo -en '\033[30;46m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourTextBrightWhite() - { - - if [[ $colourful = true ]]; then - echo -en '\033[1;97m'"$(ColourReset "${1:-}")" - else - echo -n "${1:-}" - fi - - } 2>/dev/null - -ColourReset() - { - - echo -en "${1:-}"'\033[0m' - - } 2>/dev/null - -StripANSI() - { - - # QTS 4.2.6 BusyBox `sed` doesn't fully support extended regexes, so code stripping only works with a real `sed` - - if [[ -e $GNU_SED_CMD && -e $GNU_SED_CMD ]]; then # KLUDGE: yes, it looks weird, but during Entware startup, weird things happen. Need to check for this file multiple times to ensure it's there before attempting to run it. - $GNU_SED_CMD -r 's/\x1B\[[0-9;]*m//g' <<< "${1:-}" - else - echo "${1:-}" # can't strip, so pass thru original message unaltered - fi - - } 2>/dev/null - -LaunchQPKGActionForks - diff --git a/workshop/table.sh b/workshop/table.sh deleted file mode 100755 index 43f113265..000000000 --- a/workshop/table.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -readonly REPORT_OUTPUT_PATHFILE=report.ansi - -Tabilise() - { - - # Generate an ANSI-aware table with auto-width columns. - - # With many thanks to Stephane Chazelas for writing this: - # https://unix.stackexchange.com/a/121139/259233 - - awk '{ - nf[NR]=NF - for (i = 1; i <= NF; i++) { - cell[NR,i] = $i - gsub(/\033\[[0-9;]*[mK]/, "", $i) - len[NR,i] = l = length($i) - if (l > max[i]) max[i] = l - } - } - END { - for (row = 1; row <= NR; row++) { - for (col = 1; col < nf[row]; col++) - printf "%s%*s%s", cell[row,col], max[col]-len[row,col], "", OFS - print cell[row,nf[row]] - } - - }' FS='|' OFS=' ' - - } - -Tabilise < "$REPORT_OUTPUT_PATHFILE" diff --git a/workshop/test-bg-tracking.sh b/workshop/test-bg-tracking.sh deleted file mode 100755 index b6da266ea..000000000 --- a/workshop/test-bg-tracking.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -# get background procs to cleanup their own pid files. - -runme() - { - - # Input: - # $pidfile (global) = the pidfile for this process, containing the PID. - - trap '[[ -e $pidfile ]] && rm "$pidfile"; exit' SIGINT - -# [[ -e $pidfile ]] && echo "pidfile contains: '$(<$pidfile)'" - echo "pidfile: [$pidfile], start sleep" - cmd='sleep 15' - - eval "$cmd" - - echo "pidfile: [$pidfile], end sleep" - - [[ -e $pidfile ]] && rm "$pidfile" - - } - -basepath=~/workspace/proc -mkdir -p "$basepath" -echo "root PID: [$$]" - -for ((i=1; i<=10; i++)); do - pidfile=$(mktemp "$basepath"/bgproc_XXXXXX) # Set $pidfile here, before launching background process so it's inherited by child. - - runme & - echo "$!" > "$pidfile" - sleep 1 -done - -echo 'waiting for background procs to exit...' -wait 2>/dev/null - -echo 'done waiting for background procs, now waiting to exit script...' -sleep 5 - -echo "and exit" - diff --git a/workshop/test-loop-var-assignment.sh b/workshop/test-loop-var-assignment.sh deleted file mode 100755 index ac6013837..000000000 --- a/workshop/test-loop-var-assignment.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -init() - { - -active_test=false -local active_test_msg='active first' - -autoupdate=false -autoupdate_msg='auto second' - -backup=false -backup_msg='back third' - -clean=false -clean_msg='clen fourth' - -echo "before:" -echo -e "\t$active_test_msg" -echo -e "\t$autoupdate_msg" -echo -e "\t$backup_msg" -echo -e "\t$clean_msg" - -a='' -b='' - -for a in active_test autoupdate backup clean; do -# if [[ ${!a} = true ]]; then - : # "$a"_msg=$(TextBrightGreen "${!a}_msg") -# else - b=${a}_msg - local ${a}_msg="${!b} addendum" -# fi -done - -echo "after:" -echo -e "\t$active_test_msg" -echo -e "\t$autoupdate_msg" -echo -e "\t$backup_msg" -echo -e "\t$clean_msg" - - } - -init