mercurial/config.py
author Arseniy Alekseyev <aalekseyev@janestreet.com
Thu, 24 Oct 2024 17:35:53 +0200
changeset 52081 a021da4ec509
parent 51863 f4733654f144
permissions -rw-r--r--
merge: add a config to allow conflict-free merge of changes on adjacent lines This change adds a config to make it no longer a conflict to merge changes made on adjacent lines. The reason these changes are considered a conflict is that there's no region of text at the relevant position (sync region) that's kept unchanged by both sides of the merge. The problem can be solved by making the sync regions being a bit more powerful: we can keep a 0-length sync region if we find that a block unchanged by one side is ajacent to a block unchanged by the other side. Since these 0-length sync regions are emitted using the ~same algorithm as the normal non-empty sync regions, this change involves no arbitrary decisions and I expect it to work pretty well. 0-length sync regions do create an ambiguity in a special case where two pairs of adjacent regions "meet" at the same point. This corresponds to an insertion made at the same place by the two sides of the merge, and this still results in a conflict.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8229
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     1
# config.py - configuration parsing for Mercurial
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     2
#
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46622
diff changeset
     3
#  Copyright 2009 Olivia Mackall <olivia@selenic.com> and others
8229
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     4
#
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10042
diff changeset
     6
# GNU General Public License version 2 or any later version.
8229
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     7
51863
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 51289
diff changeset
     8
from __future__ import annotations
25923
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     9
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    10
import errno
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    11
import os
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    12
51289
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
    13
from typing import (
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
    14
    List,
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
    15
    Tuple,
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
    16
)
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
    17
25923
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    18
from .i18n import _
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    19
from . import (
43276
d201a637c971 py3: encode underlying error message during parse error of %include
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 43106
diff changeset
    20
    encoding,
25923
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    21
    error,
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    22
    util,
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    23
)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    25
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48920
diff changeset
    26
class config:
45254
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
    27
    def __init__(self, data=None):
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    28
        self._current_source_level = 0
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
        self._data = {}
19087
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    30
        self._unset = []
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
        if data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
            for k in data._data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
                self._data[k] = data[k].copy()
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    34
            self._current_source_level = data._current_source_level + 1
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    35
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    36
    def new_source(self):
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    37
        """increment the source counter
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    38
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    39
        This is used to define source priority when reading"""
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    40
        self._current_source_level += 1
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    41
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
    def copy(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
        return config(self)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    44
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    45
    def __contains__(self, section):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
        return section in self._data
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    47
27696
e70c97cc9243 config: add hasconfig method and supporting plumbing
Bryan O'Sullivan <bos@serpentine.com>
parents: 25923
diff changeset
    48
    def hasitem(self, section, item):
e70c97cc9243 config: add hasconfig method and supporting plumbing
Bryan O'Sullivan <bos@serpentine.com>
parents: 25923
diff changeset
    49
        return item in self._data.get(section, {})
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    50
8186
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    51
    def __getitem__(self, section):
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    52
        return self._data.get(section, {})
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    53
8186
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    54
    def __iter__(self):
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    55
        for d in self.sections():
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    56
            yield d
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    57
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    58
    def update(self, src):
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    59
        current_level = self._current_source_level
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    60
        current_level += 1
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    61
        max_level = self._current_source_level
19087
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    62
        for s, n in src._unset:
34357
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    63
            ds = self._data.get(s, None)
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    64
            if ds is not None and n in ds:
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    65
                self._data[s] = ds.preparewrite()
19087
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    66
                del self._data[s][n]
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    67
        for s in src:
34357
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    68
            ds = self._data.get(s, None)
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    69
            if ds:
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    70
                self._data[s] = ds.preparewrite()
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    71
            else:
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
    72
                self._data[s] = util.cowsortdict()
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    73
            for k, v in src._data[s].items():
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    74
                value, source, level = v
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    75
                level += current_level
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    76
                max_level = max(level, current_level)
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    77
                self._data[s][k] = (value, source, level)
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
    78
        self._current_source_level = max_level
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    79
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    80
    def _get(self, section, item):
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    81
        return self._data.get(section, {}).get(item)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
    82
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
    def get(self, section, item, default=None):
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    84
        result = self._get(section, item)
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    85
        if result is None:
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    86
            return default
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    87
        return result[0]
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    88
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    89
    def backup(self, section, key):
17527
6e11d5cf8e39 spelling: value
timeless@mozdev.org
parents: 16944
diff changeset
    90
        """return a tuple allowing restore to reinstall a previous value
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    91
17530
0dff04ffa15d grammar: it-handles
timeless@mozdev.org
parents: 17527
diff changeset
    92
        The main reason we need it is because it handles the "no data" case.
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    93
        """
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    94
        try:
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    95
            item = self._data[section][key]
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    96
        except KeyError:
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    97
            return (section, key)
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    98
        else:
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
    99
            return (section, key) + item
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   100
8198
cf9accffd0b3 config: getsource -> source
Matt Mackall <mpm@selenic.com>
parents: 8193
diff changeset
   101
    def source(self, section, item):
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   102
        result = self._get(section, item)
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   103
        if result is None:
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   104
            return b""
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   105
        return result[1]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   106
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   107
    def level(self, section, item):
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   108
        result = self._get(section, item)
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   109
        if result is None:
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   110
            return None
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   111
        return result[2]
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   112
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   113
    def sections(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
        return sorted(self._data.keys())
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   115
51289
7bd7fcc711f2 pytype: drop the last inline type comment
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50929
diff changeset
   116
    def items(self, section: bytes) -> List[Tuple[bytes, bytes]]:
48920
b4ab4fd23199 config: remove pycompat.iteritems()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48890
diff changeset
   117
        items = self._data.get(section, {}).items()
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   118
        return [(k, v[0]) for (k, v) in items]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   119
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   120
    def set(self, section, item, value, source=b""):
48890
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   121
        assert not isinstance(
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   122
            section, str
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   123
        ), b'config section may not be unicode strings on Python 3'
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   124
        assert not isinstance(
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   125
            item, str
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   126
        ), b'config item may not be unicode strings on Python 3'
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   127
        assert not isinstance(
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   128
            value, str
f5127b87f160 config: remove conditional asserts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   129
        ), b'config values may not be unicode strings on Python 3'
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
        if section not in self:
34357
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
   131
            self._data[section] = util.cowsortdict()
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
   132
        else:
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
   133
            self._data[section] = self._data[section].preparewrite()
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   134
        self._data[section][item] = (value, source, self._current_source_level)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   135
46620
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   136
    def alter(self, section, key, new_value):
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   137
        """alter a value without altering its source or level
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   138
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   139
        This method is meant to be used by `ui.fixconfig` only."""
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   140
        item = self._data[section][key]
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   141
        size = len(item)
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   142
        new_item = (new_value,) + item[1:]
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   143
        assert len(new_item) == size
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   144
        self._data[section][key] = new_item
7621ab4005bf config: use a new `alter` method in `fixconfig`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45942
diff changeset
   145
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   146
    def restore(self, data):
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   147
        """restore data returned by self.backup"""
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   148
        if len(data) != 2:
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   149
            # restore old data
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   150
            section, key = data[:2]
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   151
            item = data[2:]
34357
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
   152
            self._data[section] = self._data[section].preparewrite()
46621
d3df397e7a59 config: track "source" along side value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46620
diff changeset
   153
            self._data[section][key] = item
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   154
        else:
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   155
            # no data before, remove everything
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   156
            section, item = data
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   157
            if section in self._data:
22037
8665c647da6e config: fix restoreconfig of non existing config
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 21910
diff changeset
   158
                self._data[section].pop(item, None)
15919
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
   159
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   160
    def parse(self, src, data, sections=None, remap=None, include=None):
30349
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   161
        sectionre = util.re.compile(br'\[([^\[]+)\]')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   162
        itemre = util.re.compile(br'([^=\s][^=]*?)\s*=\s*(.*\S|)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   163
        contre = util.re.compile(br'\s+(\S|\S.*\S)\s*$')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   164
        emptyre = util.re.compile(br'(;|#|\s*$)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   165
        commentre = util.re.compile(br'(;|#)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   166
        unsetre = util.re.compile(br'%unset\s+(\S+)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   167
        includere = util.re.compile(br'%include\s+(\S|\S.*\S)\s*$')
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   168
        section = b""
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
        item = None
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
        line = 0
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
   171
        cont = False
8180
6fc30fe7f3e7 hgweb: use config.config
Matt Mackall <mpm@selenic.com>
parents: 8144
diff changeset
   172
34713
e5a2cfc524d4 config: allow remapping the default section
Yuya Nishihara <yuya@tcha.org>
parents: 34454
diff changeset
   173
        if remap:
e5a2cfc524d4 config: allow remapping the default section
Yuya Nishihara <yuya@tcha.org>
parents: 34454
diff changeset
   174
            section = remap.get(section, section)
e5a2cfc524d4 config: allow remapping the default section
Yuya Nishihara <yuya@tcha.org>
parents: 34454
diff changeset
   175
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8312
diff changeset
   176
        for l in data.splitlines(True):
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   177
            line += 1
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   178
            if line == 1 and l.startswith(b'\xef\xbb\xbf'):
16348
f350021ee32e config: discard UTF-8 BOM if found
Matt Mackall <mpm@selenic.com>
parents: 15919
diff changeset
   179
                # Someone set us up the BOM
f350021ee32e config: discard UTF-8 BOM if found
Matt Mackall <mpm@selenic.com>
parents: 15919
diff changeset
   180
                l = l[3:]
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
            if cont:
14642
fdcdb221a922 config: handle comment lines in continuations (issue2854)
Matt Mackall <mpm@selenic.com>
parents: 14486
diff changeset
   182
                if commentre.match(l):
fdcdb221a922 config: handle comment lines in continuations (issue2854)
Matt Mackall <mpm@selenic.com>
parents: 14486
diff changeset
   183
                    continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   184
                m = contre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   185
                if m:
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   186
                    if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   187
                        continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   188
                    v = self.get(section, item) + b"\n" + m.group(1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   189
                    self.set(section, item, v, b"%s:%d" % (src, line))
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   190
                    continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   191
                item = None
9469
7f0f882af23d config: abort on indented non-continuation lines (issue1829)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8312
diff changeset
   192
                cont = False
8183
2858ab754995 config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents: 8180
diff changeset
   193
            m = includere.match(l)
25095
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   194
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   195
            if m and include:
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   196
                expanded = util.expandpath(m.group(1))
45254
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   197
                try:
45257
668af67bfd18 config: remove now-unused `abs` argument from `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45256
diff changeset
   198
                    include(expanded, remap=remap, sections=sections)
45254
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   199
                except IOError as inst:
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   200
                    if inst.errno != errno.ENOENT:
45894
9dc1351d0b5f errors: raise ConfigError on failure to parse config file
Martin von Zweigbergk <martinvonz@google.com>
parents: 45777
diff changeset
   201
                        raise error.ConfigError(
45254
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   202
                            _(b"cannot include %s (%s)")
45257
668af67bfd18 config: remove now-unused `abs` argument from `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45256
diff changeset
   203
                            % (expanded, encoding.strtolocal(inst.strerror)),
45254
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   204
                            b"%s:%d" % (src, line),
3f54242781e9 config: remove now-unused support for "includepaths"
Martin von Zweigbergk <martinvonz@google.com>
parents: 45208
diff changeset
   205
                        )
8183
2858ab754995 config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents: 8180
diff changeset
   206
                continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   207
            if emptyre.match(l):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
                continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   209
            m = sectionre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   210
            if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   211
                section = m.group(1)
8298
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
   212
                if remap:
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
   213
                    section = remap.get(section, section)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
                if section not in self:
34357
c41444a39de2 config: use copy-on-write to improve copy performance
Jun Wu <quark@fb.com>
parents: 34131
diff changeset
   215
                    self._data[section] = util.cowsortdict()
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   216
                continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   217
            m = itemre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   218
            if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   219
                item = m.group(1)
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
   220
                cont = True
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   221
                if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   222
                    continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   223
                self.set(section, item, m.group(2), b"%s:%d" % (src, line))
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   224
                continue
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   225
            m = unsetre.match(l)
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   226
            if m:
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   227
                name = m.group(1)
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   228
                if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   229
                    continue
13031
3da456d0c885 code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents: 11292
diff changeset
   230
                if self.get(section, name) is not None:
34454
0efdfb57b05c config: add a missing preparewrite() call
Jun Wu <quark@fb.com>
parents: 34357
diff changeset
   231
                    self._data[section] = self._data[section].preparewrite()
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   232
                    del self._data[section][name]
19087
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
   233
                self._unset.append((section, name))
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   234
                continue
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   235
45777
0883413e09bc config: move message about leading spaces in config to config.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 45257
diff changeset
   236
            message = l.rstrip()
0883413e09bc config: move message about leading spaces in config to config.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 45257
diff changeset
   237
            if l.startswith(b' '):
0883413e09bc config: move message about leading spaces in config to config.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 45257
diff changeset
   238
                message = b"unexpected leading whitespace: %s" % message
45894
9dc1351d0b5f errors: raise ConfigError on failure to parse config file
Martin von Zweigbergk <martinvonz@google.com>
parents: 45777
diff changeset
   239
            raise error.ConfigError(message, (b"%s:%d" % (src, line)))
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   240
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   241
    def read(self, path, fp=None, sections=None, remap=None):
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   242
        self.new_source()
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   243
        if not fp:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   244
            fp = util.posixfile(path, b'rb')
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45894
diff changeset
   245
        assert (
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45894
diff changeset
   246
            getattr(fp, 'mode', 'rb') == 'rb'
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45894
diff changeset
   247
        ), b'config files must be opened in binary mode, got fp=%r mode=%r' % (
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45894
diff changeset
   248
            fp,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45894
diff changeset
   249
            fp.mode,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   250
        )
45208
f7f142d74df3 config: pass both relative and absolute paths to `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   251
45256
83ca8d6f3206 config: re-calculate absolute %include path in `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45254
diff changeset
   252
        dir = os.path.dirname(path)
83ca8d6f3206 config: re-calculate absolute %include path in `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45254
diff changeset
   253
45257
668af67bfd18 config: remove now-unused `abs` argument from `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45256
diff changeset
   254
        def include(rel, remap, sections):
45256
83ca8d6f3206 config: re-calculate absolute %include path in `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 45254
diff changeset
   255
            abs = os.path.normpath(os.path.join(dir, rel))
45208
f7f142d74df3 config: pass both relative and absolute paths to `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   256
            self.read(abs, remap=remap, sections=sections)
46622
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   257
            # anything after the include has a higher level
a3dced4b7b04 config: track the "level" of a value
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46621
diff changeset
   258
            self.new_source()
45208
f7f142d74df3 config: pass both relative and absolute paths to `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   259
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   260
        self.parse(
45208
f7f142d74df3 config: pass both relative and absolute paths to `include` callback
Martin von Zweigbergk <martinvonz@google.com>
parents: 43506
diff changeset
   261
            path, fp.read(), sections=sections, remap=remap, include=include
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41317
diff changeset
   262
        )