[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Towards a better configuration API for apt



  As we all know, apt's configuration mechanism works more or less like
this:

    _config.Find(optionName, default);
    _config.Set(optionName, value);

  In other words, the default value of a configuration option is provided
at the time that an option name is looked up.  This is convenient, but
can be rather error-prone:

  * There is no way to ensure that the defaults passed to Find() are
    consistent -- and while I can't recall specific instances, I'm
    pretty sure at least one or two actual bugs in aptitude have been
    caused by inconsistent defaults passed to Find().

  * If the option name passed to Find() is mis-spelled, any user
    configuration will be silently ignored and the default value
    used instead.

  * If the option name passed to Set() is mis-spelled, the Set() call
    will silently "fail" (actually create a mis-spelled configuration
    option that will be ignored by correctly spelled Find()s).

  * There's no easy way to see all the configuration options a program
    uses, other than clever invocations of "grep".


  I think that if we could design a configuration API from scratch, it
would look something like this:

  * On startup, the program registers all its configuration options with
    their default values.

  * When passed a configuration option that was not registered, both
    Find() and Set() generate warnings; Find() returns "" (false, 0)
    and Set() does nothing.  Find() does not accept a default parameter
    as an argument.

  There are a few other things I can imagine adding, such as docstrings
for configuration options, explicit support for user configuration
files in ~, or callbacks that get invoked when configuration options
change.  But I want to limit the scope of this mail to addressing the
problems with implicitly defined configuration options.


  Unfortunately, we already have the configuration API that we have, and
lots of programs are written against it.  Can we get there from here?


  I don't think we can fix this quickly, since all programs using apt
would have to be updated.  But I think there is a way to do a slow
transition (over a period of some years) to an API like the one I
sketched out.

  * In the first phase, we add a way for a program to explicitly state
    the portion of the configuration namespace that it uses, and to
    explicitly set default values via an API call.

    The default settings in this phase will have the same effect as
    calling _config->Set during program initialization: if a
    configuration option is predefined, then the default value passed to
    Find will be ignored, and the predefined default will be used
    instead.  In addition, setting a configuration option (named, for
    instance, Debug::UndefinedConfigurationSettings) will cause warnings
    to be generated whenever a configuration option that wasn't predefined
    is set or read.

  * The second phase (T=first phase + N Debian release cycles) looks
    exactly like the first, except that warnings about configuration
    options that aren't predefined are no longer optional, and will
    include a note that non-predefined values are a deprecated feature.

  * The final phase (T=second phase + N Debian release cycles) is to
    change the apt API to remove support for passing a default value,
    and to generate an error if client code tries to set or query an
    undefined option.


  So, is there any interest in this?  I think the code changes should
be minor if we can agree on what the new APIs and/or file formats should
look like, and I'd be willing to do some of the work on it.

  As a start, I would suggest maybe a member function "RegisterOption()"
which would be passed a fully qualified path to the configuration item,
along with the default value of that item, as it would be given to Set().
Registering the same option twice should fail with a warning message.
Libraries that use the apt libraries should provide an initialization
routine that registers the library's options as a side-effect.


  Daniel


Reply to: