<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Thanks for sending this out and sorry for not paying attention to
      it for so long.</p>
    <p>The relevant parts of the sprint discussion, I think, are in the
      sections "Friendly HG Breakout" and "
      <meta charset="utf-8">
      Experimental as a Tag instead of a Name" (those are the two places
      where "registry" came up. There's also some related discussion in
      the "
      <meta charset="utf-8">
      Flags and defaults breakout" breakout, but that stuff has mostly
      been sent in patches by Rodrigo and myself already.<br>
    </p>
    <p>I have to take a closer look at this patch and at Jun's immutable
      config stuff to see if these interact at all. I also think that
      David SP was thinking about some config registry stuff as well. I
      may play with this idea during the freeze to see if I can come up
      with a nice incremental conversion as well.</p>
    <p>Again, thanks for the RFC. I'll try to dive in deeper soon.</p>
    <p>~Ryan<br>
    </p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 3/24/17 5:41 PM, Gregory Szorc
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAKQoGakNEYQywsatqpJXLtkr8AUL0aLETW2jhXndDsgLxdzM+w@mail.gmail.com"
      type="cite">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <div dir="ltr">On Fri, Mar 24, 2017 at 10:24 AM, Martin von
        Zweigbergk <span dir="ltr"><<a moz-do-not-send="true"
            href="mailto:martinvonz@google.com" target="_blank">martinvonz@google.com</a>></span>
        wrote:<br>
        <div class="gmail_extra">
          <div class="gmail_quote">
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex"><span
                class="">On Sun, Mar 12, 2017 at 12:18 PM, Gregory Szorc
                <<a moz-do-not-send="true"
                  href="mailto:gregory.szorc@gmail.com">gregory.szorc@gmail.com</a>>
                wrote:<br>
                > # HG changeset patch<br>
                > # User Gregory Szorc <<a moz-do-not-send="true"
                  href="mailto:gregory.szorc@gmail.com">gregory.szorc@gmail.com</a>><br>
                > # Date 1489346234 25200<br>
                > #      Sun Mar 12 12:17:14 2017 -0700<br>
                > # Node ID dd26bc2a3056879181851aaa3ff4ac<wbr>cbfc42e1ad<br>
                > # Parent  62939e0148f170b67ca8c7374f36c4<wbr>13b67fd387<br>
                > configoptions: introduce registrar for config
                options<br>
                <br>
              </span>I like the direction. I missed the discussion at
              the sprint. Was the<br>
              consensus that this is the way to go?<br>
            </blockquote>
            <div><br>
            </div>
            <div>There were some side discussions. Not anything formal
              IIRC.<br>
            </div>
            <div> </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              <br>
              What's the next step? Will you send a non-RFC series
              adding a few<br>
              users as well? I'm also curious to see the "Actually
              hooking it up to<br>
              config loading" step.<br>
            </blockquote>
            <div><br>
            </div>
            <div>I have no plans to work on this.<br>
              <br>
              I put the RFC out there because there were a number of
              conversations around overhauling configs and I wanted a
              tangible prototype for a formal config declaration
              mechanism to be in people's minds so they could consider
              benefits that a more formal config mechanism would have.
              (I think it can solve a lot of problems around things like
              environment variable mappings, config aliases, stronger
              type checking, mapping configs to command arguments, etc.)<br>
            </div>
            <div> </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">
              <div>
                <div class="h5"><br>
                  ><br>
                  > Various talks at the sprint have revolved around
                  establishing more<br>
                  > formalization around config options. Specific
                  problems we'd like<br>
                  > to solve or are thinking about solving include:<br>
                  ><br>
                  > * Experimental config options not documented and
                  are not discoverable<br>
                  >   to end-users.<br>
                  > * Config options aren't strongly typed (it
                  depends how they are<br>
                  >   accessed).<br>
                  > * Config options for extensions don't appear in
                  `hg help config`.<br>
                  > * There is no formal mechanism to map a config
                  option to command<br>
                  >   argument behavior. e.g. have a config option
                  imply a command<br>
                  >   argument. Instead, logic is done in the command
                  implementation,<br>
                  >   which results in inconsistent behavior, error
                  messages, weird<br>
                  >   `hg help <command>` output.<br>
                  > * Config option validation is done at the call
                  site and not as part<br>
                  >   of config loading or command dispatching.<br>
                  > * Config options are declared by side-effect all
                  over the repo. It<br>
                  >   might be nicer to have a single "registry" so
                  the full context of<br>
                  >   all options is easily referenced.<br>
                  > * No mechanism to "alias" an old config option to
                  a new one. e.g.<br>
                  >   carrying over "experimental.feature" to its
                  final value.<br>
                  ><br>
                  > This patch introduces a very eary proof of
                  concept for improving<br>
                  > the situation. It adds config options to the
                  "registrar" mechanism,<br>
                  > which allows their declaration to be formalized
                  and recorded in<br>
                  > a central location. This is conceptually similar
                  to populating a<br>
                  > central dict with the data. I chose to use
                  decorators and (for now)<br>
                  > empty functions for declaring config options.
                  This allows docstrings<br>
                  > to be used for writing the config help.<br>
                  ><br>
                  > In the future, one could imagine actually calling
                  the function<br>
                  > declaring the config option. It could receive a
                  ui instance and<br>
                  > an object defining the command being invoked. The
                  function could<br>
                  > then look for conflicting options, adjust command
                  arguments, etc.<br>
                  > It could do so in a way that is consistent across
                  commands. e.g.<br>
                  > a ConfigOptionConflict exception could be raised
                  and the ui or<br>
                  > dispatcher could consistently format that error
                  condition rather<br>
                  > than leaving it to individual command functions
                  to raise on their<br>
                  > own.<br>
                  ><br>
                  > It's worth noting that we need all the *core*
                  options defined in<br>
                  > a central file because of lazy module loading. If
                  a module isn't<br>
                  > loaded, the config option declarations wouldn't
                  be called!<br>
                  ><br>
                  > There are several things missing from this patch
                  and open issues to<br>
                  > resolve:<br>
                  ><br>
                  > * i18n of help text<br>
                  > * Actually using docstrings in `hg help`<br>
                  > * Hooking up strong typing or hinted typing<br>
                  > * Figuring out how to declare config options with
                  sub-options<br>
                  > * Better solution for declaring config options
                  that have both global<br>
                  >   options and per-item sub-options (like
                  hostsecurity.ciphers)<br>
                  > * Actually hooking it up to config loading<br>
                  > * Mechanism for declaring config options in
                  extensions<br>
                  ><br>
                  > diff --git a/mercurial/configoptions.py
                  b/mercurial/configoptions.py<br>
                  > new file mode 100644<br>
                  > --- /dev/null<br>
                  > +++ b/mercurial/configoptions.py<br>
                  > @@ -0,0 +1,102 @@<br>
                  > +# configoptions.py -- Declaration of
                  configuration options<br>
                  > +#<br>
                  > +# Copyright 2017 Gregory Szorc <<a
                    moz-do-not-send="true"
                    href="mailto:gregory.szorc@gmail.com">gregory.szorc@gmail.com</a>><br>
                  > +#<br>
                  > +# This software may be used and distributed
                  according to the terms of the<br>
                  > +# GNU General Public License version 2 or any
                  later version.<br>
                  > +<br>
                  > +from . import (<br>
                  > +    registrar,<br>
                  > +)<br>
                  > +<br>
                  > +configoption = registrar.configoption()<br>
                  > +<br>
                  > +@configoption('hostsecurity.<wbr>ciphers')<br>
                  > +def optionciphers():<br>
                  > +    """Defines the cryptographic ciphers to use
                  for connections.<br>
                  > +<br>
                  > +    Value must be a valid OpenSSL Cipher List
                  Format as documented at<br>
                  > +    <a moz-do-not-send="true"
href="https://urldefense.proofpoint.com/v2/url?u=https-3A__www.openssl.org_docs_manmaster_apps_ciphers.html-23CIPHER-2DLIST-2DFORMAT&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Jw8rundaE7TbmqBYd1txIQ&m=6FYVT5Po5N2vyslmzAdZmMlUq8oQi1a-uYeozyLWArw&s=JbBgutXmiKYWcHYWQaz5_9SUBel8KfUtwNVbTj_RPRA&e="
                    rel="noreferrer" target="_blank">https://www.openssl.org/docs/<wbr>manmaster/apps/ciphers.html#<wbr>CIPHER-LIST-FORMAT</a>.<br>
                  > +<br>
                  > +    This setting is for advanced users only.
                  Setting to incorrect values<br>
                  > +    can significantly lower connection security
                  or decrease performance.<br>
                  > +    You have been warned.<br>
                  > +<br>
                  > +    This option requires Python 2.7.<br>
                  > +    """<br>
                  > +<br>
                  > +@configoption('hostsecurity.<wbr>minimumprotocol')<br>
                  > +def optionminimumprotocol():<br>
                  > +    """Defines the minimum channel encryption
                  protocol to use.<br>
                  > +<br>
                  > +    By default, the highest version of TLS
                  supported by both client and<br>
                  > +    server is used.<br>
                  > +<br>
                  > +    Allowed values are: ``tls1.0``, ``tls1.1``,
                  ``tls1.2``.<br>
                  > +<br>
                  > +    When running on an old Python version, only
                  ``tls1.0`` is allowed since<br>
                  > +    old versions of Python only support up to
                  TLS 1.0.<br>
                  > +<br>
                  > +    When running a Python that supports modern
                  TLS versions, the default is<br>
                  > +    ``tls1.1``. ``tls1.0`` can still be used to
                  allow TLS 1.0. However, this<br>
                  > +    weakens security and should only be used as
                  a feature of last resort if<br>
                  > +    a server does not support TLS 1.1+.<br>
                  > +    """<br>
                  > +<br>
                  > +@configoption('hostsecurity.*<wbr>:ciphers')<br>
                  > +def perhostciphers():<br>
                  > +    """Per host version of
                  ``hostsecurity.ciphers``."""<br>
                  > +<br>
                  > +@configoption('hostsecurity.*<wbr>:fingerprints')<br>
                  > +def perhostfingerprints():<br>
                  > +    """A list of hashes of the DER encoded
                  peer/remote certificate. Values<br>
                  > +    have the form ``algorithm``:``fingerprint``.
                  e.g.<br>
                  > +    ``sha256:<wbr>c3ab8ff13720e8ad9047dd39466b3c<wbr>8974e592c2fa383d4a3960714caef0<wbr>c4f2``.<br>
                  > +<br>
                  > +    The following algorithms/prefixes are
                  supported: ``sha1``, ``sha256``,<br>
                  > +    ``sha512``.<br>
                  > +<br>
                  > +    Use of ``sha256`` or ``sha512`` is
                  preferred.<br>
                  > +<br>
                  > +    If a fingerprint is specified, the CA chain
                  is not validated for this<br>
                  > +    host and Mercurial will require the remote
                  certificate to match one<br>
                  > +    of the fingerprints specified. This means if
                  the server updates its<br>
                  > +    certificate, Mercurial will abort until a
                  new fingerprint is defined.<br>
                  > +    This can provide stronger security than
                  traditional CA-based validation<br>
                  > +    at the expense of convenience.<br>
                  > +<br>
                  > +    This option takes precedence over
                  ``verifycertsfile``.<br>
                  > +    """<br>
                  > +<br>
                  > +@configoption('hostsecurity.*<wbr>:minimumprotocol')<br>
                  > +def perhostminimumprotocol():<br>
                  > +    """This behaves like ``minimumprotocol`` as
                  described above except it<br>
                  > +    only applies to the host on which it is
                  defined.<br>
                  > +    """<br>
                  > +<br>
                  > +@configoption('hostsecurity.*<wbr>:verifycertsfile')<br>
                  > +def perhostverifycertsfile():<br>
                  > +    """Path to file a containing a list of PEM
                  encoded certificates used to<br>
                  > +    verify the server certificate. Environment
                  variables and ``~user``<br>
                  > +    constructs are expanded in the filename.<br>
                  > +<br>
                  > +    The server certificate or the certificate's
                  certificate authority (CA)<br>
                  > +    must match a certificate from this file or
                  certificate verification<br>
                  > +    will fail and connections to the server will
                  be refused.<br>
                  > +<br>
                  > +    If defined, only certificates provided by
                  this file will be used:<br>
                  > +    ``web.cacerts`` and any system/default
                  certificates will not be<br>
                  > +    used.<br>
                  > +<br>
                  > +    This option has no effect if the per-host
                  ``fingerprints`` option<br>
                  > +    is set.<br>
                  > +<br>
                  > +    The format of the file is as follows::<br>
                  > +<br>
                  > +        -----BEGIN CERTIFICATE-----<br>
                  > +        ... (certificate in base64 PEM encoding)
                  ...<br>
                  > +        -----END CERTIFICATE-----<br>
                  > +        -----BEGIN CERTIFICATE-----<br>
                  > +        ... (certificate in base64 PEM encoding)
                  ...<br>
                  > +        -----END CERTIFICATE-----<br>
                  > +    """<br>
                  > diff --git a/mercurial/registrar.py
                  b/mercurial/registrar.py<br>
                  > --- a/mercurial/registrar.py<br>
                  > +++ b/mercurial/registrar.py<br>
                  > @@ -251,4 +251,20 @@ class templatefunc(_<wbr>templateregistrarbas<br>
                  ><br>
                  >      Otherwise, explicit
                  'templater.loadfunction()' is needed.<br>
                  >      """<br>
                  >      _getname = _funcregistrarbase._<wbr>parsefuncdecl<br>
                  > +<br>
                  > +class configoption(_<wbr>funcregistrarbase):<br>
                  > +    """Decorator to register a config option."""<br>
                  > +    def _getname(self, decl):<br>
                  > +        return decl<br>
                  > +<br>
                  > +    def _formatdoc(self, decl, doc):<br>
                  > +        return pycompat.sysstr('.'.join(decl)<wbr>)<br>
                  > +<br>
                  > +    def _extrasetup(self, name, func, *args,
                  **kwargs):<br>
                  > +        section, option = name.split('.', 1)<br>
                  > +<br>
                  > +        self._section = section<br>
                  > +        self._name = name<br>
                  > +<br>
                  > +        self._extra = kwargs<br>
                  > diff --git a/mercurial/ui.py b/mercurial/ui.py<br>
                  > --- a/mercurial/ui.py<br>
                  > +++ b/mercurial/ui.py<br>
                  > @@ -27,8 +27,9 @@ from .node import hex<br>
                  ><br>
                  >  from . import (<br>
                  >      color,<br>
                  >      config,<br>
                  > +    configoptions,<br>
                  >      encoding,<br>
                  >      error,<br>
                  >      formatter,<br>
                  >      progress,<br>
                  > @@ -135,8 +136,11 @@ class ui(object):<br>
                  >          Use uimod.ui.load() to create a ui which
                  knows global and user configs.<br>
                  >          In most cases, you should use ui.copy()
                  to create a copy of an existing<br>
                  >          ui object.<br>
                  >          """<br>
                  > +        # Ensure config options are imported as
                  a side-effect.<br>
                  > +        options = configoptions.configoption<br>
                  > +<br>
                  >          # _buffers: used for temporary capture
                  of output<br>
                  >          self._buffers = []<br>
                  >          # 3-tuple describing how each buffer in
                  the stack behaves.<br>
                  >          # Values are (capture stderr, capture
                  subprocesses, apply labels).<br>
                </div>
              </div>
              <br>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>