--- a/mercurial/ui.py Thu Oct 26 19:25:44 2006 +0200
+++ b/mercurial/ui.py Thu Oct 26 19:25:45 2006 +0200
@@ -41,7 +41,9 @@
self.traceback = traceback
self.trusted_users = {}
self.trusted_groups = {}
+ # if ucdata is not None, its keys must be a superset of cdata's
self.cdata = util.configparser()
+ self.ucdata = None
self.readconfig(util.rcpath())
self.updateopts(verbose, debug, quiet, interactive)
else:
@@ -51,6 +53,8 @@
self.trusted_users = parentui.trusted_users.copy()
self.trusted_groups = parentui.trusted_groups.copy()
self.cdata = dupconfig(self.parentui.cdata)
+ if self.parentui.ucdata:
+ self.ucdata = dupconfig(self.parentui.ucdata)
if self.parentui.overlay:
self.overlay = dupconfig(self.parentui.overlay)
@@ -95,7 +99,7 @@
group = util.groupname(st.st_gid)
if user not in tusers and group not in tgroups:
if warn:
- self.warn(_('Not reading file %s from untrusted '
+ self.warn(_('Not trusting file %s from untrusted '
'user %s, group %s\n') % (f, user, group))
return False
return True
@@ -108,12 +112,30 @@
fp = open(f)
except IOError:
continue
- if not self._is_trusted(fp, f):
- continue
+ cdata = self.cdata
+ trusted = self._is_trusted(fp, f)
+ if not trusted:
+ if self.ucdata is None:
+ self.ucdata = dupconfig(self.cdata)
+ cdata = self.ucdata
+ elif self.ucdata is not None:
+ # use a separate configparser, so that we don't accidentally
+ # override ucdata settings later on.
+ cdata = util.configparser()
+
try:
- self.cdata.readfp(fp, f)
+ cdata.readfp(fp, f)
except ConfigParser.ParsingError, inst:
- raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
+ msg = _("Failed to parse %s\n%s") % (f, inst)
+ if trusted:
+ raise util.Abort(msg)
+ self.warn(_("Ignored: %s\n") % msg)
+
+ if trusted:
+ if cdata != self.cdata:
+ updateconfig(cdata, self.cdata)
+ if self.ucdata is not None:
+ updateconfig(cdata, self.ucdata)
# override data from config files with data set with ui.setconfig
if self.overlay:
updateconfig(self.overlay, self.cdata)
@@ -127,7 +149,10 @@
self.readhooks.append(hook)
def readsections(self, filename, *sections):
- "read filename and add only the specified sections to the config data"
+ """Read filename and add only the specified sections to the config data
+
+ The settings are added to the trusted config data.
+ """
if not sections:
return
@@ -143,6 +168,8 @@
cdata.add_section(section)
updateconfig(cdata, self.cdata, sections)
+ if self.ucdata:
+ updateconfig(cdata, self.ucdata, sections)
def fixconfig(self, section=None, name=None, value=None, root=None):
# translate paths relative to root (or home) into absolute paths
@@ -150,7 +177,7 @@
if root is None:
root = os.getcwd()
items = section and [(name, value)] or []
- for cdata in self.cdata, self.overlay:
+ for cdata in self.cdata, self.ucdata, self.overlay:
if not cdata: continue
if not items and cdata.has_section('paths'):
pathsitems = cdata.items('paths')
@@ -181,59 +208,98 @@
def setconfig(self, section, name, value):
if not self.overlay:
self.overlay = util.configparser()
- for cdata in (self.overlay, self.cdata):
+ for cdata in (self.overlay, self.cdata, self.ucdata):
+ if not cdata: continue
if not cdata.has_section(section):
cdata.add_section(section)
cdata.set(section, name, value)
self.fixconfig(section, name, value)
- def _config(self, section, name, default, funcname):
- if self.cdata.has_option(section, name):
+ def _get_cdata(self, untrusted):
+ if untrusted and self.ucdata:
+ return self.ucdata
+ return self.cdata
+
+ def _config(self, section, name, default, funcname, untrusted, abort):
+ cdata = self._get_cdata(untrusted)
+ if cdata.has_option(section, name):
try:
- func = getattr(self.cdata, funcname)
+ func = getattr(cdata, funcname)
return func(section, name)
except ConfigParser.InterpolationError, inst:
- raise util.Abort(_("Error in configuration section [%s] "
- "parameter '%s':\n%s")
- % (section, name, inst))
+ msg = _("Error in configuration section [%s] "
+ "parameter '%s':\n%s") % (section, name, inst)
+ if abort:
+ raise util.Abort(msg)
+ self.warn(_("Ignored: %s\n") % msg)
return default
- def config(self, section, name, default=None):
- return self._config(section, name, default, 'get')
+ def _configcommon(self, section, name, default, funcname, untrusted):
+ value = self._config(section, name, default, funcname,
+ untrusted, abort=True)
+ if self.debugflag and not untrusted and self.ucdata:
+ uvalue = self._config(section, name, None, funcname,
+ untrusted=True, abort=False)
+ if uvalue is not None and uvalue != value:
+ self.warn(_("Ignoring untrusted configuration option "
+ "%s.%s = %s\n") % (section, name, uvalue))
+ return value
- def configbool(self, section, name, default=False):
- return self._config(section, name, default, 'getboolean')
+ def config(self, section, name, default=None, untrusted=False):
+ return self._configcommon(section, name, default, 'get', untrusted)
- def configlist(self, section, name, default=None):
+ def configbool(self, section, name, default=False, untrusted=False):
+ return self._configcommon(section, name, default, 'getboolean',
+ untrusted)
+
+ def configlist(self, section, name, default=None, untrusted=False):
"""Return a list of comma/space separated strings"""
- result = self.config(section, name)
+ result = self.config(section, name, untrusted=untrusted)
if result is None:
result = default or []
if isinstance(result, basestring):
result = result.replace(",", " ").split()
return result
- def has_config(self, section):
+ def has_config(self, section, untrusted=False):
'''tell whether section exists in config.'''
- return self.cdata.has_section(section)
+ cdata = self._get_cdata(untrusted)
+ return cdata.has_section(section)
- def configitems(self, section):
+ def _configitems(self, section, untrusted, abort):
items = {}
- if self.cdata.has_section(section):
+ cdata = self._get_cdata(untrusted)
+ if cdata.has_section(section):
try:
- items.update(dict(self.cdata.items(section)))
+ items.update(dict(cdata.items(section)))
except ConfigParser.InterpolationError, inst:
- raise util.Abort(_("Error in configuration section [%s]:\n%s")
- % (section, inst))
+ msg = _("Error in configuration section [%s]:\n"
+ "%s") % (section, inst)
+ if abort:
+ raise util.Abort(msg)
+ self.warn(_("Ignored: %s\n") % msg)
+ return items
+
+ def configitems(self, section, untrusted=False):
+ items = self._configitems(section, untrusted=untrusted, abort=True)
+ if self.debugflag and not untrusted and self.ucdata:
+ uitems = self._configitems(section, untrusted=True, abort=False)
+ keys = uitems.keys()
+ keys.sort()
+ for k in keys:
+ if uitems[k] != items.get(k):
+ self.warn(_("Ignoring untrusted configuration option "
+ "%s.%s = %s\n") % (section, k, uitems[k]))
x = items.items()
x.sort()
return x
- def walkconfig(self):
- sections = self.cdata.sections()
+ def walkconfig(self, untrusted=False):
+ cdata = self._get_cdata(untrusted)
+ sections = cdata.sections()
sections.sort()
for section in sections:
- for name, value in self.configitems(section):
+ for name, value in self.configitems(section, untrusted):
yield section, name, value.replace('\n', '\\n')
def extensions(self):