configs: pin --configfile configs

Summary:
Previously, only --config configs were pinned in the uiconfig. "pinned"
means that no matter what values were loaded underneath, those pinned values
would not be changed. This allows CLI specified configs to take precendence
regardless of what and when config files are loaded. --configfile configs were
not pinned in the same way, despite it seeming like they should be pinned. In
fact, during clone we "reload" the config, which causes the --configfile value
to be lost.

Let's make --configfile pin all of it's configs as well.

This has a bit of an unfortunate side effect. When we do clone via hg-clone we
pass --configfile /etc/mercurial/repo-specific/$REPO.rc so the clone has the
right configuration. This diff means that those values are now loaded in a
pinned state, so dynamicconfig cannot overwrite them and the values cannot be
deny-listed.

The longterm solution to this would be to stop using --configfile during clone,
and instead use --config remotefilelog.reponame=$REPO and allow dynamicconfig to
generate the rest. But for now it's probably fine to let them be pinned.

Reviewed By: quark-zju

Differential Revision: D26677599

fbshipit-source-id: 2837a5b5d14bb42b49eaf9d1d0019f2ea0620a9e
This commit is contained in:
Durham Goode 2021-03-11 10:11:36 -08:00 committed by Facebook GitHub Bot
parent 36b6b30e0d
commit ed7b192f9a
4 changed files with 52 additions and 53 deletions

View File

@ -615,22 +615,11 @@ def _runcatch(req):
debugtrace = {"pdb": pdb.set_trace}
debugmortem = {"pdb": pdb.post_mortem}
# --config takes prescendence over --configfile, so process
# --configfile first --config second.
for configfile in req.earlyoptions["configfile"]:
req.ui.readconfig(configfile)
# read --config before doing anything else
# (e.g. to change trust settings for reading .hg/hgrc)
cfgs = _parseconfig(req.ui, req.earlyoptions["config"])
_parseconfig(req.ui, req.earlyoptions)
if req.repo:
for configfile in req.earlyoptions["configfile"]:
req.repo.ui.readconfig(configfile)
# copy configs that were passed on the cmdline (--config) to
# the repo ui
for sec, name, val in cfgs:
req.repo.ui.setconfig(sec, name, val, source="--config")
_parseconfig(req.repo.ui, req.earlyoptions)
# developer config: ui.debugger
debugger = ui.config("ui", "debugger")
@ -888,26 +877,32 @@ def _parse(ui, args):
return (cmd, cmd and entry[0] or None, args, options, cmdoptions, aliases)
def _parseconfig(ui, config):
def _parseconfig(ui, earlyoptions):
"""parse the --config options from the command line"""
configs = []
for cfg in config:
# --config takes prescendence over --configfile, so process
# --configfile first then --config second.
for configfile in earlyoptions["configfile"]:
tempconfig = uiconfig.uiconfig()
tempconfig.readconfig(configfile)
# Set the configfile values one-by-one so they get put in the internal
# _pinnedconfigs list and don't get overwritten in the future.
for section, name, value in tempconfig.walkconfig():
ui.setconfig(section, name, value, configfile)
for cfg in earlyoptions["config"]:
try:
name, value = [cfgelem.strip() for cfgelem in cfg.split("=", 1)]
section, name = name.split(".", 1)
if not section or not name:
raise IndexError
ui.setconfig(section, name, value, "--config")
configs.append((section, name, value))
except (IndexError, ValueError):
raise error.Abort(
_("malformed --config option: %r " "(use --config section.name=value)")
% cfg
)
return configs
def _earlyparseopts(ui, args):
try:

View File

@ -43,4 +43,4 @@ Order relative to --config
Attribution works
$ hg config --configfile $TESTTMP/simple.rc mysection --debug
$TESTTMP/simple.rc:2: mysection.myname=myvalue
$TESTTMP/simple.rc: mysection.myname=myvalue

View File

@ -190,8 +190,6 @@ Verify we load and verify dynamicconfigs during clone
> bar=True
> EOF
$ hg clone ssh://user@dummy/server client2 --configfile $TESTTMP/good_hgrc --config configs.testdynamicconfigsubset=good_hgrc --config configs.validatedynamicconfig=True --config configs.mismatchwarn=True
Config mismatch: foo.bar has 'None' (dynamic) vs 'True' (file)
Config mismatch: foo.bar has 'None' (dynamic) vs 'True' (file)
no changes found
Hook ran!
updating to branch default
@ -210,10 +208,13 @@ Verify unicode characters in configs can be logged to our sampling extension
> [foo]
> bar = Å
> EOF
$ hg -R client2 log -q -r . --configfile $TESTTMP/good_hgrc --config configs.validatedynamicconfig=True --config configs.mismatchsampling=1 --config extensions.sampling= --config sampling.filepath=$TESTTMP/sampling.log --config sampling.key.config_mismatch=mismatches --config configs.testdynamicconfigsubset=good_hgrc
$ cp client2/.hg/hgrc client2/.hg/hgrc.bak
$ echo "%include $TESTTMP/good_hgrc" >> client2/.hg/hgrc
$ hg -R client2 log -q -r . --config configs.validatedynamicconfig=True --config configs.mismatchsampling=1 --config extensions.sampling= --config sampling.filepath=$TESTTMP/sampling.log --config sampling.key.config_mismatch=mismatches --config configs.testdynamicconfigsubset=good_hgrc
000000000000
$ cat $TESTTMP/sampling.log
{"category": "mismatches", "data": {"actual": null, "config": "foo.bar", "expected": "\\u00c5", "metrics_type": "config_mismatch", "msg": "Config mismatch: foo.bar has 'None' (dynamic) vs '\\u00c5' (file)\\n", "repo": "reponame-default"}}\x00{"category": "mismatches", "data": {"actual": null, "config": "foo.bar", "expected": "\\u00c5", "metrics_type": "config_mismatch", "msg": "Config mismatch: foo.bar has 'None' (dynamic) vs '\\u00c5' (file)\\n", "repo": "reponame-default"}}\x00 (no-eol) (esc)
$ mv client2/.hg/hgrc.bak client2/.hg/hgrc
Verify hgrc.dynamic is updated even if the original command is outside the repo
$ echo "[junk_on_the_end]" >> client2/.hg/hgrc.dynamic

View File

@ -16,7 +16,8 @@ testui.setconfig("devel", "all-warnings", False, "test")
parsed = dispatch._parseconfig(
testui,
[
{
"config": [
"values.string=string value",
"values.bool1=true",
"values.bool2=false",
@ -46,6 +47,8 @@ parsed = dispatch._parseconfig(
"date.birth=2005-04-19T00:00:00",
"date.invalid=invalid",
],
"configfile": [],
},
)
print(repr(testui.configitems("values")))