#!/bin/sh # Copyright (c) 2017, 2021, 2023 Jonas 'Sortie' Termansen. # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # tix-upgrade # Upgrade operating system and ports. set -e cachedir="" clean=false collection="" download_only=false fetch_options= ports_only=false sysroot="" upgrade_ports=false upgrade_system=false wait="" dashdash= previous_option= for argument do if test -n "$previous_option"; then eval $previous_option=\$argument previous_option= shift continue fi case $argument in *=?*) parameter=$(expr "X$argument" : '[^=]*=\(.*\)' || true) ;; *=) parameter= ;; *) parameter=yes ;; esac case $dashdash$argument in --) dashdash=yes ;; -w) wait=-w ;; --cachedir=*) cachedir=$parameter ;; --cachedir) previous_option=cachedir ;; --clean) clean=true ;; --collection=*) collection=$parameter ;; --collection) previous_option=collection ;; --download-only) download_only=true ;; --insecure-downgrade-to-http) fetch_options="$fetch_options $argument" ;; --insecure-no-check-certificate) fetch_options="$fetch_options $argument" ;; --ports) upgrade_ports=true ;; --system) upgrade_system=true ;; --sysroot) previous_option=sysroot ;; --sysroot=*) sysroot=$parameter ;; --wait) wait=--wait ;; -*) echo "$0: unrecognized option $argument" >&2 exit 1 ;; *) break ;; esac shift done if test -n "$previous_option"; then echo "$0: option '$argument' requires an argument" >&2 exit 1 fi # TODO: Reject additional operands. if [ -z "$collection" ]; then collection="$sysroot" fi if [ -n "$collection" ]; then collection=$(cd "$collection" && pwd) fi if ! $upgrade_ports && ! $upgrade_system; then # TODO: Ability to set default in /etc/upgrade.conf. upgrade_ports=true upgrade_system=true fi # Update only ports if this isn't a whole system installation. if [ ! -e "$collection/tix/manifest/system" ]; then upgrade_system=false fi if [ -z "$cachedir" ]; then cachedir="$collection/var/cache/tix" fi if $clean; then echo "Removing cache directory: $cachedir" rm -rf -- "$cachedir" fi mkdir -p -- "$cachedir" mkdir -p -- "$cachedir/new" # Fetch the latest official release.sig.sh and its matching sha256sum file. tix-fetch $fetch_options \ --collection="$collection" \ --output-release-sig-file="$cachedir/new/release.sh.sig" \ --output-sha256sum="$cachedir/new/sha256sum" # If release.sig.sh or sha256sum changed, clean the cache directory of downloads # that were currently in progress as they might not have the right checksums. # TODO: This requires diff(1) in the base system! Avoid that. Get a cmp(1)! if ! diff -- "$cachedir/release.sh.sig" \ "$cachedir/new/release.sh.sig" 1>/dev/null 2>/dev/null || ! diff -- "$cachedir/sha256sum" \ "$cachedir/new/sha256sum" 1>/dev/null 2>/dev/null; then rm -rf -- "$cachedir/boot" rm -rf -- "$cachedir/repository" rm -rf -- "$cachedir/sysroot" fi # Store the new release.sig.sh and sha256sum files so we can resume the download # if cancelled and these files still match. mv -- "$cachedir/new/release.sh.sig" "$cachedir/release.sh.sig" mv -- "$cachedir/new/sha256sum" "$cachedir/sha256sum" rm -rf -- "$cachedir/new" mkdir -p "$cachedir/boot" mkdir -p "$cachedir/repository" # TODO: Support upgrading across releases, renamed channels, etc. if $upgrade_system; then # Fetch the base system initrds from the mirror. # TODO: What about the system source code in /src? # TODO: Get the overlay initrd if it exists. tix-fetch $fetch_options \ --collection="$collection" \ --input-release-sig-file="$cachedir/release.sh.sig" \ --input-sha256sum="$cachedir/sha256sum" \ -c --initrd -O "$cachedir/boot" -- system fi if $upgrade_ports; then # Fetch each port from the mirror. ports=$(LC_ALL=C ls -- "$collection/tix/tixinfo") # TODO: Handle new mandatory / recommended ports. # TODO: Handle renamed ports. # TODO: This fails if the port does not exist upstream. mkdir -p "$cachedir/repository" for port in $ports; do # The port has a hash if if it exists upstream. sha256=$(tix-fetch $fetch_options \ --collection="$collection" \ --input-release-sig-file="$cachedir/release.sh.sig" \ --input-sha256sum="$cachedir/sha256sum" \ --sha256 --port -- $port) # If the port exists upstream, get the latest version. if [ -n "$sha256" ]; then tix-fetch $fetch_options \ --collection="$collection" \ --input-release-sig-file="$cachedir/release.sh.sig" \ --input-sha256sum="$cachedir/sha256sum" \ -c --port -O "$cachedir/repository" -- $port fi done fi # Stop if only downloading. if $download_only; then exit fi rm -rf -- "$cachedir/sysroot" mkdir -p -- "$cachedir/sysroot" # Extract the base system into the sysroot. if $upgrade_system; then echo "Extracting system.tar.xz..." tar -C "$cachedir/sysroot" -xJf "$cachedir/boot/system.tar.xz" rm -f "$cachedir/boot/system.tar.xz" fi # Extract the ports into the sysroot. full= if $upgrade_ports; then full=--full for port in $ports; do echo "Extracting $port.tix.tar.xz..." tar -C "$cachedir/sysroot" -xJf "$cachedir/repository/$port.tix.tar.xz" rm -f "$cachedir/repository/$port.tix.tar.xz" done fi case "$upgrade_system$upgrade_ports" in truefalse) what_to_upgrade=--system;; falsetrue) what_to_upgrade=--ports;; *) what_to_upgrade=;; esac # Merge the new sysroot onto the installation. sysmerge -t "$collection" $what_to_upgrade $full $wait "$cachedir/sysroot" rm -rf -- "$cachedir/boot" rm -rf -- "$cachedir/repository" rm -rf -- "$cachedir/sysroot"