summaryrefslogtreecommitdiff
path: root/scripts/version-check.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/version-check.sh')
-rw-r--r--scripts/version-check.sh214
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}"