[PATCH RFC] ui: add support for a tweakdefaults knob

Martin von Zweigbergk martinvonz at google.com
Thu Jun 15 01:14:04 EDT 2017


On Wed, Jun 14, 2017 at 6:37 PM, Augie Fackler <raf at durin42.com> wrote:
> # HG changeset patch
> # User Augie Fackler <augie at google.com>
> # Date 1497488194 14400
> #      Wed Jun 14 20:56:34 2017 -0400
> # Node ID 0e5ea7a86a8021d02218c35b07366ac6081ab3fb
> # Parent  3abba5bc34546951b11b1bd3f5e5c77b90d950d1
> ui: add support for a tweakdefaults knob
>
> We've been talking for years about a one-stop config knob to opt in to
> better behavior. There have been a lot of ideas thrown around, but
> they all seem to be too complicated to get anyone to actually do the
> work.. As such, this patch is the stupidest thing that can possibly
> work in the name of getting a good feature to users.
>
> Right now it's just three config settings that I think are generally
> uncontroversial, but I expect to add more soon. That will likely
> include adding new config knobs for the express purpose of adding them
> to tweakdefaults.
>
> diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
> --- a/mercurial/help/config.txt
> +++ b/mercurial/help/config.txt
> @@ -2071,6 +2071,15 @@ User interface controls.
>      on all exceptions, even those recognized by Mercurial (such as
>      IOError or MemoryError). (default: False)
>
> +``tweakdefaults``
> +
> +    By default Mercurial's behavior changes very little from release
> +    to release, but over time the recommended config settings
> +    shift. Enable this config to opt in to get automatic tweaks to
> +    Mercurial's behavior over time. This config setting will have no
> +    effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
> +    not include ``tweakdefaults``. (default: False)
> +
>  ``username``
>      The committer of a changeset created when running "commit".
>      Typically a person's name and email address, e.g. ``Fred Widget
> diff --git a/mercurial/ui.py b/mercurial/ui.py
> --- a/mercurial/ui.py
> +++ b/mercurial/ui.py
> @@ -43,6 +43,20 @@ urlreq = util.urlreq
>  _keepalnum = ''.join(c for c in map(pycompat.bytechr, range(256))
>                       if not c.isalnum())
>
> +# The config knobs that will be altered (if unset) by ui.tweakdefaults.
> +tweakrc = """
> +[ui]
> +# The rollback command is dangerous. As a rule, don't use it.
> +rollback = False
> +
> +[commands]
> +# Make `hg status` emit cwd-relative paths by default.
> +status.relative = yes
> +
> +[diff]
> +git = 1
> +"""
> +
>  samplehgrcs = {
>      'user':
>  """# example user config (see 'hg help config' for more info)
> @@ -182,6 +196,7 @@ class ui(object):
>              self.fin = src.fin
>              self.pageractive = src.pageractive
>              self._disablepager = src._disablepager
> +            self._tweaked = src._tweaked
>
>              self._tcfg = src._tcfg.copy()
>              self._ucfg = src._ucfg.copy()
> @@ -205,6 +220,7 @@ class ui(object):
>              self.fin = util.stdin
>              self.pageractive = False
>              self._disablepager = False
> +            self._tweaked = False
>
>              # shared read-only environment
>              self.environ = encoding.environ
> @@ -241,8 +257,29 @@ class ui(object):
>                      u.fixconfig(section=section)
>              else:
>                  raise error.ProgrammingError('unknown rctype: %s' % t)
> +        u._maybetweakdefaults()
>          return u
>
> +    def _maybetweakdefaults(self):
> +        if not self.configbool('ui', 'tweakdefaults'):
> +            return
> +        if self._tweaked or self.plain('tweakdefaults'):
> +            return
> +
> +        # Note: it is SUPER IMPORTANT that you set self._tweaked to
> +        # True *before* any calls to setconfig(), otherwise you'll get
> +        # infinite recursion between setconfig and this method.
> +        #
> +        # TODO: We should extract an inner method in setconfig() to
> +        # avoid this weirdness.
> +        self._tweaked = True
> +        tmpcfg = config.config()
> +        tmpcfg.parse('<tweakdefaults>', tweakrc)
> +        for section in tmpcfg:
> +            for name, value in tmpcfg.items(section):
> +                if not self.hasconfig(section, name):
> +                    self.setconfig(section, name, value, "<tweakdefaults>")
> +
>      def copy(self):
>          return self.__class__(self)
>
> @@ -387,6 +424,7 @@ class ui(object):
>          for cfg in (self._ocfg, self._tcfg, self._ucfg):
>              cfg.set(section, name, value, source)
>          self.fixconfig(section=section)
> +        self._maybetweakdefaults()
>
>      def _data(self, untrusted):
>          return untrusted and self._ucfg or self._tcfg
> diff --git a/tests/test-status.t b/tests/test-status.t
> --- a/tests/test-status.t
> +++ b/tests/test-status.t
> @@ -107,6 +107,29 @@ combining patterns with root and pattern
>    ? a/in_a
>    ? b/in_b
>
> +tweaking defaults works
> +  $ hg status --cwd a --config ui.tweakdefaults=yes
> +  ? 1/in_a_1
> +  ? in_a
> +  ? ../b/1/in_b_1
> +  ? ../b/2/in_b_2
> +  ? ../b/in_b
> +  ? ../in_root
> +  $ HGPLAIN=1 hg status --cwd a --config ui.tweakdefaults=yes
> +  ? a/1/in_a_1 (glob)
> +  ? a/in_a (glob)
> +  ? b/1/in_b_1 (glob)
> +  ? b/2/in_b_2 (glob)
> +  ? b/in_b (glob)
> +  ? in_root
> +  $ HGPLAINEXCEPT=tweakdefaults hg status --cwd a --config ui.tweakdefaults=yes
> +  ? 1/in_a_1
> +  ? in_a
> +  ? ../b/1/in_b_1
> +  ? ../b/2/in_b_2
> +  ? ../b/in_b
> +  ? ../in_root
> +
>  relative paths can be requested
>
>    $ cat >> $HGRCPATH <<EOF
> @@ -128,6 +151,19 @@ relative paths can be requested
>    ? b/in_b (glob)
>    ? in_root
>
> +if relative paths are explicitly off, tweakdefaults doesn't change it

At what config level is the tweaking done? I didn't understand the
code well enough to tell. Concretely, let's say I have
ui.tweakdefaults=yes in my system setting and
command.status.relative=no in my local settings would I get relative
status or not? I would assume not. How about the inverse
(command.status.relative=no in my system settings and
ui.tweakdefaults=yes in my local settings)? I'm not sure what I would
expect in this case, but probably to not get relative status. (It's a
weird example because there's no reason to set
command.status.relative=no in the system settings, but there are
probably more reasonable examples for non-boolean options).

> +  $ cat >> $HGRCPATH <<EOF
> +  > [commands]
> +  > status.relative = False
> +  > EOF
> +  $ hg status --cwd a --config ui.tweakdefaults=yes
> +  ? a/1/in_a_1 (glob)
> +  ? a/in_a (glob)
> +  ? b/1/in_b_1 (glob)
> +  ? b/2/in_b_2 (glob)
> +  ? b/in_b (glob)
> +  ? in_root
> +
>    $ cd ..
>
>    $ hg init repo2
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list