mercurial/config.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Sat, 17 Jun 2017 18:41:55 +0200
changeset 33001 0d757af1ea67
parent 32358 6a773d3050c9
child 34146 0fa781320203
permissions -rw-r--r--
configitems: add a basic class to hold config item information The goal of this class is allow explicit declaration for the available config option. This class will hold the data for one specific config item. To keep it simple we start centralizing the handling of the default config value. In the future we can expect more data to be carried on this class. For example: - documentation, - status (experimental, advanced, normal, deprecated), - aliases, - expected type, - etc...
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
#
ddf3d6656e7c config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 8222
diff changeset
     3
#  Copyright 2009 Matt Mackall <mpm@selenic.com> and others
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
25923
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     8
from __future__ import absolute_import
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
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    13
from .i18n import _
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    14
from . import (
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    15
    error,
31315
c920efa9d34b config: guard against setconfig specifying unicode values on py3
Augie Fackler <raf@durin42.com>
parents: 31186
diff changeset
    16
    pycompat,
25923
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    17
    util,
a027a0813b44 config: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    18
)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
8186
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    20
class config(object):
31383
d30fb3de4b40 config: avoid using a mutable default
Martijn Pieters <mjpieters@fb.com>
parents: 31315
diff changeset
    21
    def __init__(self, data=None, includepaths=None):
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
        self._data = {}
8185
dc10a7a3f1d4 config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents: 8184
diff changeset
    23
        self._source = {}
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
    24
        self._unset = []
31383
d30fb3de4b40 config: avoid using a mutable default
Martijn Pieters <mjpieters@fb.com>
parents: 31315
diff changeset
    25
        self._includepaths = includepaths or []
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
        if data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
            for k in data._data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
                self._data[k] = data[k].copy()
8185
dc10a7a3f1d4 config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents: 8184
diff changeset
    29
            self._source = data._source.copy()
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
    def copy(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
        return config(self)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    def __contains__(self, section):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
        return section in self._data
27696
e70c97cc9243 config: add hasconfig method and supporting plumbing
Bryan O'Sullivan <bos@serpentine.com>
parents: 25923
diff changeset
    34
    def hasitem(self, section, item):
e70c97cc9243 config: add hasconfig method and supporting plumbing
Bryan O'Sullivan <bos@serpentine.com>
parents: 25923
diff changeset
    35
        return item in self._data.get(section, {})
8186
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    36
    def __getitem__(self, section):
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    37
        return self._data.get(section, {})
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    38
    def __iter__(self):
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    39
        for d in self.sections():
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
    40
            yield d
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    41
    def update(self, src):
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
    42
        for s, n in src._unset:
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    43
            if s in self and n in self._data[s]:
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    44
                del self._data[s][n]
7d82ad4b3727 config: discard "%unset" values defined in the other files read in previously
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17537
diff changeset
    45
                del self._source[(s, n)]
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    46
        for s in src:
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
            if s not in self:
21813
c2262004c2e2 config: move config.sortdict class into util
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 20789
diff changeset
    48
                self._data[s] = util.sortdict()
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    49
            self._data[s].update(src._data[s])
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
    50
        self._source.update(src._source)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
    def get(self, section, item, default=None):
8185
dc10a7a3f1d4 config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents: 8184
diff changeset
    52
        return self._data.get(section, {}).get(item, default)
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
    53
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    54
    def backup(self, section, item):
17527
6e11d5cf8e39 spelling: value
timeless@mozdev.org
parents: 16944
diff changeset
    55
        """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
    56
17530
0dff04ffa15d grammar: it-handles
timeless@mozdev.org
parents: 17527
diff changeset
    57
        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
    58
        """
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    59
        try:
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    60
            value = self._data[section][item]
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    61
            source = self.source(section, item)
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    62
            return (section, item, value, source)
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    63
        except KeyError:
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    64
            return (section, item)
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    65
8198
cf9accffd0b3 config: getsource -> source
Matt Mackall <mpm@selenic.com>
parents: 8193
diff changeset
    66
    def source(self, section, item):
8185
dc10a7a3f1d4 config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents: 8184
diff changeset
    67
        return self._source.get((section, item), "")
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
    def sections(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
        return sorted(self._data.keys())
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
    def items(self, section):
32358
6a773d3050c9 config: make config.items() return a copy
Martin von Zweigbergk <martinvonz@google.com>
parents: 31488
diff changeset
    71
        return list(self._data.get(section, {}).iteritems())
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
    def set(self, section, item, value, source=""):
31315
c920efa9d34b config: guard against setconfig specifying unicode values on py3
Augie Fackler <raf@durin42.com>
parents: 31186
diff changeset
    73
        if pycompat.ispy3:
c920efa9d34b config: guard against setconfig specifying unicode values on py3
Augie Fackler <raf@durin42.com>
parents: 31186
diff changeset
    74
            assert not isinstance(value, str), (
c920efa9d34b config: guard against setconfig specifying unicode values on py3
Augie Fackler <raf@durin42.com>
parents: 31186
diff changeset
    75
                '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
    76
        if section not in self:
21813
c2262004c2e2 config: move config.sortdict class into util
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 20789
diff changeset
    77
            self._data[section] = util.sortdict()
8185
dc10a7a3f1d4 config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents: 8184
diff changeset
    78
        self._data[section][item] = value
20789
d19c9bdbbf35 config: don't set source when no source is specified - don't overwrite with ''
Mads Kiilerich <madski@unity3d.com>
parents: 19087
diff changeset
    79
        if source:
d19c9bdbbf35 config: don't set source when no source is specified - don't overwrite with ''
Mads Kiilerich <madski@unity3d.com>
parents: 19087
diff changeset
    80
            self._source[(section, item)] = source
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
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
    82
    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
    83
        """restore data returned by self.backup"""
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    84
        if len(data) == 4:
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    85
            # restore old 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
    86
            section, item, value, source = 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
    87
            self._data[section][item] = value
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
            self._source[(section, item)] = source
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    89
        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
    90
            # 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
    91
            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
    92
            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
    93
                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
    94
            self._source.pop((section, item), None)
69e792cf7851 config: have a way to backup and restore value in config
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 14696
diff changeset
    95
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
    96
    def parse(self, src, data, sections=None, remap=None, include=None):
30359
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
    97
        sectionre = util.re.compile(br'\[([^\[]+)\]')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
    98
        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
    99
        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
   100
        emptyre = util.re.compile(br'(;|#|\s*$)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   101
        commentre = util.re.compile(br'(;|#)')
954002426f78 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com>
parents: 27696
diff changeset
   102
        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
   103
        includere = util.re.compile(br'%include\s+(\S|\S.*\S)\s*$')
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
        section = ""
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
        item = None
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
        line = 0
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
   107
        cont = False
8180
6fc30fe7f3e7 hgweb: use config.config
Matt Mackall <mpm@selenic.com>
parents: 8144
diff changeset
   108
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8312
diff changeset
   109
        for l in data.splitlines(True):
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
            line += 1
16348
f350021ee32e config: discard UTF-8 BOM if found
Matt Mackall <mpm@selenic.com>
parents: 15919
diff changeset
   111
            if line == 1 and l.startswith('\xef\xbb\xbf'):
f350021ee32e config: discard UTF-8 BOM if found
Matt Mackall <mpm@selenic.com>
parents: 15919
diff changeset
   112
                # Someone set us up the BOM
f350021ee32e config: discard UTF-8 BOM if found
Matt Mackall <mpm@selenic.com>
parents: 15919
diff changeset
   113
                l = l[3:]
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   114
            if cont:
14642
fdcdb221a922 config: handle comment lines in continuations (issue2854)
Matt Mackall <mpm@selenic.com>
parents: 14486
diff changeset
   115
                if commentre.match(l):
fdcdb221a922 config: handle comment lines in continuations (issue2854)
Matt Mackall <mpm@selenic.com>
parents: 14486
diff changeset
   116
                    continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
                m = contre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   118
                if m:
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   119
                    if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   120
                        continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
                    v = self.get(section, item) + "\n" + m.group(1)
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   122
                    self.set(section, item, v, "%s:%d" % (src, line))
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
                    continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
                item = None
9469
7f0f882af23d config: abort on indented non-continuation lines (issue1829)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 8312
diff changeset
   125
                cont = False
8183
2858ab754995 config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents: 8180
diff changeset
   126
            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
   127
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   128
            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
   129
                expanded = util.expandpath(m.group(1))
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   130
                includepaths = [os.path.dirname(src)] + self._includepaths
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   131
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   132
                for base in includepaths:
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   133
                    inc = os.path.normpath(os.path.join(base, expanded))
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   134
10042
7cdd2a7db2c2 config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents: 9471
diff changeset
   135
                    try:
7cdd2a7db2c2 config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents: 9471
diff changeset
   136
                        include(inc, remap=remap, sections=sections)
25095
3182965b3971 config: give it an includepaths option for looking for config files
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 22419
diff changeset
   137
                        break
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25095
diff changeset
   138
                    except IOError as inst:
14486
4e3eda05189b config: ignore include errors for nonexistent files
Matt Mackall <mpm@selenic.com>
parents: 13664
diff changeset
   139
                        if inst.errno != errno.ENOENT:
4e3eda05189b config: ignore include errors for nonexistent files
Matt Mackall <mpm@selenic.com>
parents: 13664
diff changeset
   140
                            raise error.ParseError(_("cannot include %s (%s)")
4e3eda05189b config: ignore include errors for nonexistent files
Matt Mackall <mpm@selenic.com>
parents: 13664
diff changeset
   141
                                                   % (inc, inst.strerror),
4e3eda05189b config: ignore include errors for nonexistent files
Matt Mackall <mpm@selenic.com>
parents: 13664
diff changeset
   142
                                                   "%s:%s" % (src, line))
8183
2858ab754995 config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents: 8180
diff changeset
   143
                continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
            if emptyre.match(l):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   145
                continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   146
            m = sectionre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   147
            if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   148
                section = m.group(1)
8298
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
   149
                if remap:
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
   150
                    section = remap.get(section, section)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   151
                if section not in self:
21813
c2262004c2e2 config: move config.sortdict class into util
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 20789
diff changeset
   152
                    self._data[section] = util.sortdict()
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
                continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
            m = itemre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   155
            if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
                item = m.group(1)
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
   157
                cont = True
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   158
                if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   159
                    continue
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   160
                self.set(section, item, m.group(2), "%s:%d" % (src, line))
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
                continue
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   162
            m = unsetre.match(l)
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   163
            if m:
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   164
                name = m.group(1)
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   165
                if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
   166
                    continue
13031
3da456d0c885 code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents: 11292
diff changeset
   167
                if self.get(section, name) is not None:
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   168
                    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
   169
                self._unset.append((section, name))
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   170
                continue
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
   171
11288
2123aad24d56 error: add new ParseError for various parsing errors
Matt Mackall <mpm@selenic.com>
parents: 11224
diff changeset
   172
            raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   173
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   174
    def read(self, path, fp=None, sections=None, remap=None):
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
   175
        if not fp:
31164
fd3f4bf9325e config: load included config files in binary mode
Augie Fackler <raf@durin42.com>
parents: 30359
diff changeset
   176
            fp = util.posixfile(path, 'rb')
31186
99c5843b228d config: add sanity assert that files are opened as binary
Augie Fackler <raf@durin42.com>
parents: 31165
diff changeset
   177
        assert getattr(fp, 'mode', r'rb') == r'rb', (
99c5843b228d config: add sanity assert that files are opened as binary
Augie Fackler <raf@durin42.com>
parents: 31165
diff changeset
   178
            'config files must be opened in binary mode, got fp=%r mode=%r' % (
99c5843b228d config: add sanity assert that files are opened as binary
Augie Fackler <raf@durin42.com>
parents: 31165
diff changeset
   179
                fp, fp.mode))
31165
8266802f0fa4 config: pass some optional args as keywords
Augie Fackler <raf@durin42.com>
parents: 31164
diff changeset
   180
        self.parse(path, fp.read(),
8266802f0fa4 config: pass some optional args as keywords
Augie Fackler <raf@durin42.com>
parents: 31164
diff changeset
   181
                   sections=sections, remap=remap, include=self.read)
31488
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   182
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   183
def parselist(value):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   184
    """parse a configuration value as a list of comma/space separated strings
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   185
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   186
    >>> parselist('this,is "a small" ,test')
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   187
    ['this', 'is', 'a small', 'test']
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   188
    """
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   189
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   190
    def _parse_plain(parts, s, offset):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   191
        whitespace = False
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   192
        while offset < len(s) and (s[offset:offset + 1].isspace()
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   193
                                   or s[offset:offset + 1] == ','):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   194
            whitespace = True
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   195
            offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   196
        if offset >= len(s):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   197
            return None, parts, offset
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   198
        if whitespace:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   199
            parts.append('')
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   200
        if s[offset:offset + 1] == '"' and not parts[-1]:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   201
            return _parse_quote, parts, offset + 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   202
        elif s[offset:offset + 1] == '"' and parts[-1][-1] == '\\':
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   203
            parts[-1] = parts[-1][:-1] + s[offset:offset + 1]
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   204
            return _parse_plain, parts, offset + 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   205
        parts[-1] += s[offset:offset + 1]
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   206
        return _parse_plain, parts, offset + 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   207
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   208
    def _parse_quote(parts, s, offset):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   209
        if offset < len(s) and s[offset:offset + 1] == '"': # ""
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   210
            parts.append('')
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   211
            offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   212
            while offset < len(s) and (s[offset:offset + 1].isspace() or
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   213
                    s[offset:offset + 1] == ','):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   214
                offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   215
            return _parse_plain, parts, offset
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   216
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   217
        while offset < len(s) and s[offset:offset + 1] != '"':
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   218
            if (s[offset:offset + 1] == '\\' and offset + 1 < len(s)
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   219
                    and s[offset + 1:offset + 2] == '"'):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   220
                offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   221
                parts[-1] += '"'
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   222
            else:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   223
                parts[-1] += s[offset:offset + 1]
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   224
            offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   225
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   226
        if offset >= len(s):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   227
            real_parts = _configlist(parts[-1])
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   228
            if not real_parts:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   229
                parts[-1] = '"'
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   230
            else:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   231
                real_parts[0] = '"' + real_parts[0]
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   232
                parts = parts[:-1]
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   233
                parts.extend(real_parts)
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   234
            return None, parts, offset
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   235
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   236
        offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   237
        while offset < len(s) and s[offset:offset + 1] in [' ', ',']:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   238
            offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   239
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   240
        if offset < len(s):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   241
            if offset + 1 == len(s) and s[offset:offset + 1] == '"':
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   242
                parts[-1] += '"'
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   243
                offset += 1
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   244
            else:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   245
                parts.append('')
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   246
        else:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   247
            return None, parts, offset
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   248
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   249
        return _parse_plain, parts, offset
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   250
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   251
    def _configlist(s):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   252
        s = s.rstrip(' ,')
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   253
        if not s:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   254
            return []
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   255
        parser, parts, offset = _parse_plain, [''], 0
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   256
        while parser:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   257
            parser, parts, offset = parser(parts, s, offset)
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   258
        return parts
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   259
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   260
    if value is not None and isinstance(value, bytes):
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   261
        result = _configlist(value.lstrip(' ,\n'))
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   262
    else:
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   263
        result = value
a7c687c35119 ui: move configlist parser to config.py
Jun Wu <quark@fb.com>
parents: 31383
diff changeset
   264
    return result or []