3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
4 # |
4 # |
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 import os, ConfigParser |
8 import ConfigParser |
9 from i18n import gettext as _ |
9 from i18n import gettext as _ |
10 from demandload import * |
10 from demandload import * |
11 demandload(globals(), "re socket sys util") |
11 demandload(globals(), "os re socket sys util") |
12 |
12 |
13 class ui(object): |
13 class ui(object): |
14 def __init__(self, verbose=False, debug=False, quiet=False, |
14 def __init__(self, verbose=False, debug=False, quiet=False, |
15 interactive=True): |
15 interactive=True, parentui=None): |
16 self.overlay = {} |
16 self.overlay = {} |
17 self.cdata = ConfigParser.SafeConfigParser() |
17 if parentui is None: |
18 self.readconfig(util.rcpath) |
18 # this is the parent of all ui children |
19 |
19 self.parentui = None |
20 self.quiet = self.configbool("ui", "quiet") |
20 self.cdata = ConfigParser.SafeConfigParser() |
21 self.verbose = self.configbool("ui", "verbose") |
21 self.readconfig(util.rcpath) |
22 self.debugflag = self.configbool("ui", "debug") |
22 |
23 self.interactive = self.configbool("ui", "interactive", True) |
23 self.quiet = self.configbool("ui", "quiet") |
24 |
24 self.verbose = self.configbool("ui", "verbose") |
25 self.updateopts(verbose, debug, quiet, interactive) |
25 self.debugflag = self.configbool("ui", "debug") |
26 self.diffcache = None |
26 self.interactive = self.configbool("ui", "interactive", True) |
|
27 |
|
28 self.updateopts(verbose, debug, quiet, interactive) |
|
29 self.diffcache = None |
|
30 else: |
|
31 # parentui may point to an ui object which is already a child |
|
32 self.parentui = parentui.parentui or parentui |
|
33 parent_cdata = self.parentui.cdata |
|
34 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults()) |
|
35 # make interpolation work |
|
36 for section in parent_cdata.sections(): |
|
37 self.cdata.add_section(section) |
|
38 for name, value in parent_cdata.items(section, raw=True): |
|
39 self.cdata.set(section, name, value) |
|
40 |
|
41 def __getattr__(self, key): |
|
42 return getattr(self.parentui, key) |
27 |
43 |
28 def updateopts(self, verbose=False, debug=False, quiet=False, |
44 def updateopts(self, verbose=False, debug=False, quiet=False, |
29 interactive=True): |
45 interactive=True): |
30 self.quiet = (self.quiet or quiet) and not verbose and not debug |
46 self.quiet = (self.quiet or quiet) and not verbose and not debug |
31 self.verbose = (self.verbose or verbose) or debug |
47 self.verbose = (self.verbose or verbose) or debug |
32 self.debugflag = (self.debugflag or debug) |
48 self.debugflag = (self.debugflag or debug) |
33 self.interactive = (self.interactive and interactive) |
49 self.interactive = (self.interactive and interactive) |
34 |
50 |
35 def readconfig(self, fn): |
51 def readconfig(self, fn, root=None): |
36 if isinstance(fn, basestring): |
52 if isinstance(fn, basestring): |
37 fn = [fn] |
53 fn = [fn] |
38 for f in fn: |
54 for f in fn: |
39 try: |
55 try: |
40 self.cdata.read(f) |
56 self.cdata.read(f) |
41 except ConfigParser.ParsingError, inst: |
57 except ConfigParser.ParsingError, inst: |
42 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst)) |
58 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst)) |
|
59 # translate paths relative to root (or home) into absolute paths |
|
60 if root is None: |
|
61 root = os.path.expanduser('~') |
|
62 for name, path in self.configitems("paths"): |
|
63 if path.find("://") == -1 and not os.path.isabs(path): |
|
64 self.cdata.set("paths", name, os.path.join(root, path)) |
43 |
65 |
44 def setconfig(self, section, name, val): |
66 def setconfig(self, section, name, val): |
45 self.overlay[(section, name)] = val |
67 self.overlay[(section, name)] = val |
46 |
68 |
47 def config(self, section, name, default=None): |
69 def config(self, section, name, default=None): |
48 if self.overlay.has_key((section, name)): |
70 if self.overlay.has_key((section, name)): |
49 return self.overlay[(section, name)] |
71 return self.overlay[(section, name)] |
50 if self.cdata.has_option(section, name): |
72 if self.cdata.has_option(section, name): |
51 return self.cdata.get(section, name) |
73 try: |
52 return default |
74 return self.cdata.get(section, name) |
|
75 except ConfigParser.InterpolationError, inst: |
|
76 raise util.Abort(_("Error in configuration:\n%s") % inst) |
|
77 if self.parentui is None: |
|
78 return default |
|
79 else: |
|
80 return self.parentui.config(section, name, default) |
53 |
81 |
54 def configbool(self, section, name, default=False): |
82 def configbool(self, section, name, default=False): |
55 if self.overlay.has_key((section, name)): |
83 if self.overlay.has_key((section, name)): |
56 return self.overlay[(section, name)] |
84 return self.overlay[(section, name)] |
57 if self.cdata.has_option(section, name): |
85 if self.cdata.has_option(section, name): |
58 return self.cdata.getboolean(section, name) |
86 try: |
59 return default |
87 return self.cdata.getboolean(section, name) |
|
88 except ConfigParser.InterpolationError, inst: |
|
89 raise util.Abort(_("Error in configuration:\n%s") % inst) |
|
90 if self.parentui is None: |
|
91 return default |
|
92 else: |
|
93 return self.parentui.configbool(section, name, default) |
60 |
94 |
61 def configitems(self, section): |
95 def configitems(self, section): |
|
96 items = {} |
|
97 if self.parentui is not None: |
|
98 items = dict(self.parentui.configitems(section)) |
62 if self.cdata.has_section(section): |
99 if self.cdata.has_section(section): |
63 return self.cdata.items(section) |
100 try: |
64 return [] |
101 items.update(dict(self.cdata.items(section))) |
65 |
102 except ConfigParser.InterpolationError, inst: |
66 def walkconfig(self): |
103 raise util.Abort(_("Error in configuration:\n%s") % inst) |
67 seen = {} |
104 x = items.items() |
|
105 x.sort() |
|
106 return x |
|
107 |
|
108 def walkconfig(self, seen=None): |
|
109 if seen is None: |
|
110 seen = {} |
68 for (section, name), value in self.overlay.iteritems(): |
111 for (section, name), value in self.overlay.iteritems(): |
69 yield section, name, value |
112 yield section, name, value |
70 seen[section, name] = 1 |
113 seen[section, name] = 1 |
71 for section in self.cdata.sections(): |
114 for section in self.cdata.sections(): |
72 for name, value in self.cdata.items(section): |
115 for name, value in self.cdata.items(section): |
73 if (section, name) in seen: continue |
116 if (section, name) in seen: continue |
74 yield section, name, value.replace('\n', '\\n') |
117 yield section, name, value.replace('\n', '\\n') |
75 seen[section, name] = 1 |
118 seen[section, name] = 1 |
|
119 if self.parentui is not None: |
|
120 for parent in self.parentui.walkconfig(seen): |
|
121 yield parent |
76 |
122 |
77 def extensions(self): |
123 def extensions(self): |
78 return self.configitems("extensions") |
124 return self.configitems("extensions") |
79 |
125 |
80 def diffopts(self): |
126 def diffopts(self): |