Patchwork D9926: config: track the "level" of a value

login
register
mail settings
Submitter phabricator
Date Jan. 30, 2021, 1:40 a.m.
Message ID <differential-rev-PHID-DREV-l3ngfjv5c4n5dwbixz5c-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48237/
State Superseded
Headers show

Comments

phabricator - Jan. 30, 2021, 1:40 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Config value now remember the "level" of the config that loaded it. This will be
  used to ensure good priority management for alias.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9926

AFFECTED FILES
  mercurial/config.py
  mercurial/ui.py

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -304,6 +304,11 @@ 
                 if k in self.environ:
                     self._exportableenviron[k] = self.environ[k]
 
+    def _new_source(self):
+        self._ocfg.new_source()
+        self._tcfg.new_source()
+        self._ucfg.new_source()
+
     @classmethod
     def load(cls):
         """Create a ui and load global and user configs"""
@@ -315,6 +320,7 @@ 
             elif t == b'resource':
                 u.read_resource_config(f, trust=True)
             elif t == b'items':
+                u._new_source()
                 sections = set()
                 for section, name, value, source in f:
                     # do not set u._ocfg
@@ -327,6 +333,7 @@ 
             else:
                 raise error.ProgrammingError(b'unknown rctype: %s' % t)
         u._maybetweakdefaults()
+        u._new_source()  # anything after that is a different level
         return u
 
     def _maybetweakdefaults(self):
diff --git a/mercurial/config.py b/mercurial/config.py
--- a/mercurial/config.py
+++ b/mercurial/config.py
@@ -22,11 +22,19 @@ 
 
 class config(object):
     def __init__(self, data=None):
+        self._current_source_level = 0
         self._data = {}
         self._unset = []
         if data:
             for k in data._data:
                 self._data[k] = data[k].copy()
+            self._current_source_level = data._current_source_level + 1
+
+    def new_source(self):
+        """increment the source counter
+
+        This is used to define source priority when reading"""
+        self._current_source_level += 1
 
     def copy(self):
         return config(self)
@@ -45,6 +53,9 @@ 
             yield d
 
     def update(self, src):
+        current_level = self._current_source_level
+        current_level += 1
+        max_level = self._current_source_level
         for s, n in src._unset:
             ds = self._data.get(s, None)
             if ds is not None and n in ds:
@@ -56,7 +67,12 @@ 
                 self._data[s] = ds.preparewrite()
             else:
                 self._data[s] = util.cowsortdict()
-            self._data[s].update(src._data[s])
+            for k, v in src._data[s].items():
+                value, source, level = v
+                level += current_level
+                max_level = max(level, current_level)
+                self._data[s][k] = (value, source, level)
+        self._current_source_level = max_level
 
     def _get(self, section, item):
         return self._data.get(section, {}).get(item)
@@ -85,12 +101,18 @@ 
             return b""
         return result[1]
 
+    def level(self, section, item):
+        result = self._get(section, item)
+        if result is None:
+            return None
+        return result[2]
+
     def sections(self):
         return sorted(self._data.keys())
 
     def items(self, section):
         items = pycompat.iteritems(self._data.get(section, {}))
-        return [(k, v) for (k, (v, s)) in items]
+        return [(k, v[0]) for (k, v) in items]
 
     def set(self, section, item, value, source=b""):
         if pycompat.ispy3:
@@ -107,7 +129,7 @@ 
             self._data[section] = util.cowsortdict()
         else:
             self._data[section] = self._data[section].preparewrite()
-        self._data[section][item] = (value, source)
+        self._data[section][item] = (value, source, self._current_source_level)
 
     def alter(self, section, key, new_value):
         """alter a value, to be used by `ui.fixconfig`"""
@@ -213,6 +235,7 @@ 
             raise error.ConfigError(message, (b"%s:%d" % (src, line)))
 
     def read(self, path, fp=None, sections=None, remap=None):
+        self.new_source()
         if not fp:
             fp = util.posixfile(path, b'rb')
         assert (
@@ -227,6 +250,8 @@ 
         def include(rel, remap, sections):
             abs = os.path.normpath(os.path.join(dir, rel))
             self.read(abs, remap=remap, sections=sections)
+            # anything after the include has a higher level
+            self.new_source()
 
         self.parse(
             path, fp.read(), sections=sections, remap=remap, include=include