46 def __iter__(self): |
43 def __iter__(self): |
47 for d in self.sections(): |
44 for d in self.sections(): |
48 yield d |
45 yield d |
49 |
46 |
50 def update(self, src): |
47 def update(self, src): |
51 self._source = self._source.preparewrite() |
|
52 for s, n in src._unset: |
48 for s, n in src._unset: |
53 ds = self._data.get(s, None) |
49 ds = self._data.get(s, None) |
54 if ds is not None and n in ds: |
50 if ds is not None and n in ds: |
55 self._data[s] = ds.preparewrite() |
51 self._data[s] = ds.preparewrite() |
56 del self._data[s][n] |
52 del self._data[s][n] |
57 del self._source[(s, n)] |
|
58 for s in src: |
53 for s in src: |
59 ds = self._data.get(s, None) |
54 ds = self._data.get(s, None) |
60 if ds: |
55 if ds: |
61 self._data[s] = ds.preparewrite() |
56 self._data[s] = ds.preparewrite() |
62 else: |
57 else: |
63 self._data[s] = util.cowsortdict() |
58 self._data[s] = util.cowsortdict() |
64 self._data[s].update(src._data[s]) |
59 self._data[s].update(src._data[s]) |
65 self._source.update(src._source) |
60 |
|
61 def _get(self, section, item): |
|
62 return self._data.get(section, {}).get(item) |
66 |
63 |
67 def get(self, section, item, default=None): |
64 def get(self, section, item, default=None): |
68 return self._data.get(section, {}).get(item, default) |
65 result = self._get(section, item) |
69 |
66 if result is None: |
70 def backup(self, section, item): |
67 return default |
|
68 return result[0] |
|
69 |
|
70 def backup(self, section, key): |
71 """return a tuple allowing restore to reinstall a previous value |
71 """return a tuple allowing restore to reinstall a previous value |
72 |
72 |
73 The main reason we need it is because it handles the "no data" case. |
73 The main reason we need it is because it handles the "no data" case. |
74 """ |
74 """ |
75 try: |
75 try: |
76 value = self._data[section][item] |
76 item = self._data[section][key] |
77 source = self.source(section, item) |
|
78 return (section, item, value, source) |
|
79 except KeyError: |
77 except KeyError: |
80 return (section, item) |
78 return (section, key) |
|
79 else: |
|
80 return (section, key) + item |
81 |
81 |
82 def source(self, section, item): |
82 def source(self, section, item): |
83 return self._source.get((section, item), b"") |
83 result = self._get(section, item) |
|
84 if result is None: |
|
85 return b"" |
|
86 return result[1] |
84 |
87 |
85 def sections(self): |
88 def sections(self): |
86 return sorted(self._data.keys()) |
89 return sorted(self._data.keys()) |
87 |
90 |
88 def items(self, section): |
91 def items(self, section): |
89 return list(pycompat.iteritems(self._data.get(section, {}))) |
92 items = pycompat.iteritems(self._data.get(section, {})) |
|
93 return [(k, v) for (k, (v, s)) in items] |
90 |
94 |
91 def set(self, section, item, value, source=b""): |
95 def set(self, section, item, value, source=b""): |
92 if pycompat.ispy3: |
96 if pycompat.ispy3: |
93 assert not isinstance( |
97 assert not isinstance( |
94 section, str |
98 section, str |
101 ), b'config values may not be unicode strings on Python 3' |
105 ), b'config values may not be unicode strings on Python 3' |
102 if section not in self: |
106 if section not in self: |
103 self._data[section] = util.cowsortdict() |
107 self._data[section] = util.cowsortdict() |
104 else: |
108 else: |
105 self._data[section] = self._data[section].preparewrite() |
109 self._data[section] = self._data[section].preparewrite() |
106 self._data[section][item] = value |
110 self._data[section][item] = (value, source) |
107 if source: |
|
108 self._source = self._source.preparewrite() |
|
109 self._source[(section, item)] = source |
|
110 |
111 |
111 def alter(self, section, key, new_value): |
112 def alter(self, section, key, new_value): |
112 """alter a value without altering its source or level |
113 """alter a value without altering its source or level |
113 |
114 |
114 This method is meant to be used by `ui.fixconfig` only.""" |
115 This method is meant to be used by `ui.fixconfig` only.""" |
118 assert len(new_item) == size |
119 assert len(new_item) == size |
119 self._data[section][key] = new_item |
120 self._data[section][key] = new_item |
120 |
121 |
121 def restore(self, data): |
122 def restore(self, data): |
122 """restore data returned by self.backup""" |
123 """restore data returned by self.backup""" |
123 self._source = self._source.preparewrite() |
124 if len(data) != 2: |
124 if len(data) == 4: |
|
125 # restore old data |
125 # restore old data |
126 section, item, value, source = data |
126 section, key = data[:2] |
|
127 item = data[2:] |
127 self._data[section] = self._data[section].preparewrite() |
128 self._data[section] = self._data[section].preparewrite() |
128 self._data[section][item] = value |
129 self._data[section][key] = item |
129 self._source[(section, item)] = source |
|
130 else: |
130 else: |
131 # no data before, remove everything |
131 # no data before, remove everything |
132 section, item = data |
132 section, item = data |
133 if section in self._data: |
133 if section in self._data: |
134 self._data[section].pop(item, None) |
134 self._data[section].pop(item, None) |
135 self._source.pop((section, item), None) |
|
136 |
135 |
137 def parse(self, src, data, sections=None, remap=None, include=None): |
136 def parse(self, src, data, sections=None, remap=None, include=None): |
138 sectionre = util.re.compile(br'\[([^\[]+)\]') |
137 sectionre = util.re.compile(br'\[([^\[]+)\]') |
139 itemre = util.re.compile(br'([^=\s][^=]*?)\s*=\s*(.*\S|)') |
138 itemre = util.re.compile(br'([^=\s][^=]*?)\s*=\s*(.*\S|)') |
140 contre = util.re.compile(br'\s+(\S|\S.*\S)\s*$') |
139 contre = util.re.compile(br'\s+(\S|\S.*\S)\s*$') |