diff --git a/cros_upgrade_chroot b/cros_upgrade_chroot new file mode 100755 index 0000000000..8f8ac6b328 --- /dev/null +++ b/cros_upgrade_chroot @@ -0,0 +1,100 @@ +#!/bin/bash + +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Load common constants. This should be the first executable line. +# The path to common.sh should be relative to your script's location. +. "$(dirname $0)/common.sh" + +# Script must be run inside the chroot +restart_in_chroot_if_needed $* + +DEFINE_string version "" \ + "Assume current chroot version is this." +DEFINE_boolean force_latest "${FLAGS_false}" \ + "Assume latest version and recreate the version file" +DEFINE_boolean skipfirst "${FLAGS_false}" \ + "Skip the first upgrade. This may be dangerous." + +FLAGS "$@" || exit 1 + +VERSION_FILE=~/.version + +###################################################################### + +# Latest version is the version of last upgrade.d file. +# Name format is ${number}_${short_description} +# Versions must be -n sorted, that is, the first continuous sequence +# of numbers is what counts. 12_ is before 111_, etc. +LATEST_VERSION=$( + ls "$(dirname $0)/upgrade.d" | grep "^[0-9]*_" | \ + sort -n | tail -n 1 | cut -f1 -d'_' +) +CHROOT_VERSION=$(cat ${VERSION_FILE}) +# Check if it's a number. +if ! [ "${CHROOT_VERSION}" -ge "0" ] &> /dev/null; then + error "Your chroot version file ${VERSION_FILE} is bogus: ${CHROOT_VERSION}" + exit 1 +fi + +if [ -n "${FLAGS_force_latest}" ]; then + echo "${LATEST_VERSION}" > "${VERSION_FILE}" + exit 0 +fi + +if [ -n "${FLAGS_skipfirst}" ]; then + if [ "${CHROOT_VERSION}" -lt "${LATEST_VERSION}" ]; then + CHROOT_VERSION=$(expr ${CHROOT_VERSION} + 1) + fi +fi + +if [ -n "${FLAGS_version}" ]; then + # Check if it's a number. + if [ "${FLAGS_version}" -ge "0" ] &> /dev/null; then + CHROOT_VERSION="${FLAGS_version}" + else + error "Trying to force invalid version: ${FLAGS_version}" + exit 1 + fi +fi + +# default goes here +if ! [ -f "${VERSION_FILE}" ]; then + warn "Warning: chroot of unknown version, assuming 0" + echo "0" > "${VERSION_FILE}" +fi + +if [ "${LATEST_VERSION}" -gt "${CHROOT_VERSION}" ]; then + echo "Outdated chroot found" + + pushd "$(dirname $0)/upgrade.d/" 1> /dev/null + for n in $(seq "$(expr ${CHROOT_VERSION} + 1)" "${LATEST_VERSION}"); do + # Deprecation check; Deprecation can be done by removing old upgrade + # scripts and causing too old chroots to have to start over. + # This also means that the scripts have to form a continuous sequence. + if ! [ -f ${n}_* ]; then + error "Fatal: Upgrade ${n} doesn't exist." + error "Your chroot is too old, you need to re-create it!" + exit 1 + fi + + info "Rollup $(echo ${n}_*)" + + # Attempt the upgrade. + # NOTE: We source the upgrade scripts because: + # 1) We can impose set -something on them. + # 2) They can reuse local variables and functions (fe. from common.sh) + # A side effect is that the scripts have to be internally enclosed in + # a code block, otherwise simply running "exit" in any of them would + # terminate the master script, and there would be no way to pass the + # return value from them. + if ! source ${n}_*; then + error "Fatal: failed to upgrade ${n}!" + exit 1 + fi + echo "${n}" > "${VERSION_FILE}" + done + popd 1> /dev/null +fi diff --git a/upgrade.d/1_init b/upgrade.d/1_init new file mode 100644 index 0000000000..0fc41c80ad --- /dev/null +++ b/upgrade.d/1_init @@ -0,0 +1,4 @@ +{ + info "You have just been upgraded to chroot version 1! Congratulations!" + return 0 +}