comparison mercurial/ui.py @ 8144:fca54469480e

ui: introduce new config parser
author Matt Mackall <mpm@selenic.com>
date Thu, 23 Apr 2009 15:40:10 -0500
parents 507c49e297e1
children c8cb471fc9c2
comparison
equal deleted inserted replaced
8143:507c49e297e1 8144:fca54469480e
5 # This software may be used and distributed according to the terms 5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference. 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 from i18n import _ 8 from i18n import _
9 import errno, getpass, os, re, socket, sys, tempfile 9 import errno, getpass, os, re, socket, sys, tempfile
10 import ConfigParser, traceback, util 10 import config, traceback, util, error
11 11
12 def updateconfig(source, dest, sections=None): 12 _booleans = {'1':True, 'yes':True, 'true':True, 'on':True,
13 if not sections: 13 '0':False, 'no':False, 'false':False, 'off':False}
14 sections = source.sections()
15 for section in sections:
16 if not dest.has_section(section):
17 dest.add_section(section)
18 if not source.has_section(section):
19 continue
20 for name, value in source.items(section, raw=True):
21 dest.set(section, name, value)
22 14
23 class ui(object): 15 class ui(object):
24 def __init__(self, parentui=None): 16 def __init__(self, parentui=None):
25 self.buffers = [] 17 self.buffers = []
26 self.quiet = self.verbose = self.debugflag = self.traceback = False 18 self.quiet = self.verbose = self.debugflag = self.traceback = False
27 self.interactive = self.report_untrusted = True 19 self.interactive = self.report_untrusted = True
28 self.overlay = util.configparser() 20 self.overlay = config.config()
29 self.cdata = util.configparser() 21 self.cdata = config.config()
30 self.ucdata = util.configparser() 22 self.ucdata = config.config()
31 self.parentui = None 23 self.parentui = None
32 self.trusted_users = {} 24 self.trusted_users = {}
33 self.trusted_groups = {} 25 self.trusted_groups = {}
34 26
35 if parentui: 27 if parentui:
36 # parentui may point to an ui object which is already a child 28 # parentui may point to an ui object which is already a child
37 self.parentui = parentui.parentui or parentui 29 self.parentui = parentui.parentui or parentui
38 updateconfig(self.parentui.cdata, self.cdata) 30 self.cdata.update(self.parentui.cdata)
39 updateconfig(self.parentui.ucdata, self.ucdata) 31 self.ucdata.update(self.parentui.ucdata)
40 # we want the overlay from the parent, not the root 32 # we want the overlay from the parent, not the root
41 updateconfig(parentui.overlay, self.overlay) 33 self.overlay.update(parentui.overlay)
42 self.buffers = parentui.buffers 34 self.buffers = parentui.buffers
43 self.trusted_users = parentui.trusted_users.copy() 35 self.trusted_users = parentui.trusted_users.copy()
44 self.trusted_groups = parentui.trusted_groups.copy() 36 self.trusted_groups = parentui.trusted_groups.copy()
45 self.fixconfig() 37 self.fixconfig()
46 else: 38 else:
87 except IOError: 79 except IOError:
88 if not sections: # ignore unless we were looking for something 80 if not sections: # ignore unless we were looking for something
89 return 81 return
90 raise 82 raise
91 83
92 cdata = util.configparser() 84 cdata = config.config()
93 trusted = sections or assumetrusted or self._is_trusted(fp, filename) 85 trusted = sections or assumetrusted or self._is_trusted(fp, filename)
94 86
95 try: 87 try:
96 cdata.readfp(fp, filename) 88 cdata.read(filename, fp)
97 except ConfigParser.ParsingError, inst: 89 except error.ConfigError, inst:
98 msg = _("Failed to parse %s\n%s") % (filename, inst)
99 if trusted: 90 if trusted:
100 raise util.Abort(msg) 91 raise
101 self.warn(_("Ignored: %s\n") % msg) 92 self.warn(_("Ignored: %s\n") % str(inst))
102 93
103 if trusted: 94 if trusted:
104 updateconfig(cdata, self.cdata, sections) 95 self.cdata.update(cdata, sections)
105 updateconfig(self.overlay, self.cdata, sections) 96 self.cdata.update(self.overlay, sections)
106 updateconfig(cdata, self.ucdata, sections) 97 self.ucdata.update(cdata, sections)
107 updateconfig(self.overlay, self.ucdata, sections) 98 self.ucdata.update(self.overlay, sections)
108 99
109 if root is None: 100 if root is None:
110 root = os.path.expanduser('~') 101 root = os.path.expanduser('~')
111 self.fixconfig(root=root) 102 self.fixconfig(root=root)
112 103
115 if section is None or section == 'paths': 106 if section is None or section == 'paths':
116 if root is None: 107 if root is None:
117 root = os.getcwd() 108 root = os.getcwd()
118 items = section and [(name, value)] or [] 109 items = section and [(name, value)] or []
119 for cdata in self.cdata, self.ucdata, self.overlay: 110 for cdata in self.cdata, self.ucdata, self.overlay:
120 if not items and cdata.has_section('paths'): 111 if not items and 'paths' in cdata:
121 pathsitems = cdata.items('paths') 112 pathsitems = cdata.items('paths')
122 else: 113 else:
123 pathsitems = items 114 pathsitems = items
124 for n, path in pathsitems: 115 for n, path in pathsitems:
125 if path and "://" not in path and not os.path.isabs(path): 116 if path and "://" not in path and not os.path.isabs(path):
147 for group in self.configlist('trusted', 'groups'): 138 for group in self.configlist('trusted', 'groups'):
148 self.trusted_groups[group] = 1 139 self.trusted_groups[group] = 1
149 140
150 def setconfig(self, section, name, value): 141 def setconfig(self, section, name, value):
151 for cdata in (self.overlay, self.cdata, self.ucdata): 142 for cdata in (self.overlay, self.cdata, self.ucdata):
152 if not cdata.has_section(section):
153 cdata.add_section(section)
154 cdata.set(section, name, value) 143 cdata.set(section, name, value)
155 self.fixconfig(section, name, value) 144 self.fixconfig(section, name, value)
156 145
157 def _get_cdata(self, untrusted): 146 def _get_cdata(self, untrusted):
158 if untrusted: 147 if untrusted:
159 return self.ucdata 148 return self.ucdata
160 return self.cdata 149 return self.cdata
161 150
162 def _config(self, section, name, default, funcname, untrusted, abort): 151 def config(self, section, name, default=None, untrusted=False):
163 cdata = self._get_cdata(untrusted) 152 value = self._get_cdata(untrusted).get(section, name, default)
164 if cdata.has_option(section, name):
165 try:
166 func = getattr(cdata, funcname)
167 return func(section, name)
168 except (ConfigParser.InterpolationError, ValueError), inst:
169 msg = _("Error in configuration section [%s] "
170 "parameter '%s':\n%s") % (section, name, inst)
171 if abort:
172 raise util.Abort(msg)
173 self.warn(_("Ignored: %s\n") % msg)
174 return default
175
176 def _configcommon(self, section, name, default, funcname, untrusted):
177 value = self._config(section, name, default, funcname,
178 untrusted, abort=True)
179 if self.debugflag and not untrusted: 153 if self.debugflag and not untrusted:
180 uvalue = self._config(section, name, None, funcname, 154 uvalue = self.ucdata.get(section, name)
181 untrusted=True, abort=False)
182 if uvalue is not None and uvalue != value: 155 if uvalue is not None and uvalue != value:
183 self.warn(_("Ignoring untrusted configuration option " 156 self.warn(_("Ignoring untrusted configuration option "
184 "%s.%s = %s\n") % (section, name, uvalue)) 157 "%s.%s = %s\n") % (section, name, uvalue))
185 return value 158 return value
186 159
187 def config(self, section, name, default=None, untrusted=False):
188 return self._configcommon(section, name, default, 'get', untrusted)
189
190 def configbool(self, section, name, default=False, untrusted=False): 160 def configbool(self, section, name, default=False, untrusted=False):
191 return self._configcommon(section, name, default, 'getboolean', 161 v = self.config(section, name, None, untrusted)
192 untrusted) 162 if v == None:
163 return default
164 if v.lower() not in _booleans:
165 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
166 % (section, name, v))
167 return _booleans[v.lower()]
193 168
194 def configlist(self, section, name, default=None, untrusted=False): 169 def configlist(self, section, name, default=None, untrusted=False):
195 """Return a list of comma/space separated strings""" 170 """Return a list of comma/space separated strings"""
196 result = self.config(section, name, untrusted=untrusted) 171 result = self.config(section, name, untrusted=untrusted)
197 if result is None: 172 if result is None:
200 result = result.replace(",", " ").split() 175 result = result.replace(",", " ").split()
201 return result 176 return result
202 177
203 def has_section(self, section, untrusted=False): 178 def has_section(self, section, untrusted=False):
204 '''tell whether section exists in config.''' 179 '''tell whether section exists in config.'''
205 cdata = self._get_cdata(untrusted) 180 return section in self._get_cdata(untrusted)
206 return cdata.has_section(section) 181
207 182 def configitems(self, section, untrusted=False):
208 def _configitems(self, section, untrusted, abort): 183 items = self._get_cdata(untrusted).items(section)
209 items = {} 184 if self.debugflag and not untrusted:
210 cdata = self._get_cdata(untrusted) 185 for k,v in self.ucdata.items(section):
211 if cdata.has_section(section): 186 if self.cdata.get(section, k) != v:
212 try: 187 self.warn(_("Ignoring untrusted configuration option "
213 items.update(dict(cdata.items(section))) 188 "%s.%s = %s\n") % (section, k, v))
214 except ConfigParser.InterpolationError, inst:
215 msg = _("Error in configuration section [%s]:\n"
216 "%s") % (section, inst)
217 if abort:
218 raise util.Abort(msg)
219 self.warn(_("Ignored: %s\n") % msg)
220 return items 189 return items
221
222 def configitems(self, section, untrusted=False):
223 items = self._configitems(section, untrusted=untrusted, abort=True)
224 if self.debugflag and not untrusted:
225 uitems = self._configitems(section, untrusted=True, abort=False)
226 for k in util.sort(uitems):
227 if uitems[k] != items.get(k):
228 self.warn(_("Ignoring untrusted configuration option "
229 "%s.%s = %s\n") % (section, k, uitems[k]))
230 return util.sort(items.items())
231 190
232 def walkconfig(self, untrusted=False): 191 def walkconfig(self, untrusted=False):
233 cdata = self._get_cdata(untrusted) 192 cdata = self._get_cdata(untrusted)
234 sections = cdata.sections() 193 for section in cdata.sections():
235 sections.sort()
236 for section in sections:
237 for name, value in self.configitems(section, untrusted): 194 for name, value in self.configitems(section, untrusted):
238 yield section, name, str(value).replace('\n', '\\n') 195 yield section, name, str(value).replace('\n', '\\n')
239 196
240 def username(self): 197 def username(self):
241 """Return default username to be used in commits. 198 """Return default username to be used in commits.