##// END OF EJS Templates
Cleanup: unifiy the coding style in the ui.py configitems forwarders....
Markus F.X.J. Oberhumer -
r2388:74d56933 default
parent child Browse files
Show More
@@ -1,349 +1,345
1 1 # ui.py - user interface bits for mercurial
2 2 #
3 3 # Copyright 2005 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 import ConfigParser
9 9 from i18n import gettext as _
10 10 from demandload import *
11 11 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
12 12 demandload(globals(), "templater traceback util")
13 13
14 14 class ui(object):
15 15 def __init__(self, verbose=False, debug=False, quiet=False,
16 16 interactive=True, traceback=False, parentui=None):
17 17 self.overlay = {}
18 18 if parentui is None:
19 19 # this is the parent of all ui children
20 20 self.parentui = None
21 21 self.cdata = ConfigParser.SafeConfigParser()
22 22 self.readconfig(util.rcpath())
23 23
24 24 self.quiet = self.configbool("ui", "quiet")
25 25 self.verbose = self.configbool("ui", "verbose")
26 26 self.debugflag = self.configbool("ui", "debug")
27 27 self.interactive = self.configbool("ui", "interactive", True)
28 28 self.traceback = traceback
29 29
30 30 self.updateopts(verbose, debug, quiet, interactive)
31 31 self.diffcache = None
32 32 self.header = []
33 33 self.prev_header = []
34 34 self.revlogopts = self.configrevlog()
35 35 else:
36 36 # parentui may point to an ui object which is already a child
37 37 self.parentui = parentui.parentui or parentui
38 38 parent_cdata = self.parentui.cdata
39 39 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
40 40 # make interpolation work
41 41 for section in parent_cdata.sections():
42 42 self.cdata.add_section(section)
43 43 for name, value in parent_cdata.items(section, raw=True):
44 44 self.cdata.set(section, name, value)
45 45
46 46 def __getattr__(self, key):
47 47 return getattr(self.parentui, key)
48 48
49 49 def updateopts(self, verbose=False, debug=False, quiet=False,
50 50 interactive=True, traceback=False, config=[]):
51 51 self.quiet = (self.quiet or quiet) and not verbose and not debug
52 52 self.verbose = (self.verbose or verbose) or debug
53 53 self.debugflag = (self.debugflag or debug)
54 54 self.interactive = (self.interactive and interactive)
55 55 self.traceback = self.traceback or traceback
56 56 for cfg in config:
57 57 try:
58 58 name, value = cfg.split('=', 1)
59 59 section, name = name.split('.', 1)
60 60 if not self.cdata.has_section(section):
61 61 self.cdata.add_section(section)
62 62 if not section or not name:
63 63 raise IndexError
64 64 self.cdata.set(section, name, value)
65 65 except (IndexError, ValueError):
66 66 raise util.Abort(_('malformed --config option: %s') % cfg)
67 67
68 68 def readconfig(self, fn, root=None):
69 69 if isinstance(fn, basestring):
70 70 fn = [fn]
71 71 for f in fn:
72 72 try:
73 73 self.cdata.read(f)
74 74 except ConfigParser.ParsingError, inst:
75 75 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
76 76 # translate paths relative to root (or home) into absolute paths
77 77 if root is None:
78 78 root = os.path.expanduser('~')
79 79 for name, path in self.configitems("paths"):
80 80 if path and path.find("://") == -1 and not os.path.isabs(path):
81 81 self.cdata.set("paths", name, os.path.join(root, path))
82 82
83 83 def setconfig(self, section, name, val):
84 84 self.overlay[(section, name)] = val
85 85
86 86 def config(self, section, name, default=None):
87 87 if self.overlay.has_key((section, name)):
88 88 return self.overlay[(section, name)]
89 89 if self.cdata.has_option(section, name):
90 90 try:
91 91 return self.cdata.get(section, name)
92 92 except ConfigParser.InterpolationError, inst:
93 93 raise util.Abort(_("Error in configuration:\n%s") % inst)
94 94 if self.parentui is None:
95 95 return default
96 96 else:
97 97 return self.parentui.config(section, name, default)
98 98
99 99 def configbool(self, section, name, default=False):
100 100 if self.overlay.has_key((section, name)):
101 101 return self.overlay[(section, name)]
102 102 if self.cdata.has_option(section, name):
103 103 try:
104 104 return self.cdata.getboolean(section, name)
105 105 except ConfigParser.InterpolationError, inst:
106 106 raise util.Abort(_("Error in configuration:\n%s") % inst)
107 107 if self.parentui is None:
108 108 return default
109 109 else:
110 110 return self.parentui.configbool(section, name, default)
111 111
112 112 def has_config(self, section):
113 113 '''tell whether section exists in config.'''
114 114 return self.cdata.has_section(section)
115 115
116 116 def configitems(self, section):
117 117 items = {}
118 118 if self.parentui is not None:
119 119 items = dict(self.parentui.configitems(section))
120 120 if self.cdata.has_section(section):
121 121 try:
122 122 items.update(dict(self.cdata.items(section)))
123 123 except ConfigParser.InterpolationError, inst:
124 124 raise util.Abort(_("Error in configuration:\n%s") % inst)
125 125 x = items.items()
126 126 x.sort()
127 127 return x
128 128
129 129 def walkconfig(self, seen=None):
130 130 if seen is None:
131 131 seen = {}
132 132 for (section, name), value in self.overlay.iteritems():
133 133 yield section, name, value
134 134 seen[section, name] = 1
135 135 for section in self.cdata.sections():
136 136 for name, value in self.cdata.items(section):
137 137 if (section, name) in seen: continue
138 138 yield section, name, value.replace('\n', '\\n')
139 139 seen[section, name] = 1
140 140 if self.parentui is not None:
141 141 for parent in self.parentui.walkconfig(seen):
142 142 yield parent
143 143
144 144 def extensions(self):
145 145 return self.configitems("extensions")
146 146
147 147 def hgignorefiles(self):
148 result = []
149 cfgitems = self.configitems("ui")
150 for key, value in cfgitems:
151 if key == 'ignore' or key.startswith('ignore.'):
152 path = os.path.expanduser(value)
153 result.append(path)
154 return result
148 ret = []
149 for k, v in self.configitems("ui"):
150 if k == 'ignore' or k.startswith('ignore.'):
151 ret.append(os.path.expanduser(v))
152 return ret
155 153
156 154 def configrevlog(self):
157 155 ret = {}
158 for x in self.configitems("revlog"):
159 k = x[0].lower()
160 ret[k] = x[1]
156 for k, v in self.configitems("revlog"):
157 ret[k.lower()] = v
161 158 return ret
159
162 160 def diffopts(self):
163 161 if self.diffcache:
164 162 return self.diffcache
165 163 ret = { 'showfunc' : True, 'ignorews' : False}
166 for x in self.configitems("diff"):
167 k = x[0].lower()
168 v = x[1]
164 for k, v in self.configitems("diff"):
169 165 if v:
170 166 v = v.lower()
171 167 if v == 'true':
172 value = True
168 v = True
173 169 else:
174 value = False
175 ret[k] = value
170 v = False
171 ret[k.lower()] = v
176 172 self.diffcache = ret
177 173 return ret
178 174
179 175 def username(self):
180 176 """Return default username to be used in commits.
181 177
182 178 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
183 179 and stop searching if one of these is set.
184 180 Abort if found username is an empty string to force specifying
185 181 the commit user elsewhere, e.g. with line option or repo hgrc.
186 182 If not found, use ($LOGNAME or $USER or $LNAME or
187 183 $USERNAME) +"@full.hostname".
188 184 """
189 185 user = os.environ.get("HGUSER")
190 186 if user is None:
191 187 user = self.config("ui", "username")
192 188 if user is None:
193 189 user = os.environ.get("EMAIL")
194 190 if user is None:
195 191 try:
196 192 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
197 193 except KeyError:
198 194 raise util.Abort(_("Please specify a username."))
199 195 return user
200 196
201 197 def shortuser(self, user):
202 198 """Return a short representation of a user name or email address."""
203 199 if not self.verbose: user = util.shortuser(user)
204 200 return user
205 201
206 202 def expandpath(self, loc):
207 203 """Return repository location relative to cwd or from [paths]"""
208 204 if loc.find("://") != -1 or os.path.exists(loc):
209 205 return loc
210 206
211 207 return self.config("paths", loc, loc)
212 208
213 209 def write(self, *args):
214 210 if self.header:
215 211 if self.header != self.prev_header:
216 212 self.prev_header = self.header
217 213 self.write(*self.header)
218 214 self.header = []
219 215 for a in args:
220 216 sys.stdout.write(str(a))
221 217
222 218 def write_header(self, *args):
223 219 for a in args:
224 220 self.header.append(str(a))
225 221
226 222 def write_err(self, *args):
227 223 try:
228 224 if not sys.stdout.closed: sys.stdout.flush()
229 225 for a in args:
230 226 sys.stderr.write(str(a))
231 227 except IOError, inst:
232 228 if inst.errno != errno.EPIPE:
233 229 raise
234 230
235 231 def flush(self):
236 232 try: sys.stdout.flush()
237 233 except: pass
238 234 try: sys.stderr.flush()
239 235 except: pass
240 236
241 237 def readline(self):
242 238 return sys.stdin.readline()[:-1]
243 239 def prompt(self, msg, pat=None, default="y"):
244 240 if not self.interactive: return default
245 241 while 1:
246 242 self.write(msg, " ")
247 243 r = self.readline()
248 244 if not pat or re.match(pat, r):
249 245 return r
250 246 else:
251 247 self.write(_("unrecognized response\n"))
252 248 def getpass(self, prompt=None, default=None):
253 249 if not self.interactive: return default
254 250 return getpass.getpass(prompt or _('password: '))
255 251 def status(self, *msg):
256 252 if not self.quiet: self.write(*msg)
257 253 def warn(self, *msg):
258 254 self.write_err(*msg)
259 255 def note(self, *msg):
260 256 if self.verbose: self.write(*msg)
261 257 def debug(self, *msg):
262 258 if self.debugflag: self.write(*msg)
263 259 def edit(self, text, user):
264 260 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
265 261 text=True)
266 262 try:
267 263 f = os.fdopen(fd, "w")
268 264 f.write(text)
269 265 f.close()
270 266
271 267 editor = (os.environ.get("HGEDITOR") or
272 268 self.config("ui", "editor") or
273 269 os.environ.get("EDITOR", "vi"))
274 270
275 271 util.system("%s \"%s\"" % (editor, name),
276 272 environ={'HGUSER': user},
277 273 onerr=util.Abort, errprefix=_("edit failed"))
278 274
279 275 f = open(name)
280 276 t = f.read()
281 277 f.close()
282 278 t = re.sub("(?m)^HG:.*\n", "", t)
283 279 finally:
284 280 os.unlink(name)
285 281
286 282 return t
287 283
288 284 def sendmail(self):
289 285 '''send mail message. object returned has one method, sendmail.
290 286 call as sendmail(sender, list-of-recipients, msg).'''
291 287
292 288 def smtp():
293 289 '''send mail using smtp.'''
294 290
295 291 s = smtplib.SMTP()
296 292 mailhost = self.config('smtp', 'host')
297 293 if not mailhost:
298 294 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
299 295 mailport = int(self.config('smtp', 'port', 25))
300 296 self.note(_('sending mail: smtp host %s, port %s\n') %
301 297 (mailhost, mailport))
302 298 s.connect(host=mailhost, port=mailport)
303 299 if self.configbool('smtp', 'tls'):
304 300 self.note(_('(using tls)\n'))
305 301 s.ehlo()
306 302 s.starttls()
307 303 s.ehlo()
308 304 username = self.config('smtp', 'username')
309 305 password = self.config('smtp', 'password')
310 306 if username and password:
311 307 self.note(_('(authenticating to mail server as %s)\n') %
312 308 (username))
313 309 s.login(username, password)
314 310 return s
315 311
316 312 class sendmail(object):
317 313 '''send mail using sendmail.'''
318 314
319 315 def __init__(self, ui, program):
320 316 self.ui = ui
321 317 self.program = program
322 318
323 319 def sendmail(self, sender, recipients, msg):
324 320 cmdline = '%s -f %s %s' % (
325 321 self.program, templater.email(sender),
326 322 ' '.join(map(templater.email, recipients)))
327 323 self.ui.note(_('sending mail: %s\n') % cmdline)
328 324 fp = os.popen(cmdline, 'w')
329 325 fp.write(msg)
330 326 ret = fp.close()
331 327 if ret:
332 328 raise util.Abort('%s %s' % (
333 329 os.path.basename(self.program.split(None, 1)[0]),
334 330 util.explain_exit(ret)[0]))
335 331
336 332 method = self.config('email', 'method', 'smtp')
337 333 if method == 'smtp':
338 334 mail = smtp()
339 335 else:
340 336 mail = sendmail(self, method)
341 337 return mail
342 338
343 339 def print_exc(self):
344 340 '''print exception traceback if traceback printing enabled.
345 341 only to call in exception handler. returns true if traceback
346 342 printed.'''
347 343 if self.traceback:
348 344 traceback.print_exc()
349 345 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now