diff --git a/eden/scm/edenscm/mercurial/configitems.py b/eden/scm/edenscm/mercurial/configitems.py index c04869e898..965174a356 100644 --- a/eden/scm/edenscm/mercurial/configitems.py +++ b/eden/scm/edenscm/mercurial/configitems.py @@ -165,7 +165,6 @@ coreconfigitem("commit", "description-size-limit", default=None) coreconfigitem("commit", "extras-size-limit", default=None) coreconfigitem("committemplate", ".*", default=None, generic=True) coreconfigitem("connectionpool", "lifetime", default=None) -coreconfigitem("configs", "autogeneratedynamicconfig", default=False) coreconfigitem("configs", "generationtime", default=-1) coreconfigitem("configs", "loaddynamicconfig", default=False) coreconfigitem("configs", "mismatchsampling", default=10000) diff --git a/eden/scm/edenscm/mercurial/uiconfig.py b/eden/scm/edenscm/mercurial/uiconfig.py index 1599b9d517..07a344680d 100644 --- a/eden/scm/edenscm/mercurial/uiconfig.py +++ b/eden/scm/edenscm/mercurial/uiconfig.py @@ -13,6 +13,7 @@ from __future__ import absolute_import import contextlib import os import random +import re import subprocess import time from typing import List, Optional, Tuple @@ -562,15 +563,33 @@ def loaddynamicconfig(ui, path): hgrcdyn = os.path.join(path, "hgrc.dynamic") - if ui.configbool("configs", "autogeneratedynamicconfig"): - if not os.path.exists(hgrcdyn): - try: - ui.debug("synchronously generating dynamic config\n") - subprocess.check_call(["hg", "debugdynamicconfig"]) - except Exception as ex: - raise error.Abort( - _("unable to generate dynamic Mercurial config: %s") % ex - ) + # Check the version of the existing generated config. If it doesn't + # match the current version, regenerate it immediately. + try: + with open(hgrcdyn, "r") as f: + content = f.read() + matches = re.search("^# version=(.*)$", content, re.MULTILINE) + version = matches.group(1) if matches else None + except IOError: + version = None + + if version is None or version != util.version(): + try: + ui.debug( + "synchronously generating dynamic config - new version %s, old version %s\n" + % (util.version(), version) + ) + reponame = ui.config("remotefilelog", "reponame") or "" + generatedynamicconfig(ui, reponame, path) + except Exception as ex: + # TODO: Eventually this should throw an exception, once we're + # confident it's reliable. + ui.log( + "exceptions", + "unable to generate dynamicconfig", + exception_type="DynamicconfigGeneration", + exception_msg="unable to generate dynamicconfig: %s" % str(ex), + ) ui.readconfig(hgrcdyn, path) @@ -617,15 +636,14 @@ def validatedynamicconfig(ui): ] # Configs that are allowed to be different, usually because they must come # from external configuration (like hotfixes). - whitelist = [ - ("extensions", "hotfix"), - ] + whitelist = [("extensions", "hotfix")] testrcs = ui.configlist("configs", "testdynamicconfigsubset") if testrcs: originalrcs.extend(testrcs) - issues = ui._uiconfig._rcfg.ensure_location_supersets("hgrc.dynamic", - originalrcs, whitelist) + issues = ui._uiconfig._rcfg.ensure_location_supersets( + "hgrc.dynamic", originalrcs, whitelist + ) for section, key, dynamic_value, file_value in issues: msg = _("Config mismatch: %s.%s has '%s' (dynamic) vs '%s' (file)\n") % ( @@ -639,20 +657,24 @@ def validatedynamicconfig(ui): samplerate = ui.configint("configs", "mismatchsampling") if random.randint(1, samplerate) == 1: + reponame = ui.config("remotefilelog", "reponame") ui.log( "config_mismatch", msg, config="%s.%s" % (section, key), expected=file_value, actual=dynamic_value, + repo=reponame or "unknown", ) + def applydynamicconfig(ui, reponame): if ui.configbool("configs", "loaddynamicconfig"): dynamicconfig.applydynamicconfig(ui._uiconfig._rcfg._rcfg, reponame) validatedynamicconfig(ui) + def generatedynamicconfig(ui, reponame, sharedpath): if ui.configbool("configs", "loaddynamicconfig"): dynamicconfig.generatedynamicconfig(reponame, sharedpath) diff --git a/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/Cargo.toml b/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/Cargo.toml index 6224bb97c2..2772bd1cf7 100644 --- a/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/Cargo.toml +++ b/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/Cargo.toml @@ -10,6 +10,7 @@ cpython-ext = { path = "../../../../lib/cpython-ext", default-features = false } dynamicconfig = { path = "../../../../lib/dynamicconfig" } configparser = { path = "../../../../lib/configparser" } pyconfigparser = { path = "../pyconfigparser" } +version = { path = "../../../../lib/version" } [features] python2 = ["cpython/python27-sys", "cpython-ext/python2"] diff --git a/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/src/lib.rs b/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/src/lib.rs index db85d8e6d8..1cda1169a0 100644 --- a/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/src/lib.rs +++ b/eden/scm/edenscmnative/bindings/modules/pydynamicconfig/src/lib.rs @@ -9,7 +9,6 @@ use std::fs; -use anyhow::{format_err, Error}; use cpython::*; use cpython_ext::{error::ResultPyErrExt, PyNone, PyPathBuf}; @@ -68,7 +67,8 @@ fn generatedynamicconfig( .map_pyerr(py)?; let config_str = config.to_string(); let config_str = format!( - "# Generated by `hg debugdynamicconfig` - DO NOT MODIFY\n{}", + "# version={}\n# Generated by `hg debugdynamicconfig` - DO NOT MODIFY\n{}", + ::version::VERSION, config_str ); diff --git a/eden/scm/lib/hgcommands/src/commands.rs b/eden/scm/lib/hgcommands/src/commands.rs index 3f4f0a425b..0921ffcde4 100644 --- a/eden/scm/lib/hgcommands/src/commands.rs +++ b/eden/scm/lib/hgcommands/src/commands.rs @@ -298,7 +298,8 @@ pub fn debugdynamicconfig(_opts: NoOpts, _io: &mut IO, repo: Repo) -> Result let config = Generator::new(repo_name)?.execute()?; let config_str = config.to_string(); let config_str = format!( - "# Generated by `hg debugdynamicconfig` - DO NOT MODIFY\n{}", + "# version={}\n# Generated by `hg debugdynamicconfig` - DO NOT MODIFY\n{}", + ::version::VERSION, config_str ); diff --git a/eden/scm/tests/test-debugdynamicconfig.t b/eden/scm/tests/test-debugdynamicconfig.t index 13f1e7588b..cc832c4b8d 100644 --- a/eden/scm/tests/test-debugdynamicconfig.t +++ b/eden/scm/tests/test-debugdynamicconfig.t @@ -16,6 +16,7 @@ Verify it can be manually generated $ hg debugdynamicconfig $ cat .hg/hgrc.dynamic + # version=4.4.2* (glob) # Generated by `hg debugdynamicconfig` - DO NOT MODIFY [section] key=value @@ -27,10 +28,9 @@ Verify it can be automatically synchronously generated $ rm .hg/hgrc.dynamic $ hg config section.key - [1] - $ hg config section.key --config configs.autogeneratedynamicconfig=True value $ cat .hg/hgrc.dynamic + # version=4.4.2* (glob) # Generated by `hg debugdynamicconfig` - DO NOT MODIFY [section] key=value @@ -51,6 +51,7 @@ Verify it can be automatically asynchronously regenerated $ hg config section2.key2 value2 $ cat .hg/hgrc.dynamic + # version=4.4.2* (glob) # Generated by `hg debugdynamicconfig` - DO NOT MODIFY [section] key=value @@ -83,6 +84,7 @@ Verify we generate and load from a shared repo $ test -f .hg/hgrc.dynamic [1] $ cat ../shared/.hg/hgrc.dynamic + # version=4.4.2* (glob) # Generated by `hg debugdynamicconfig` - DO NOT MODIFY [section] key=value @@ -93,6 +95,33 @@ Verify we generate and load from a shared repo $ hg config section.key value +Verify we regenerate configs if the Mercurial version differs + $ cat > ../shared/.hg/hgrc.dynamic < # version=1 + > [section3] + > key3=value3 + > EOF + $ hg config section3.key3 + [1] + $ hg config section.key + value + $ cat ../shared/.hg/hgrc.dynamic + # version=4.4.2* (glob) + # Generated by `hg debugdynamicconfig` - DO NOT MODIFY + [section] + key=value + + [section2] + key2=value2 + +Verify we don't regenerate configs if the Mercurial version hasn't changed + $ cat >> ../shared/.hg/hgrc.dynamic < [section3] + > key3=value3 + > EOF + $ hg config section3.key3 + value3 + Verify we load dynamicconfigs during clone $ newserver server $ cd $TESTTMP @@ -109,6 +138,7 @@ Verify we load dynamicconfigs during clone Hook ran! Hook ran! $ cat client2/.hg/hgrc.dynamic + # version=4.4.2* (glob) # Generated by `hg debugdynamicconfig` - DO NOT MODIFY [hooks] pretxnclose=echo "Hook ran!"