#!/bin/bash # Backward updates mechanism set -e source /usr/local/etc/library.sh # Updates folder contains the "history" of updates updates_dir="$1" [ -d "$updates_dir" ] || { echo "$updates_dir does not exist. Abort" >&2; exit 1; } # Get the array of updates dir # The files in updates dir are sorted by tag number # Files names follow the syntax of a tag: x.y.z.sh while read line ; do updates_list+=("$line") done < <( ls -1 "$updates_dir" | sort -V) starting_checkpoint=0 len=${#updates_list[@]} end_of_list=$((len - 1)) # The latest checkpoint is the newer version in updates dir latest_checkpoint=${updates_list[$end_of_list]} latest_checkpoint_version=$( basename "$latest_checkpoint" .sh ) if [[ -f /usr/local/etc/ncp-version ]]; then current_version=$( grep -oP "\d+\.\d+\.\d+" /usr/local/etc/ncp-version | cut -d'v' -f1 ) else current_version="v0.0.0" fi # Compare current version with latest checkpoint # If the current version is more recent than the latest checkpoint there is no need for backward updates if is_more_recent_than "$latest_checkpoint_version" "$current_version" ; then # Execute a series of updates of older versions # Binary search to find the right checkpoint to begin the updates # Checkpoints are considered the updates files # An update file will update the system to the version it has as a tag # .sh will update ncp to version # An update is *applicable* when it is more recent than the current version # An older update/checkpoint is not *applicable* to our system lower_bound=0 upper_bound=$end_of_list while [ $lower_bound -le $upper_bound ]; do x=$((upper_bound + lower_bound)) mid=$((x / 2)) #Compare mid's version with current version mid_version=$( basename ${updates_list[$mid]} .sh ) if is_more_recent_than "$mid_version" "$current_version" ; then # Mid's version update is applicable to the current version # Check if the previous checkpoint (mid-1) is applicable previous=$((mid - 1)) previous_version=$( basename ${updates_list[$previous]} .sh ) if [ "$mid" -gt 0 ] ; then #Compare previous's version with current version # If the previous checkpoint is not applicable then mid is the starting checkpoint # Otherwise keep on binary searching if is_more_recent_than "$current_version" "$previous_version" ; then starting_checkpoint=$mid break fi else # mid is at 0, so this is the starting checkpoint starting_checkpoint=$mid break fi # Continue searching for starting checkpoint upper_bound=$((mid - 1)) else # Mid's version update is not applicable to the current version # Check if the next checkpoint (mid+1) is applicable next=$((mid + 1)) next_version=$( basename ${updates_list[$next]} .sh ) #Compare next's version with current version # If next checkpoint is not applicable then next is the starting checkpoint # Otherwise keep on binary searching if is_more_recent_than "$current_version" "$next_version" ; then # Continue searching for starting checkpoint lower_bound=$((mid + 1)) else # The next version is the starting checkpoint starting_checkpoint=$next break fi fi done # Starting checkpoint has been found so update the system for the rest updates for(( i="$starting_checkpoint"; i<="$end_of_list"; i++)); do update_file=${updates_list[$i]} tag_update=$( basename "$update_file" .sh ) bash "$updates_dir/$update_file" || { echo "Error while applying update $(basename "$update_file" .sh). Exiting..." exit 1 } echo "v$tag_update" > /usr/local/etc/ncp-version [[ $i != $end_of_list ]] && echo -e "NextCloudPi updated to version v$tag_update" || true done fi