mercurial/ui.py
changeset 3552 9b52239dc740
parent 3551 3b07e223534b
child 3557 f7dee427cd14
equal deleted inserted replaced
3551:3b07e223534b 3552:9b52239dc740
    39             self.debugflag = debug
    39             self.debugflag = debug
    40             self.interactive = interactive
    40             self.interactive = interactive
    41             self.traceback = traceback
    41             self.traceback = traceback
    42             self.trusted_users = {}
    42             self.trusted_users = {}
    43             self.trusted_groups = {}
    43             self.trusted_groups = {}
       
    44             # if ucdata is not None, its keys must be a superset of cdata's
    44             self.cdata = util.configparser()
    45             self.cdata = util.configparser()
       
    46             self.ucdata = None
    45             self.readconfig(util.rcpath())
    47             self.readconfig(util.rcpath())
    46             self.updateopts(verbose, debug, quiet, interactive)
    48             self.updateopts(verbose, debug, quiet, interactive)
    47         else:
    49         else:
    48             # parentui may point to an ui object which is already a child
    50             # parentui may point to an ui object which is already a child
    49             self.parentui = parentui.parentui or parentui
    51             self.parentui = parentui.parentui or parentui
    50             self.readhooks = self.parentui.readhooks[:]
    52             self.readhooks = self.parentui.readhooks[:]
    51             self.trusted_users = parentui.trusted_users.copy()
    53             self.trusted_users = parentui.trusted_users.copy()
    52             self.trusted_groups = parentui.trusted_groups.copy()
    54             self.trusted_groups = parentui.trusted_groups.copy()
    53             self.cdata = dupconfig(self.parentui.cdata)
    55             self.cdata = dupconfig(self.parentui.cdata)
       
    56             if self.parentui.ucdata:
       
    57                 self.ucdata = dupconfig(self.parentui.ucdata)
    54             if self.parentui.overlay:
    58             if self.parentui.overlay:
    55                 self.overlay = dupconfig(self.parentui.overlay)
    59                 self.overlay = dupconfig(self.parentui.overlay)
    56 
    60 
    57     def __getattr__(self, key):
    61     def __getattr__(self, key):
    58         return getattr(self.parentui, key)
    62         return getattr(self.parentui, key)
    93             st = util.fstat(fp)
    97             st = util.fstat(fp)
    94             user = util.username(st.st_uid)
    98             user = util.username(st.st_uid)
    95             group = util.groupname(st.st_gid)
    99             group = util.groupname(st.st_gid)
    96             if user not in tusers and group not in tgroups:
   100             if user not in tusers and group not in tgroups:
    97                 if warn:
   101                 if warn:
    98                     self.warn(_('Not reading file %s from untrusted '
   102                     self.warn(_('Not trusting file %s from untrusted '
    99                                 'user %s, group %s\n') % (f, user, group))
   103                                 'user %s, group %s\n') % (f, user, group))
   100                 return False
   104                 return False
   101         return True
   105         return True
   102 
   106 
   103     def readconfig(self, fn, root=None):
   107     def readconfig(self, fn, root=None):
   106         for f in fn:
   110         for f in fn:
   107             try:
   111             try:
   108                 fp = open(f)
   112                 fp = open(f)
   109             except IOError:
   113             except IOError:
   110                 continue
   114                 continue
   111             if not self._is_trusted(fp, f):
   115             cdata = self.cdata
   112                 continue
   116             trusted = self._is_trusted(fp, f)
       
   117             if not trusted:
       
   118                 if self.ucdata is None:
       
   119                     self.ucdata = dupconfig(self.cdata)
       
   120                 cdata = self.ucdata
       
   121             elif self.ucdata is not None:
       
   122                 # use a separate configparser, so that we don't accidentally
       
   123                 # override ucdata settings later on.
       
   124                 cdata = util.configparser()
       
   125 
   113             try:
   126             try:
   114                 self.cdata.readfp(fp, f)
   127                 cdata.readfp(fp, f)
   115             except ConfigParser.ParsingError, inst:
   128             except ConfigParser.ParsingError, inst:
   116                 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
   129                 msg = _("Failed to parse %s\n%s") % (f, inst)
       
   130                 if trusted:
       
   131                     raise util.Abort(msg)
       
   132                 self.warn(_("Ignored: %s\n") % msg)
       
   133 
       
   134             if trusted:
       
   135                 if cdata != self.cdata:
       
   136                     updateconfig(cdata, self.cdata)
       
   137                 if self.ucdata is not None:
       
   138                     updateconfig(cdata, self.ucdata)
   117         # override data from config files with data set with ui.setconfig
   139         # override data from config files with data set with ui.setconfig
   118         if self.overlay:
   140         if self.overlay:
   119             updateconfig(self.overlay, self.cdata)
   141             updateconfig(self.overlay, self.cdata)
   120         if root is None:
   142         if root is None:
   121             root = os.path.expanduser('~')
   143             root = os.path.expanduser('~')
   125 
   147 
   126     def addreadhook(self, hook):
   148     def addreadhook(self, hook):
   127         self.readhooks.append(hook)
   149         self.readhooks.append(hook)
   128 
   150 
   129     def readsections(self, filename, *sections):
   151     def readsections(self, filename, *sections):
   130         "read filename and add only the specified sections to the config data"
   152         """Read filename and add only the specified sections to the config data
       
   153 
       
   154         The settings are added to the trusted config data.
       
   155         """
   131         if not sections:
   156         if not sections:
   132             return
   157             return
   133 
   158 
   134         cdata = util.configparser()
   159         cdata = util.configparser()
   135         try:
   160         try:
   141         for section in sections:
   166         for section in sections:
   142             if not cdata.has_section(section):
   167             if not cdata.has_section(section):
   143                 cdata.add_section(section)
   168                 cdata.add_section(section)
   144 
   169 
   145         updateconfig(cdata, self.cdata, sections)
   170         updateconfig(cdata, self.cdata, sections)
       
   171         if self.ucdata:
       
   172             updateconfig(cdata, self.ucdata, sections)
   146 
   173 
   147     def fixconfig(self, section=None, name=None, value=None, root=None):
   174     def fixconfig(self, section=None, name=None, value=None, root=None):
   148         # translate paths relative to root (or home) into absolute paths
   175         # translate paths relative to root (or home) into absolute paths
   149         if section is None or section == 'paths':
   176         if section is None or section == 'paths':
   150             if root is None:
   177             if root is None:
   151                 root = os.getcwd()
   178                 root = os.getcwd()
   152             items = section and [(name, value)] or []
   179             items = section and [(name, value)] or []
   153             for cdata in self.cdata, self.overlay:
   180             for cdata in self.cdata, self.ucdata, self.overlay:
   154                 if not cdata: continue
   181                 if not cdata: continue
   155                 if not items and cdata.has_section('paths'):
   182                 if not items and cdata.has_section('paths'):
   156                     pathsitems = cdata.items('paths')
   183                     pathsitems = cdata.items('paths')
   157                 else:
   184                 else:
   158                     pathsitems = items
   185                     pathsitems = items
   179                     self.trusted_groups[group] = 1
   206                     self.trusted_groups[group] = 1
   180 
   207 
   181     def setconfig(self, section, name, value):
   208     def setconfig(self, section, name, value):
   182         if not self.overlay:
   209         if not self.overlay:
   183             self.overlay = util.configparser()
   210             self.overlay = util.configparser()
   184         for cdata in (self.overlay, self.cdata):
   211         for cdata in (self.overlay, self.cdata, self.ucdata):
       
   212             if not cdata: continue
   185             if not cdata.has_section(section):
   213             if not cdata.has_section(section):
   186                 cdata.add_section(section)
   214                 cdata.add_section(section)
   187             cdata.set(section, name, value)
   215             cdata.set(section, name, value)
   188         self.fixconfig(section, name, value)
   216         self.fixconfig(section, name, value)
   189 
   217 
   190     def _config(self, section, name, default, funcname):
   218     def _get_cdata(self, untrusted):
   191         if self.cdata.has_option(section, name):
   219         if untrusted and self.ucdata:
       
   220             return self.ucdata
       
   221         return self.cdata
       
   222 
       
   223     def _config(self, section, name, default, funcname, untrusted, abort):
       
   224         cdata = self._get_cdata(untrusted)
       
   225         if cdata.has_option(section, name):
   192             try:
   226             try:
   193                 func = getattr(self.cdata, funcname)
   227                 func = getattr(cdata, funcname)
   194                 return func(section, name)
   228                 return func(section, name)
   195             except ConfigParser.InterpolationError, inst:
   229             except ConfigParser.InterpolationError, inst:
   196                 raise util.Abort(_("Error in configuration section [%s] "
   230                 msg = _("Error in configuration section [%s] "
   197                                    "parameter '%s':\n%s")
   231                         "parameter '%s':\n%s") % (section, name, inst)
   198                                  % (section, name, inst))
   232                 if abort:
       
   233                     raise util.Abort(msg)
       
   234                 self.warn(_("Ignored: %s\n") % msg)
   199         return default
   235         return default
   200 
   236 
   201     def config(self, section, name, default=None):
   237     def _configcommon(self, section, name, default, funcname, untrusted):
   202         return self._config(section, name, default, 'get')
   238         value = self._config(section, name, default, funcname,
   203 
   239                              untrusted, abort=True)
   204     def configbool(self, section, name, default=False):
   240         if self.debugflag and not untrusted and self.ucdata:
   205         return self._config(section, name, default, 'getboolean')
   241             uvalue = self._config(section, name, None, funcname,
   206 
   242                                   untrusted=True, abort=False)
   207     def configlist(self, section, name, default=None):
   243             if uvalue is not None and uvalue != value:
       
   244                 self.warn(_("Ignoring untrusted configuration option "
       
   245                             "%s.%s = %s\n") % (section, name, uvalue))
       
   246         return value
       
   247 
       
   248     def config(self, section, name, default=None, untrusted=False):
       
   249         return self._configcommon(section, name, default, 'get', untrusted)
       
   250 
       
   251     def configbool(self, section, name, default=False, untrusted=False):
       
   252         return self._configcommon(section, name, default, 'getboolean',
       
   253                                   untrusted)
       
   254 
       
   255     def configlist(self, section, name, default=None, untrusted=False):
   208         """Return a list of comma/space separated strings"""
   256         """Return a list of comma/space separated strings"""
   209         result = self.config(section, name)
   257         result = self.config(section, name, untrusted=untrusted)
   210         if result is None:
   258         if result is None:
   211             result = default or []
   259             result = default or []
   212         if isinstance(result, basestring):
   260         if isinstance(result, basestring):
   213             result = result.replace(",", " ").split()
   261             result = result.replace(",", " ").split()
   214         return result
   262         return result
   215 
   263 
   216     def has_config(self, section):
   264     def has_config(self, section, untrusted=False):
   217         '''tell whether section exists in config.'''
   265         '''tell whether section exists in config.'''
   218         return self.cdata.has_section(section)
   266         cdata = self._get_cdata(untrusted)
   219 
   267         return cdata.has_section(section)
   220     def configitems(self, section):
   268 
       
   269     def _configitems(self, section, untrusted, abort):
   221         items = {}
   270         items = {}
   222         if self.cdata.has_section(section):
   271         cdata = self._get_cdata(untrusted)
       
   272         if cdata.has_section(section):
   223             try:
   273             try:
   224                 items.update(dict(self.cdata.items(section)))
   274                 items.update(dict(cdata.items(section)))
   225             except ConfigParser.InterpolationError, inst:
   275             except ConfigParser.InterpolationError, inst:
   226                 raise util.Abort(_("Error in configuration section [%s]:\n%s")
   276                 msg = _("Error in configuration section [%s]:\n"
   227                                  % (section, inst))
   277                         "%s") % (section, inst)
       
   278                 if abort:
       
   279                     raise util.Abort(msg)
       
   280                 self.warn(_("Ignored: %s\n") % msg)
       
   281         return items
       
   282 
       
   283     def configitems(self, section, untrusted=False):
       
   284         items = self._configitems(section, untrusted=untrusted, abort=True)
       
   285         if self.debugflag and not untrusted and self.ucdata:
       
   286             uitems = self._configitems(section, untrusted=True, abort=False)
       
   287             keys = uitems.keys()
       
   288             keys.sort()
       
   289             for k in keys:
       
   290                 if uitems[k] != items.get(k):
       
   291                     self.warn(_("Ignoring untrusted configuration option "
       
   292                                 "%s.%s = %s\n") % (section, k, uitems[k]))
   228         x = items.items()
   293         x = items.items()
   229         x.sort()
   294         x.sort()
   230         return x
   295         return x
   231 
   296 
   232     def walkconfig(self):
   297     def walkconfig(self, untrusted=False):
   233         sections = self.cdata.sections()
   298         cdata = self._get_cdata(untrusted)
       
   299         sections = cdata.sections()
   234         sections.sort()
   300         sections.sort()
   235         for section in sections:
   301         for section in sections:
   236             for name, value in self.configitems(section):
   302             for name, value in self.configitems(section, untrusted):
   237                 yield section, name, value.replace('\n', '\\n')
   303                 yield section, name, value.replace('\n', '\\n')
   238 
   304 
   239     def extensions(self):
   305     def extensions(self):
   240         result = self.configitems("extensions")
   306         result = self.configitems("extensions")
   241         for i, (key, value) in enumerate(result):
   307         for i, (key, value) in enumerate(result):