#!/usr/bin/env bash # # SPDX-License-Identifier: GPL-2.0 # # Copyright (c) 2013-2023 Igor Pecovnik, igor@armbian.com # # This file is a part of the Armbian Build Framework # https://github.com/armbian/build/ # called by artifact-rootfs::artifact_rootfs_prepare_version() function calculate_rootfs_cache_id() { # Validate that AGGREGATED_ROOTFS_HASH is set [[ -z "${AGGREGATED_ROOTFS_HASH}" ]] && exit_with_error "AGGREGATED_ROOTFS_HASH is not set at calculate_rootfs_cache_id()" # If the vars are already set and not empty, exit_with_error [[ "x${packages_hash}x" != "xx" ]] && exit_with_error "packages_hash is already set" [[ "x${cache_type}x" != "xx" ]] && exit_with_error "cache_type is already set" declare -i short_hash_size=6 # get the hashes of the lib/ bash sources involved... declare hash_files="undetermined" calculate_hash_for_files "${SRC}"/lib/functions/rootfs/create-cache.sh "${SRC}"/lib/functions/rootfs/rootfs-create.sh declare bash_hash="${hash_files}" declare bash_hash_short="${bash_hash:0:${short_hash_size}}" # hash hooks that affect the rootfs declare -a extension_hooks_to_hash=("custom_apt_repo") declare -a extension_hooks_hashed=("$(dump_extension_method_sources_functions "${extension_hooks_to_hash[@]}")") declare hash_hooks="undetermined" hash_hooks="$(echo "${extension_hooks_hashed[@]}" | sha256sum | cut -d' ' -f1)" declare hash_hooks_short="${hash_hooks:0:${short_hash_size}}" # AGGREGATED_ROOTFS_HASH is produced by aggregation.py declare -g -r packages_hash="${AGGREGATED_ROOTFS_HASH:0:12}-H${hash_hooks_short}-B${bash_hash_short}" declare cache_type="cli" [[ ${BUILD_DESKTOP} == yes ]] && cache_type="xfce-desktop" [[ -n ${DESKTOP_ENVIRONMENT} ]] && cache_type="${DESKTOP_ENVIRONMENT}-desktop" [[ ${BUILD_MINIMAL} == yes ]] && cache_type="minimal" # allow extensions to modify cache_type, since they may have used add_packages_to_rootfs() or remove_packages() cache_type="${cache_type}${EXTRA_ROOTFS_NAME:-""}" declare -g -r cache_type="${cache_type}" declare -g -r rootfs_cache_id="${packages_hash}" display_alert "calculate_rootfs_cache_id: done." "cache_type: '${cache_type}' - rootfs_cache_id: '${rootfs_cache_id}'" "debug" } # called by artifact-rootfs::artifact_rootfs_build_from_sources() function create_new_rootfs_cache() { : "${artifact_final_file:?artifact_final_file is not set}" : "${artifact_final_file_basename:?artifact_final_file_basename is not set}" [[ ! -d "${SDCARD:?}" ]] && exit_with_error "create_new_rootfs_cache: ${SDCARD} is not a directory" # validate cache_type is set [[ -n "${cache_type}" ]] || exit_with_error "create_new_rootfs_cache: cache_type is not set" # validate packages_hash is set [[ -n "${packages_hash}" ]] || exit_with_error "create_new_rootfs_cache: packages_hash is not set" # compatibility with legacy code... declare -g cache_name="${artifact_final_file_basename}" declare -g cache_fname=${artifact_final_file} display_alert "Creating new rootfs cache" "'${cache_name}'" "info" create_new_rootfs_cache_via_debootstrap # in rootfs-create.sh create_new_rootfs_cache_tarball # in rootfs-create.sh return 0 # protect against possible future short-circuiting above this } # this builds/gets cached rootfs artifact, extracts it to "${SDCARD}" function get_or_create_rootfs_cache_chroot_sdcard() { if [[ "${ROOT_FS_CREATE_ONLY}" == yes ]]; then exit_with_error "Using deprecated ROOT_FS_CREATE_ONLY=yes, that is not longer supported. use 'rootfs' CLI command." fi # build the rootfs artifact; capture the filename... declare -g artifact_final_file artifact_version artifact_final_file artifact_file_relative WHAT="rootfs" build_artifact_for_image # has its own logging sections, for now declare -g cache_fname="${artifact_final_file}" # Setup the cleanup handler, possibly "again", since the artifact already set it up and consumed it, if cache missed. LOG_SECTION="prepare_rootfs_build_params_and_trap" do_with_logging prepare_rootfs_build_params_and_trap LOG_SECTION="extract_rootfs_artifact" do_with_logging extract_rootfs_artifact return 0 } function extract_rootfs_artifact() { : "${artifact_file_relative:?artifact_file_relative is not set}" : "${artifact_final_file:?artifact_final_file is not set}" # compatibility with legacy code... declare cache_name="${artifact_file_relative}" declare cache_fname=${artifact_final_file} if [[ ! -f "${cache_fname}" ]]; then exit_with_error "get_or_create_rootfs_cache_chroot_sdcard: extract: ${cache_fname} is not a file" fi # validate sanity [[ "x${SDCARD}x" == "xx" ]] && exit_with_error "get_or_create_rootfs_cache_chroot_sdcard: extract: SDCARD: ${SDCARD} is not set" [[ ! -d "${SDCARD}" ]] && exit_with_error "get_or_create_rootfs_cache_chroot_sdcard: ${SDCARD} is not a directory" # @TODO: validate SDCARD is empty; if not, the artifact build "leaked" a cleanup local date_diff=$((($(date +%s) - $(stat -c %Y "${cache_fname}")) / 86400)) display_alert "Extracting ${artifact_version}" "${date_diff} days old" "info" pv -p -b -r -c -N "$(logging_echo_prefix_for_pv "extract_rootfs") ${artifact_version}" "${cache_fname}" | zstdmt -dc | tar xp --xattrs -C "${SDCARD}"/ declare -a pv_tar_zstdmt_pipe_status=("${PIPESTATUS[@]}") # capture and the pipe_status array from PIPESTATUS declare one_pipe_status for one_pipe_status in "${pv_tar_zstdmt_pipe_status[@]}"; do if [[ "$one_pipe_status" != "0" ]]; then exit_with_error "get_or_create_rootfs_cache_chroot_sdcard: extract: ${cache_fname} failed (${pv_tar_zstdmt_pipe_status[*]}) - corrupt cache?" fi done wait_for_disk_sync "after restoring rootfs cache" run_host_command_logged rm -v "${SDCARD}"/etc/resolv.conf run_host_command_logged echo "nameserver ${NAMESERVER}" ">" "${SDCARD}"/etc/resolv.conf # all sources etc. # armbian repo is NOT yet included here, since we'll be building the image, and don't want the repo interferring. create_sources_list_and_deploy_repo_key "image-early" "${RELEASE}" "${SDCARD}/" return 0 }