diff options
Diffstat (limited to 'scripts/version-check.sh')
-rw-r--r-- | scripts/version-check.sh | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/scripts/version-check.sh b/scripts/version-check.sh new file mode 100644 index 0000000..1f4fea4 --- /dev/null +++ b/scripts/version-check.sh @@ -0,0 +1,214 @@ +# This script checks the version of the configuration file and either +# alerts the user about the need to run the upgrade, or attempts to +# perform such an upgrade. + +CFGFILE="${1}" + +. "${CT_LIB_DIR}/scripts/functions" +. "${CFGFILE}" + +# If an old config does not define a version, assume it is 0. This is used +# if we run this script on an old full .config file, not restored from a +# defconfig. +CT_CONFIG_VERSION="${CT_CONFIG_VERSION:-0}" +if [ "${CT_CONFIG_VERSION_CURRENT}" == "${CT_CONFIG_VERSION}" ]; then + # Nothing to do + exit 0 +fi + +if [ -z "${CT_UPGRADECONFIG}" ]; then + if [ "${CT_CONFIG_VERSION}" != "0" ]; then + oldversion="is version ${CT_CONFIG_VERSION}" + else + oldversion="has no version" + fi + cat 2>&1 <<EOF + +Configuration file was generated by an older version of crosstool-NG; +configuration file ${oldversion}; crosstool-NG currently expects +version ${CT_CONFIG_VERSION_CURRENT}. If this configuration file was generated by a crosstool-NG +version 1.23.0 or later, you can run 'ct-ng upgradeconfig'. +Compatibility with previous releases is not guaranteed. In any case, +verify the resulting configuration. + +EOF + if [ "${CT_VCHECK}" = "strict" ]; then + exit 1 + else + exit 0 + fi +fi + +# From now on, we're running actual upgrade, not just a check. Preserve the CT_xxx +# variables that we need using a different prefix so that we can unset the stale +# values at each iteration. +MY_LIB_DIR="${CT_LIB_DIR}" +MY_CONFIG_VERSION_CURRENT="${CT_CONFIG_VERSION_CURRENT}" + +is_set() +{ + if [ "x${val+set}" = "xset" ]; then + return 0 + else + return 1 + fi +} + +info() +{ + # $opt comes from the caller + echo "INFO ${opt:+:: ${opt} }:: $1" >&2 +} + +warning() +{ + # $opt comes from the caller + echo "WARN ${opt:+:: ${opt} }:: $1" >&2 +} + +error() +{ + # $opt comes from the caller + echo " ERR ${opt:+:: ${opt} }:: $1" >&2 + exit 1 +} + +warning_if_set() +{ + if is_set; then + warning "$@" + fi +} + +# When a symbol is replaced with a newer version. If it is a choice and +# the replacement existed in the old version as well, add a replacement_for +# handler for the other symbol to avoid kconfig warnings. +replace() +{ + local newopt="${1}" + + if is_set; then + info "No longer supported; replacing with '${newopt}'". + opt="${newopt}" + else + # Wasn't set; just drop it silently + unset opt + fi +} + +# Avoid multiple definitions for a symbol when multiple old symbols are folded into one +# in a new version. If any of the variable names passed as arguments are set, skip +# emitting this variable (which, presumably, is "not set"). +replacement_for() +{ + while [ -n "${1}" ]; do + if [ -n "${!1}" ]; then + unset opt + return + fi + shift + done +} + +# Helper: takes ${ln} in the caller's environment and sets ${opt} and ${val} +# accordingly. Returns 0 if this line was an option, 1 otherwise. +set_opt_and_val() +{ + case "${ln}" in + CT_*=*) + opt=${ln%%=*} + val=${ln#*=} + case "${val}" in + \"*\") + val="${val%\"}" + val="${val#\"}" + q=\" + ;; + esac + return 0 + ;; + "# CT_"*" is not set") + opt=${ln#* } + opt=${opt%% *} + return 0 + ;; + *) + ;; + esac + return 1 +} + + +# Main upgrade driver. One version at a time, read line by line, interpret +# the options and replace anything that needs replacing. +input="${CFGFILE}" +while :; do + # Purge any possibly stale values + unset "${!CT_@}" + # Reload the next input so that the upgrade function can rely on other CT_xxx variables, + # not just the currently processed variable. + . "${input}" + v=${CT_CONFIG_VERSION:-0} + if [ "${v}" -ge "${MY_CONFIG_VERSION_CURRENT}" ]; then + break + fi + + vn=$[ v + 1 ] + info "Upgrading v${v} to v${vn}" + if [ ! -r "${MY_LIB_DIR}/scripts/upgrade/v${v}" ]; then + error "Missing upgrade script for v${v} of the config file" + fi + unset upgrade + . "${MY_LIB_DIR}/scripts/upgrade/v${v}" + # First pass: read in the whole file and mark the options mentioned; + # it may not be possible to upgrade a defconfig if some non-trivial + # option dependencies need to be resolved. We are not interested in + # values yet. + unset selected_opts + declare -A selected_opts + while read ln; do + if set_opt_and_val; then + selected_opts[${opt}]=1 + fi + done < "${input}" + + # Second pass: actually upgrade the options. + { + while read ln; do + unset opt + unset val + q= + if set_opt_and_val; then + case "${opt}" in + CT_CONFIG_VERSION_CURRENT|CT_CONFIG_VERSION) + continue + ;; + esac + else + echo "${ln}" + fi + upgrade + # Emit the option(s) + if [ x${opt+set} = x ]; then + continue + elif [ x${val+set} = x ]; then + echo "# ${opt} is not set" + else + echo "${opt}=${q}${val}${q}" + fi + done + echo "CT_CONFIG_VERSION=\"${vn}\"" + echo "CT_CONFIG_VERSION_CURRENT=\"${CT_CONFIG_VERSION_CURRENT}\"" + } < "${input}" > "${CFGFILE}.${vn}" + unset opt + v=${vn} + rm -f "${input}" + input="${CFGFILE}.${vn}" + # Ideally, we'd do 'ct-ng olddefconfig' after each step with the appropriate + # Kconfig so that the next step would be able to use auto-set values from the + # previous step. However, that would require us to keep archived config/ trees + # from every config file version, which is not practical. So, I decided to defer + # this until it is actually needed. Even then, it is probably sufficient to only + # keep the versions where there is such a dependency. +done +mv "${CFGFILE}.${MY_CONFIG_VERSION_CURRENT}" "${CFGFILE}" |