changeset 3351:04fa31a43b93

merge with crew
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
date Wed, 11 Oct 2006 23:31:05 +0200
parents ab900698b832 (diff) b02e60097bbe (current diff)
children 69fe021cc23e 2edf53386d86
files
diffstat 7 files changed, 233 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Wed Oct 11 13:56:35 2006 -0700
+++ b/mercurial/commands.py	Wed Oct 11 23:31:05 2006 +0200
@@ -2463,7 +2463,7 @@
                " accesslog errorlog webdir_conf")
     for o in optlist.split():
         if opts[o]:
-            ui.setconfig("web", o, opts[o])
+            ui.setconfig("web", o, str(opts[o]))
 
     if repo is None and not ui.config("web", "webdir_conf"):
         raise hg.RepoError(_("There is no Mercurial repository here"
@@ -3275,6 +3275,20 @@
                 ui.warn(_("module %s overrides %s\n") % (name, t))
         table.update(cmdtable)
 
+def parseconfig(config):
+    """parse the --config options from the command line"""
+    parsed = []
+    for cfg in config:
+        try:
+            name, value = cfg.split('=', 1)
+            section, name = name.split('.', 1)
+            if not section or not name:
+                raise IndexError
+            parsed.append((section, name, value))
+        except (IndexError, ValueError):
+            raise util.Abort(_('malformed --config option: %s') % cfg)
+    return parsed
+
 def dispatch(args):
     for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
         num = getattr(signal, name, None)
@@ -3304,10 +3318,6 @@
                     (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
             atexit.register(print_time)
 
-        u.updateopts(options["verbose"], options["debug"], options["quiet"],
-                     not options["noninteractive"], options["traceback"],
-                     options["config"])
-
         # enter the debugger before command execution
         if options['debugger']:
             pdb.set_trace()
@@ -3320,6 +3330,10 @@
                     raise util.Abort('%s: %s' %
                                      (options['cwd'], inst.strerror))
 
+            u.updateopts(options["verbose"], options["debug"], options["quiet"],
+                         not options["noninteractive"], options["traceback"],
+                         parseconfig(options["config"]))
+
             path = u.expandpath(options["repository"]) or ""
             repo = path and hg.repository(u, path=path) or None
             if repo and not repo.local():
@@ -3349,11 +3363,6 @@
             else:
                 d = lambda: func(u, *args, **cmdoptions)
 
-            # reupdate the options, repo/.hg/hgrc may have changed them
-            u.updateopts(options["verbose"], options["debug"], options["quiet"],
-                         not options["noninteractive"], options["traceback"],
-                         options["config"])
-
             try:
                 if options['profile']:
                     import hotshot, hotshot.stats
--- a/mercurial/localrepo.py	Wed Oct 11 13:56:35 2006 -0700
+++ b/mercurial/localrepo.py	Wed Oct 11 23:31:05 2006 +0200
@@ -54,7 +54,7 @@
         except IOError:
             pass
 
-        v = self.ui.revlogopts
+        v = self.ui.configrevlog()
         self.revlogversion = int(v.get('format', revlog.REVLOG_DEFAULT_FORMAT))
         self.revlogv1 = self.revlogversion != revlog.REVLOGV0
         fl = v.get('flags', None)
--- a/mercurial/ui.py	Wed Oct 11 13:56:35 2006 -0700
+++ b/mercurial/ui.py	Wed Oct 11 23:31:05 2006 +0200
@@ -10,61 +10,75 @@
 demandload(globals(), "errno getpass os re socket sys tempfile")
 demandload(globals(), "ConfigParser mdiff templater traceback util")
 
+def dupconfig(orig):
+    new = ConfigParser.SafeConfigParser(orig.defaults())
+    updateconfig(orig, new)
+    return new
+
+def updateconfig(source, dest):
+    for section in source.sections():
+        if not dest.has_section(section):
+            dest.add_section(section)
+        for name, value in source.items(section, raw=True):
+            dest.set(section, name, value)
+
 class ui(object):
     def __init__(self, verbose=False, debug=False, quiet=False,
                  interactive=True, traceback=False, parentui=None):
-        self.overlay = {}
+        self.overlay = None
+        self.header = []
+        self.prev_header = []
         if parentui is None:
             # this is the parent of all ui children
             self.parentui = None
             self.readhooks = []
+            self.quiet = quiet
+            self.verbose = verbose
+            self.debugflag = debug
+            self.interactive = interactive
+            self.traceback = traceback
             self.cdata = ConfigParser.SafeConfigParser()
             self.readconfig(util.rcpath())
-
-            self.quiet = self.configbool("ui", "quiet")
-            self.verbose = self.configbool("ui", "verbose")
-            self.debugflag = self.configbool("ui", "debug")
-            self.interactive = self.configbool("ui", "interactive", True)
-            self.traceback = traceback
-
             self.updateopts(verbose, debug, quiet, interactive)
-            self.diffcache = None
-            self.header = []
-            self.prev_header = []
-            self.revlogopts = self.configrevlog()
         else:
             # parentui may point to an ui object which is already a child
             self.parentui = parentui.parentui or parentui
-            self.readhooks = parentui.readhooks[:]
-            parent_cdata = self.parentui.cdata
-            self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
-            # make interpolation work
-            for section in parent_cdata.sections():
-                self.cdata.add_section(section)
-                for name, value in parent_cdata.items(section, raw=True):
-                    self.cdata.set(section, name, value)
+            self.readhooks = self.parentui.readhooks[:]
+            self.cdata = dupconfig(self.parentui.cdata)
+            if self.parentui.overlay:
+                self.overlay = dupconfig(self.parentui.overlay)
 
     def __getattr__(self, key):
         return getattr(self.parentui, key)
 
     def updateopts(self, verbose=False, debug=False, quiet=False,
                    interactive=True, traceback=False, config=[]):
-        self.quiet = (self.quiet or quiet) and not verbose and not debug
-        self.verbose = ((self.verbose or verbose) or debug) and not self.quiet
-        self.debugflag = (self.debugflag or debug)
-        self.interactive = (self.interactive and interactive)
+        for section, name, value in config:
+            self.setconfig(section, name, value)
+
+        if quiet or verbose or debug:
+            self.setconfig('ui', 'quiet', str(bool(quiet)))
+            self.setconfig('ui', 'verbose', str(bool(verbose)))
+            self.setconfig('ui', 'debug', str(bool(debug)))
+
+        self.verbosity_constraints()
+
+        if not interactive:
+            self.setconfig('ui', 'interactive', 'False')
+            self.interactive = False
+
         self.traceback = self.traceback or traceback
-        for cfg in config:
-            try:
-                name, value = cfg.split('=', 1)
-                section, name = name.split('.', 1)
-                if not self.cdata.has_section(section):
-                    self.cdata.add_section(section)
-                if not section or not name:
-                    raise IndexError
-                self.cdata.set(section, name, value)
-            except (IndexError, ValueError):
-                raise util.Abort(_('malformed --config option: %s') % cfg)
+
+    def verbosity_constraints(self):
+        self.quiet = self.configbool('ui', 'quiet')
+        self.verbose = self.configbool('ui', 'verbose')
+        self.debugflag = self.configbool('ui', 'debug')
+
+        if self.debugflag:
+            self.verbose = True
+            self.quiet = False
+        elif self.verbose and self.quiet:
+            self.quiet = self.verbose = False
 
     def readconfig(self, fn, root=None):
         if isinstance(fn, basestring):
@@ -74,35 +88,67 @@
                 self.cdata.read(f)
             except ConfigParser.ParsingError, inst:
                 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
-        # translate paths relative to root (or home) into absolute paths
+        # override data from config files with data set with ui.setconfig
+        if self.overlay:
+            updateconfig(self.overlay, self.cdata)
         if root is None:
             root = os.path.expanduser('~')
-        for name, path in self.configitems("paths"):
-            if path and "://" not in path and not os.path.isabs(path):
-                self.cdata.set("paths", name, os.path.join(root, path))
+        self.fixconfig(root=root)
         for hook in self.readhooks:
             hook(self)
 
     def addreadhook(self, hook):
         self.readhooks.append(hook)
 
-    def setconfig(self, section, name, val):
-        self.overlay[(section, name)] = val
+    def fixconfig(self, section=None, name=None, value=None, root=None):
+        # translate paths relative to root (or home) into absolute paths
+        if section is None or section == 'paths':
+            if root is None:
+                root = os.getcwd()
+            items = section and [(name, value)] or []
+            for cdata in self.cdata, self.overlay:
+                if not cdata: continue
+                if not items and cdata.has_section('paths'):
+                    pathsitems = cdata.items('paths')
+                else:
+                    pathsitems = items
+                for n, path in pathsitems:
+                    if path and "://" not in path and not os.path.isabs(path):
+                        cdata.set("paths", n, os.path.join(root, path))
 
-    def config(self, section, name, default=None):
-        if self.overlay.has_key((section, name)):
-            return self.overlay[(section, name)]
+        # update quiet/verbose/debug and interactive status
+        if section is None or section == 'ui':
+            if name is None or name in ('quiet', 'verbose', 'debug'):
+                self.verbosity_constraints()
+
+            if name is None or name == 'interactive':
+                self.interactive = self.configbool("ui", "interactive", True)
+
+    def setconfig(self, section, name, value):
+        if not self.overlay:
+            self.overlay = ConfigParser.SafeConfigParser()
+        for cdata in (self.overlay, self.cdata):
+            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):
             try:
-                return self.cdata.get(section, name)
+                func = getattr(self.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))
-        if self.parentui is None:
-            return default
-        else:
-            return self.parentui.config(section, name, default)
+        return default
+
+    def config(self, section, name, default=None):
+        return self._config(section, name, default, 'get')
+
+    def configbool(self, section, name, default=False):
+        return self._config(section, name, default, 'getboolean')
 
     def configlist(self, section, name, default=None):
         """Return a list of comma/space separated strings"""
@@ -113,29 +159,12 @@
             result = result.replace(",", " ").split()
         return result
 
-    def configbool(self, section, name, default=False):
-        if self.overlay.has_key((section, name)):
-            return self.overlay[(section, name)]
-        if self.cdata.has_option(section, name):
-            try:
-                return self.cdata.getboolean(section, name)
-            except ConfigParser.InterpolationError, inst:
-                raise util.Abort(_("Error in configuration section [%s] "
-                                   "parameter '%s':\n%s")
-                                 % (section, name, inst))
-        if self.parentui is None:
-            return default
-        else:
-            return self.parentui.configbool(section, name, default)
-
     def has_config(self, section):
         '''tell whether section exists in config.'''
         return self.cdata.has_section(section)
 
     def configitems(self, section):
         items = {}
-        if self.parentui is not None:
-            items = dict(self.parentui.configitems(section))
         if self.cdata.has_section(section):
             try:
                 items.update(dict(self.cdata.items(section)))
@@ -146,24 +175,12 @@
         x.sort()
         return x
 
-    def walkconfig(self, seen=None):
-        if seen is None:
-            seen = {}
-        for (section, name), value in self.overlay.iteritems():
-            yield section, name, value
-            seen[section, name] = 1
-        for section in self.cdata.sections():
-            try:
-                for name, value in self.cdata.items(section):
-                    if (section, name) in seen: continue
-                    yield section, name, value.replace('\n', '\\n')
-                    seen[section, name] = 1
-            except ConfigParser.InterpolationError, inst:
-                raise util.Abort(_("Error in configuration section [%s]:\n%s")
-                                 % (section, inst))
-        if self.parentui is not None:
-            for parent in self.parentui.walkconfig(seen):
-                yield parent
+    def walkconfig(self):
+        sections = self.cdata.sections()
+        sections.sort()
+        for section in sections:
+            for name, value in self.configitems(section):
+                yield section, name, value.replace('\n', '\\n')
 
     def extensions(self):
         result = self.configitems("extensions")
--- a/tests/test-globalopts.out	Wed Oct 11 13:56:35 2006 -0700
+++ b/tests/test-globalopts.out	Wed Oct 11 23:31:05 2006 +0200
@@ -105,6 +105,7 @@
 
 
 %% --traceback
+Traceback (most recent call last):
 %% --time
 Time: real x.x secs (user x.x+x.x sys x.x+x.x)
 %% --version
--- a/tests/test-ui-config	Wed Oct 11 13:56:35 2006 -0700
+++ b/tests/test-ui-config	Wed Oct 11 23:31:05 2006 +0200
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 
-from mercurial import ui, util
+from mercurial import ui, util, commands
 
 testui = ui.ui()
-testui.updateopts(config=[
+parsed = commands.parseconfig([
     'values.string=string value',
     'values.bool1=true',
     'values.bool2=false',
@@ -17,6 +17,7 @@
     'interpolation.value4=%(bad)1',
     'interpolation.value5=%bad2',
 ])
+testui.updateopts(config=parsed)
 
 print repr(testui.configitems('values'))
 print repr(testui.configitems('lists'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-ui-verbosity	Wed Oct 11 23:31:05 2006 +0200
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+import os
+from mercurial import ui
+
+hgrc = os.environ['HGRCPATH']
+
+print '      hgrc settings    command line options      final result   '
+print '    quiet verbo debug   quiet verbo debug      quiet verbo debug'
+
+for i in xrange(64):
+    hgrc_quiet   = bool(i & 1<<0)
+    hgrc_verbose = bool(i & 1<<1)
+    hgrc_debug   = bool(i & 1<<2)
+    cmd_quiet    = bool(i & 1<<3)
+    cmd_verbose  = bool(i & 1<<4)
+    cmd_debug    = bool(i & 1<<5)
+
+    f = open(hgrc, 'w')
+    f.write('[ui]\n')
+    if hgrc_quiet:
+        f.write('quiet = True\n')
+    if hgrc_verbose:
+        f.write('verbose = True\n')
+    if hgrc_debug:
+        f.write('debug = True\n')
+    f.close()
+
+    u = ui.ui()
+    u.updateopts(quiet=cmd_quiet, verbose=cmd_verbose, debug=cmd_debug)
+
+    check = ''
+    if u.debugflag:
+        if not u.verbose or u.quiet:
+            check = ' *'
+    elif u.verbose and u.quiet:
+        check = ' +'
+
+    print ('%2d  %5s %5s %5s   %5s %5s %5s  ->  %5s %5s %5s%s'
+           % (i, hgrc_quiet, hgrc_verbose, hgrc_debug,
+              cmd_quiet, cmd_verbose, cmd_debug,
+              u.quiet, u.verbose, u.debugflag, check))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-ui-verbosity.out	Wed Oct 11 23:31:05 2006 +0200
@@ -0,0 +1,66 @@
+      hgrc settings    command line options      final result   
+    quiet verbo debug   quiet verbo debug      quiet verbo debug
+ 0  False False False   False False False  ->  False False False
+ 1   True False False   False False False  ->   True False False
+ 2  False  True False   False False False  ->  False  True False
+ 3   True  True False   False False False  ->  False False False
+ 4  False False  True   False False False  ->  False  True  True
+ 5   True False  True   False False False  ->  False  True  True
+ 6  False  True  True   False False False  ->  False  True  True
+ 7   True  True  True   False False False  ->  False  True  True
+ 8  False False False    True False False  ->   True False False
+ 9   True False False    True False False  ->   True False False
+10  False  True False    True False False  ->   True False False
+11   True  True False    True False False  ->   True False False
+12  False False  True    True False False  ->   True False False
+13   True False  True    True False False  ->   True False False
+14  False  True  True    True False False  ->   True False False
+15   True  True  True    True False False  ->   True False False
+16  False False False   False  True False  ->  False  True False
+17   True False False   False  True False  ->  False  True False
+18  False  True False   False  True False  ->  False  True False
+19   True  True False   False  True False  ->  False  True False
+20  False False  True   False  True False  ->  False  True False
+21   True False  True   False  True False  ->  False  True False
+22  False  True  True   False  True False  ->  False  True False
+23   True  True  True   False  True False  ->  False  True False
+24  False False False    True  True False  ->  False False False
+25   True False False    True  True False  ->  False False False
+26  False  True False    True  True False  ->  False False False
+27   True  True False    True  True False  ->  False False False
+28  False False  True    True  True False  ->  False False False
+29   True False  True    True  True False  ->  False False False
+30  False  True  True    True  True False  ->  False False False
+31   True  True  True    True  True False  ->  False False False
+32  False False False   False False  True  ->  False  True  True
+33   True False False   False False  True  ->  False  True  True
+34  False  True False   False False  True  ->  False  True  True
+35   True  True False   False False  True  ->  False  True  True
+36  False False  True   False False  True  ->  False  True  True
+37   True False  True   False False  True  ->  False  True  True
+38  False  True  True   False False  True  ->  False  True  True
+39   True  True  True   False False  True  ->  False  True  True
+40  False False False    True False  True  ->  False  True  True
+41   True False False    True False  True  ->  False  True  True
+42  False  True False    True False  True  ->  False  True  True
+43   True  True False    True False  True  ->  False  True  True
+44  False False  True    True False  True  ->  False  True  True
+45   True False  True    True False  True  ->  False  True  True
+46  False  True  True    True False  True  ->  False  True  True
+47   True  True  True    True False  True  ->  False  True  True
+48  False False False   False  True  True  ->  False  True  True
+49   True False False   False  True  True  ->  False  True  True
+50  False  True False   False  True  True  ->  False  True  True
+51   True  True False   False  True  True  ->  False  True  True
+52  False False  True   False  True  True  ->  False  True  True
+53   True False  True   False  True  True  ->  False  True  True
+54  False  True  True   False  True  True  ->  False  True  True
+55   True  True  True   False  True  True  ->  False  True  True
+56  False False False    True  True  True  ->  False  True  True
+57   True False False    True  True  True  ->  False  True  True
+58  False  True False    True  True  True  ->  False  True  True
+59   True  True False    True  True  True  ->  False  True  True
+60  False False  True    True  True  True  ->  False  True  True
+61   True False  True    True  True  True  ->  False  True  True
+62  False  True  True    True  True  True  ->  False  True  True
+63   True  True  True    True  True  True  ->  False  True  True