summaryrefslogtreecommitdiff
path: root/scripts/version-check.sh
blob: 1f4fea412dc0167e7900f132b2de6c386551b541 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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}"