##// END OF EJS Templates
ui.py: make walkconfig use configitems...
Alexis S. L. Carvalho -
r3342:4eeb79b4 default
parent child Browse files
Show More
@@ -1,296 +1,294 b''
1 1 # ui.py - user interface bits for mercurial
2 2 #
3 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import gettext as _
9 9 from demandload import *
10 10 demandload(globals(), "errno getpass os re socket sys tempfile")
11 11 demandload(globals(), "ConfigParser mdiff templater traceback util")
12 12
13 13 class ui(object):
14 14 def __init__(self, verbose=False, debug=False, quiet=False,
15 15 interactive=True, traceback=False, parentui=None):
16 16 self.overlay = {}
17 17 self.header = []
18 18 self.prev_header = []
19 19 if parentui is None:
20 20 # this is the parent of all ui children
21 21 self.parentui = None
22 22 self.readhooks = []
23 23 self.cdata = ConfigParser.SafeConfigParser()
24 24 self.readconfig(util.rcpath())
25 25
26 26 self.quiet = self.configbool("ui", "quiet")
27 27 self.verbose = self.configbool("ui", "verbose")
28 28 self.debugflag = self.configbool("ui", "debug")
29 29 self.interactive = self.configbool("ui", "interactive", True)
30 30 self.traceback = traceback
31 31
32 32 self.updateopts(verbose, debug, quiet, interactive)
33 33 else:
34 34 # parentui may point to an ui object which is already a child
35 35 self.parentui = parentui.parentui or parentui
36 36 self.readhooks = self.parentui.readhooks[:]
37 37 parent_cdata = self.parentui.cdata
38 38 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
39 39 # make interpolation work
40 40 for section in parent_cdata.sections():
41 41 self.cdata.add_section(section)
42 42 for name, value in parent_cdata.items(section, raw=True):
43 43 self.cdata.set(section, name, value)
44 44
45 45 def __getattr__(self, key):
46 46 return getattr(self.parentui, key)
47 47
48 48 def updateopts(self, verbose=False, debug=False, quiet=False,
49 49 interactive=True, traceback=False, config=[]):
50 50 self.quiet = (self.quiet or quiet) and not verbose and not debug
51 51 self.verbose = ((self.verbose or verbose) or debug) and not self.quiet
52 52 self.debugflag = (self.debugflag or debug)
53 53 self.interactive = (self.interactive and interactive)
54 54 self.traceback = self.traceback or traceback
55 55 for cfg in config:
56 56 try:
57 57 name, value = cfg.split('=', 1)
58 58 section, name = name.split('.', 1)
59 59 if not self.cdata.has_section(section):
60 60 self.cdata.add_section(section)
61 61 if not section or not name:
62 62 raise IndexError
63 63 self.cdata.set(section, name, value)
64 64 except (IndexError, ValueError):
65 65 raise util.Abort(_('malformed --config option: %s') % cfg)
66 66
67 67 def readconfig(self, fn, root=None):
68 68 if isinstance(fn, basestring):
69 69 fn = [fn]
70 70 for f in fn:
71 71 try:
72 72 self.cdata.read(f)
73 73 except ConfigParser.ParsingError, inst:
74 74 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
75 75 # translate paths relative to root (or home) into absolute paths
76 76 if root is None:
77 77 root = os.path.expanduser('~')
78 78 for name, path in self.configitems("paths"):
79 79 if path and "://" not in path and not os.path.isabs(path):
80 80 self.cdata.set("paths", name, os.path.join(root, path))
81 81 for hook in self.readhooks:
82 82 hook(self)
83 83
84 84 def addreadhook(self, hook):
85 85 self.readhooks.append(hook)
86 86
87 87 def setconfig(self, section, name, val):
88 88 self.overlay[(section, name)] = val
89 89
90 90 def _config(self, section, name, default, funcname):
91 91 if self.overlay.has_key((section, name)):
92 92 return self.overlay[(section, name)]
93 93 if self.cdata.has_option(section, name):
94 94 try:
95 95 func = getattr(self.cdata, funcname)
96 96 return func(section, name)
97 97 except ConfigParser.InterpolationError, inst:
98 98 raise util.Abort(_("Error in configuration section [%s] "
99 99 "parameter '%s':\n%s")
100 100 % (section, name, inst))
101 101 if self.parentui is None:
102 102 return default
103 103 else:
104 104 return self.parentui._config(section, name, default, funcname)
105 105
106 106 def config(self, section, name, default=None):
107 107 return self._config(section, name, default, 'get')
108 108
109 109 def configbool(self, section, name, default=False):
110 110 return self._config(section, name, default, 'getboolean')
111 111
112 112 def configlist(self, section, name, default=None):
113 113 """Return a list of comma/space separated strings"""
114 114 result = self.config(section, name)
115 115 if result is None:
116 116 result = default or []
117 117 if isinstance(result, basestring):
118 118 result = result.replace(",", " ").split()
119 119 return result
120 120
121 121 def has_config(self, section):
122 122 '''tell whether section exists in config.'''
123 123 return self.cdata.has_section(section)
124 124
125 125 def configitems(self, section):
126 126 items = {}
127 127 if self.parentui is not None:
128 128 items = dict(self.parentui.configitems(section))
129 129 if self.cdata.has_section(section):
130 130 try:
131 131 items.update(dict(self.cdata.items(section)))
132 132 except ConfigParser.InterpolationError, inst:
133 133 raise util.Abort(_("Error in configuration section [%s]:\n%s")
134 134 % (section, inst))
135 135 x = items.items()
136 136 x.sort()
137 137 return x
138 138
139 139 def walkconfig(self, seen=None):
140 140 if seen is None:
141 141 seen = {}
142 142 for (section, name), value in self.overlay.iteritems():
143 143 yield section, name, value
144 144 seen[section, name] = 1
145 for section in self.cdata.sections():
146 try:
147 for name, value in self.cdata.items(section):
148 if (section, name) in seen: continue
149 yield section, name, value.replace('\n', '\\n')
150 seen[section, name] = 1
151 except ConfigParser.InterpolationError, inst:
152 raise util.Abort(_("Error in configuration section [%s]:\n%s")
153 % (section, inst))
145 sections = self.cdata.sections()
146 sections.sort()
147 for section in sections:
148 for name, value in self.configitems(section):
149 if (section, name) in seen: continue
150 yield section, name, value.replace('\n', '\\n')
151 seen[section, name] = 1
154 152 if self.parentui is not None:
155 153 for parent in self.parentui.walkconfig(seen):
156 154 yield parent
157 155
158 156 def extensions(self):
159 157 result = self.configitems("extensions")
160 158 for i, (key, value) in enumerate(result):
161 159 if value:
162 160 result[i] = (key, os.path.expanduser(value))
163 161 return result
164 162
165 163 def hgignorefiles(self):
166 164 result = []
167 165 for key, value in self.configitems("ui"):
168 166 if key == 'ignore' or key.startswith('ignore.'):
169 167 result.append(os.path.expanduser(value))
170 168 return result
171 169
172 170 def configrevlog(self):
173 171 result = {}
174 172 for key, value in self.configitems("revlog"):
175 173 result[key.lower()] = value
176 174 return result
177 175
178 176 def username(self):
179 177 """Return default username to be used in commits.
180 178
181 179 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
182 180 and stop searching if one of these is set.
183 181 Abort if found username is an empty string to force specifying
184 182 the commit user elsewhere, e.g. with line option or repo hgrc.
185 183 If not found, use ($LOGNAME or $USER or $LNAME or
186 184 $USERNAME) +"@full.hostname".
187 185 """
188 186 user = os.environ.get("HGUSER")
189 187 if user is None:
190 188 user = self.config("ui", "username")
191 189 if user is None:
192 190 user = os.environ.get("EMAIL")
193 191 if user is None:
194 192 try:
195 193 user = '%s@%s' % (util.getuser(), socket.getfqdn())
196 194 except KeyError:
197 195 raise util.Abort(_("Please specify a username."))
198 196 return user
199 197
200 198 def shortuser(self, user):
201 199 """Return a short representation of a user name or email address."""
202 200 if not self.verbose: user = util.shortuser(user)
203 201 return user
204 202
205 203 def expandpath(self, loc, default=None):
206 204 """Return repository location relative to cwd or from [paths]"""
207 205 if "://" in loc or os.path.isdir(loc):
208 206 return loc
209 207
210 208 path = self.config("paths", loc)
211 209 if not path and default is not None:
212 210 path = self.config("paths", default)
213 211 return path or loc
214 212
215 213 def write(self, *args):
216 214 if self.header:
217 215 if self.header != self.prev_header:
218 216 self.prev_header = self.header
219 217 self.write(*self.header)
220 218 self.header = []
221 219 for a in args:
222 220 sys.stdout.write(str(a))
223 221
224 222 def write_header(self, *args):
225 223 for a in args:
226 224 self.header.append(str(a))
227 225
228 226 def write_err(self, *args):
229 227 try:
230 228 if not sys.stdout.closed: sys.stdout.flush()
231 229 for a in args:
232 230 sys.stderr.write(str(a))
233 231 except IOError, inst:
234 232 if inst.errno != errno.EPIPE:
235 233 raise
236 234
237 235 def flush(self):
238 236 try: sys.stdout.flush()
239 237 except: pass
240 238 try: sys.stderr.flush()
241 239 except: pass
242 240
243 241 def readline(self):
244 242 return sys.stdin.readline()[:-1]
245 243 def prompt(self, msg, pat=None, default="y"):
246 244 if not self.interactive: return default
247 245 while 1:
248 246 self.write(msg, " ")
249 247 r = self.readline()
250 248 if not pat or re.match(pat, r):
251 249 return r
252 250 else:
253 251 self.write(_("unrecognized response\n"))
254 252 def getpass(self, prompt=None, default=None):
255 253 if not self.interactive: return default
256 254 return getpass.getpass(prompt or _('password: '))
257 255 def status(self, *msg):
258 256 if not self.quiet: self.write(*msg)
259 257 def warn(self, *msg):
260 258 self.write_err(*msg)
261 259 def note(self, *msg):
262 260 if self.verbose: self.write(*msg)
263 261 def debug(self, *msg):
264 262 if self.debugflag: self.write(*msg)
265 263 def edit(self, text, user):
266 264 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
267 265 text=True)
268 266 try:
269 267 f = os.fdopen(fd, "w")
270 268 f.write(text)
271 269 f.close()
272 270
273 271 editor = (os.environ.get("HGEDITOR") or
274 272 self.config("ui", "editor") or
275 273 os.environ.get("EDITOR", "vi"))
276 274
277 275 util.system("%s \"%s\"" % (editor, name),
278 276 environ={'HGUSER': user},
279 277 onerr=util.Abort, errprefix=_("edit failed"))
280 278
281 279 f = open(name)
282 280 t = f.read()
283 281 f.close()
284 282 t = re.sub("(?m)^HG:.*\n", "", t)
285 283 finally:
286 284 os.unlink(name)
287 285
288 286 return t
289 287
290 288 def print_exc(self):
291 289 '''print exception traceback if traceback printing enabled.
292 290 only to call in exception handler. returns true if traceback
293 291 printed.'''
294 292 if self.traceback:
295 293 traceback.print_exc()
296 294 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now