diff --git a/.github/workflows/code-linting.yml b/.github/workflows/code-linting.yml index f0ff7fed..2a27263f 100644 --- a/.github/workflows/code-linting.yml +++ b/.github/workflows/code-linting.yml @@ -33,6 +33,9 @@ jobs: name: "Codacy" if: "${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' && github.repository_owner == 'micro5k' }}" runs-on: ubuntu-latest + concurrency: + group: "${{ github.repository_id }}-${{ github.workflow }}-codacy" + cancel-in-progress: true permissions: security-events: write diff --git a/README.rst b/README.rst index 6a1f8f7e..8810e5c0 100644 --- a/README.rst +++ b/README.rst @@ -37,6 +37,10 @@ Release :alt: Downloads of the latest OSS release :target: `Release`_ +.. image:: https://img.shields.io/github/downloads/micro5k/microg-unofficial-installer/nightly/total.svg?cacheSeconds=3600 + :alt: Downloads of the latest OSS nightly + :target: `Release`_ + .. image:: https://img.shields.io/github/downloads/micro5k/microg-unofficial-installer/total.svg?cacheSeconds=3600 :alt: Total OSS downloads :target: `Release`_ diff --git a/build.sh b/build.sh index f6ea21af..2766b46e 100755 --- a/build.sh +++ b/build.sh @@ -160,7 +160,13 @@ rm -rf "${TEMP_DIR:?}"/* || ui_error 'Failed to empty our temp dir' MODULE_ID="$(simple_get_prop 'id' "${MAIN_DIR:?}/zip-content/module.prop")" || ui_error 'Failed to parse the module id string' MODULE_VER="$(simple_get_prop 'version' "${MAIN_DIR:?}/zip-content/module.prop")" || ui_error 'Failed to parse the module version string' MODULE_AUTHOR="$(simple_get_prop 'author' "${MAIN_DIR:?}/zip-content/module.prop")" || ui_error 'Failed to parse the module author string' -FILENAME="${MODULE_ID:?}-${MODULE_VER:?}${ZIP_SHORT_COMMIT_ID:+-}${ZIP_SHORT_COMMIT_ID-}-${BUILD_TYPE:?}-by-${MODULE_AUTHOR:?}" + +FILENAME_START="${MODULE_ID:?}-${MODULE_VER:?}" +FILENAME_END="-${BUILD_TYPE:?}-by-${MODULE_AUTHOR:?}" +FILENAME="${FILENAME_START:?}${ZIP_SHORT_COMMIT_ID:+-}${ZIP_SHORT_COMMIT_ID-}${FILENAME_END:?}" + +FILENAME_EXT='.zip' + case "${MODULE_VER:?}" in *'-alpha') MODULE_IS_ALPHA='true' ;; *) MODULE_IS_ALPHA='false' ;; @@ -271,30 +277,30 @@ fi find "${TEMP_DIR}/zip-content" -exec touch -c -t 200802290333.46 '{}' + || ui_error 'Failed to set the modification date of files' # Remove the previously built files (if they exist) -rm -f "${OUT_DIR:?}/${FILENAME:?}"*.zip || ui_error 'Failed to remove the previously built files' -rm -f "${OUT_DIR:?}/${FILENAME:?}"*.zip.md5 || ui_error 'Failed to remove the previously built files' -rm -f "${OUT_DIR:?}/${FILENAME:?}"*.zip.sha256 || ui_error 'Failed to remove the previously built files' +rm -f "${OUT_DIR:?}/${FILENAME_START:?}"*"${FILENAME_END:?}"*"${FILENAME_EXT:?}" || ui_error 'Failed to remove the previously built files' +rm -f "${OUT_DIR:?}/${FILENAME_START:?}"*"${FILENAME_END:?}"*"${FILENAME_EXT:?}".md5 || ui_error 'Failed to remove the previously built files' +rm -f "${OUT_DIR:?}/${FILENAME_START:?}"*"${FILENAME_END:?}"*"${FILENAME_EXT:?}".sha256 || ui_error 'Failed to remove the previously built files' # Compress (it ensure that the list of files to compress is in the same order under all OSes) # Note: Unicode filenames in the zip are disabled since we don't need them and also zipsigner.jar chokes on them cd "${TEMP_DIR}/zip-content" || ui_error 'Failed to change the folder' echo 'Zipping...' -find . -type f | LC_ALL=C sort | zip -D -9 -X -UN=n -nw "${TEMP_DIR}/flashable.zip" -@ || ui_error 'Failed compressing' -FILENAME="${FILENAME}-signed" +find . -type f | LC_ALL=C sort | zip -D -9 -X -UN=n -nw "${TEMP_DIR}/flashable${FILENAME_EXT:?}" -@ || ui_error 'Failed compressing' +FILENAME="${FILENAME:?}-signed" # Sign and zipalign echo '' echo 'Signing and zipaligning...' mkdir -p "${TEMP_DIR:?}/zipsign" -java -Duser.timezone=UTC -Dzip.encoding=Cp437 -Djava.io.tmpdir="${TEMP_DIR}/zipsign" -jar "${MAIN_DIR}/tools/zipsigner.jar" "${TEMP_DIR}/flashable.zip" "${TEMP_DIR}/${FILENAME}.zip" || ui_error 'Failed signing and zipaligning' +java -Duser.timezone=UTC -Dzip.encoding=Cp437 -Djava.io.tmpdir="${TEMP_DIR:?}/zipsign" -jar "${MAIN_DIR:?}/tools/zipsigner.jar" "${TEMP_DIR:?}/flashable${FILENAME_EXT:?}" "${TEMP_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}" || ui_error 'Failed signing and zipaligning' if test "${FAST_BUILD:-false}" = 'false'; then echo '' - zip -T "${TEMP_DIR}/${FILENAME}.zip" || ui_error 'The zip file is corrupted' + zip -T "${TEMP_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}" || ui_error 'The zip file is corrupted' fi -cp -f "${TEMP_DIR}/${FILENAME}.zip" "${OUT_DIR}/${FILENAME}.zip" || ui_error 'Failed to copy the final file' +cp -f "${TEMP_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}" "${OUT_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}" || ui_error 'Failed to copy the final file' -cd "${OUT_DIR}" || ui_error 'Failed to change the folder' +cd "${OUT_DIR:?}" || ui_error 'Failed to change the folder' # Cleanup remnants rm -rf -- "${TEMP_DIR:?}" & @@ -303,21 +309,19 @@ rm -rf -- "${TEMP_DIR:?}" & echo '' # Generate info -ZIP_FILENAME="${FILENAME:?}.zip" - -sha256sum "${ZIP_FILENAME:?}" > "${OUT_DIR:?}/${ZIP_FILENAME:?}.sha256" || ui_error 'Failed to compute the SHA-256 hash' -ZIP_SHA256="$(cut -d ' ' -f '1' -s 0< "${OUT_DIR:?}/${ZIP_FILENAME:?}.sha256")" || ui_error 'Failed to read the SHA-256 hash' +sha256sum "${FILENAME:?}${FILENAME_EXT:?}" > "${OUT_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}.sha256" || ui_error 'Failed to compute the SHA-256 hash' +ZIP_SHA256="$(cut -d ' ' -f '1' -s 0< "${OUT_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}.sha256")" || ui_error 'Failed to read the SHA-256 hash' ZIP_MD5='' if test "${FAST_BUILD:-false}" = 'false'; then - md5sum "${ZIP_FILENAME:?}" > "${OUT_DIR:?}/${ZIP_FILENAME:?}.md5" || ui_error 'Failed to compute the MD5 hash' - ZIP_MD5="$(cut -d ' ' -f '1' -s 0< "${OUT_DIR:?}/${ZIP_FILENAME:?}.md5")" || ui_error 'Failed to read the MD5 hash' + md5sum "${FILENAME:?}${FILENAME_EXT:?}" > "${OUT_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}.md5" || ui_error 'Failed to compute the MD5 hash' + ZIP_MD5="$(cut -d ' ' -f '1' -s 0< "${OUT_DIR:?}/${FILENAME:?}${FILENAME_EXT:?}.md5")" || ui_error 'Failed to read the MD5 hash' fi if test -n "${ZIP_SHORT_COMMIT_ID?}"; then printf '%s\n' "Short commit ID: ${ZIP_SHORT_COMMIT_ID:?}" fi -printf '%s\n' "Filename: ${ZIP_FILENAME:?}" +printf '%s\n' "Filename: ${FILENAME:?}${FILENAME_EXT:?}" printf '%s\n' "SHA-256: ${ZIP_SHA256:?}" if test -n "${ZIP_MD5?}"; then printf '%s\n' "MD5: ${ZIP_MD5:?}" @@ -327,7 +331,7 @@ fi if test "${GITHUB_JOB:-false}" != 'false'; then { printf 'ZIP_FOLDER=%s\n' "${OUT_DIR?}" - printf 'ZIP_FILENAME=%s\n' "${ZIP_FILENAME?}" + printf 'ZIP_FILENAME=%s\n' "${FILENAME?}${FILENAME_EXT?}" printf 'ZIP_VERSION=%s\n' "${MODULE_VER?}" printf 'ZIP_SHORT_COMMIT_ID=%s\n' "${ZIP_SHORT_COMMIT_ID?}" printf 'ZIP_BUILD_TYPE=%s\n' "${BUILD_TYPE?}" diff --git a/dependencies.gradle b/dependencies.gradle index 33ca1665..a0abff6e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -9,5 +9,5 @@ ext { gradleSha256Sum = 'f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6' // -- DEPENDENCIES -- - gradleDevelocityVersion = '3.19' + gradleDevelocityVersion = '3.19.1' } diff --git a/zip-content/customize.sh b/zip-content/customize.sh index b9d8dd7a..72c93aa1 100644 --- a/zip-content/customize.sh +++ b/zip-content/customize.sh @@ -338,13 +338,14 @@ fi "${OUR_BB:?}" mkdir -p "${TMP_PATH:?}" || ui_error "Failed to create the temp folder" set_perm_safe 0 0 0755 "${TMP_PATH:?}" -PREVIOUS_PATH="${PATH}" +PREVIOUS_PATH="${PATH:-%empty}" DEVICE_GETPROP="$(command -v getprop)" || DEVICE_GETPROP='' +DEVICE_STAT="$(command -v stat)" || DEVICE_STAT='' DEVICE_MOUNT="$(command -v mount)" || DEVICE_MOUNT='' DEVICE_PM="$(command -v pm)" || DEVICE_PM='' DEVICE_AM="$(command -v am)" || DEVICE_AM='' -readonly PREVIOUS_PATH DEVICE_GETPROP DEVICE_MOUNT DEVICE_PM DEVICE_AM -export PREVIOUS_PATH DEVICE_GETPROP DEVICE_MOUNT DEVICE_PM DEVICE_AM +readonly PREVIOUS_PATH DEVICE_GETPROP DEVICE_STAT DEVICE_MOUNT DEVICE_PM DEVICE_AM +export PREVIOUS_PATH DEVICE_GETPROP DEVICE_STAT DEVICE_MOUNT DEVICE_PM DEVICE_AM if test "${TEST_INSTALL:-false}" = 'false'; then create_dir_safe "${TMP_PATH:?}/bin" diff --git a/zip-content/inc/common-functions.sh b/zip-content/inc/common-functions.sh index 5b23be22..ecee918a 100644 --- a/zip-content/inc/common-functions.sh +++ b/zip-content/inc/common-functions.sh @@ -793,7 +793,7 @@ initialize() DATA_INIT_STATUS=1 ui_debug "Mounted: ${DATA_PATH:-}" else - ui_warning "The data partition cannot be mounted, so updates of installed / removed apps cannot be deleted and their Dalvik cache cannot be cleaned, but it doesn't matter if you do a factory reset" + ui_warning "The data partition cannot be mounted, so updates of installed / removed apps cannot be automatically deleted and their Dalvik cache cannot be automatically cleaned. I suggest to manually do a factory reset after flashing this ZIP." fi fi readonly DATA_PATH @@ -876,7 +876,7 @@ clean_previous_installations() ui_error "Something is wrong because '${SYS_PATH?}' is NOT really writable!!!" fi - _initial_free_space="$(_get_free_space)" || _initial_free_space='-1' + _initial_free_space="$(get_free_disk_space_of_partition "${SYS_PATH:?}")" || _initial_free_space='-1' rm -f -- "${SYS_PATH:?}/etc/write-test-file.dat" || ui_error 'Failed to delete the test file' @@ -1006,11 +1006,11 @@ _something_exists() return 1 } -_get_free_space() +_get_free_disk_space_of_partition_using_df() { local _skip_first='true' - df -P -- "${SYS_MOUNTPOINT:?}" | while IFS=' ' read -r _ _ _ available_space _; do + df -B1 -P -- "${1:?}" | while IFS=' ' read -r _ _ _ available_space _; do if test "${_skip_first?}" = 'true'; then _skip_first='false' continue @@ -1027,14 +1027,16 @@ _get_free_space() _wait_free_space_changes() { - local _max_attempts='15' + local _max_attempts + + _max_attempts='15' if test -n "${1?}"; then _max_attempts="${1:?}"; fi printf 'Waiting..' while test "${_max_attempts:?}" -gt 0 && _max_attempts="$((_max_attempts - 1))"; do printf '.' - if test "$(_get_free_space || true)" != "${2:?}"; then + if test "$(get_free_disk_space_of_partition "${SYS_PATH:?}" || :)" != "${2:?}"; then break fi sleep 1 @@ -1058,7 +1060,7 @@ _do_rollback_last_app_internal() local _backup_ifs _skip_first _initial_free_space _vanity_name _installed_file_list if test ! -s "${TMP_PATH:?}/processed-${1:?}s.log"; then return 1; fi - _initial_free_space="$(_get_free_space)" || return 2 + _initial_free_space="$(get_free_disk_space_of_partition "${SYS_PATH:?}")" || return 2 _installed_file_list="$(tail -n '1' -- "${TMP_PATH:?}/processed-${1:?}s.log")" || ui_error "Failed to read processed-${1?}s.log" test -n "${_installed_file_list?}" || return 3 @@ -1087,7 +1089,7 @@ _do_rollback_last_app_internal() _wait_free_space_changes '' "${_initial_free_space:?}" # Reclaiming free space may take some time ui_debug '' - sed -ie '$ d' -- "${TMP_PATH:?}/processed-${1:?}s.log" || ui_error "Failed to remove the last line from read processed-${1?}s.log" + sed -ie '$ d' "${TMP_PATH:?}/processed-${1:?}s.log" || ui_error "Failed to remove the last line from processed-${1?}s.log" if command 1> /dev/null -v 'rollback_complete_callback'; then export CURRENTLY_ROLLBACKING='true' @@ -1124,16 +1126,55 @@ _is_free_space_error() return 1 # NOT found } +get_size_of_file() +{ + local _stat_result + + if _stat_result="$(stat 2> /dev/null -c '%s' -- "${1:?}")"; then + : # OK + elif test -n "${DEVICE_STAT?}" && _stat_result="$(PATH="${PREVIOUS_PATH:?}" "${DEVICE_STAT:?}" -c '%s' -- "${1:?}")"; then + : # OK + else + _stat_result='' + fi + + if test -n "${_stat_result?}" && printf '%s\n' "${_stat_result:?}"; then + return 0 + fi + + return 1 +} + +get_free_disk_space_of_partition() +{ + local _stat_result + + if _stat_result="$(stat 2> /dev/null -f -c '%f * %S' -- "${1:?}")"; then + : # OK + elif test -n "${DEVICE_STAT?}" && _stat_result="$(PATH="${PREVIOUS_PATH:?}" "${DEVICE_STAT:?}" 2> /dev/null -f -c '%f * %S' -- "${1:?}")"; then + : # OK + else + _stat_result='' + fi + + if test -n "${_stat_result?}" && printf '%s\n' "$((_stat_result))"; then + return 0 + fi + + printf '%s\n' '-1' + return 1 +} + get_disk_space_usage_of_file_or_folder() { local _result - if _result="$(du 2> /dev/null -s -B 1 -- "${1:?}" | cut -f 1 -s)" && test -n "${_result?}"; then - printf '%u\n' "${_result:?}" + if _result="$(du 2> /dev/null -s -B1 -- "${1:?}" | cut -f 1 -s)" && test -n "${_result?}"; then + printf '%s\n' "${_result:?}" elif _result="$(du -s -k -- "${1:?}" | cut -f 1 -s)" && test -n "${_result?}"; then - printf '%u\n' "$((_result * 1024))" + printf '%s\n' "$((_result * 1024))" else - printf '%d\n' '-1' + printf '%s\n' '-1' return 1 fi } @@ -1184,21 +1225,30 @@ verify_disk_space() { local _needed_space_bytes _free_space_bytes - _needed_space_bytes="$(get_disk_space_usage_of_file_or_folder "${TMP_PATH:?}/files")" || _needed_space_bytes='-1' - _free_space_bytes="$(($(stat -f -c '%f * %S' -- "${1:?}")))" || _free_space_bytes='-1' + if _needed_space_bytes="$(get_disk_space_usage_of_file_or_folder "${TMP_PATH:?}/files")" && test -n "${_needed_space_bytes?}"; then + ui_msg "Disk space required: $(convert_bytes_to_mb "${_needed_space_bytes:?}" || :) MB" + else + _needed_space_bytes='-1' + fi - ui_msg "Disk space required: $(convert_bytes_to_mb "${_needed_space_bytes:?}" || true) MB" - ui_msg "Free disk space: $(convert_bytes_to_mb "${_free_space_bytes:?}" || true) MB ($(convert_bytes_to_human_readable_format "${_free_space_bytes:?}" || true))" + if _free_space_bytes="$(get_free_disk_space_of_partition "${1:?}")" && test -n "${_free_space_bytes?}"; then + ui_msg "Free disk space: $(convert_bytes_to_mb "${_free_space_bytes:?}" || :) MB ($(convert_bytes_to_human_readable_format "${_free_space_bytes:?}" || :))" + else + ui_warning "Unable to get free disk space, output for '${1?}' => $(stat -f -c '%f * %S' -- "${1:?}" || :)" + _free_space_bytes='-1' + fi - if test "${_needed_space_bytes:?}" -lt 0 || test "${_free_space_bytes:?}" -lt 0; then + if test "${_needed_space_bytes:?}" -gt 0 && test "${_free_space_bytes:?}" -ge 0; then + : # OK + else ui_msg_empty_line - ui_warning "Unable to verify needed space, continuing anyway" + ui_warning 'Unable to verify needed space, continuing anyway' return 0 fi - if test "${_needed_space_bytes:?}" -ge "${_free_space_bytes:?}"; then return 1; fi + if test "${_free_space_bytes:?}" -gt "${_needed_space_bytes:?}"; then return 0; fi - return 0 + return 1 } perform_secure_copy_to_device() @@ -1230,9 +1280,16 @@ perform_secure_copy_to_device() touch 2> /dev/null "${SYS_PATH:?}/etc/zips/${MODULE_ID:?}.failed" || : ui_debug '' - df -h -T -- "${SYS_MOUNTPOINT:?}" || true + df 2> /dev/null -B1 -P -- "${SYS_MOUNTPOINT:?}" || : + ui_debug '' + df 2> /dev/null -h -T -- "${SYS_MOUNTPOINT:?}" || df -h -- "${SYS_MOUNTPOINT:?}" || : ui_debug '' + local _free_space_bytes + if _free_space_bytes="$(get_free_disk_space_of_partition "${SYS_PATH:?}")" && test -n "${_free_space_bytes?}"; then + ui_debug "Free disk space: $(convert_bytes_to_mb "${_free_space_bytes:?}" || :) MB ($(convert_bytes_to_human_readable_format "${_free_space_bytes:?}" || :))" + fi + if test -n "${_error_text?}"; then ui_error "Failed to copy '${1?}' to the device due to => $(printf '%s\n' "${_error_text?}" | head -n 1 || :)" fi @@ -1915,12 +1972,12 @@ setup_app() move_rename_file "${TMP_PATH:?}/origin/etc/default-permissions/default-permissions-${_filename:?}.xml" "${TMP_PATH:?}/files/etc/default-permissions/default-permissions-${_output_name:?}.xml" || ui_error "Failed to setup the default permissions xml of '${_vanity_name?}'" _installed_file_list="${_installed_file_list?}|etc/default-permissions/default-permissions-${_output_name:?}.xml" fi - if test "${_url_handling:?}" != 'false'; then + if test "${_url_handling:?}" != 'false' && test "${CURRENTLY_ROLLBACKING:-false}" != 'true'; then add_line_in_file_after_string "${TMP_PATH:?}/files/etc/sysconfig/google.xml" '' " " || ui_error "Failed to auto-enable URL handling for '${_vanity_name?}'" fi move_rename_file "${TMP_PATH:?}/origin/${_dir:?}/${_filename:?}.apk" "${TMP_PATH:?}/files/${_output_dir:?}/${_output_name:?}.apk" || ui_error "Failed to setup the app => '${_vanity_name?}'" - if test "${CURRENTLY_ROLLBACKING:-false}" != 'true' && test "${_optional:?}" = 'true' && test "$(stat -c '%s' -- "${TMP_PATH:?}/files/${_output_dir:?}/${_output_name:?}.apk" || printf '0' || true)" -gt 300000; then + if test "${CURRENTLY_ROLLBACKING:-false}" != 'true' && test "${_optional:?}" = 'true' && test "$(get_size_of_file "${TMP_PATH:?}/files/${_output_dir:?}/${_output_name:?}.apk" || printf '0' || :)" -gt 300000; then _installed_file_list="${_installed_file_list#|}" printf '%s\n' "${_vanity_name:?}|${_output_dir:?}/${_output_name:?}.apk|${_installed_file_list?}" 1>> "${TMP_PATH:?}/processed-${_dir:?}s.log" || ui_error "Failed to update processed-${_dir?}s.log" fi diff --git a/zip-content/setprop-settings-list.csv.license b/zip-content/setprop-settings-list.csv.license index f24ebfe5..0964adac 100644 --- a/zip-content/setprop-settings-list.csv.license +++ b/zip-content/setprop-settings-list.csv.license @@ -1,2 +1,4 @@ SPDX-FileCopyrightText: none SPDX-License-Identifier: CC0-1.0 + +Note: The referenced file contains the list of all the options configurable with setprop