Commit cf3cddd1 authored by Ulf Magnusson's avatar Ulf Magnusson Committed by Carles Cufi
Browse files

menuconfig: Prompt for save when Kconfig files change



Update menuconfig and Kconfiglib to upstream revision 16539b4f223fa, to
add the commit below.

    menuconfig: Prompt for save if a different .config would be saved

    Previously, menuconfig.py only prompted for saving the configuration
    if .config didn't exist or the user changed symbol values within the
    interface.

    Also make it prompt for save if Kconfig symbols have been added,
    removed, or have had their defaults changed, provided it would make
    the saved .config differ from the loaded one.

    This usually won't matter for correctness, because loading an
    outdated configuration performs an implicit olddefconfig, but it's
    less confusing.

    Also add a Kconfig.missing_syms attribute that records all
    assignments to undefined symbols in the most recently loaded .config
    file. This is needed to implement the check for whether the saved
    .config would be different.

    As an unrelated change, always prompt for saving if a .config has
    been loaded from within the menuconfig interface. The intention is
    probably often to save the configuration somewhere else, even if it
    isn't modified.

Signed-off-by: default avatarUlf Magnusson <Ulf.Magnusson@nordicsemi.no>
parent 80bc21e0
Loading
Loading
Loading
Loading
+39 −23
Original line number Diff line number Diff line
@@ -700,6 +700,14 @@ class Kconfig(object):
      enabled will get added to Kconfig.warnings. See the various
      Kconfig.enable/disable_*_warnings() functions.

    missing_syms:
      A list with (name, value) tuples for all assignments to undefined symbols
      within the most recently loaded .config file(s). 'name' is the symbol
      name without the 'CONFIG_' prefix. 'value' is a string that gives the
      right-hand side of the assignment verbatim.

      See Kconfig.load_config() as well.

    srctree:
      The value of the $srctree environment variable when the configuration was
      loaded, or the empty string if $srctree wasn't set. This gives nice
@@ -747,6 +755,7 @@ class Kconfig(object):
        "m",
        "mainmenu_text",
        "menus",
        "missing_syms",
        "modules",
        "n",
        "named_choices",
@@ -863,6 +872,8 @@ class Kconfig(object):
        self.const_syms = {}
        self.defined_syms = []

        self.missing_syms = []

        self.named_choices = {}
        self.choices = []

@@ -1032,10 +1043,15 @@ class Kconfig(object):
        "# CONFIG_FOO is not set" within a .config file sets the user value of
        FOO to n. The C tools work the same way.

        The Symbol.user_value attribute can be inspected afterwards to see what
        value the symbol was assigned in the .config file (if any). The user
        value might differ from Symbol.str/tri_value if there are unsatisfied
        dependencies.
        For each symbol, the Symbol.user_value attribute holds the value the
        symbol was assigned in the .config file (if any). The user value might
        differ from Symbol.str/tri_value if there are unsatisfied dependencies.

        Calling this function also updates the Kconfig.missing_syms attribute
        with a list of all assignments to undefined symbols within the
        configuration file. Kconfig.missing_syms is cleared if 'replace' is
        True, and appended to otherwise. See the documentation for
        Kconfig.missing_syms as well.

        Raises (possibly a subclass of) IOError on IO errors ('errno',
        'strerror', and 'filename' are available). Note that IOError can be
@@ -1115,6 +1131,8 @@ class Kconfig(object):
    def _load_config(self, filename, replace):
        with self._open_config(filename) as f:
            if replace:
                self.missing_syms = []

                # If we're replacing the configuration, keep track of which
                # symbols and choices got set so that we can unset the rest
                # later. This avoids invalidating everything and is faster.
@@ -1140,14 +1158,12 @@ class Kconfig(object):
                if match:
                    name, val = match.groups()
                    if name not in syms:
                        self._warn_undef_assign_load(name, val, filename,
                                                     linenr)
                        self._undef_assign(name, val, filename, linenr)
                        continue

                    sym = syms[name]
                    if not sym.nodes:
                        self._warn_undef_assign_load(name, val, filename,
                                                     linenr)
                        self._undef_assign(name, val, filename, linenr)
                        continue

                    if sym.orig_type in _BOOL_TRISTATE:
@@ -1209,11 +1225,14 @@ class Kconfig(object):

                    name = match.group(1)
                    if name not in syms:
                        self._warn_undef_assign_load(name, "n", filename,
                                                     linenr)
                        self._undef_assign(name, "n", filename, linenr)
                        continue

                    sym = syms[name]
                    if not sym.nodes:
                        self._undef_assign(name, "n", filename, linenr)
                        continue

                    if sym.orig_type not in _BOOL_TRISTATE:
                        continue

@@ -1251,6 +1270,16 @@ class Kconfig(object):
                if not choice._was_set:
                    choice.unset_value()

    def _undef_assign(self, name, val, filename, linenr):
        # Called for assignments to undefined symbols during .config loading

        self.missing_syms.append((name, val))

        if self._warn_for_undef_assign:
            self._warn(
                "attempt to assign the value '{}' to the undefined symbol {}"
                .format(val, name), filename, linenr)

    def write_autoconf(self, filename,
                       header="/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
        r"""
@@ -3617,19 +3646,6 @@ class Kconfig(object):
            if self._warn_to_stderr:
                sys.stderr.write(msg + "\n")

    def _warn_undef_assign(self, msg, filename, linenr):
        # See the class documentation

        if self._warn_for_undef_assign:
            self._warn(msg, filename, linenr)

    def _warn_undef_assign_load(self, name, val, filename, linenr):
        # Special version for load_config()

        self._warn_undef_assign(
            'attempt to assign the value "{}" to the undefined symbol {}'
            .format(val, name), filename, linenr)

    def _warn_override(self, msg, filename, linenr):
        # See the class documentation

+31 −4
Original line number Diff line number Diff line
@@ -192,7 +192,7 @@ import sys
import textwrap

from kconfiglib import Symbol, Choice, MENU, COMMENT, MenuNode, \
                       BOOL, STRING, INT, HEX, UNKNOWN, \
                       BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN, \
                       AND, OR, \
                       expr_str, expr_value, split_expr, \
                       standard_sc_expr_str, \
@@ -631,8 +631,8 @@ def menuconfig(kconf):

    _kconf = kconf

    # Always prompt for save if the configuration file doesn't exist
    _conf_changed = not kconf.load_config()
    # Load existing configuration and set _conf_changed True if it is outdated
    _conf_changed = _load_config()

    # Any visible items in the top menu?
    _show_all = False
@@ -678,6 +678,33 @@ def menuconfig(kconf):
    # curses has been de-initialized.
    print(curses.wrapper(_menuconfig))

def _load_config():
    # Loads any existing .config file. See the Kconfig.load_config() docstring.
    #
    # Returns True if .config is missing or outdated. We always prompt for
    # saving the configuration in that case.

    if not _kconf.load_config() or _kconf.missing_syms:
        # Either no .config, or assignments to undefined symbols in the
        # existing .config (which would get removed when saving)
        return True

    for sym in _kconf.unique_defined_syms:
        if sym.user_value is None:
            if sym.config_string:
                # Unwritten symbol
                return True
        elif sym.type in (BOOL, TRISTATE):
            if sym.tri_value != sym.user_value:
                # Written bool/tristate symbol, new value
                return True
        elif sym.str_value != sym.user_value:
            # Written string/int/hex symbol, new value
            return True

    # No need to prompt for save
    return False

# Global variables used below:
#
#   _stdscr:
@@ -811,7 +838,7 @@ def _menuconfig(stdscr):
                    continue

            if _load_dialog():
                _conf_changed = False
                _conf_changed = True

        elif c in ("s", "S"):
            if _save_dialog(_kconf.write_config, standard_config_filename(),